完善权限系统

This commit is contained in:
BBIT-Kai
2025-12-08 18:11:48 +08:00
parent c53926afd6
commit dbdc222541
1503 changed files with 132197 additions and 885 deletions
+89
View File
@@ -0,0 +1,89 @@
import { sha256 } from 'js-sha256';
import { baseRequestClient, requestClient } from '#/api/request';
export namespace AuthApi {
/** 登录接口参数 */
export interface LoginParams {
account?: string;
password?: string;
}
/** 注册 */
export interface RegisterParams {
account?: string;
code?: string;
password?: string;
}
export interface Token {
token: string;
expiresAt: number;
expiresStr: string;
}
/** 登录接口返回值 */
export interface LoginResult {
userId: string;
accessToken: Token;
refreshToken: Token;
}
export interface RefreshTokenResult {
accessToken: Token;
refreshToken: Token;
}
}
/**
* 登录
*/
export async function loginApi(data: AuthApi.LoginParams) {
// 密码加密
data.password = sha256(data.password?.toString() || '');
// 去掉data中的username参数
delete data.username;
return requestClient.post<AuthApi.LoginResult>('/user/login', data);
}
/**
* 发送验证码
*/
export async function sendCodeApi(str: string) {
return requestClient.post<any>('/user/sendCode', { str });
}
/**
* 注册
*/
export async function registerApi(data: AuthApi.RegisterParams) {
// 密码加密
data.password = sha256(data.password?.toString() || '');
return requestClient.post<AuthApi.LoginResult>('/user/register', data);
}
/**
* 刷新accessToken
*/
export async function refreshTokenApi(refreshToken: null | string) {
return requestClient.post<AuthApi.RefreshTokenResult>('/user/refreshToken', {
refreshToken,
});
}
/**
* 退出登录
*/
export async function logoutApi() {
return baseRequestClient.post('/auth/logout', null, {
withCredentials: true,
});
}
/**
* 获取用户权限码
*/
export async function getAccessCodesApi() {
// return requestClient.get<string[]>('/auth/codes');
return [];
}
+4
View File
@@ -0,0 +1,4 @@
export * from './auth';
export * from './menu';
export * from './remote';
export * from './user';
+22
View File
@@ -0,0 +1,22 @@
import type { RouteRecordStringComponent } from '@vben/types';
import { SystemMenuApi } from '#/api';
import { pyRequestClient } from '#/api/request';
/**
* 获取用户所有菜单
*/
export async function getMenuListForUser() {
return pyRequestClient.get<RouteRecordStringComponent[]>(
'/system/menu/list/0',
);
}
/**
* 获取菜单数据列表
*/
export async function getMenuListForAll(plat_id:number) {
return pyRequestClient.get<Array<SystemMenuApi.SystemMenu>>(
`/system/menu/list/all/${plat_id}`,
);
}
+24
View File
@@ -0,0 +1,24 @@
import { requestClient } from '#/api/request';
/**
* 获取在线设备列表数据
*/
export async function refreshDeviceList(name = '') {
return requestClient.get('/remote/refreshDeviceList', { params: { name } });
}
/**
* 按照端口连接设备
*/
export async function connectDeviceByPort(port: string) {
return requestClient.get('/remote/connectLocalDevice', {
params: { port },
});
}
/**
* 断开连接
*/
export async function disConnectAll() {
return requestClient.get('/remote/disConnectAll');
}
+15
View File
@@ -0,0 +1,15 @@
import type { UserInfo } from '@vben/types';
import { requestClient } from '#/api/request';
/**
* 获取用户信息
*/
export async function getUserInfoApi() {
return requestClient.get<UserInfo>('/user/getUserInfo');
}
// export async function getUserInfoApi(user_id: string) {
// return requestClient.get<UserInfo>('/user/getUserInfo', {
// params: { user_id },
// });
// }
+6
View File
@@ -0,0 +1,6 @@
export * from './iva';
export * from './iva-sc';
export * from './license';
export * from './sca';
export * from './sca2';
export * from './ticket';
+25
View File
@@ -0,0 +1,25 @@
import { pyRequestClient } from '#/api/request';
/**
* 获取已分析的视频列表
*/
export async function refreshSCVideoList(name = '', page = 1, pageSize = 9) {
return pyRequestClient.get('/cv/getScVideoList', {
params: { name, page, page_size: pageSize },
});
}
/**
* 获取已分析的视频
*/
export async function refreshSCVideoDetail(vId = '') {
return pyRequestClient.get('/cv/getAnalyticsDetailBySCVideoId', {
params: { vId },
});
}
/**
* 上传视频分析任务
*/
export async function getIVASCUploadToken() {
return pyRequestClient.get('/cv/getIVASCUploadToken');
}
+28
View File
@@ -0,0 +1,28 @@
import { requestClient } from '#/api/request';
/**
* 获取已分析的视频列表
*/
export async function refreshVideoList(name = '') {
return requestClient.get('/iva/getVideoList', { params: { name } });
}
/**
* 获取已分析的视频
*/
export async function refreshVideoDetail(vId = '') {
return requestClient.get('/iva/getAnalyticsDetailByVideoId', {
params: { vId },
});
}
/**
* 上传视频分析任务
*/
export async function createVideoTask(formData: FormData) {
return requestClient.post('/iva/createVideoTask', formData, {
headers: {
'Content-Type': 'multipart/form-data',
},
});
}
+21
View File
@@ -0,0 +1,21 @@
import { pyRequestClient } from '#/api/request';
/**
* 获取已分析的图片列表
*/
export async function refreshLicenseImageList(page = 1, pageSize = 10) {
return pyRequestClient.get('/cv/getLicenseImageList', {
params: { page, page_size: pageSize },
});
}
/**
* 上传图片分析任务
*/
export async function createLicenseImageTask(formData: FormData) {
return pyRequestClient.post('/cv/createLicenseImageTask', formData, {
headers: {
'Content-Type': 'multipart/form-data',
},
});
}
+19
View File
@@ -0,0 +1,19 @@
import { requestClient } from '#/api/request';
/**
* 获取已分析的图片列表
*/
export async function refreshImageList(name = '') {
return requestClient.get('/sca/getImageList', { params: { name } });
}
/**
* 上传图片分析任务
*/
export async function createImageTask(formData: FormData) {
return requestClient.post('/sca/createImageTask', formData, {
headers: {
'Content-Type': 'multipart/form-data',
},
});
}
+25
View File
@@ -0,0 +1,25 @@
import { pyRequestClient } from '#/api/request';
/**
* 获取已分析的图片列表
*/
export async function refreshImageListV2(name = '', page = 1, pageSize = 9) {
return pyRequestClient.get('/cv/getSilkwormCocoonAnalysisTasks', {
params: { name, page, page_size: pageSize },
});
}
/**
* 上传图片分析任务
*/
export async function createImageTaskV2(formData: FormData) {
return pyRequestClient.post(
'/cv/createSilkwormCocoonAnalysisTask',
formData,
{
headers: {
'Content-Type': 'multipart/form-data',
},
},
);
}
+19
View File
@@ -0,0 +1,19 @@
import { pyRequestClient } from '#/api/request';
/**
* 获取已分析的图片列表
*/
export async function refreshTicketImageList() {
return pyRequestClient.get('/cv/getTicketImageList');
}
/**
* 上传图片分析任务
*/
export async function createTicketImageTask(formData: FormData) {
return pyRequestClient.post('/cv/createTicketImageTaskV2', formData, {
headers: {
'Content-Type': 'multipart/form-data',
},
});
}
+4
View File
@@ -0,0 +1,4 @@
export * from './core';
export * from './cv';
export * from './llm';
export * from './manager';
+36
View File
@@ -0,0 +1,36 @@
import { pyRequestClient } from '#/api/request';
/**
* 获取AI列表
*/
export async function getAIBotList() {
return pyRequestClient.get('/llm/aiListForBot');
}
/**
* 获取对话列表
*/
export async function getSessions() {
return pyRequestClient.get('/llm/sessionsForBot');
}
/**
* 获取聊天记录
*/
export async function getHistory(sessionId: string) {
return pyRequestClient.get('/llm/history', { params: { sessionId } });
}
/**
* 聊天
*/
export async function chatWithBot(
aiId: string,
sessionId: null | string,
userInput: string,
) {
return pyRequestClient.post('/llm/chatForBot', {
aiId,
sessionId,
userInput,
});
}
+6
View File
@@ -0,0 +1,6 @@
export * from './bot';
export * from './report';
export * from './report-bot';
export * from './report-data';
export * from './service';
export * from './service-knowledge';
@@ -0,0 +1,26 @@
import { pyRequestClient } from '#/api/request';
/**
* 保存智能体name: str
available_report_tables:list[str]
description: str
role: str
service: str
welcome_words: str
title: str
*/
export async function saveBot(data: {
available_kn_bases: string[];
available_module: string;
available_report_tables: string[];
description: string;
id?: string;
name: string;
report_id: string;
role: string;
service: string;
title: string;
welcome_words: string;
}) {
return pyRequestClient.post('/llm/saveBot', data);
}
@@ -0,0 +1,44 @@
import { pyRequestClient } from '#/api/request';
/**
* 获取表列表
*/
export async function refreshTableList() {
return pyRequestClient.get('/llm/tableList');
}
/**
* 获取字段列表
*/
export async function refreshFieldList(tableId: string) {
return pyRequestClient.get('/llm/fieldList', {
params: {
tableId,
},
});
}
/**
* 新增表
*/
export async function addTable(data: { description: string; name: string }) {
return pyRequestClient.post('/llm/addTable', data);
}
/**
* 新增字段
*/
export async function addField(data: {
description?: string;
is_active?: boolean;
name: string;
table_id: string;
type: string;
}) {
return pyRequestClient.post('/llm/addField', {
name: data.name,
type: data.type,
description: data.description ?? '', // 如果没填就传空字符串
is_active: data.is_active ?? false, // 如果没勾选就传 false
table_id: data.table_id,
});
}
+55
View File
@@ -0,0 +1,55 @@
import { pyRequestClient } from '#/api/request';
/**
* 获取AI列表
*/
export async function getAIReportList() {
return pyRequestClient.get('/llm/aiListForReport');
}
/**
* 获取报表列表
*/
export async function getReports() {
return pyRequestClient.get('/llm/reports');
}
export async function getReport(reportId: string) {
return pyRequestClient.get('/llm/report', { params: { reportId } });
}
/**
* 保存
*/
export async function saveReport(data: { reportId: string }) {
return pyRequestClient.post('/llm/saveReport', data);
}
/**
* 获取
*/
export async function getHistory1(sessionId: string) {
return pyRequestClient.get('/llm/history', { params: { sessionId } });
}
/**
* 聊天
*/
export async function chatWithReport(
aiId: string,
companyId: null | string,
reportId: null | string,
userInput: string,
) {
return pyRequestClient.post('/llm/chatWithReport', {
aiId,
companyId,
reportId,
userInput,
});
}
/**
* 获取租户列表
*/
export async function getCompany() {
return pyRequestClient.get('/llm/companyList');
}
@@ -0,0 +1,44 @@
import { pyRequestClient } from '#/api/request';
/**
* 获取知识库列表
*/
export async function refreshKnowledgeBaseListForService() {
return pyRequestClient.get('/llm/knowledgeBaseListForService');
}
/**
* 获取知识列表
*/
export async function refreshKnowledgeList(knowledgeBaseId: string) {
return pyRequestClient.get('/llm/knowledgeList', {
params: {
knowledgeBaseId,
},
});
}
/**
* 新增知识库
*/
export async function addKnowledgeBase(data: {
description: string;
name: string;
}) {
return pyRequestClient.post('/llm/addKnowledgeBase', data);
}
/**
* 新增知识
*/
export async function addKnowledge(data: {
is_active?: boolean;
knowledge_base_id: string;
text: string;
}) {
return pyRequestClient.post('/llm/addKnowledge', {
text: data.text,
is_active: data.is_active ?? false, // 默认 false
knowledge_base_id: data.knowledge_base_id,
});
}
+29
View File
@@ -0,0 +1,29 @@
import { pyRequestClient } from '#/api/request';
/**
* 获取AI列表
*/
export async function getAIBotListForService() {
return pyRequestClient.get('/llm/aiListForService');
}
/**
* 获取对话列表
*/
export async function getSessionsForService() {
return pyRequestClient.get('/llm/sessionsForService');
}
/**
* 聊天
*/
export async function chatWithService(
aiId: string,
sessionId: null | string,
userInput: string,
) {
return pyRequestClient.post('/llm/chatForService', {
aiId,
sessionId,
userInput,
});
}
@@ -0,0 +1,53 @@
import { pyRequestClient } from '#/api/request';
export namespace SystemDeptApi {
export interface SystemDept {
[key: string]: any;
children?: SystemDept[];
id: string;
name: string;
comment?: string;
}
}
/**
* 获取部门列表数据
*/
async function getDeptList() {
return pyRequestClient.get<Array<SystemDeptApi.SystemDept>>(
'/system/dept/list',
);
}
/**
* 创建部门
* @param data 部门数据
*/
async function createDept(
data: Omit<SystemDeptApi.SystemDept, 'children' | 'id'>,
) {
return pyRequestClient.post('/system/dept/add', data);
}
/**
* 更新部门
*
* @param id 部门 ID
* @param data 部门数据
*/
async function updateDept(
id: string,
data: Omit<SystemDeptApi.SystemDept, 'children' | 'id'>,
) {
return pyRequestClient.put(`/system/dept/${id}`, data);
}
/**
* 删除部门
* @param id 部门 ID
*/
async function deleteDept(id: string) {
return pyRequestClient.delete(`/system/dept/${id}`);
}
export { createDept, deleteDept, getDeptList, updateDept };
@@ -0,0 +1,4 @@
export * from './dept';
export * from './menu';
export * from './role';
export * from './user';
+149
View File
@@ -0,0 +1,149 @@
import type { Recordable } from '@vben/types';
import { pyRequestClient } from '#/api/request';
export namespace SystemMenuApi {
/** 徽标颜色集合 */
export const BadgeVariants = [
'default',
'destructive',
'primary',
'success',
'warning',
] as const;
/** 徽标类型集合 */
export const BadgeTypes = ['dot', 'normal'] as const;
/** 菜单类型集合 */
export const MenuTypes = [
'catalog',
'menu',
'embedded',
'link',
'button',
] as const;
/** 系统菜单 */
export interface SystemMenu {
[key: string]: any;
/** 后端权限标识 */
authCode: string;
/** 子级 */
children?: SystemMenu[];
/** 组件 */
component?: string;
/** 菜单ID */
id: string;
/** 菜单元数据 */
meta?: {
/** 激活时显示的图标 */
activeIcon?: string;
/** 作为路由时,需要激活的菜单的Path */
activePath?: string;
/** 固定在标签栏 */
affixTab?: boolean;
/** 在标签栏固定的顺序 */
affixTabOrder?: number;
/** 徽标内容(当徽标类型为normal时有效) */
badge?: string;
/** 徽标类型 */
badgeType?: (typeof BadgeTypes)[number];
/** 徽标颜色 */
badgeVariants?: (typeof BadgeVariants)[number];
/** 在菜单中隐藏下级 */
hideChildrenInMenu?: boolean;
/** 在面包屑中隐藏 */
hideInBreadcrumb?: boolean;
/** 在菜单中隐藏 */
hideInMenu?: boolean;
/** 在标签栏中隐藏 */
hideInTab?: boolean;
/** 菜单图标 */
icon?: string;
/** 内嵌Iframe的URL */
iframeSrc?: string;
/** 是否缓存页面 */
keepAlive?: boolean;
/** 外链页面的URL */
link?: string;
/** 同一个路由最大打开的标签数 */
maxNumOfOpenTab?: number;
/** 无需基础布局 */
noBasicLayout?: boolean;
/** 是否在新窗口打开 */
openInNewWindow?: boolean;
/** 菜单排序 */
order?: number;
/** 额外的路由参数 */
query?: Recordable<any>;
/** 菜单标题 */
title?: string;
};
/** 菜单名称 */
name: string;
/** 路由路径 */
path: string;
/** 父级ID */
pid: string;
/** 重定向 */
redirect?: string;
/** 菜单类型 */
type: (typeof MenuTypes)[number];
}
}
async function isMenuNameExists(
name: string,
id?: SystemMenuApi.SystemMenu['id'],
) {
return pyRequestClient.get<boolean>('/system/menu/name-exists/0', {
params: { id, name },
});
}
async function isMenuPathExists(
path: string,
id?: SystemMenuApi.SystemMenu['id'],
) {
return pyRequestClient.get<boolean>('/system/menu/path-exists/0', {
params: { id, path },
});
}
/**
* 创建菜单
* @param data 菜单数据
*/
async function createMenu(
plat_id:number,
data: Omit<SystemMenuApi.SystemMenu, 'children' | 'id'>,
) {
return pyRequestClient.post(`/system/menu/${plat_id}`, data);
}
/**
* 更新菜单
*
* @param id 菜单 ID
* @param data 菜单数据
*/
async function updateMenu(
id: string,
data: Omit<SystemMenuApi.SystemMenu, 'children' | 'id'>,
) {
return pyRequestClient.put(`/system/menu/${id}`, data);
}
/**
* 删除菜单
* @param id 菜单 ID
*/
async function deleteMenu(id: string) {
return pyRequestClient.delete(`/system/menu/${id}`);
}
export {
createMenu,
deleteMenu,
isMenuNameExists,
isMenuPathExists,
updateMenu,
};
@@ -0,0 +1,60 @@
import type { Recordable } from '@vben/types';
import { pyRequestClient } from '#/api/request';
export namespace SystemRoleApi {
export interface SystemRole {
[key: string]: any;
id: string;
name: string;
permissions: string[];
remark?: string;
}
}
/**
* 获取角色列表数据
*/
async function getRoleList(params: Recordable<any>) {
return pyRequestClient.get<Array<SystemRoleApi.SystemRole>>(
'/system/role/list',
{ params },
);
}
async function getAllRoleList() {
return pyRequestClient.get<Array<SystemRoleApi.SystemRole>>(
'/system/role/all',
);
}
/**
* 创建角色
* @param data 角色数据
*/
async function createRole(data: Omit<SystemRoleApi.SystemRole, 'id'>) {
return pyRequestClient.post('/system/role', data);
}
/**
* 更新角色
*
* @param id 角色 ID
* @param data 角色数据
*/
async function updateRole(
id: string,
data: Omit<SystemRoleApi.SystemRole, 'id'>,
) {
return pyRequestClient.put(`/system/role/${id}`, data);
}
/**
* 删除角色
* @param id 角色 ID
*/
async function deleteRole(id: string) {
return pyRequestClient.delete(`/system/role/${id}`);
}
export { createRole, deleteRole, getRoleList, updateRole ,getAllRoleList};
@@ -0,0 +1,73 @@
import type { Recordable } from '@vben/types';
import { pyRequestClient } from '#/api/request';
import { sha256 } from "js-sha256";
export namespace SystemUserApi {
export interface SystemUser {
[key: string]: any;
id: string;
email?: string;
name: string;
roles: string[];
phone?: string;
status: 0 | 1;
dept_id?: string;
dept_name?: string;
}
}
/**
* 获取用户列表数据
*/
async function getUserList(params: Recordable<any>) {
return pyRequestClient.get<Array<SystemUserApi.SystemUser>>(
'/system/user/list',
{ params },
);
}
/**
* 创建用户
* @param data 用户数据
*/
async function createUser(data: Omit<SystemUserApi.SystemUser, 'id'>) {
data.password_hash = sha256(data.password?.toString() || '');
delete data.password;
return pyRequestClient.post('/system/user', data);
}
/**
* 更新用户
*
* @param id 用户 ID
* @param data 用户数据
*/
async function updateUser(
id: string,
data: Omit<SystemUserApi.SystemUser, 'id'>,
) {
return pyRequestClient.put(`/system/user/${id}`, data);
}
/**
* 更新用户(部分更新)
*
* @param id 用户 ID
* @param data 需要更新的字段(部分字段即可)
*/
async function updateUserPatch(
id: string,
data: Partial<Omit<SystemUserApi.SystemUser, 'id'>>,
) {
return pyRequestClient.patch(`/system/user/${id}`, data);
}
/**
* 删除用户
* @param id 用户 ID
*/
async function deleteUser(id: string) {
return pyRequestClient.delete(`/system/user/${id}`);
}
export { createUser, deleteUser, getUserList, updateUser,updateUserPatch };
+124
View File
@@ -0,0 +1,124 @@
/**
* 该文件可自行根据业务逻辑进行调整
*/
import type { RequestClientOptions } from '@vben/request';
import { useAppConfig } from '@vben/hooks';
import { preferences } from '@vben/preferences';
import {
authenticateResponseInterceptor,
defaultResponseInterceptor,
errorMessageResponseInterceptor,
RequestClient,
} from '@vben/request';
import { useAccessStore } from '@vben/stores';
import { message } from 'ant-design-vue';
import { useAuthStore } from '#/store';
import { refreshTokenApi } from './core';
const { apiURL, pyApiURL } = useAppConfig(
import.meta.env,
import.meta.env.PROD,
);
function createRequestClient(baseURL: string, options?: RequestClientOptions) {
const client = new RequestClient({
...options,
baseURL,
});
/**
* 重新认证逻辑
*/
async function doReAuthenticate() {
console.warn('Access token or refresh token is invalid or expired. ');
const accessStore = useAccessStore();
const authStore = useAuthStore();
accessStore.setAccessToken(null);
if (
preferences.app.loginExpiredMode === 'modal' &&
accessStore.isAccessChecked
) {
accessStore.setLoginExpired(true);
} else {
await authStore.logout();
}
}
/**
* 刷新token逻辑
*/
async function doRefreshToken() {
const accessStore = useAccessStore();
const resp = await refreshTokenApi(accessStore.refreshToken);
const newAccessToken = resp.accessToken.token;
const newRefreshToken = resp.refreshToken.token;
if (newAccessToken) {
accessStore.setAccessToken(newAccessToken);
accessStore.setRefreshToken(newRefreshToken);
}
return newAccessToken;
}
function formatToken(token: null | string) {
return token ? `Bearer ${token}` : null;
}
// 请求头处理
client.addRequestInterceptor({
fulfilled: async (config) => {
const accessStore = useAccessStore();
config.headers.Authorization = formatToken(accessStore.accessToken);
config.headers['Accept-Language'] = preferences.app.locale;
return config;
},
});
// 处理返回的响应数据格式
client.addResponseInterceptor(
defaultResponseInterceptor({
codeField: 'status',
dataField: 'data',
successCode: true,
}),
);
// token过期的处理
client.addResponseInterceptor(
authenticateResponseInterceptor({
client,
doReAuthenticate,
doRefreshToken,
enableRefreshToken: preferences.app.enableRefreshToken,
formatToken,
}),
);
// 通用的错误处理,如果没有进入上面的错误处理逻辑,就会进入这里
client.addResponseInterceptor(
errorMessageResponseInterceptor((msg: string, error) => {
// 这里可以根据业务进行定制,你可以拿到 error 内的信息进行定制化处理,根据不同的 code 做不同的提示,而不是直接使用 message.error 提示 msg
// 当前mock接口返回的错误字段是 error 或者 message
const responseData = error?.response?.data ?? {};
const errorMessage = responseData?.error ?? responseData?.message ?? '';
// 如果没有错误信息,则会根据状态码进行提示
message.error(errorMessage || msg);
}),
);
return client;
}
export const requestClient = createRequestClient(apiURL, {
responseReturn: 'data',
});
export const pyRequestClient = createRequestClient(pyApiURL, {
responseReturn: 'data',
});
export const baseRequestClient = new RequestClient({ baseURL: apiURL });