This commit is contained in:
lijianyou
2025-09-30 15:00:32 +08:00
parent 1b262f06b8
commit b4e759cf69
202 changed files with 22035 additions and 0 deletions
+79
View File
@@ -0,0 +1,79 @@
import { defineStore } from 'pinia';
import http from './http';
import { Response } from '@/types';
import { useMenuStore } from './menu';
import { useAuthStore } from '@/plugins';
export interface Profile {
account: Account;
permissions: string[];
role: string;
}
export interface Account {
username: string;
avatar: string;
gender: number;
}
export type TokenResult = {
token: string;
expires: number;
code: number,
erro: string,
};
export const useAccountStore = defineStore('account', {
state() {
return {
account: {} as Account,
permissions: [] as string[],
role: '',
logged: true,
logged2: false
};
},
actions: {
async login(username: string, password: string) {
return http
.request<TokenResult, Response<TokenResult>>('api/auth/login', 'post_json', { username, password })
.then(async (response) => {
if (response.code === 200 && response.data.code === 0) {
this.logged = true;
this.logged2 = true
console.log(response)
http.setAuthorization(`Bearer ${response.data.token}`, response.data.expires);
// await useMenuStore().getMenuList();
return response.data;
} else {
this.logged2 = false
return Promise.reject(response);
}
});
},
async logout() {
return new Promise<boolean>((resolve) => {
localStorage.removeItem('stepin-menu');
http.removeAuthorization();
// this.logged = false;
resolve(true);
});
},
async profile() {
return http.request<Account, Response<Profile>>('/account', 'get').then((response) => {
if (response.code === 0) {
const { setAuthorities } = useAuthStore();
const { account, permissions, role } = response.data;
this.account = account;
this.permissions = permissions;
this.role = role;
setAuthorities(permissions);
return response.data;
} else {
return Promise.reject(response);
}
});
},
setLogged(logged: boolean) {
this.logged = logged;
},
},
});
+181
View File
@@ -0,0 +1,181 @@
import { defineStore, storeToRefs } from 'pinia';
import http from './http';
import { ref, watch } from 'vue';
import { Response } from '@/types';
// import { RouteOption } from '@/router/interface';
// import { addRoutes, removeRoute } from '@/router/dynamicRoutes';
// import { useSettingStore } from './setting';
// import { RouteRecordRaw, RouteMeta } from 'vue-router';
// import { useAuthStore } from '@/plugins';
// import router from '@/router';
// export interface MenuProps {
// id?: number;
// name: string;
// path: string;
// title?: string;
// icon?: string;
// badge?: number | string;
// target?: '_self' | '_blank';
// link?: string;
// component: string;
// renderMenu?: boolean;
// permission?: string;
// parent?: string;
// children?: MenuProps[];
// cacheable?: boolean;
// view?: string;
// }
export const useApiStore = defineStore('coreapi', () => {
//检查是否已经初始化过了
async function apiCheckInitStatus() {
return { code: 0 }
// const initStatus = localStorage.getItem('ddns-init');
// if (initStatus && initStatus === '1') {
// return { code: 0 }
// } else {
// return http
// .request<any, Response<any>>('/api/init/Check', 'GET')
// .then((res) => {
// // console.log(res)
// if (res.data.code === 0) {
// // localStorage.setItem('ddns-init', '1')
// }
// return res.data;
// })
// .finally(() => {
// });
// }
}
//初始化系统配置
async function apiInit(request: object) {
console.log(request)
return http
.request<any, Response<any>>('/api/init/Init', 'post_json', request)
.then((res) => {
// console.log(res)
return res.data;
})
.finally(() => {
});
}
//获取配置
async function apiGetConfig() {
return http
.request<any, Response<any>>('/api/config/GetConfig', 'GET')
.then((res) => {
console.log(res)
return res.data;
})
.finally(() => {
});
}
//修改配置
async function apiUpdateConfig(request: object) {
return http
.request<any, Response<any>>('/api/config/UpdateConfig', 'post_json', request)
.then((res) => {
console.log(res)
return res.data;
})
.finally(() => {
});
}
//后台日志
async function apiGetLogs(param: string) {
return http.request<any, Response<any>>('/api/logs/GetLog?' + param, 'get').then(r => {
// console.log(r)
return r.data;
}).finally(() => {
});
}
//用户信息-头像
async function apiUserInfo() {
return http.request<any, Response<any>>('/api/auth/GetUserAvatar', 'get').then(r => {
return r.data;
}).finally(() => {
});
}
//密码修改
async function apiChangePwd(param: object) {
return http.request<any, Response<any>>('/api/auth/UpdatePwd', 'post_json', param).then(r => {
return r.data;
}).finally(() => {
});
}
//StartJobNow
async function StartJobNow() {
return http.request<any, Response<any>>('/api/config/ExecuteJobNow', 'get').then(r => {
return r.data;
}).finally(() => {
});
}
async function VideoStatics() {
return http.request<any, Response<any>>('/api/video/statics', 'get').then(r => {
return r.data;
}).finally(() => {
});
}
//视频查询
async function VideoPageList(param: object) {
return http.request<any, Response<any>>('/api/video/paged', 'post_json', param).then(r => {
return r.data;
}).finally(() => {
});
}
//cookies
async function CookiePageList(param: object) {
return http.request<any, Response<any>>('/api/config/paged', 'post_json', param).then(r => {
return r.data;
}).finally(() => {
});
}
async function UpdateConfig(param: object) {
return http.request<any, Response<any>>('/api/config/update', 'post_json', param).then(r => {
return r.data;
}).finally(() => {
});
}
async function deleteCookie(id: string) {
return http.request<any, Response<any>>('/api/config/delete?id=' + id, 'get').then(r => {
return r.data;
}).finally(() => {
});
}
return {
deleteCookie,
UpdateConfig,
apiCheckInitStatus,
apiInit,
apiGetConfig,
apiUpdateConfig,
apiGetLogs,
apiUserInfo,
apiChangePwd,
StartJobNow,
VideoStatics,
VideoPageList,
CookiePageList
};
});
+76
View File
@@ -0,0 +1,76 @@
import { AxiosRequestConfig, AxiosResponse } from 'axios';
import createHttp from '@/utils/axiosHttp';
import { isResponse } from '@/types';
import NProgress from 'nprogress';
import { useAccountStore } from '@/store';
const http = createHttp({
timeout: 60000,
baseURL: '/',
withCredentials: true,
xsrfCookieName: 'Authorization',
xsrfHeaderName: 'Authorization',
});
const isAxiosResponse = (obj: any): obj is AxiosResponse => {
return typeof obj === 'object' && obj.status && obj.statusText && obj.headers && obj.config;
};
// progress 进度条 -- 开启
http.interceptors.request.use((req: AxiosRequestConfig) => {
if (!NProgress.isStarted()) {
NProgress.start();
}
return req;
});
// 解析响应结果
http.interceptors.response.use(
(rep: AxiosResponse<String>) => {
const { data } = rep;
// if (data.code != null)
// console.log(data)
// if (data.code === 401) {
// console.log(data)
// }
if (isResponse(data)) {
return data.code === 0 ? data : Promise.reject(data);
}
return Promise.reject({ message: rep.statusText, code: rep.status, data });
},
(error) => {
// console.log(error)
// debugger
if (error.response.status === 401) {
useAccountStore().setLogged(false)
} else {
if (error.response && isAxiosResponse(error.response)) {
return Promise.reject({
message: error.response.statusText,
code: error.response.status,
data: error.response.data,
});
}
}
return Promise.reject(error);
}
);
// progress 进度条 -- 关闭
http.interceptors.response.use(
(rep) => {
if (NProgress.isStarted()) {
NProgress.done();
}
return rep;
},
(error) => {
if (NProgress.isStarted()) {
NProgress.done();
}
return error;
}
);
export default http;
+10
View File
@@ -0,0 +1,10 @@
import { createPinia } from 'pinia';
export { storeToRefs } from 'pinia';
export * from './account';
export * from './menu';
export * from './setting';
export * from './coreapi';
const pinia = createPinia();
export default pinia;
+266
View File
@@ -0,0 +1,266 @@
import { defineStore, storeToRefs } from 'pinia';
import http from './http';
import { ref, watch } from 'vue';
import { Response } from '@/types';
import { RouteOption } from '@/router/interface';
import { addRoutes, removeRoute } from '@/router/dynamicRoutes';
import { useSettingStore } from './setting';
import { RouteRecordRaw, RouteMeta } from 'vue-router';
import { useAuthStore } from '@/plugins';
import router from '@/router';
export interface MenuProps {
id?: number;
name: string;
path: string;
title?: string;
icon?: string;
badge?: number | string;
target?: '_self' | '_blank';
link?: string;
component: string;
renderMenu?: boolean;
permission?: string;
parent?: string;
children?: MenuProps[];
cacheable?: boolean;
view?: string;
}
/**
* 过滤菜单
* @param routes
* @param parentPermission
*/
function doMenuFilter(routes: Readonly<RouteRecordRaw[]>, parentPermission?: string) {
const { hasAuthority } = useAuthStore();
const setCache = (meta: RouteMeta) => {
meta._cache = {
renderMenu: meta.renderMenu,
};
};
routes.forEach((route) => {
const required = route.meta?.permission ?? parentPermission;
// if (route.meta?.renderMenu === undefined && required) {
if (required) {
route.meta = route.meta ?? {};
setCache(route.meta);
route.meta.renderMenu = hasAuthority(route.meta.permission);
}
if (route.children) {
doMenuFilter(route.children, required);
}
});
}
/**
* 重置过滤
* @param routes
*/
function resetMenuFilter(routes: Readonly<RouteRecordRaw[]>) {
const resetCache = (meta: RouteMeta) => {
if (meta._cache) {
meta.renderMenu = meta._cache?.renderMenu;
}
delete meta._cache;
};
routes.forEach((route) => {
if (route.meta) {
resetCache(route.meta);
}
if (route.children) {
resetMenuFilter(route.children);
}
});
}
// 菜单数据转为路由数据
const toRoutes = (list: MenuProps[]): RouteOption[] => {
return list.map((item) => ({
name: item.name,
path: item.path,
component: item.component,
children: item.children && toRoutes(item.children),
meta: {
title: item.title,
permission: item.permission,
icon: item.icon,
renderMenu: item.renderMenu,
cacheable: item.cacheable,
href: item.link,
badge: /^(false|true)$/i.test(item.badge + '') ? JSON.parse(item.badge + '') : item.badge,
target: item.target,
view: item.view,
},
}));
};
export const useMenuStore = defineStore('menu', () => {
const menuList = ref<MenuProps[]>([]);
const loading = ref(false);
const { filterMenu } = storeToRefs(useSettingStore());
const checkMenuPermission = () => {
if (filterMenu.value) {
doMenuFilter(router.options.routes);
console.log(router.options.routes);
} else {
resetMenuFilter(router.options.routes);
}
};
checkMenuPermission();
watch(filterMenu, checkMenuPermission);
const presetList = [
// {
// id: 1,
// name: 'workplace',
// title: '变更记录',
// icon: 'DashboardOutlined',
// badge: '',
// target: '_self',
// path: '/workplace',
// component: '@/pages/workplace',
// renderMenu: true,
// parent: null,
// permission: null,
// cacheable: true,
// },
// {
// id: 2,
// name: 'set',
// title: '我的配置',
// icon: 'SettingOutlined',
// badge: '',
// target: '_self',
// path: '/set',
// component: '@/pages/set',
// renderMenu: true,
// parent: null,
// permission: null,
// cacheable: true,
// },
// {
// id: 3,
// name: 'logs',
// title: '系统日志',
// icon: 'UnorderedListOutlined',
// badge: '',
// target: '_self',
// path: '/logs',
// component: '@/pages/logs',
// renderMenu: true,
// parent: null,
// permission: null,
// // cacheable: true,
// }
];
function getlocalMenus() {
const menuStr = localStorage.getItem('stepin-menu');
// debugger;
let menus = [];
if (!menuStr) {
menus = presetList;
localStorage.setItem('stepin-menu', JSON.stringify(menus));
} else {
menus = JSON.parse(menuStr);
}
// menus = presetList;
// console.log('menus', menus)
return menus;
}
function getMenuList() {
loading.value = true;
let localMenus = getlocalMenus();
const menuMap = localMenus.reduce((p, c) => {
p[c.name] = c;
return p;
}, {});
localMenus.forEach((menu) => {
menu.renderMenu = !!menu.renderMenu;
if (menu.parent) {
const parent = menuMap[menu.parent];
parent.children = parent.children ?? [];
parent.children.push(menu);
}
});
const res = {
message: 'success',
code: 0,
data: localMenus.filter((menu) => !menu.parent),
};
const { data } = res;
menuList.value = data;
// console.log(data)
addRoutes(toRoutes(data));
checkMenuPermission();
// loading.value = false;
setTimeout(() => {
loading.value = false;
}, 100);
return data;
// return http
// .request<MenuProps[], Response<MenuProps[]>>('/menu', 'GET')
// .then((res) => {
// const { data } = res;
// menuList.value = data;
// addRoutes(toRoutes(data));
// checkMenuPermission();
// return data;
// })
// .finally(() => (loading.value = false));
}
async function addMenu(menu: MenuProps) {
return http
.request<any, Response<any>>('/menu', 'POST_JSON', menu)
.then((res) => {
return res.data;
})
.finally(getMenuList);
}
async function updateMenu(menu: MenuProps) {
return http
.request<any, Response<any>>('/menu', 'PUT_JSON', menu)
.then((res) => {
return res.data;
})
.finally(getMenuList);
}
async function removeMenu(id: number) {
return http
.request<any, Response<any>>('/menu', 'DELETE', { id })
.then(async (res) => {
if (res.code === 0) {
removeRoute(res.data.name);
}
})
.finally(getMenuList);
}
return {
loading,
menuList,
getMenuList,
addMenu,
updateMenu,
removeMenu,
};
});
+36
View File
@@ -0,0 +1,36 @@
import { defineStore } from 'pinia';
import { ref } from 'vue';
export type Navigation = 'side' | 'head' | 'mix';
export const useSettingStore = defineStore('setting', () => {
const navigation = ref<Navigation>('head');
const useTabs = ref<boolean>(true);
const theme = ref('header-purple');
const contentClass = ref('common');
const filterMenu = ref(false);
function setNavigation(nav: Navigation) {
navigation.value = nav;
}
function setTheme(value: string) {
theme.value = value;
}
function setContentClass(className: string) {
contentClass.value = className;
}
function setFilterMenu(filter: boolean) {
filterMenu.value = filter;
}
return {
navigation,
useTabs,
theme,
contentClass,
filterMenu,
setNavigation,
setTheme,
setContentClass,
setFilterMenu,
};
});