Merge remote-tracking branch 'yudao/dev' into dev-new
This commit is contained in:
BIN
apps/web-antd/public/static/imgs/ai/dall2.jpg
Normal file
BIN
apps/web-antd/public/static/imgs/ai/dall2.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 108 KiB |
BIN
apps/web-antd/public/static/imgs/ai/dall3.jpg
Normal file
BIN
apps/web-antd/public/static/imgs/ai/dall3.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 87 KiB |
BIN
apps/web-antd/public/static/imgs/ai/qingxi.jpg
Normal file
BIN
apps/web-antd/public/static/imgs/ai/qingxi.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 86 KiB |
BIN
apps/web-antd/public/static/imgs/ai/ziran.jpg
Normal file
BIN
apps/web-antd/public/static/imgs/ai/ziran.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 121 KiB |
@@ -12,6 +12,7 @@ import {
|
||||
} from '@vben/plugins/vxe-table';
|
||||
import {
|
||||
erpNumberFormatter,
|
||||
formatPast2,
|
||||
formatToFractionDigit,
|
||||
isFunction,
|
||||
isString,
|
||||
@@ -296,32 +297,7 @@ setupVbenVxeTable({
|
||||
|
||||
vxeUI.formats.add('formatPast2', {
|
||||
tableCellFormatMethod({ cellValue }) {
|
||||
if (cellValue === null || cellValue === undefined) {
|
||||
return '';
|
||||
}
|
||||
// 定义时间单位常量,便于维护
|
||||
const SECOND = 1000;
|
||||
const MINUTE = 60 * SECOND;
|
||||
const HOUR = 60 * MINUTE;
|
||||
const DAY = 24 * HOUR;
|
||||
|
||||
// 计算各时间单位
|
||||
const day = Math.floor(cellValue / DAY);
|
||||
const hour = Math.floor((cellValue % DAY) / HOUR);
|
||||
const minute = Math.floor((cellValue % HOUR) / MINUTE);
|
||||
const second = Math.floor((cellValue % MINUTE) / SECOND);
|
||||
|
||||
// 根据时间长短返回不同格式
|
||||
if (day > 0) {
|
||||
return `${day} 天${hour} 小时 ${minute} 分钟`;
|
||||
}
|
||||
if (hour > 0) {
|
||||
return `${hour} 小时 ${minute} 分钟`;
|
||||
}
|
||||
if (minute > 0) {
|
||||
return `${minute} 分钟`;
|
||||
}
|
||||
return second > 0 ? `${second} 秒` : `${0} 秒`;
|
||||
return formatPast2(cellValue);
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
75
apps/web-antd/src/api/ai/chat/conversation/index.ts
Normal file
75
apps/web-antd/src/api/ai/chat/conversation/index.ts
Normal file
@@ -0,0 +1,75 @@
|
||||
import type { PageResult } from '@vben/request';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace AiChatConversationApi {
|
||||
export interface ChatConversationVO {
|
||||
id: number; // ID 编号
|
||||
userId: number; // 用户编号
|
||||
title: string; // 对话标题
|
||||
pinned: boolean; // 是否置顶
|
||||
roleId: number; // 角色编号
|
||||
modelId: number; // 模型编号
|
||||
model: string; // 模型标志
|
||||
temperature: number; // 温度参数
|
||||
maxTokens: number; // 单条回复的最大 Token 数量
|
||||
maxContexts: number; // 上下文的最大 Message 数量
|
||||
createTime?: Date; // 创建时间
|
||||
// 额外字段
|
||||
systemMessage?: string; // 角色设定
|
||||
modelName?: string; // 模型名字
|
||||
roleAvatar?: string; // 角色头像
|
||||
modelMaxTokens?: string; // 模型的单条回复的最大 Token 数量
|
||||
modelMaxContexts?: string; // 模型的上下文的最大 Message 数量
|
||||
}
|
||||
}
|
||||
|
||||
// 获得【我的】聊天对话
|
||||
export function getChatConversationMy(id: number) {
|
||||
return requestClient.get<AiChatConversationApi.ChatConversationVO>(
|
||||
`/ai/chat/conversation/get-my?id=${id}`,
|
||||
);
|
||||
}
|
||||
|
||||
// 新增【我的】聊天对话
|
||||
export function createChatConversationMy(
|
||||
data: AiChatConversationApi.ChatConversationVO,
|
||||
) {
|
||||
return requestClient.post('/ai/chat/conversation/create-my', data);
|
||||
}
|
||||
|
||||
// 更新【我的】聊天对话
|
||||
export function updateChatConversationMy(
|
||||
data: AiChatConversationApi.ChatConversationVO,
|
||||
) {
|
||||
return requestClient.put(`/ai/chat/conversation/update-my`, data);
|
||||
}
|
||||
|
||||
// 删除【我的】聊天对话
|
||||
export function deleteChatConversationMy(id: number) {
|
||||
return requestClient.delete(`/ai/chat/conversation/delete-my?id=${id}`);
|
||||
}
|
||||
|
||||
// 删除【我的】所有对话,置顶除外
|
||||
export function deleteChatConversationMyByUnpinned() {
|
||||
return requestClient.delete(`/ai/chat/conversation/delete-by-unpinned`);
|
||||
}
|
||||
|
||||
// 获得【我的】聊天对话列表
|
||||
export function getChatConversationMyList() {
|
||||
return requestClient.get<AiChatConversationApi.ChatConversationVO[]>(
|
||||
`/ai/chat/conversation/my-list`,
|
||||
);
|
||||
}
|
||||
|
||||
// 获得【我的】聊天对话列表
|
||||
export function getChatConversationPage(params: any) {
|
||||
return requestClient.get<
|
||||
PageResult<AiChatConversationApi.ChatConversationVO[]>
|
||||
>(`/ai/chat/conversation/page`, { params });
|
||||
}
|
||||
|
||||
// 管理员删除消息
|
||||
export function deleteChatConversationByAdmin(id: number) {
|
||||
return requestClient.delete(`/ai/chat/conversation/delete-by-admin?id=${id}`);
|
||||
}
|
||||
95
apps/web-antd/src/api/ai/chat/message/index.ts
Normal file
95
apps/web-antd/src/api/ai/chat/message/index.ts
Normal file
@@ -0,0 +1,95 @@
|
||||
import type { PageResult } from '@vben/request';
|
||||
|
||||
import { useAppConfig } from '@vben/hooks';
|
||||
import { fetchEventSource } from '@vben/request';
|
||||
import { useAccessStore } from '@vben/stores';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
const { apiURL } = useAppConfig(import.meta.env, import.meta.env.PROD);
|
||||
const accessStore = useAccessStore();
|
||||
export namespace AiChatMessageApi {
|
||||
export interface ChatMessageVO {
|
||||
id: number; // 编号
|
||||
conversationId: number; // 对话编号
|
||||
type: string; // 消息类型
|
||||
userId: string; // 用户编号
|
||||
roleId: string; // 角色编号
|
||||
model: number; // 模型标志
|
||||
modelId: number; // 模型编号
|
||||
content: string; // 聊天内容
|
||||
tokens: number; // 消耗 Token 数量
|
||||
segmentIds?: number[]; // 段落编号
|
||||
segments?: {
|
||||
content: string; // 段落内容
|
||||
documentId: number; // 文档编号
|
||||
documentName: string; // 文档名称
|
||||
id: number; // 段落编号
|
||||
}[];
|
||||
createTime: Date; // 创建时间
|
||||
roleAvatar: string; // 角色头像
|
||||
userAvatar: string; // 用户头像
|
||||
}
|
||||
}
|
||||
|
||||
// 消息列表
|
||||
export function getChatMessageListByConversationId(
|
||||
conversationId: null | number,
|
||||
) {
|
||||
return requestClient.get<AiChatMessageApi.ChatMessageVO[]>(
|
||||
`/ai/chat/message/list-by-conversation-id?conversationId=${conversationId}`,
|
||||
);
|
||||
}
|
||||
|
||||
// 发送 Stream 消息
|
||||
export function sendChatMessageStream(
|
||||
conversationId: number,
|
||||
content: string,
|
||||
ctrl: any,
|
||||
enableContext: boolean,
|
||||
onMessage: any,
|
||||
onError: any,
|
||||
onClose: any,
|
||||
) {
|
||||
const token = accessStore.accessToken;
|
||||
return fetchEventSource(`${apiURL}/ai/chat/message/send-stream`, {
|
||||
method: 'post',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
openWhenHidden: true,
|
||||
body: JSON.stringify({
|
||||
conversationId,
|
||||
content,
|
||||
useContext: enableContext,
|
||||
}),
|
||||
onmessage: onMessage,
|
||||
onerror: onError,
|
||||
onclose: onClose,
|
||||
signal: ctrl.signal,
|
||||
});
|
||||
}
|
||||
|
||||
// 删除消息
|
||||
export function deleteChatMessage(id: number) {
|
||||
return requestClient.delete(`/ai/chat/message/delete?id=${id}`);
|
||||
}
|
||||
|
||||
// 删除指定对话的消息
|
||||
export function deleteByConversationId(conversationId: number) {
|
||||
return requestClient.delete(
|
||||
`/ai/chat/message/delete-by-conversation-id?conversationId=${conversationId}`,
|
||||
);
|
||||
}
|
||||
// 获得消息分页
|
||||
export function getChatMessagePage(params: any) {
|
||||
return requestClient.get<PageResult<AiChatMessageApi.ChatMessageVO>>(
|
||||
'/ai/chat/message/page',
|
||||
{ params },
|
||||
);
|
||||
}
|
||||
// 管理员删除消息
|
||||
export function deleteChatMessageByAdmin(id: number) {
|
||||
return requestClient.delete(`/ai/chat/message/delete-by-admin?id=${id}`);
|
||||
}
|
||||
112
apps/web-antd/src/api/ai/image/index.ts
Normal file
112
apps/web-antd/src/api/ai/image/index.ts
Normal file
@@ -0,0 +1,112 @@
|
||||
import type { PageParam, PageResult } from '@vben/request';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace AiImageApi {
|
||||
export interface ImageMidjourneyButtonsVO {
|
||||
customId: string; // MJ::JOB::upsample::1::85a4b4c1-8835-46c5-a15c-aea34fad1862 动作标识
|
||||
emoji: string; // 图标 emoji
|
||||
label: string; // Make Variations 文本
|
||||
style: number; // 样式: 2(Primary)、3(Green)
|
||||
}
|
||||
// AI 绘图 VO
|
||||
export interface ImageVO {
|
||||
id: number; // 编号
|
||||
platform: string; // 平台
|
||||
model: string; // 模型
|
||||
prompt: string; // 提示词
|
||||
width: number; // 图片宽度
|
||||
height: number; // 图片高度
|
||||
status: number; // 状态
|
||||
publicStatus: boolean; // 公开状态
|
||||
picUrl: string; // 任务地址
|
||||
errorMessage: string; // 错误信息
|
||||
options: any; // 配置 Map<string, string>
|
||||
taskId: number; // 任务编号
|
||||
buttons: ImageMidjourneyButtonsVO[]; // mj 操作按钮
|
||||
createTime: Date; // 创建时间
|
||||
finishTime: Date; // 完成时间
|
||||
}
|
||||
|
||||
export interface ImageDrawReqVO {
|
||||
prompt: string; // 提示词
|
||||
modelId: number; // 模型
|
||||
style: string; // 图像生成的风格
|
||||
width: string; // 图片宽度
|
||||
height: string; // 图片高度
|
||||
options: object; // 绘制参数,Map<String, String>
|
||||
}
|
||||
|
||||
export interface ImageMidjourneyImagineReqVO {
|
||||
prompt: string; // 提示词
|
||||
modelId: number; // 模型
|
||||
base64Array?: string[]; // size不能为空
|
||||
width: string; // 图片宽度
|
||||
height: string; // 图片高度
|
||||
version: string; // 版本
|
||||
}
|
||||
|
||||
export interface ImageMidjourneyActionVO {
|
||||
id: number; // 图片编号
|
||||
customId: string; // MJ::JOB::upsample::1::85a4b4c1-8835-46c5-a15c-aea34fad1862 动作标识
|
||||
}
|
||||
}
|
||||
|
||||
// 获取【我的】绘图分页
|
||||
export function getImagePageMy(params: PageParam) {
|
||||
return requestClient.get<PageResult<AiImageApi.ImageVO>>(
|
||||
'/ai/image/my-page',
|
||||
{ params },
|
||||
);
|
||||
}
|
||||
|
||||
// 获取【我的】绘图记录
|
||||
export function getImageMy(id: number) {
|
||||
return requestClient.get<AiImageApi.ImageVO>(`/ai/image/get-my?id=${id}`);
|
||||
}
|
||||
|
||||
// 获取【我的】绘图记录列表
|
||||
export function getImageListMyByIds(ids: number[]) {
|
||||
return requestClient.get<AiImageApi.ImageVO[]>(`/ai/image/my-list-by-ids`, {
|
||||
params: { ids: ids.join(',') },
|
||||
});
|
||||
}
|
||||
|
||||
// 生成图片
|
||||
export function drawImage(data: AiImageApi.ImageDrawReqVO) {
|
||||
return requestClient.post(`/ai/image/draw`, data);
|
||||
}
|
||||
|
||||
// 删除【我的】绘画记录
|
||||
export function deleteImageMy(id: number) {
|
||||
return requestClient.delete(`/ai/image/delete-my?id=${id}`);
|
||||
}
|
||||
|
||||
// ================ midjourney 专属 ================
|
||||
// 【Midjourney】生成图片
|
||||
export function midjourneyImagine(
|
||||
data: AiImageApi.ImageMidjourneyImagineReqVO,
|
||||
) {
|
||||
return requestClient.post(`/ai/image/midjourney/imagine`, data);
|
||||
}
|
||||
|
||||
// 【Midjourney】Action 操作(二次生成图片)
|
||||
export function midjourneyAction(data: AiImageApi.ImageMidjourneyActionVO) {
|
||||
return requestClient.post(`/ai/image/midjourney/action`, data);
|
||||
}
|
||||
|
||||
// ================ 绘图管理 ================
|
||||
// 查询绘画分页
|
||||
export function getImagePage(params: any) {
|
||||
return requestClient.get<AiImageApi.ImageVO[]>(`/ai/image/page`, { params });
|
||||
}
|
||||
|
||||
// 更新绘画发布状态
|
||||
export function updateImage(data: any) {
|
||||
return requestClient.put(`/ai/image/update`, data);
|
||||
}
|
||||
|
||||
// 删除绘画
|
||||
export function deleteImage(id: number) {
|
||||
return requestClient.delete(`/ai/image/delete?id=${id}`);
|
||||
}
|
||||
50
apps/web-antd/src/api/ai/knowledge/document/index.ts
Normal file
50
apps/web-antd/src/api/ai/knowledge/document/index.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
import type { PageParam, PageResult } from '@vben/request';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace AiKnowledgeDocumentApi {
|
||||
export interface KnowledgeDocumentVO {
|
||||
id: number; // 编号
|
||||
knowledgeId: number; // 知识库编号
|
||||
name: string; // 文档名称
|
||||
contentLength: number; // 字符数
|
||||
tokens: number; // token 数
|
||||
segmentMaxTokens: number; // 分片最大 token 数
|
||||
retrievalCount: number; // 召回次数
|
||||
status: number; // 是否启用
|
||||
}
|
||||
}
|
||||
|
||||
// 查询知识库文档分页
|
||||
export function getKnowledgeDocumentPage(params: PageParam) {
|
||||
return requestClient.get<
|
||||
PageResult<AiKnowledgeDocumentApi.KnowledgeDocumentVO>
|
||||
>('/ai/knowledge/document/page', { params });
|
||||
}
|
||||
|
||||
// 查询知识库文档详情
|
||||
export function getKnowledgeDocument(id: number) {
|
||||
return requestClient.get(`/ai/knowledge/document/get?id=${id}`);
|
||||
}
|
||||
// 新增知识库文档(单个)
|
||||
export function createKnowledge(data: any) {
|
||||
return requestClient.post('/ai/knowledge/document/create', data);
|
||||
}
|
||||
// 新增知识库文档(多个)
|
||||
export function createKnowledgeDocumentList(data: any) {
|
||||
return requestClient.post('/ai/knowledge/document/create-list', data);
|
||||
}
|
||||
|
||||
// 修改知识库文档
|
||||
export function updateKnowledgeDocument(data: any) {
|
||||
return requestClient.put('/ai/knowledge/document/update', data);
|
||||
}
|
||||
|
||||
// 修改知识库文档状态
|
||||
export function updateKnowledgeDocumentStatus(data: any) {
|
||||
return requestClient.put('/ai/knowledge/document/update-status', data);
|
||||
}
|
||||
// 删除知识库文档
|
||||
export function deleteKnowledgeDocument(id: number) {
|
||||
return requestClient.delete(`/ai/knowledge/document/delete?id=${id}`);
|
||||
}
|
||||
50
apps/web-antd/src/api/ai/knowledge/knowledge/index.ts
Normal file
50
apps/web-antd/src/api/ai/knowledge/knowledge/index.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
import type { PageParam, PageResult } from '@vben/request';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace AiKnowledgeKnowledgeApi {
|
||||
export interface KnowledgeVO {
|
||||
id: number; // 编号
|
||||
name: string; // 知识库名称
|
||||
description: string; // 知识库描述
|
||||
embeddingModelId: number; // 嵌入模型编号,高质量模式时维护
|
||||
topK: number; // topK
|
||||
similarityThreshold: number; // 相似度阈值
|
||||
}
|
||||
}
|
||||
|
||||
// 查询知识库分页
|
||||
export function getKnowledgePage(params: PageParam) {
|
||||
return requestClient.get<PageResult<AiKnowledgeKnowledgeApi.KnowledgeVO>>(
|
||||
'/ai/knowledge/page',
|
||||
{ params },
|
||||
);
|
||||
}
|
||||
|
||||
// 查询知识库详情
|
||||
export function getKnowledge(id: number) {
|
||||
return requestClient.get<AiKnowledgeKnowledgeApi.KnowledgeVO>(
|
||||
`/ai/knowledge/get?id=${id}`,
|
||||
);
|
||||
}
|
||||
// 新增知识库
|
||||
export function createKnowledge(data: AiKnowledgeKnowledgeApi.KnowledgeVO) {
|
||||
return requestClient.post('/ai/knowledge/create', data);
|
||||
}
|
||||
|
||||
// 修改知识库
|
||||
export function updateKnowledge(data: AiKnowledgeKnowledgeApi.KnowledgeVO) {
|
||||
return requestClient.put('/ai/knowledge/update', data);
|
||||
}
|
||||
|
||||
// 删除知识库
|
||||
export function deleteKnowledge(id: number) {
|
||||
return requestClient.delete(`/ai/knowledge/delete?id=${id}`);
|
||||
}
|
||||
|
||||
// 获取知识库简单列表
|
||||
export function getSimpleKnowledgeList() {
|
||||
return requestClient.get<AiKnowledgeKnowledgeApi.KnowledgeVO[]>(
|
||||
'/ai/knowledge/simple-list',
|
||||
);
|
||||
}
|
||||
76
apps/web-antd/src/api/ai/knowledge/segment/index.ts
Normal file
76
apps/web-antd/src/api/ai/knowledge/segment/index.ts
Normal file
@@ -0,0 +1,76 @@
|
||||
import type { PageParam, PageResult } from '@vben/request';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace AiKnowledgeSegmentApi {
|
||||
// AI 知识库分段 VO
|
||||
export interface KnowledgeSegmentVO {
|
||||
id: number; // 编号
|
||||
documentId: number; // 文档编号
|
||||
knowledgeId: number; // 知识库编号
|
||||
vectorId: string; // 向量库编号
|
||||
content: string; // 切片内容
|
||||
contentLength: number; // 切片内容长度
|
||||
tokens: number; // token 数量
|
||||
retrievalCount: number; // 召回次数
|
||||
status: number; // 文档状态
|
||||
createTime: number; // 创建时间
|
||||
}
|
||||
}
|
||||
|
||||
// 查询知识库分段分页
|
||||
export function getKnowledgeSegmentPage(params: PageParam) {
|
||||
return requestClient.get<
|
||||
PageResult<AiKnowledgeSegmentApi.KnowledgeSegmentVO>
|
||||
>('/ai/knowledge/segment/page', { params });
|
||||
}
|
||||
|
||||
// 查询知识库分段详情
|
||||
export function getKnowledgeSegment(id: number) {
|
||||
return requestClient.get<AiKnowledgeSegmentApi.KnowledgeSegmentVO>(
|
||||
`/ai/knowledge/segment/get?id=${id}`,
|
||||
);
|
||||
}
|
||||
// 新增知识库分段
|
||||
export function createKnowledgeSegment(
|
||||
data: AiKnowledgeSegmentApi.KnowledgeSegmentVO,
|
||||
) {
|
||||
return requestClient.post('/ai/knowledge/segment/create', data);
|
||||
}
|
||||
|
||||
// 修改知识库分段
|
||||
export function updateKnowledgeSegment(
|
||||
data: AiKnowledgeSegmentApi.KnowledgeSegmentVO,
|
||||
) {
|
||||
return requestClient.put('/ai/knowledge/segment/update', data);
|
||||
}
|
||||
|
||||
// 修改知识库分段状态
|
||||
export function updateKnowledgeSegmentStatus(data: any) {
|
||||
return requestClient.put('/ai/knowledge/segment/update-status', data);
|
||||
}
|
||||
// 删除知识库分段
|
||||
export function deleteKnowledgeSegment(id: number) {
|
||||
return requestClient.delete(`/ai/knowledge/segment/delete?id=${id}`);
|
||||
}
|
||||
|
||||
// 切片内容
|
||||
export function splitContent(url: string, segmentMaxTokens: number) {
|
||||
return requestClient.get('/ai/knowledge/segment/split', {
|
||||
params: { url, segmentMaxTokens },
|
||||
});
|
||||
}
|
||||
|
||||
// 获取文档处理列表
|
||||
export function getKnowledgeSegmentProcessList(documentIds: number[]) {
|
||||
return requestClient.get('/ai/knowledge/segment/get-process-list', {
|
||||
params: { documentIds: documentIds.join(',') },
|
||||
});
|
||||
}
|
||||
|
||||
// 搜索知识库分段
|
||||
export function searchKnowledgeSegment(params: any) {
|
||||
return requestClient.get('/ai/knowledge/segment/search', {
|
||||
params,
|
||||
});
|
||||
}
|
||||
64
apps/web-antd/src/api/ai/mindmap/index.ts
Normal file
64
apps/web-antd/src/api/ai/mindmap/index.ts
Normal file
@@ -0,0 +1,64 @@
|
||||
import { useAppConfig } from '@vben/hooks';
|
||||
import { fetchEventSource } from '@vben/request';
|
||||
import { useAccessStore } from '@vben/stores';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
const { apiURL } = useAppConfig(import.meta.env, import.meta.env.PROD);
|
||||
const accessStore = useAccessStore();
|
||||
export namespace AiMindmapApi {
|
||||
// AI 思维导图 VO
|
||||
export interface MindMapVO {
|
||||
id: number; // 编号
|
||||
userId: number; // 用户编号
|
||||
prompt: string; // 生成内容提示
|
||||
generatedContent: string; // 生成的思维导图内容
|
||||
platform: string; // 平台
|
||||
model: string; // 模型
|
||||
errorMessage: string; // 错误信息
|
||||
}
|
||||
|
||||
// AI 思维导图生成 VO
|
||||
export interface AiMindMapGenerateReqVO {
|
||||
prompt: string;
|
||||
}
|
||||
}
|
||||
|
||||
export function generateMindMap({
|
||||
data,
|
||||
onClose,
|
||||
onMessage,
|
||||
onError,
|
||||
ctrl,
|
||||
}: {
|
||||
ctrl: AbortController;
|
||||
data: AiMindmapApi.AiMindMapGenerateReqVO;
|
||||
onClose?: (...args: any[]) => void;
|
||||
onError?: (...args: any[]) => void;
|
||||
onMessage?: (res: any) => void;
|
||||
}) {
|
||||
const token = accessStore.accessToken;
|
||||
return fetchEventSource(`${apiURL}/ai/mind-map/generate-stream`, {
|
||||
method: 'post',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
openWhenHidden: true,
|
||||
body: JSON.stringify(data),
|
||||
onmessage: onMessage,
|
||||
onerror: onError,
|
||||
onclose: onClose,
|
||||
signal: ctrl.signal,
|
||||
});
|
||||
}
|
||||
|
||||
// 查询思维导图分页
|
||||
export function getMindMapPage(params: any) {
|
||||
return requestClient.get(`/ai/mind-map/page`, { params });
|
||||
}
|
||||
|
||||
// 删除思维导图
|
||||
export function deleteMindMap(id: number) {
|
||||
return requestClient.delete(`/ai/mind-map/delete?id=${id}`);
|
||||
}
|
||||
50
apps/web-antd/src/api/ai/model/apiKey/index.ts
Normal file
50
apps/web-antd/src/api/ai/model/apiKey/index.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
import type { PageParam, PageResult } from '@vben/request';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace AiModelApiKeyApi {
|
||||
export interface ApiKeyVO {
|
||||
id: number; // 编号
|
||||
name: string; // 名称
|
||||
apiKey: string; // 密钥
|
||||
platform: string; // 平台
|
||||
url: string; // 自定义 API 地址
|
||||
status: number; // 状态
|
||||
}
|
||||
}
|
||||
|
||||
// 查询 API 密钥分页
|
||||
export function getApiKeyPage(params: PageParam) {
|
||||
return requestClient.get<PageResult<AiModelApiKeyApi.ApiKeyVO>>(
|
||||
'/ai/api-key/page',
|
||||
{ params },
|
||||
);
|
||||
}
|
||||
|
||||
// 获得 API 密钥列表
|
||||
export function getApiKeySimpleList() {
|
||||
return requestClient.get<AiModelApiKeyApi.ApiKeyVO[]>(
|
||||
'/ai/api-key/simple-list',
|
||||
);
|
||||
}
|
||||
|
||||
// 查询 API 密钥详情
|
||||
export function getApiKey(id: number) {
|
||||
return requestClient.get<AiModelApiKeyApi.ApiKeyVO>(
|
||||
`/ai/api-key/get?id=${id}`,
|
||||
);
|
||||
}
|
||||
// 新增 API 密钥
|
||||
export function createApiKey(data: AiModelApiKeyApi.ApiKeyVO) {
|
||||
return requestClient.post('/ai/api-key/create', data);
|
||||
}
|
||||
|
||||
// 修改 API 密钥
|
||||
export function updateApiKey(data: AiModelApiKeyApi.ApiKeyVO) {
|
||||
return requestClient.put('/ai/api-key/update', data);
|
||||
}
|
||||
|
||||
// 删除 API 密钥
|
||||
export function deleteApiKey(id: number) {
|
||||
return requestClient.delete(`/ai/api-key/delete?id=${id}`);
|
||||
}
|
||||
85
apps/web-antd/src/api/ai/model/chatRole/index.ts
Normal file
85
apps/web-antd/src/api/ai/model/chatRole/index.ts
Normal file
@@ -0,0 +1,85 @@
|
||||
import type { PageParam, PageResult } from '@vben/request';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace AiModelChatRoleApi {
|
||||
export interface ChatRoleVO {
|
||||
id: number; // 角色编号
|
||||
modelId: number; // 模型编号
|
||||
name: string; // 角色名称
|
||||
avatar: string; // 角色头像
|
||||
category: string; // 角色类别
|
||||
sort: number; // 角色排序
|
||||
description: string; // 角色描述
|
||||
systemMessage: string; // 角色设定
|
||||
welcomeMessage: string; // 角色设定
|
||||
publicStatus: boolean; // 是否公开
|
||||
status: number; // 状态
|
||||
knowledgeIds?: number[]; // 引用的知识库 ID 列表
|
||||
toolIds?: number[]; // 引用的工具 ID 列表
|
||||
}
|
||||
|
||||
// AI 聊天角色 分页请求 vo
|
||||
export interface ChatRolePageReqVO {
|
||||
name?: string; // 角色名称
|
||||
category?: string; // 角色类别
|
||||
publicStatus: boolean; // 是否公开
|
||||
pageNo: number; // 是否公开
|
||||
pageSize: number; // 是否公开
|
||||
}
|
||||
}
|
||||
|
||||
// 查询聊天角色分页
|
||||
export function getChatRolePage(params: PageParam) {
|
||||
return requestClient.get<PageResult<AiModelChatRoleApi.ChatRoleVO>>(
|
||||
'/ai/chat-role/page',
|
||||
{ params },
|
||||
);
|
||||
}
|
||||
|
||||
// 查询聊天角色详情
|
||||
export function getChatRole(id: number) {
|
||||
return requestClient.get<AiModelChatRoleApi.ChatRoleVO>(
|
||||
`/ai/chat-role/get?id=${id}`,
|
||||
);
|
||||
}
|
||||
// 新增聊天角色
|
||||
export function createChatRole(data: AiModelChatRoleApi.ChatRoleVO) {
|
||||
return requestClient.post('/ai/chat-role/create', data);
|
||||
}
|
||||
|
||||
// 修改聊天角色
|
||||
export function updateChatRole(data: AiModelChatRoleApi.ChatRoleVO) {
|
||||
return requestClient.put('/ai/chat-role/update', data);
|
||||
}
|
||||
|
||||
// 删除聊天角色
|
||||
export function deleteChatRole(id: number) {
|
||||
return requestClient.delete(`/ai/chat-role/delete?id=${id}`);
|
||||
}
|
||||
|
||||
// ======= chat 聊天
|
||||
// 获取 my role
|
||||
export function getMyPage(params: AiModelChatRoleApi.ChatRolePageReqVO) {
|
||||
return requestClient.get('/ai/chat-role/my-page', { params });
|
||||
}
|
||||
|
||||
// 获取角色分类
|
||||
export function getCategoryList() {
|
||||
return requestClient.get('/ai/chat-role/category-list');
|
||||
}
|
||||
|
||||
// 创建角色
|
||||
export function createMy(data: AiModelChatRoleApi.ChatRoleVO) {
|
||||
return requestClient.post('/ai/chat-role/create-my', data);
|
||||
}
|
||||
|
||||
// 更新角色
|
||||
export function updateMy(data: AiModelChatRoleApi.ChatRoleVO) {
|
||||
return requestClient.put('/ai/chat-role/update', data);
|
||||
}
|
||||
|
||||
// 删除角色 my
|
||||
export function deleteMy(id: number) {
|
||||
return requestClient.delete(`/ai/chat-role/delete-my?id=${id}`);
|
||||
}
|
||||
55
apps/web-antd/src/api/ai/model/model/index.ts
Normal file
55
apps/web-antd/src/api/ai/model/model/index.ts
Normal file
@@ -0,0 +1,55 @@
|
||||
import type { PageParam, PageResult } from '@vben/request';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace AiModelModelApi {
|
||||
export interface ModelVO {
|
||||
id: number; // 编号
|
||||
keyId: number; // API 秘钥编号
|
||||
name: string; // 模型名字
|
||||
model: string; // 模型标识
|
||||
platform: string; // 模型平台
|
||||
type: number; // 模型类型
|
||||
sort: number; // 排序
|
||||
status: number; // 状态
|
||||
temperature?: number; // 温度参数
|
||||
maxTokens?: number; // 单条回复的最大 Token 数量
|
||||
maxContexts?: number; // 上下文的最大 Message 数量
|
||||
}
|
||||
}
|
||||
|
||||
// 查询模型分页
|
||||
export function getModelPage(params: PageParam) {
|
||||
return requestClient.get<PageResult<AiModelModelApi.ModelVO>>(
|
||||
'/ai/model/page',
|
||||
{ params },
|
||||
);
|
||||
}
|
||||
|
||||
// 获得模型列表
|
||||
export function getModelSimpleList(type?: number) {
|
||||
return requestClient.get<AiModelModelApi.ModelVO[]>('/ai/model/simple-list', {
|
||||
params: {
|
||||
type,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// 查询模型详情
|
||||
export function getModel(id: number) {
|
||||
return requestClient.get<AiModelModelApi.ModelVO>(`/ai/model/get?id=${id}`);
|
||||
}
|
||||
// 新增模型
|
||||
export function createModel(data: AiModelModelApi.ModelVO) {
|
||||
return requestClient.post('/ai/model/create', data);
|
||||
}
|
||||
|
||||
// 修改模型
|
||||
export function updateModel(data: AiModelModelApi.ModelVO) {
|
||||
return requestClient.put('/ai/model/update', data);
|
||||
}
|
||||
|
||||
// 删除模型
|
||||
export function deleteModel(id: number) {
|
||||
return requestClient.delete(`/ai/model/delete?id=${id}`);
|
||||
}
|
||||
43
apps/web-antd/src/api/ai/model/tool/index.ts
Normal file
43
apps/web-antd/src/api/ai/model/tool/index.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
import type { PageParam, PageResult } from '@vben/request';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace AiModelToolApi {
|
||||
export interface ToolVO {
|
||||
id: number; // 工具编号
|
||||
name: string; // 工具名称
|
||||
description: string; // 工具描述
|
||||
status: number; // 状态
|
||||
}
|
||||
}
|
||||
|
||||
// 查询工具分页
|
||||
export function getToolPage(params: PageParam) {
|
||||
return requestClient.get<PageResult<AiModelToolApi.ToolVO>>('/ai/tool/page', {
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
// 查询工具详情
|
||||
export function getTool(id: number) {
|
||||
return requestClient.get<AiModelToolApi.ToolVO>(`/ai/tool/get?id=${id}`);
|
||||
}
|
||||
// 新增工具
|
||||
export function createTool(data: AiModelToolApi.ToolVO) {
|
||||
return requestClient.post('/ai/tool/create', data);
|
||||
}
|
||||
|
||||
// 修改工具
|
||||
export function updateTool(data: AiModelToolApi.ToolVO) {
|
||||
return requestClient.put('/ai/tool/update', data);
|
||||
}
|
||||
|
||||
// 删除工具
|
||||
export function deleteTool(id: number) {
|
||||
return requestClient.delete(`/ai/tool/delete?id=${id}`);
|
||||
}
|
||||
|
||||
// 获取工具简单列表
|
||||
export function getToolSimpleList() {
|
||||
return requestClient.get<AiModelToolApi.ToolVO[]>('/ai/tool/simple-list');
|
||||
}
|
||||
44
apps/web-antd/src/api/ai/music/index.ts
Normal file
44
apps/web-antd/src/api/ai/music/index.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
import type { PageParam, PageResult } from '@vben/request';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace AiMusicApi {
|
||||
// AI 音乐 VO
|
||||
export interface MusicVO {
|
||||
id: number; // 编号
|
||||
userId: number; // 用户编号
|
||||
title: string; // 音乐名称
|
||||
lyric: string; // 歌词
|
||||
imageUrl: string; // 图片地址
|
||||
audioUrl: string; // 音频地址
|
||||
videoUrl: string; // 视频地址
|
||||
status: number; // 音乐状态
|
||||
gptDescriptionPrompt: string; // 描述词
|
||||
prompt: string; // 提示词
|
||||
platform: string; // 模型平台
|
||||
model: string; // 模型
|
||||
generateMode: number; // 生成模式
|
||||
tags: string; // 音乐风格标签
|
||||
duration: number; // 音乐时长
|
||||
publicStatus: boolean; // 是否发布
|
||||
taskId: string; // 任务id
|
||||
errorMessage: string; // 错误信息
|
||||
}
|
||||
}
|
||||
|
||||
// 查询音乐分页
|
||||
export function getMusicPage(params: PageParam) {
|
||||
return requestClient.get<PageResult<AiMusicApi.MusicVO>>(`/ai/music/page`, {
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
// 更新音乐
|
||||
export function updateMusic(data: any) {
|
||||
return requestClient.put('/ai/music/update', data);
|
||||
}
|
||||
|
||||
// 删除音乐
|
||||
export function deleteMusic(id: number) {
|
||||
return requestClient.delete(`/ai/music/delete?id=${id}`);
|
||||
}
|
||||
29
apps/web-antd/src/api/ai/workflow/index.ts
Normal file
29
apps/web-antd/src/api/ai/workflow/index.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import type { PageParam, PageResult } from '@vben/request';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
export function getWorkflowPage(params: PageParam) {
|
||||
return requestClient.get<PageResult<any>>('/ai/workflow/page', {
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
export const getWorkflow = (id: number | string) => {
|
||||
return requestClient.get(`/ai/workflow/get?id=${id}`);
|
||||
};
|
||||
|
||||
export const createWorkflow = (data: any) => {
|
||||
return requestClient.post('/ai/workflow/create', data);
|
||||
};
|
||||
|
||||
export const updateWorkflow = (data: any) => {
|
||||
return requestClient.put('/ai/workflow/update', data);
|
||||
};
|
||||
|
||||
export const deleteWorkflow = (id: number | string) => {
|
||||
return requestClient.delete(`/ai/workflow/delete?id=${id}`);
|
||||
};
|
||||
|
||||
export const testWorkflow = (data: any) => {
|
||||
return requestClient.post('/ai/workflow/test', data);
|
||||
};
|
||||
95
apps/web-antd/src/api/ai/write/index.ts
Normal file
95
apps/web-antd/src/api/ai/write/index.ts
Normal file
@@ -0,0 +1,95 @@
|
||||
import type { PageParam, PageResult } from '@vben/request';
|
||||
|
||||
import type { AiWriteTypeEnum } from '#/utils';
|
||||
|
||||
import { useAppConfig } from '@vben/hooks';
|
||||
import { fetchEventSource } from '@vben/request';
|
||||
import { useAccessStore } from '@vben/stores';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
const { apiURL } = useAppConfig(import.meta.env, import.meta.env.PROD);
|
||||
const accessStore = useAccessStore();
|
||||
export namespace AiWriteApi {
|
||||
export interface WriteVO {
|
||||
type: AiWriteTypeEnum.REPLY | AiWriteTypeEnum.WRITING; // 1:撰写 2:回复
|
||||
prompt: string; // 写作内容提示 1。撰写 2回复
|
||||
originalContent: string; // 原文
|
||||
length: number; // 长度
|
||||
format: number; // 格式
|
||||
tone: number; // 语气
|
||||
language: number; // 语言
|
||||
userId?: number; // 用户编号
|
||||
platform?: string; // 平台
|
||||
model?: string; // 模型
|
||||
generatedContent?: string; // 生成的内容
|
||||
errorMessage?: string; // 错误信息
|
||||
createTime?: Date; // 创建时间
|
||||
}
|
||||
|
||||
export interface AiWritePageReqVO extends PageParam {
|
||||
userId?: number; // 用户编号
|
||||
type?: AiWriteTypeEnum; // 写作类型
|
||||
platform?: string; // 平台
|
||||
createTime?: [string, string]; // 创建时间
|
||||
}
|
||||
|
||||
export interface AiWriteRespVo {
|
||||
id: number;
|
||||
userId: number;
|
||||
type: number;
|
||||
platform: string;
|
||||
model: string;
|
||||
prompt: string;
|
||||
generatedContent: string;
|
||||
originalContent: string;
|
||||
length: number;
|
||||
format: number;
|
||||
tone: number;
|
||||
language: number;
|
||||
errorMessage: string;
|
||||
createTime: string;
|
||||
}
|
||||
}
|
||||
|
||||
export function writeStream({
|
||||
data,
|
||||
onClose,
|
||||
onMessage,
|
||||
onError,
|
||||
ctrl,
|
||||
}: {
|
||||
ctrl: AbortController;
|
||||
data: Partial<AiWriteApi.WriteVO>;
|
||||
onClose?: (...args: any[]) => void;
|
||||
onError?: (...args: any[]) => void;
|
||||
onMessage?: (res: any) => void;
|
||||
}) {
|
||||
const token = accessStore.accessToken;
|
||||
return fetchEventSource(`${apiURL}/ai/write/generate-stream`, {
|
||||
method: 'post',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
openWhenHidden: true,
|
||||
body: JSON.stringify(data),
|
||||
onmessage: onMessage,
|
||||
onerror: onError,
|
||||
onclose: onClose,
|
||||
signal: ctrl.signal,
|
||||
});
|
||||
}
|
||||
|
||||
// 获取写作列表
|
||||
export function getWritePage(params: any) {
|
||||
return requestClient.get<PageResult<AiWriteApi.AiWritePageReqVO>>(
|
||||
`/ai/write/page`,
|
||||
{ params },
|
||||
);
|
||||
}
|
||||
|
||||
// 删除音乐
|
||||
export function deleteWrite(id: number) {
|
||||
return requestClient.delete(`/ai/write/delete`, { params: { id } });
|
||||
}
|
||||
57
apps/web-antd/src/api/basic/productunit/index.ts
Normal file
57
apps/web-antd/src/api/basic/productunit/index.ts
Normal file
@@ -0,0 +1,57 @@
|
||||
import type { PageParam, PageResult } from '@vben/request';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace ProductUnitApi {
|
||||
/** 产品单位信息 */
|
||||
export interface ProductUnit {
|
||||
id: number; // 编号
|
||||
groupId?: number; // 分组编号
|
||||
name?: string; // 单位名称
|
||||
basic?: number; // 基础单位
|
||||
number?: number; // 单位数量/相对于基础单位
|
||||
usageType: number; // 用途
|
||||
}
|
||||
}
|
||||
|
||||
/** 查询产品单位分页 */
|
||||
export function getProductUnitPage(params: PageParam) {
|
||||
return requestClient.get<PageResult<ProductUnitApi.ProductUnit>>(
|
||||
'/basic/product-unit/page',
|
||||
{ params },
|
||||
);
|
||||
}
|
||||
|
||||
/** 查询产品单位详情 */
|
||||
export function getProductUnit(id: number) {
|
||||
return requestClient.get<ProductUnitApi.ProductUnit>(
|
||||
`/basic/product-unit/get?id=${id}`,
|
||||
);
|
||||
}
|
||||
|
||||
/** 新增产品单位 */
|
||||
export function createProductUnit(data: ProductUnitApi.ProductUnit) {
|
||||
return requestClient.post('/basic/product-unit/create', data);
|
||||
}
|
||||
|
||||
/** 修改产品单位 */
|
||||
export function updateProductUnit(data: ProductUnitApi.ProductUnit) {
|
||||
return requestClient.put('/basic/product-unit/update', data);
|
||||
}
|
||||
|
||||
/** 删除产品单位 */
|
||||
export function deleteProductUnit(id: number) {
|
||||
return requestClient.delete(`/basic/product-unit/delete?id=${id}`);
|
||||
}
|
||||
|
||||
/** 批量删除产品单位 */
|
||||
export function deleteProductUnitListByIds(ids: number[]) {
|
||||
return requestClient.delete(
|
||||
`/basic/product-unit/delete-list?ids=${ids.join(',')}`,
|
||||
);
|
||||
}
|
||||
|
||||
/** 导出产品单位 */
|
||||
export function exportProductUnit(params: any) {
|
||||
return requestClient.download('/basic/product-unit/export-excel', params);
|
||||
}
|
||||
61
apps/web-antd/src/api/basic/productunitgroup/index.ts
Normal file
61
apps/web-antd/src/api/basic/productunitgroup/index.ts
Normal file
@@ -0,0 +1,61 @@
|
||||
import type { PageParam, PageResult } from '@vben/request';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace ProductUnitGroupApi {
|
||||
/** 产品单位组信息 */
|
||||
export interface ProductUnitGroup {
|
||||
id: number; // 编号
|
||||
name?: string; // 产品单位组名称
|
||||
status?: number; // 开启状态
|
||||
}
|
||||
}
|
||||
|
||||
/** 查询产品单位组分页 */
|
||||
export function getProductUnitGroupPage(params: PageParam) {
|
||||
return requestClient.get<PageResult<ProductUnitGroupApi.ProductUnitGroup>>(
|
||||
'/basic/product-unit-group/page',
|
||||
{ params },
|
||||
);
|
||||
}
|
||||
|
||||
/** 查询产品单位组详情 */
|
||||
export function getProductUnitGroup(id: number) {
|
||||
return requestClient.get<ProductUnitGroupApi.ProductUnitGroup>(
|
||||
`/basic/product-unit-group/get?id=${id}`,
|
||||
);
|
||||
}
|
||||
|
||||
/** 新增产品单位组 */
|
||||
export function createProductUnitGroup(
|
||||
data: ProductUnitGroupApi.ProductUnitGroup,
|
||||
) {
|
||||
return requestClient.post('/basic/product-unit-group/create', data);
|
||||
}
|
||||
|
||||
/** 修改产品单位组 */
|
||||
export function updateProductUnitGroup(
|
||||
data: ProductUnitGroupApi.ProductUnitGroup,
|
||||
) {
|
||||
return requestClient.put('/basic/product-unit-group/update', data);
|
||||
}
|
||||
|
||||
/** 删除产品单位组 */
|
||||
export function deleteProductUnitGroup(id: number) {
|
||||
return requestClient.delete(`/basic/product-unit-group/delete?id=${id}`);
|
||||
}
|
||||
|
||||
/** 批量删除产品单位组 */
|
||||
export function deleteProductUnitGroupListByIds(ids: number[]) {
|
||||
return requestClient.delete(
|
||||
`/basic/product-unit-group/delete-list?ids=${ids.join(',')}`,
|
||||
);
|
||||
}
|
||||
|
||||
/** 导出产品单位组 */
|
||||
export function exportProductUnitGroup(params: any) {
|
||||
return requestClient.download(
|
||||
'/basic/product-unit-group/export-excel',
|
||||
params,
|
||||
);
|
||||
}
|
||||
@@ -4,8 +4,7 @@ import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace BpmProcessDefinitionApi {
|
||||
/** 流程定义 */
|
||||
// TODO @ziye:不用 VO 后缀哈
|
||||
export interface ProcessDefinitionVO {
|
||||
export interface ProcessDefinition {
|
||||
id: string;
|
||||
version: number;
|
||||
deploymentTime: number;
|
||||
@@ -21,7 +20,7 @@ export namespace BpmProcessDefinitionApi {
|
||||
|
||||
/** 查询流程定义 */
|
||||
export async function getProcessDefinition(id?: string, key?: string) {
|
||||
return requestClient.get<BpmProcessDefinitionApi.ProcessDefinitionVO>(
|
||||
return requestClient.get<BpmProcessDefinitionApi.ProcessDefinition>(
|
||||
'/bpm/process-definition/get',
|
||||
{
|
||||
params: { id, key },
|
||||
@@ -32,13 +31,13 @@ export async function getProcessDefinition(id?: string, key?: string) {
|
||||
/** 分页查询流程定义 */
|
||||
export async function getProcessDefinitionPage(params: PageParam) {
|
||||
return requestClient.get<
|
||||
PageResult<BpmProcessDefinitionApi.ProcessDefinitionVO>
|
||||
PageResult<BpmProcessDefinitionApi.ProcessDefinition>
|
||||
>('/bpm/process-definition/page', { params });
|
||||
}
|
||||
|
||||
/** 查询流程定义列表 */
|
||||
export async function getProcessDefinitionList(params: any) {
|
||||
return requestClient.get<BpmProcessDefinitionApi.ProcessDefinitionVO[]>(
|
||||
return requestClient.get<BpmProcessDefinitionApi.ProcessDefinition[]>(
|
||||
'/bpm/process-definition/list',
|
||||
{
|
||||
params,
|
||||
@@ -49,6 +48,6 @@ export async function getProcessDefinitionList(params: any) {
|
||||
/** 查询流程定义列表(简单列表) */
|
||||
export async function getSimpleProcessDefinitionList() {
|
||||
return requestClient.get<
|
||||
PageResult<BpmProcessDefinitionApi.ProcessDefinitionVO>
|
||||
PageResult<BpmProcessDefinitionApi.ProcessDefinition>
|
||||
>('/bpm/process-definition/simple-list');
|
||||
}
|
||||
|
||||
@@ -4,8 +4,7 @@ import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace BpmFormApi {
|
||||
/** 流程表单 */
|
||||
// TODO @ziye:不用 VO 后缀哈
|
||||
export interface FormVO {
|
||||
export interface Form {
|
||||
id?: number | undefined;
|
||||
name: string;
|
||||
conf: string;
|
||||
@@ -18,24 +17,23 @@ export namespace BpmFormApi {
|
||||
|
||||
/** 获取表单分页列表 */
|
||||
export async function getFormPage(params: PageParam) {
|
||||
return requestClient.get<PageResult<BpmFormApi.FormVO>>('/bpm/form/page', {
|
||||
return requestClient.get<PageResult<BpmFormApi.Form>>('/bpm/form/page', {
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
/** 获取表单详情 */
|
||||
// TODO @ziye:应该不会 string 的情况呢。
|
||||
export async function getFormDetail(id: number | string) {
|
||||
return requestClient.get<BpmFormApi.FormVO>(`/bpm/form/get?id=${id}`);
|
||||
export async function getFormDetail(id: number) {
|
||||
return requestClient.get<BpmFormApi.Form>(`/bpm/form/get?id=${id}`);
|
||||
}
|
||||
|
||||
/** 创建表单 */
|
||||
export async function createForm(data: BpmFormApi.FormVO) {
|
||||
export async function createForm(data: BpmFormApi.Form) {
|
||||
return requestClient.post('/bpm/form/create', data);
|
||||
}
|
||||
|
||||
/** 更新表单 */
|
||||
export async function updateForm(data: BpmFormApi.FormVO) {
|
||||
export async function updateForm(data: BpmFormApi.Form) {
|
||||
return requestClient.put('/bpm/form/update', data);
|
||||
}
|
||||
|
||||
@@ -46,5 +44,5 @@ export async function deleteForm(id: number) {
|
||||
|
||||
/** 获取表单简单列表 */
|
||||
export async function getFormSimpleList() {
|
||||
return requestClient.get<BpmFormApi.FormVO[]>('/bpm/form/simple-list');
|
||||
return requestClient.get<BpmFormApi.Form[]>('/bpm/form/simple-list');
|
||||
}
|
||||
|
||||
@@ -3,8 +3,7 @@ import type { PageParam, PageResult } from '@vben/request';
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace BpmOALeaveApi {
|
||||
// TODO @ziye:不用 VO 后缀
|
||||
export interface LeaveVO {
|
||||
export interface Leave {
|
||||
id: number;
|
||||
status: number;
|
||||
type: number;
|
||||
@@ -18,23 +17,23 @@ export namespace BpmOALeaveApi {
|
||||
}
|
||||
|
||||
/** 创建请假申请 */
|
||||
export async function createLeave(data: BpmOALeaveApi.LeaveVO) {
|
||||
export async function createLeave(data: BpmOALeaveApi.Leave) {
|
||||
return requestClient.post('/bpm/oa/leave/create', data);
|
||||
}
|
||||
|
||||
/** 更新请假申请 */
|
||||
export async function updateLeave(data: BpmOALeaveApi.LeaveVO) {
|
||||
export async function updateLeave(data: BpmOALeaveApi.Leave) {
|
||||
return requestClient.post('/bpm/oa/leave/update', data);
|
||||
}
|
||||
|
||||
/** 获得请假申请 */
|
||||
export async function getLeave(id: number) {
|
||||
return requestClient.get<BpmOALeaveApi.LeaveVO>(`/bpm/oa/leave/get?id=${id}`);
|
||||
return requestClient.get<BpmOALeaveApi.Leave>(`/bpm/oa/leave/get?id=${id}`);
|
||||
}
|
||||
|
||||
/** 获得请假申请分页 */
|
||||
export async function getLeavePage(params: PageParam) {
|
||||
return requestClient.get<PageResult<BpmOALeaveApi.LeaveVO>>(
|
||||
return requestClient.get<PageResult<BpmOALeaveApi.Leave>>(
|
||||
'/bpm/oa/leave/page',
|
||||
{ params },
|
||||
);
|
||||
|
||||
@@ -3,9 +3,8 @@ import type { PageParam, PageResult } from '@vben/request';
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace BpmProcessExpressionApi {
|
||||
// TODO @ziye:不用 VO 后缀
|
||||
/** 流程表达式 VO */
|
||||
export interface ProcessExpressionVO {
|
||||
/** 流程表达式 */
|
||||
export interface ProcessExpression {
|
||||
id: number; // 编号
|
||||
name: string; // 表达式名字
|
||||
status: number; // 表达式状态
|
||||
@@ -16,27 +15,27 @@ export namespace BpmProcessExpressionApi {
|
||||
/** 查询流程表达式分页 */
|
||||
export async function getProcessExpressionPage(params: PageParam) {
|
||||
return requestClient.get<
|
||||
PageResult<BpmProcessExpressionApi.ProcessExpressionVO>
|
||||
PageResult<BpmProcessExpressionApi.ProcessExpression>
|
||||
>('/bpm/process-expression/page', { params });
|
||||
}
|
||||
|
||||
/** 查询流程表达式详情 */
|
||||
export async function getProcessExpression(id: number) {
|
||||
return requestClient.get<BpmProcessExpressionApi.ProcessExpressionVO>(
|
||||
return requestClient.get<BpmProcessExpressionApi.ProcessExpression>(
|
||||
`/bpm/process-expression/get?id=${id}`,
|
||||
);
|
||||
}
|
||||
|
||||
/** 新增流程表达式 */
|
||||
export async function createProcessExpression(
|
||||
data: BpmProcessExpressionApi.ProcessExpressionVO,
|
||||
data: BpmProcessExpressionApi.ProcessExpression,
|
||||
) {
|
||||
return requestClient.post<number>('/bpm/process-expression/create', data);
|
||||
}
|
||||
|
||||
/** 修改流程表达式 */
|
||||
export async function updateProcessExpression(
|
||||
data: BpmProcessExpressionApi.ProcessExpressionVO,
|
||||
data: BpmProcessExpressionApi.ProcessExpression,
|
||||
) {
|
||||
return requestClient.put<boolean>('/bpm/process-expression/update', data);
|
||||
}
|
||||
|
||||
@@ -9,29 +9,29 @@ import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace BpmProcessInstanceApi {
|
||||
// TODO @芋艿:一些注释缺少或者不对;
|
||||
export type Task = {
|
||||
export interface Task {
|
||||
id: number;
|
||||
name: string;
|
||||
};
|
||||
}
|
||||
|
||||
export type User = {
|
||||
export interface User {
|
||||
avatar: string;
|
||||
id: number;
|
||||
nickname: string;
|
||||
};
|
||||
}
|
||||
|
||||
// 审批任务信息
|
||||
export type ApprovalTaskInfo = {
|
||||
export interface ApprovalTaskInfo {
|
||||
assigneeUser: User;
|
||||
id: number;
|
||||
ownerUser: User;
|
||||
reason: string;
|
||||
signPicUrl: string;
|
||||
status: number;
|
||||
};
|
||||
}
|
||||
|
||||
// 审批节点信息
|
||||
export type ApprovalNodeInfo = {
|
||||
export interface ApprovalNodeInfo {
|
||||
candidateStrategy?: BpmCandidateStrategyEnum;
|
||||
candidateUsers?: User[];
|
||||
endTime?: Date;
|
||||
@@ -41,10 +41,10 @@ export namespace BpmProcessInstanceApi {
|
||||
startTime?: Date;
|
||||
status: number;
|
||||
tasks: ApprovalTaskInfo[];
|
||||
};
|
||||
}
|
||||
|
||||
/** 流程实例 */
|
||||
export type ProcessInstanceVO = {
|
||||
export interface ProcessInstance {
|
||||
businessKey: string;
|
||||
category: string;
|
||||
createTime: string;
|
||||
@@ -61,20 +61,20 @@ export namespace BpmProcessInstanceApi {
|
||||
startUser?: User;
|
||||
status: number;
|
||||
tasks?: BpmProcessInstanceApi.Task[];
|
||||
};
|
||||
}
|
||||
|
||||
// 审批详情
|
||||
export type ApprovalDetail = {
|
||||
export interface ApprovalDetail {
|
||||
activityNodes: BpmProcessInstanceApi.ApprovalNodeInfo[];
|
||||
formFieldsPermission: any;
|
||||
processDefinition: BpmModelApi.ProcessDefinition;
|
||||
processInstance: BpmProcessInstanceApi.ProcessInstanceVO;
|
||||
processInstance: BpmProcessInstanceApi.ProcessInstance;
|
||||
status: number;
|
||||
todoTask: BpmTaskApi.TaskVO;
|
||||
};
|
||||
todoTask: BpmTaskApi.Task;
|
||||
}
|
||||
|
||||
// 抄送流程实例 VO
|
||||
export type CopyVO = {
|
||||
// 抄送流程实例
|
||||
export interface Copy {
|
||||
activityId: string;
|
||||
activityName: string;
|
||||
createTime: number;
|
||||
@@ -90,12 +90,12 @@ export namespace BpmProcessInstanceApi {
|
||||
value: string;
|
||||
}[];
|
||||
taskId: string;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/** 查询我的流程实例分页 */
|
||||
export async function getProcessInstanceMyPage(params: PageParam) {
|
||||
return requestClient.get<PageResult<BpmProcessInstanceApi.ProcessInstanceVO>>(
|
||||
return requestClient.get<PageResult<BpmProcessInstanceApi.ProcessInstance>>(
|
||||
'/bpm/process-instance/my-page',
|
||||
{ params },
|
||||
);
|
||||
@@ -103,7 +103,7 @@ export async function getProcessInstanceMyPage(params: PageParam) {
|
||||
|
||||
/** 查询管理员流程实例分页 */
|
||||
export async function getProcessInstanceManagerPage(params: PageParam) {
|
||||
return requestClient.get<PageResult<BpmProcessInstanceApi.ProcessInstanceVO>>(
|
||||
return requestClient.get<PageResult<BpmProcessInstanceApi.ProcessInstance>>(
|
||||
'/bpm/process-instance/manager-page',
|
||||
{ params },
|
||||
);
|
||||
@@ -111,7 +111,7 @@ export async function getProcessInstanceManagerPage(params: PageParam) {
|
||||
|
||||
/** 新增流程实例 */
|
||||
export async function createProcessInstance(data: any) {
|
||||
return requestClient.post<BpmProcessInstanceApi.ProcessInstanceVO>(
|
||||
return requestClient.post<BpmProcessInstanceApi.ProcessInstance>(
|
||||
'/bpm/process-instance/create',
|
||||
data,
|
||||
);
|
||||
@@ -142,14 +142,14 @@ export async function cancelProcessInstanceByAdmin(id: number, reason: string) {
|
||||
|
||||
/** 查询流程实例详情 */
|
||||
export async function getProcessInstance(id: number) {
|
||||
return requestClient.get<BpmProcessInstanceApi.ProcessInstanceVO>(
|
||||
return requestClient.get<BpmProcessInstanceApi.ProcessInstance>(
|
||||
`/bpm/process-instance/get?id=${id}`,
|
||||
);
|
||||
}
|
||||
|
||||
/** 查询复制流程实例分页 */
|
||||
export async function getProcessInstanceCopyPage(params: PageParam) {
|
||||
return requestClient.get<PageResult<BpmProcessInstanceApi.ProcessInstanceVO>>(
|
||||
return requestClient.get<PageResult<BpmProcessInstanceApi.ProcessInstance>>(
|
||||
'/bpm/process-instance/copy/page',
|
||||
{ params },
|
||||
);
|
||||
@@ -157,9 +157,9 @@ export async function getProcessInstanceCopyPage(params: PageParam) {
|
||||
|
||||
/** 更新流程实例 */
|
||||
export async function updateProcessInstance(
|
||||
data: BpmProcessInstanceApi.ProcessInstanceVO,
|
||||
data: BpmProcessInstanceApi.ProcessInstance,
|
||||
) {
|
||||
return requestClient.put<BpmProcessInstanceApi.ProcessInstanceVO>(
|
||||
return requestClient.put<BpmProcessInstanceApi.ProcessInstance>(
|
||||
'/bpm/process-instance/update',
|
||||
data,
|
||||
);
|
||||
@@ -183,7 +183,7 @@ export async function getNextApprovalNodes(params: any) {
|
||||
|
||||
/** 获取表单字段权限 */
|
||||
export async function getFormFieldsPermission(params: any) {
|
||||
return requestClient.get<BpmProcessInstanceApi.ProcessInstanceVO>(
|
||||
return requestClient.get<BpmProcessInstanceApi.ProcessInstance>(
|
||||
`/bpm/process-instance/get-form-fields-permission`,
|
||||
{ params },
|
||||
);
|
||||
@@ -191,7 +191,7 @@ export async function getFormFieldsPermission(params: any) {
|
||||
|
||||
/** 获取流程实例 BPMN 模型视图 */
|
||||
export async function getProcessInstanceBpmnModelView(id: string) {
|
||||
return requestClient.get<BpmProcessInstanceApi.ProcessInstanceVO>(
|
||||
return requestClient.get<BpmProcessInstanceApi.ProcessInstance>(
|
||||
`/bpm/process-instance/get-bpmn-model-view?id=${id}`,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -3,9 +3,8 @@ import type { PageParam, PageResult } from '@vben/request';
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace BpmProcessListenerApi {
|
||||
// TODO @ziye:不用 VO 后缀
|
||||
/** BPM 流程监听器 VO */
|
||||
export interface ProcessListenerVO {
|
||||
/** BPM 流程监听器 */
|
||||
export interface ProcessListener {
|
||||
id: number; // 编号
|
||||
name: string; // 监听器名字
|
||||
type: string; // 监听器类型
|
||||
@@ -18,7 +17,7 @@ export namespace BpmProcessListenerApi {
|
||||
|
||||
/** 查询流程监听器分页 */
|
||||
export async function getProcessListenerPage(params: PageParam) {
|
||||
return requestClient.get<PageResult<BpmProcessListenerApi.ProcessListenerVO>>(
|
||||
return requestClient.get<PageResult<BpmProcessListenerApi.ProcessListener>>(
|
||||
'/bpm/process-listener/page',
|
||||
{ params },
|
||||
);
|
||||
@@ -26,21 +25,21 @@ export async function getProcessListenerPage(params: PageParam) {
|
||||
|
||||
/** 查询流程监听器详情 */
|
||||
export async function getProcessListener(id: number) {
|
||||
return requestClient.get<BpmProcessListenerApi.ProcessListenerVO>(
|
||||
return requestClient.get<BpmProcessListenerApi.ProcessListener>(
|
||||
`/bpm/process-listener/get?id=${id}`,
|
||||
);
|
||||
}
|
||||
|
||||
/** 新增流程监听器 */
|
||||
export async function createProcessListener(
|
||||
data: BpmProcessListenerApi.ProcessListenerVO,
|
||||
data: BpmProcessListenerApi.ProcessListener,
|
||||
) {
|
||||
return requestClient.post<number>('/bpm/process-listener/create', data);
|
||||
}
|
||||
|
||||
/** 修改流程监听器 */
|
||||
export async function updateProcessListener(
|
||||
data: BpmProcessListenerApi.ProcessListenerVO,
|
||||
data: BpmProcessListenerApi.ProcessListener,
|
||||
) {
|
||||
return requestClient.put<boolean>('/bpm/process-listener/update', data);
|
||||
}
|
||||
|
||||
@@ -5,9 +5,8 @@ import type { BpmProcessInstanceApi } from '../processInstance';
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace BpmTaskApi {
|
||||
// TODO @ziye:不用 VO 后缀;注释使用 /** */ 风格;
|
||||
/** BPM 流程监听器 VO */
|
||||
export interface TaskVO {
|
||||
/** BPM 流程监听器 */
|
||||
export interface Task {
|
||||
id: number; // 编号
|
||||
name: string; // 监听器名字
|
||||
type: string; // 监听器类型
|
||||
@@ -16,8 +15,8 @@ export namespace BpmTaskApi {
|
||||
valueType: string; // 监听器值类型
|
||||
}
|
||||
|
||||
// 流程任务 VO
|
||||
export interface TaskManagerVO {
|
||||
// 流程任务
|
||||
export interface TaskManager {
|
||||
id: string; // 编号
|
||||
name: string; // 任务名称
|
||||
createTime: number; // 创建时间
|
||||
@@ -29,7 +28,7 @@ export namespace BpmTaskApi {
|
||||
assigneeUser: any; // 处理人
|
||||
taskDefinitionKey: string; // 任务定义key
|
||||
processInstanceId: string; // 流程实例id
|
||||
processInstance: BpmProcessInstanceApi.ProcessInstanceVO; // 流程实例
|
||||
processInstance: BpmProcessInstanceApi.ProcessInstance; // 流程实例
|
||||
parentTaskId: any; // 父任务id
|
||||
children: any; // 子任务
|
||||
formId: any; // 表单id
|
||||
@@ -46,27 +45,21 @@ export namespace BpmTaskApi {
|
||||
|
||||
/** 查询待办任务分页 */
|
||||
export async function getTaskTodoPage(params: PageParam) {
|
||||
return requestClient.get<PageResult<BpmTaskApi.TaskVO>>(
|
||||
'/bpm/task/todo-page',
|
||||
{
|
||||
params,
|
||||
},
|
||||
);
|
||||
return requestClient.get<PageResult<BpmTaskApi.Task>>('/bpm/task/todo-page', {
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
/** 查询已办任务分页 */
|
||||
export async function getTaskDonePage(params: PageParam) {
|
||||
return requestClient.get<PageResult<BpmTaskApi.TaskVO>>(
|
||||
'/bpm/task/done-page',
|
||||
{
|
||||
params,
|
||||
},
|
||||
);
|
||||
return requestClient.get<PageResult<BpmTaskApi.Task>>('/bpm/task/done-page', {
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
/** 查询任务管理分页 */
|
||||
export async function getTaskManagerPage(params: PageParam) {
|
||||
return requestClient.get<PageResult<BpmTaskApi.TaskVO>>(
|
||||
return requestClient.get<PageResult<BpmTaskApi.Task>>(
|
||||
'/bpm/task/manager-page',
|
||||
{ params },
|
||||
);
|
||||
|
||||
@@ -3,9 +3,8 @@ import type { PageParam, PageResult } from '@vben/request';
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace BpmUserGroupApi {
|
||||
// TODO @ziye:不用 VO 后缀
|
||||
/** BPM 用户组 VO */
|
||||
export interface UserGroupVO {
|
||||
/** BPM 用户组 */
|
||||
export interface UserGroup {
|
||||
id: number;
|
||||
name: string;
|
||||
description: string;
|
||||
@@ -18,7 +17,7 @@ export namespace BpmUserGroupApi {
|
||||
|
||||
/** 查询用户组分页 */
|
||||
export async function getUserGroupPage(params: PageParam) {
|
||||
return requestClient.get<PageResult<BpmUserGroupApi.UserGroupVO>>(
|
||||
return requestClient.get<PageResult<BpmUserGroupApi.UserGroup>>(
|
||||
'/bpm/user-group/page',
|
||||
{ params },
|
||||
);
|
||||
@@ -26,18 +25,18 @@ export async function getUserGroupPage(params: PageParam) {
|
||||
|
||||
/** 查询用户组详情 */
|
||||
export async function getUserGroup(id: number) {
|
||||
return requestClient.get<BpmUserGroupApi.UserGroupVO>(
|
||||
return requestClient.get<BpmUserGroupApi.UserGroup>(
|
||||
`/bpm/user-group/get?id=${id}`,
|
||||
);
|
||||
}
|
||||
|
||||
/** 新增用户组 */
|
||||
export async function createUserGroup(data: BpmUserGroupApi.UserGroupVO) {
|
||||
export async function createUserGroup(data: BpmUserGroupApi.UserGroup) {
|
||||
return requestClient.post<number>('/bpm/user-group/create', data);
|
||||
}
|
||||
|
||||
/** 修改用户组 */
|
||||
export async function updateUserGroup(data: BpmUserGroupApi.UserGroupVO) {
|
||||
export async function updateUserGroup(data: BpmUserGroupApi.UserGroup) {
|
||||
return requestClient.put<boolean>('/bpm/user-group/update', data);
|
||||
}
|
||||
|
||||
@@ -48,7 +47,7 @@ export async function deleteUserGroup(id: number) {
|
||||
|
||||
/** 查询用户组列表 */
|
||||
export async function getUserGroupSimpleList() {
|
||||
return requestClient.get<BpmUserGroupApi.UserGroupVO[]>(
|
||||
return requestClient.get<BpmUserGroupApi.UserGroup[]>(
|
||||
`/bpm/user-group/simple-list`,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -65,13 +65,13 @@ export namespace InfraCodegenApi {
|
||||
}
|
||||
|
||||
/** 更新代码生成请求 */
|
||||
export interface CodegenUpdateReqVO {
|
||||
export interface CodegenUpdateReq {
|
||||
table: any | CodegenTable;
|
||||
columns: CodegenColumn[];
|
||||
}
|
||||
|
||||
/** 创建代码生成请求 */
|
||||
export interface CodegenCreateListReqVO {
|
||||
export interface CodegenCreateListReq {
|
||||
dataSourceConfigId?: number;
|
||||
tableNames: string[];
|
||||
}
|
||||
@@ -106,7 +106,7 @@ export function getCodegenTable(tableId: number) {
|
||||
}
|
||||
|
||||
/** 修改代码生成表定义 */
|
||||
export function updateCodegenTable(data: InfraCodegenApi.CodegenUpdateReqVO) {
|
||||
export function updateCodegenTable(data: InfraCodegenApi.CodegenUpdateReq) {
|
||||
return requestClient.put('/infra/codegen/update', data);
|
||||
}
|
||||
|
||||
@@ -136,9 +136,7 @@ export function getSchemaTableList(params: any) {
|
||||
}
|
||||
|
||||
/** 基于数据库的表结构,创建代码生成器的表定义 */
|
||||
export function createCodegenList(
|
||||
data: InfraCodegenApi.CodegenCreateListReqVO,
|
||||
) {
|
||||
export function createCodegenList(data: InfraCodegenApi.CodegenCreateListReq) {
|
||||
return requestClient.post('/infra/codegen/create-list', data);
|
||||
}
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@ export function deleteConfigList(ids: number[]) {
|
||||
|
||||
/** 导出参数 */
|
||||
export function exportConfig(params: any) {
|
||||
return requestClient.download('/infra/config/export', {
|
||||
return requestClient.download('/infra/config/export-excel', {
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ export namespace InfraFileApi {
|
||||
}
|
||||
|
||||
/** 文件预签名地址 */
|
||||
export interface FilePresignedUrlRespVO {
|
||||
export interface FilePresignedUrlResp {
|
||||
configId: number; // 文件配置编号
|
||||
uploadUrl: string; // 文件上传 URL
|
||||
url: string; // 文件 URL
|
||||
@@ -27,7 +27,7 @@ export namespace InfraFileApi {
|
||||
}
|
||||
|
||||
/** 上传文件 */
|
||||
export interface FileUploadReqVO {
|
||||
export interface FileUploadReq {
|
||||
file: globalThis.File;
|
||||
directory?: string;
|
||||
}
|
||||
@@ -52,7 +52,7 @@ export function deleteFileList(ids: number[]) {
|
||||
|
||||
/** 获取文件预签名地址 */
|
||||
export function getFilePresignedUrl(name: string, directory?: string) {
|
||||
return requestClient.get<InfraFileApi.FilePresignedUrlRespVO>(
|
||||
return requestClient.get<InfraFileApi.FilePresignedUrlResp>(
|
||||
'/infra/file/presigned-url',
|
||||
{
|
||||
params: { name, directory },
|
||||
@@ -67,7 +67,7 @@ export function createFile(data: InfraFileApi.File) {
|
||||
|
||||
/** 上传文件 */
|
||||
export function uploadFile(
|
||||
data: InfraFileApi.FileUploadReqVO,
|
||||
data: InfraFileApi.FileUploadReq,
|
||||
onUploadProgress?: AxiosProgressEvent,
|
||||
) {
|
||||
// 特殊:由于 upload 内部封装,即使 directory 为 undefined,也会传递给后端
|
||||
|
||||
@@ -168,7 +168,7 @@ export function deleteSpu(id: number) {
|
||||
|
||||
/** 导出商品 SPU Excel */
|
||||
export function exportSpu(params: PageParam) {
|
||||
return requestClient.download('/product/spu/export', { params });
|
||||
return requestClient.download('/product/spu/export-excel', { params });
|
||||
}
|
||||
|
||||
/** 获得商品 SPU 精简列表 */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/** 数据对照 Response VO */
|
||||
export interface MallDataComparisonRespVO<T> {
|
||||
/** 数据对照 Response */
|
||||
export interface MallDataComparisonResp<T> {
|
||||
value: T;
|
||||
reference: T;
|
||||
}
|
||||
|
||||
@@ -1,32 +1,32 @@
|
||||
import type { MallDataComparisonRespVO } from './common';
|
||||
import type { MallDataComparisonResp } from './common';
|
||||
|
||||
import { formatDate } from '@vben/utils';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace MallMemberStatisticsApi {
|
||||
/** 会员分析 Request VO */
|
||||
/** 会员分析 Request */
|
||||
export interface AnalyseReq {
|
||||
times: Date[];
|
||||
}
|
||||
|
||||
/** 会员分析对照数据 Response VO */
|
||||
/** 会员分析对照数据 Response */
|
||||
export interface AnalyseComparison {
|
||||
registerUserCount: number;
|
||||
visitUserCount: number;
|
||||
rechargeUserCount: number;
|
||||
}
|
||||
|
||||
/** 会员分析 Response VO */
|
||||
/** 会员分析 Response */
|
||||
export interface Analyse {
|
||||
visitUserCount: number;
|
||||
orderUserCount: number;
|
||||
payUserCount: number;
|
||||
atv: number;
|
||||
comparison: MallDataComparisonRespVO<AnalyseComparison>;
|
||||
comparison: MallDataComparisonResp<AnalyseComparison>;
|
||||
}
|
||||
|
||||
/** 会员地区统计 Response VO */
|
||||
/** 会员地区统计 Response */
|
||||
export interface AreaStatistics {
|
||||
areaId: number;
|
||||
areaName: string;
|
||||
@@ -36,13 +36,13 @@ export namespace MallMemberStatisticsApi {
|
||||
orderPayPrice: number;
|
||||
}
|
||||
|
||||
/** 会员性别统计 Response VO */
|
||||
/** 会员性别统计 Response */
|
||||
export interface SexStatistics {
|
||||
sex: number;
|
||||
userCount: number;
|
||||
}
|
||||
|
||||
/** 会员统计 Response VO */
|
||||
/** 会员统计 Response */
|
||||
export interface Summary {
|
||||
userCount: number;
|
||||
rechargeUserCount: number;
|
||||
@@ -50,13 +50,13 @@ export namespace MallMemberStatisticsApi {
|
||||
expensePrice: number;
|
||||
}
|
||||
|
||||
/** 会员终端统计 Response VO */
|
||||
/** 会员终端统计 Response */
|
||||
export interface TerminalStatistics {
|
||||
terminal: number;
|
||||
userCount: number;
|
||||
}
|
||||
|
||||
/** 会员数量统计 Response VO */
|
||||
/** 会员数量统计 Response */
|
||||
export interface Count {
|
||||
/** 用户访问量 */
|
||||
visitUserCount: string;
|
||||
@@ -64,7 +64,7 @@ export namespace MallMemberStatisticsApi {
|
||||
registerUserCount: number;
|
||||
}
|
||||
|
||||
/** 会员注册数量 Response VO */
|
||||
/** 会员注册数量 Response */
|
||||
export interface RegisterCount {
|
||||
date: string;
|
||||
count: number;
|
||||
@@ -114,7 +114,7 @@ export function getMemberTerminalStatisticsList() {
|
||||
/** 获得用户数量量对照 */
|
||||
export function getUserCountComparison() {
|
||||
return requestClient.get<
|
||||
MallDataComparisonRespVO<MallMemberStatisticsApi.Count>
|
||||
MallDataComparisonResp<MallMemberStatisticsApi.Count>
|
||||
>('/statistics/member/user-count-comparison');
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace MallPayStatisticsApi {
|
||||
/** 支付统计 */
|
||||
export interface PaySummaryRespVO {
|
||||
export interface PaySummaryResp {
|
||||
/** 充值金额,单位分 */
|
||||
rechargePrice: number;
|
||||
}
|
||||
@@ -10,7 +10,7 @@ export namespace MallPayStatisticsApi {
|
||||
|
||||
/** 获取钱包充值金额 */
|
||||
export function getWalletRechargePrice() {
|
||||
return requestClient.get<MallPayStatisticsApi.PaySummaryRespVO>(
|
||||
return requestClient.get<MallPayStatisticsApi.PaySummaryResp>(
|
||||
'/statistics/pay/summary',
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { PageParam, PageResult } from '@vben/request';
|
||||
|
||||
import type { MallDataComparisonRespVO } from './common';
|
||||
import type { MallDataComparisonResp } from './common';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
@@ -43,7 +43,7 @@ export namespace MallProductStatisticsApi {
|
||||
/** 获得商品统计分析 */
|
||||
export function getProductStatisticsAnalyse(params: PageParam) {
|
||||
return requestClient.get<
|
||||
MallDataComparisonRespVO<MallProductStatisticsApi.ProductStatistics>
|
||||
MallDataComparisonResp<MallProductStatisticsApi.ProductStatistics>
|
||||
>('/statistics/product/analyse', { params });
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import type { MallDataComparisonRespVO } from './common';
|
||||
import type { MallDataComparisonResp } from './common';
|
||||
|
||||
import { formatDate } from '@vben/utils';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace MallTradeStatisticsApi {
|
||||
/** 交易统计 Response VO */
|
||||
/** 交易统计 Response */
|
||||
export interface TradeSummary {
|
||||
yesterdayOrderCount: number;
|
||||
monthOrderCount: number;
|
||||
@@ -13,12 +13,12 @@ export namespace MallTradeStatisticsApi {
|
||||
monthPayPrice: number;
|
||||
}
|
||||
|
||||
/** 交易状况 Request VO */
|
||||
/** 交易状况 Request */
|
||||
export interface TradeTrendReq {
|
||||
times: [Date, Date];
|
||||
}
|
||||
|
||||
/** 交易状况统计 Response VO */
|
||||
/** 交易状况统计 Response */
|
||||
export interface TradeTrendSummary {
|
||||
time: string;
|
||||
turnoverPrice: number;
|
||||
@@ -30,7 +30,7 @@ export namespace MallTradeStatisticsApi {
|
||||
afterSaleRefundPrice: number;
|
||||
}
|
||||
|
||||
/** 交易订单数量 Response VO */
|
||||
/** 交易订单数量 Response */
|
||||
export interface TradeOrderCount {
|
||||
/** 待发货 */
|
||||
undelivered?: number;
|
||||
@@ -42,7 +42,7 @@ export namespace MallTradeStatisticsApi {
|
||||
auditingWithdraw?: number;
|
||||
}
|
||||
|
||||
/** 交易订单统计 Response VO */
|
||||
/** 交易订单统计 Response */
|
||||
export interface TradeOrderSummary {
|
||||
/** 支付订单商品数 */
|
||||
orderPayCount?: number;
|
||||
@@ -50,7 +50,7 @@ export namespace MallTradeStatisticsApi {
|
||||
orderPayPrice?: number;
|
||||
}
|
||||
|
||||
/** 订单量趋势统计 Response VO */
|
||||
/** 订单量趋势统计 Response */
|
||||
export interface TradeOrderTrend {
|
||||
/** 日期 */
|
||||
date: string;
|
||||
@@ -71,7 +71,7 @@ const formatDateParam = (params: MallTradeStatisticsApi.TradeTrendReq) => {
|
||||
/** 查询交易统计 */
|
||||
export function getTradeStatisticsSummary() {
|
||||
return requestClient.get<
|
||||
MallDataComparisonRespVO<MallTradeStatisticsApi.TradeSummary>
|
||||
MallDataComparisonResp<MallTradeStatisticsApi.TradeSummary>
|
||||
>('/statistics/trade/summary');
|
||||
}
|
||||
|
||||
@@ -80,7 +80,7 @@ export function getTradeStatisticsAnalyse(
|
||||
params: MallTradeStatisticsApi.TradeTrendReq,
|
||||
) {
|
||||
return requestClient.get<
|
||||
MallDataComparisonRespVO<MallTradeStatisticsApi.TradeTrendSummary>
|
||||
MallDataComparisonResp<MallTradeStatisticsApi.TradeTrendSummary>
|
||||
>('/statistics/trade/analyse', { params: formatDateParam(params) });
|
||||
}
|
||||
|
||||
@@ -113,7 +113,7 @@ export function getOrderCount() {
|
||||
/** 获得交易订单数量对照 */
|
||||
export function getOrderComparison() {
|
||||
return requestClient.get<
|
||||
MallDataComparisonRespVO<MallTradeStatisticsApi.TradeOrderSummary>
|
||||
MallDataComparisonResp<MallTradeStatisticsApi.TradeOrderSummary>
|
||||
>('/statistics/trade/order-comparison');
|
||||
}
|
||||
|
||||
@@ -124,7 +124,7 @@ export function getOrderCountTrendComparison(
|
||||
endTime: Date,
|
||||
) {
|
||||
return requestClient.get<
|
||||
MallDataComparisonRespVO<MallTradeStatisticsApi.TradeOrderTrend>[]
|
||||
MallDataComparisonResp<MallTradeStatisticsApi.TradeOrderTrend>[]
|
||||
>('/statistics/trade/order-count-trend', {
|
||||
params: {
|
||||
type,
|
||||
|
||||
@@ -24,7 +24,7 @@ export namespace PayAppApi {
|
||||
status: number;
|
||||
}
|
||||
|
||||
export interface AppPageReqVO extends PageParam {
|
||||
export interface AppPageReq extends PageParam {
|
||||
name?: string;
|
||||
status?: number;
|
||||
remark?: string;
|
||||
@@ -37,7 +37,7 @@ export namespace PayAppApi {
|
||||
}
|
||||
|
||||
/** 查询支付应用列表 */
|
||||
export function getAppPage(params: PayAppApi.AppPageReqVO) {
|
||||
export function getAppPage(params: PayAppApi.AppPageReq) {
|
||||
return requestClient.get<PageResult<PayAppApi.App>>('/pay/app/page', {
|
||||
params,
|
||||
});
|
||||
|
||||
@@ -20,7 +20,7 @@ export namespace DemoOrderApi {
|
||||
createTime?: Date;
|
||||
}
|
||||
|
||||
export interface OrderPageReqVO extends PageParam {
|
||||
export interface OrderPageReq extends PageParam {
|
||||
spuId?: number;
|
||||
createTime?: Date[];
|
||||
}
|
||||
@@ -32,7 +32,7 @@ export function createDemoOrder(data: DemoOrderApi.Order) {
|
||||
}
|
||||
|
||||
/** 获得示例订单分页 */
|
||||
export function getDemoOrderPage(params: DemoOrderApi.OrderPageReqVO) {
|
||||
export function getDemoOrderPage(params: DemoOrderApi.OrderPageReq) {
|
||||
return requestClient.get<PageResult<DemoOrderApi.Order>>(
|
||||
'/pay/demo-order/page',
|
||||
{
|
||||
|
||||
@@ -40,7 +40,7 @@ export namespace PayOrderApi {
|
||||
}
|
||||
|
||||
/** 支付订单分页请求 */
|
||||
export interface OrderPageReqVO extends PageParam {
|
||||
export interface OrderPageReq extends PageParam {
|
||||
merchantId?: number;
|
||||
appId?: number;
|
||||
channelId?: number;
|
||||
@@ -66,7 +66,7 @@ export namespace PayOrderApi {
|
||||
}
|
||||
|
||||
/** 支付订单导出请求 */
|
||||
export interface OrderExportReqVO {
|
||||
export interface OrderExportReq {
|
||||
merchantId?: number;
|
||||
appId?: number;
|
||||
channelId?: number;
|
||||
@@ -93,7 +93,7 @@ export namespace PayOrderApi {
|
||||
}
|
||||
|
||||
/** 查询支付订单列表 */
|
||||
export function getOrderPage(params: PayOrderApi.OrderPageReqVO) {
|
||||
export function getOrderPage(params: PayOrderApi.OrderPageReq) {
|
||||
return requestClient.get<PageResult<PayOrderApi.Order>>('/pay/order/page', {
|
||||
params,
|
||||
});
|
||||
@@ -120,6 +120,6 @@ export function submitOrder(data: any) {
|
||||
}
|
||||
|
||||
/** 导出支付订单 */
|
||||
export function exportOrder(params: PayOrderApi.OrderExportReqVO) {
|
||||
export function exportOrder(params: PayOrderApi.OrderExportReq) {
|
||||
return requestClient.download('/pay/order/export-excel', { params });
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ export namespace PayRefundApi {
|
||||
}
|
||||
|
||||
/** 退款订单分页请求 */
|
||||
export interface RefundPageReqVO extends PageParam {
|
||||
export interface RefundPageReq extends PageParam {
|
||||
merchantId?: number;
|
||||
appId?: number;
|
||||
channelId?: number;
|
||||
@@ -64,7 +64,7 @@ export namespace PayRefundApi {
|
||||
}
|
||||
|
||||
/** 退款订单导出请求 */
|
||||
export interface RefundExportReqVO {
|
||||
export interface RefundExportReq {
|
||||
merchantId?: number;
|
||||
appId?: number;
|
||||
channelId?: number;
|
||||
@@ -94,7 +94,7 @@ export namespace PayRefundApi {
|
||||
}
|
||||
|
||||
/** 查询退款订单列表 */
|
||||
export function getRefundPage(params: PayRefundApi.RefundPageReqVO) {
|
||||
export function getRefundPage(params: PayRefundApi.RefundPageReq) {
|
||||
return requestClient.get<PageResult<PayRefundApi.Refund>>(
|
||||
'/pay/refund/page',
|
||||
{
|
||||
@@ -124,6 +124,6 @@ export function deleteRefund(id: number) {
|
||||
}
|
||||
|
||||
/** 导出退款订单 */
|
||||
export function exportRefund(params: PayRefundApi.RefundExportReqVO) {
|
||||
export function exportRefund(params: PayRefundApi.RefundExportReq) {
|
||||
return requestClient.download('/pay/refund/export-excel', { params });
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ export namespace PayTransferApi {
|
||||
}
|
||||
|
||||
/** 转账单分页请求 */
|
||||
export interface TransferPageReqVO extends PageParam {
|
||||
export interface TransferPageReq extends PageParam {
|
||||
appId?: number;
|
||||
channelId?: number;
|
||||
channelCode?: string;
|
||||
@@ -36,7 +36,7 @@ export namespace PayTransferApi {
|
||||
}
|
||||
|
||||
/** 查询转账单列表 */
|
||||
export function getTransferPage(params: PayTransferApi.TransferPageReqVO) {
|
||||
export function getTransferPage(params: PayTransferApi.TransferPageReq) {
|
||||
return requestClient.get<PageResult<PayTransferApi.Transfer>>(
|
||||
'/pay/transfer/page',
|
||||
{
|
||||
|
||||
@@ -4,12 +4,12 @@ import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace PayWalletApi {
|
||||
/** 用户钱包查询参数 */
|
||||
export interface PayWalletUserReqVO {
|
||||
export interface PayWalletUserReq {
|
||||
userId: number;
|
||||
}
|
||||
|
||||
/** 钱包信息 */
|
||||
export interface WalletVO {
|
||||
export interface Wallet {
|
||||
id: number;
|
||||
userId: number;
|
||||
userType: number;
|
||||
@@ -20,7 +20,7 @@ export namespace PayWalletApi {
|
||||
}
|
||||
|
||||
/** 钱包分页请求 */
|
||||
export interface WalletPageReqVO extends PageParam {
|
||||
export interface WalletPageReq extends PageParam {
|
||||
userId?: number;
|
||||
userType?: number;
|
||||
balance?: number;
|
||||
@@ -31,15 +31,15 @@ export namespace PayWalletApi {
|
||||
}
|
||||
|
||||
/** 查询用户钱包详情 */
|
||||
export function getWallet(params: PayWalletApi.PayWalletUserReqVO) {
|
||||
return requestClient.get<PayWalletApi.WalletVO>('/pay/wallet/get', {
|
||||
export function getWallet(params: PayWalletApi.PayWalletUserReq) {
|
||||
return requestClient.get<PayWalletApi.Wallet>('/pay/wallet/get', {
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
/** 查询会员钱包列表 */
|
||||
export function getWalletPage(params: PayWalletApi.WalletPageReqVO) {
|
||||
return requestClient.get<PageResult<PayWalletApi.WalletVO>>(
|
||||
export function getWalletPage(params: PayWalletApi.WalletPageReq) {
|
||||
return requestClient.get<PageResult<PayWalletApi.Wallet>>(
|
||||
'/pay/wallet/page',
|
||||
{
|
||||
params,
|
||||
@@ -48,6 +48,6 @@ export function getWalletPage(params: PayWalletApi.WalletPageReqVO) {
|
||||
}
|
||||
|
||||
/** 修改会员钱包余额 */
|
||||
export function updateWalletBalance(data: PayWalletApi.WalletVO) {
|
||||
export function updateWalletBalance(data: PayWalletApi.Wallet) {
|
||||
return requestClient.put('/pay/wallet/update-balance', data);
|
||||
}
|
||||
|
||||
@@ -57,5 +57,5 @@ export function deleteDictDataList(ids: number[]) {
|
||||
|
||||
// 导出字典类型数据
|
||||
export function exportDictData(params: any) {
|
||||
return requestClient.download('/system/dict-data/export', { params });
|
||||
return requestClient.download('/system/dict-data/export-excel', { params });
|
||||
}
|
||||
|
||||
@@ -51,5 +51,5 @@ export function deleteDictTypeList(ids: number[]) {
|
||||
|
||||
// 导出字典类型
|
||||
export function exportDictType(params: any) {
|
||||
return requestClient.download('/system/dict-type/export', { params });
|
||||
return requestClient.download('/system/dict-type/export-excel', { params });
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ export namespace SystemMailTemplateApi {
|
||||
}
|
||||
|
||||
/** 邮件发送信息 */
|
||||
export interface MailSendReqVO {
|
||||
export interface MailSendReq {
|
||||
mail: string;
|
||||
templateCode: string;
|
||||
templateParams: Record<string, any>;
|
||||
@@ -64,6 +64,6 @@ export function deleteMailTemplateList(ids: number[]) {
|
||||
}
|
||||
|
||||
/** 发送邮件 */
|
||||
export function sendMail(data: SystemMailTemplateApi.MailSendReqVO) {
|
||||
export function sendMail(data: SystemMailTemplateApi.MailSendReq) {
|
||||
return requestClient.post('/system/mail-template/send-mail', data);
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ export namespace SystemNotifyTemplateApi {
|
||||
}
|
||||
|
||||
/** 发送站内信请求 */
|
||||
export interface NotifySendReqVO {
|
||||
export interface NotifySendReq {
|
||||
userId: number;
|
||||
userType: number;
|
||||
templateCode: string;
|
||||
@@ -74,6 +74,6 @@ export function exportNotifyTemplate(params: any) {
|
||||
}
|
||||
|
||||
/** 发送站内信 */
|
||||
export function sendNotify(data: SystemNotifyTemplateApi.NotifySendReqVO) {
|
||||
export function sendNotify(data: SystemNotifyTemplateApi.NotifySendReq) {
|
||||
return requestClient.post('/system/notify-template/send-notify', data);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ import { requestClient } from '#/api/request';
|
||||
/** OAuth2.0 授权信息响应 */
|
||||
export namespace SystemOAuth2ClientApi {
|
||||
/** 授权信息 */
|
||||
export interface AuthorizeInfoRespVO {
|
||||
export interface AuthorizeInfoResp {
|
||||
client: {
|
||||
logo: string;
|
||||
name: string;
|
||||
@@ -17,7 +17,7 @@ export namespace SystemOAuth2ClientApi {
|
||||
|
||||
/** 获得授权信息 */
|
||||
export function getAuthorize(clientId: string) {
|
||||
return requestClient.get<SystemOAuth2ClientApi.AuthorizeInfoRespVO>(
|
||||
return requestClient.get<SystemOAuth2ClientApi.AuthorizeInfoResp>(
|
||||
`/system/oauth2/authorize?clientId=${clientId}`,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2,19 +2,19 @@ import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace SystemPermissionApi {
|
||||
/** 分配用户角色请求 */
|
||||
export interface AssignUserRoleReqVO {
|
||||
export interface AssignUserRoleReq {
|
||||
userId: number;
|
||||
roleIds: number[];
|
||||
}
|
||||
|
||||
/** 分配角色菜单请求 */
|
||||
export interface AssignRoleMenuReqVO {
|
||||
export interface AssignRoleMenuReq {
|
||||
roleId: number;
|
||||
menuIds: number[];
|
||||
}
|
||||
|
||||
/** 分配角色数据权限请求 */
|
||||
export interface AssignRoleDataScopeReqVO {
|
||||
export interface AssignRoleDataScopeReq {
|
||||
roleId: number;
|
||||
dataScope: number;
|
||||
dataScopeDeptIds: number[];
|
||||
@@ -30,14 +30,14 @@ export async function getRoleMenuList(roleId: number) {
|
||||
|
||||
/** 赋予角色菜单权限 */
|
||||
export async function assignRoleMenu(
|
||||
data: SystemPermissionApi.AssignRoleMenuReqVO,
|
||||
data: SystemPermissionApi.AssignRoleMenuReq,
|
||||
) {
|
||||
return requestClient.post('/system/permission/assign-role-menu', data);
|
||||
}
|
||||
|
||||
/** 赋予角色数据权限 */
|
||||
export async function assignRoleDataScope(
|
||||
data: SystemPermissionApi.AssignRoleDataScopeReqVO,
|
||||
data: SystemPermissionApi.AssignRoleDataScopeReq,
|
||||
) {
|
||||
return requestClient.post('/system/permission/assign-role-data-scope', data);
|
||||
}
|
||||
@@ -51,7 +51,7 @@ export async function getUserRoleList(userId: number) {
|
||||
|
||||
/** 赋予用户角色 */
|
||||
export async function assignUserRole(
|
||||
data: SystemPermissionApi.AssignUserRoleReqVO,
|
||||
data: SystemPermissionApi.AssignUserRoleReq,
|
||||
) {
|
||||
return requestClient.post('/system/permission/assign-user-role', data);
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ export function deletePostList(ids: number[]) {
|
||||
|
||||
/** 导出岗位 */
|
||||
export function exportPost(params: any) {
|
||||
return requestClient.download('/system/post/export', {
|
||||
return requestClient.download('/system/post/export-excel', {
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -63,5 +63,5 @@ export function deleteSmsChannelList(ids: number[]) {
|
||||
|
||||
/** 导出短信渠道 */
|
||||
export function exportSmsChannel(params: any) {
|
||||
return requestClient.download('/system/sms-channel/export', { params });
|
||||
return requestClient.download('/system/sms-channel/export-excel', { params });
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ export namespace SystemSmsTemplateApi {
|
||||
}
|
||||
|
||||
/** 发送短信请求 */
|
||||
export interface SmsSendReqVO {
|
||||
export interface SmsSendReq {
|
||||
mobile: string;
|
||||
templateCode: string;
|
||||
templateParams: Record<string, any>;
|
||||
@@ -72,6 +72,6 @@ export function exportSmsTemplate(params: any) {
|
||||
}
|
||||
|
||||
/** 发送短信 */
|
||||
export function sendSms(data: SystemSmsTemplateApi.SmsSendReqVO) {
|
||||
export function sendSms(data: SystemSmsTemplateApi.SmsSendReq) {
|
||||
return requestClient.post('/system/sms-template/send-sms', data);
|
||||
}
|
||||
|
||||
@@ -20,14 +20,14 @@ export namespace SystemSocialUserApi {
|
||||
}
|
||||
|
||||
/** 社交绑定请求 */
|
||||
export interface SocialUserBindReqVO {
|
||||
export interface SocialUserBindReq {
|
||||
type: number;
|
||||
code: string;
|
||||
state: string;
|
||||
}
|
||||
|
||||
/** 取消社交绑定请求 */
|
||||
export interface SocialUserUnbindReqVO {
|
||||
export interface SocialUserUnbindReq {
|
||||
type: number;
|
||||
openid: string;
|
||||
}
|
||||
@@ -49,12 +49,12 @@ export function getSocialUser(id: number) {
|
||||
}
|
||||
|
||||
/** 社交绑定,使用 code 授权码 */
|
||||
export function socialBind(data: SystemSocialUserApi.SocialUserBindReqVO) {
|
||||
export function socialBind(data: SystemSocialUserApi.SocialUserBindReq) {
|
||||
return requestClient.post<boolean>('/system/social-user/bind', data);
|
||||
}
|
||||
|
||||
/** 取消社交绑定 */
|
||||
export function socialUnbind(data: SystemSocialUserApi.SocialUserUnbindReqVO) {
|
||||
export function socialUnbind(data: SystemSocialUserApi.SocialUserUnbindReq) {
|
||||
return requestClient.delete<boolean>('/system/social-user/unbind', { data });
|
||||
}
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ export function deleteUserList(ids: number[]) {
|
||||
|
||||
/** 导出用户 */
|
||||
export function exportUser(params: any) {
|
||||
return requestClient.download('/system/user/export', params);
|
||||
return requestClient.download('/system/user/export-excel', params);
|
||||
}
|
||||
|
||||
/** 下载用户导入模板 */
|
||||
|
||||
@@ -2,7 +2,7 @@ import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace SystemUserProfileApi {
|
||||
/** 用户个人中心信息 */
|
||||
export interface UserProfileRespVO {
|
||||
export interface UserProfileResp {
|
||||
id: number;
|
||||
username: string;
|
||||
nickname: string;
|
||||
@@ -19,13 +19,13 @@ export namespace SystemUserProfileApi {
|
||||
}
|
||||
|
||||
/** 更新密码请求 */
|
||||
export interface UpdatePasswordReqVO {
|
||||
export interface UpdatePasswordReq {
|
||||
oldPassword: string;
|
||||
newPassword: string;
|
||||
}
|
||||
|
||||
/** 更新个人信息请求 */
|
||||
export interface UpdateProfileReqVO {
|
||||
export interface UpdateProfileReq {
|
||||
nickname?: string;
|
||||
email?: string;
|
||||
mobile?: string;
|
||||
@@ -36,21 +36,19 @@ export namespace SystemUserProfileApi {
|
||||
|
||||
/** 获取登录用户信息 */
|
||||
export function getUserProfile() {
|
||||
return requestClient.get<SystemUserProfileApi.UserProfileRespVO>(
|
||||
return requestClient.get<SystemUserProfileApi.UserProfileResp>(
|
||||
'/system/user/profile/get',
|
||||
);
|
||||
}
|
||||
|
||||
/** 修改用户个人信息 */
|
||||
export function updateUserProfile(
|
||||
data: SystemUserProfileApi.UpdateProfileReqVO,
|
||||
) {
|
||||
export function updateUserProfile(data: SystemUserProfileApi.UpdateProfileReq) {
|
||||
return requestClient.put('/system/user/profile/update', data);
|
||||
}
|
||||
|
||||
/** 修改用户个人密码 */
|
||||
export function updateUserPassword(
|
||||
data: SystemUserProfileApi.UpdatePasswordReqVO,
|
||||
data: SystemUserProfileApi.UpdatePasswordReq,
|
||||
) {
|
||||
return requestClient.put('/system/user/profile/update-password', data);
|
||||
}
|
||||
|
||||
73
apps/web-antd/src/components/Tinyflow/Tinyflow.vue
Normal file
73
apps/web-antd/src/components/Tinyflow/Tinyflow.vue
Normal file
@@ -0,0 +1,73 @@
|
||||
<script setup lang="ts">
|
||||
import type { Item } from './ui/typing';
|
||||
|
||||
import { onMounted, onUnmounted, ref } from 'vue';
|
||||
|
||||
import { Tinyflow as TinyflowNative } from './ui/index';
|
||||
|
||||
import './ui/index.css';
|
||||
|
||||
const props = defineProps<{
|
||||
className?: string;
|
||||
data?: Record<string, any>;
|
||||
provider?: {
|
||||
internal?: () => Item[] | Promise<Item[]>;
|
||||
knowledge?: () => Item[] | Promise<Item[]>;
|
||||
llm?: () => Item[] | Promise<Item[]>;
|
||||
};
|
||||
style?: Record<string, string>;
|
||||
}>();
|
||||
|
||||
const divRef = ref<HTMLDivElement | null>(null);
|
||||
let tinyflow: null | TinyflowNative = null;
|
||||
// 定义默认的 provider 方法
|
||||
const defaultProvider = {
|
||||
llm: () => [] as Item[],
|
||||
knowledge: () => [] as Item[],
|
||||
internal: () => [] as Item[],
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
if (divRef.value) {
|
||||
// 合并默认 provider 和传入的 props.provider
|
||||
const mergedProvider = {
|
||||
...defaultProvider,
|
||||
...props.provider,
|
||||
};
|
||||
tinyflow = new TinyflowNative({
|
||||
element: divRef.value as Element,
|
||||
data: props.data || {},
|
||||
provider: mergedProvider,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
if (tinyflow) {
|
||||
tinyflow.destroy();
|
||||
tinyflow = null;
|
||||
}
|
||||
});
|
||||
|
||||
const getData = () => {
|
||||
if (tinyflow) {
|
||||
return tinyflow.getData();
|
||||
}
|
||||
console.warn('Tinyflow instance is not initialized');
|
||||
return null;
|
||||
};
|
||||
|
||||
defineExpose({
|
||||
getData,
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
ref="divRef"
|
||||
class="tinyflow"
|
||||
:class="[className]"
|
||||
:style="style"
|
||||
style="height: 100%"
|
||||
></div>
|
||||
</template>
|
||||
2
apps/web-antd/src/components/Tinyflow/index.ts
Normal file
2
apps/web-antd/src/components/Tinyflow/index.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export { default as Tinyflow } from './tinyflow.vue';
|
||||
export * from './ui/typing';
|
||||
1043
apps/web-antd/src/components/Tinyflow/ui/index.css
Normal file
1043
apps/web-antd/src/components/Tinyflow/ui/index.css
Normal file
File diff suppressed because it is too large
Load Diff
16984
apps/web-antd/src/components/Tinyflow/ui/index.ts
Normal file
16984
apps/web-antd/src/components/Tinyflow/ui/index.ts
Normal file
File diff suppressed because it is too large
Load Diff
9
apps/web-antd/src/components/Tinyflow/ui/index.umd.js
Normal file
9
apps/web-antd/src/components/Tinyflow/ui/index.umd.js
Normal file
File diff suppressed because one or more lines are too long
68
apps/web-antd/src/components/Tinyflow/ui/typing.ts
Normal file
68
apps/web-antd/src/components/Tinyflow/ui/typing.ts
Normal file
@@ -0,0 +1,68 @@
|
||||
export interface Item {
|
||||
children?: Item[];
|
||||
label: string;
|
||||
value: number | string;
|
||||
}
|
||||
|
||||
export interface Position {
|
||||
x: number;
|
||||
y: number;
|
||||
}
|
||||
|
||||
export interface Viewport {
|
||||
x: number;
|
||||
y: number;
|
||||
zoom: number;
|
||||
}
|
||||
|
||||
export interface Node {
|
||||
data?: Record<string, any>;
|
||||
draggable?: boolean;
|
||||
height?: number;
|
||||
id: string;
|
||||
position: Position;
|
||||
selected?: boolean;
|
||||
type?: string;
|
||||
width?: number;
|
||||
}
|
||||
|
||||
export interface Edge {
|
||||
animated?: boolean;
|
||||
id: string;
|
||||
label?: string;
|
||||
source: string;
|
||||
target: string;
|
||||
type?: string;
|
||||
}
|
||||
export type TinyflowData = Partial<{
|
||||
edges: Edge[];
|
||||
nodes: Node[];
|
||||
viewport: Viewport;
|
||||
}>;
|
||||
|
||||
export interface TinyflowOptions {
|
||||
data?: TinyflowData;
|
||||
element: Element | string;
|
||||
provider?: {
|
||||
internal?: () => Item[] | Promise<Item[]>;
|
||||
knowledge?: () => Item[] | Promise<Item[]>;
|
||||
llm?: () => Item[] | Promise<Item[]>;
|
||||
};
|
||||
}
|
||||
|
||||
export declare class Tinyflow {
|
||||
private _init;
|
||||
private _setOptions;
|
||||
private options;
|
||||
private rootEl;
|
||||
private svelteFlowInstance;
|
||||
constructor(options: TinyflowOptions);
|
||||
destroy(): void;
|
||||
getData(): {
|
||||
edges: Edge[];
|
||||
nodes: Node[];
|
||||
viewport: Viewport;
|
||||
};
|
||||
getOptions(): TinyflowOptions;
|
||||
setData(data: TinyflowData): void;
|
||||
}
|
||||
3
apps/web-antd/src/components/markdown-view/index.ts
Normal file
3
apps/web-antd/src/components/markdown-view/index.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export { default as MarkdownView } from './markdown-view.vue';
|
||||
|
||||
export * from './typing';
|
||||
206
apps/web-antd/src/components/markdown-view/markdown-view.vue
Normal file
206
apps/web-antd/src/components/markdown-view/markdown-view.vue
Normal file
@@ -0,0 +1,206 @@
|
||||
<script setup lang="ts">
|
||||
import type { MarkdownViewProps } from './typing';
|
||||
|
||||
import { computed, onMounted, ref } from 'vue';
|
||||
|
||||
import { MarkdownIt } from '@vben/plugins/markmap';
|
||||
|
||||
import { useClipboard } from '@vueuse/core';
|
||||
import { message } from 'ant-design-vue';
|
||||
import hljs from 'highlight.js';
|
||||
|
||||
import 'highlight.js/styles/vs2015.min.css';
|
||||
|
||||
// 定义组件属性
|
||||
const props = defineProps<MarkdownViewProps>();
|
||||
|
||||
const { copy } = useClipboard(); // 初始化 copy 到粘贴板
|
||||
const contentRef = ref<HTMLElement | null>(null);
|
||||
|
||||
const md = new MarkdownIt({
|
||||
highlight(str, lang) {
|
||||
if (lang && hljs.getLanguage(lang)) {
|
||||
try {
|
||||
const copyHtml = `<div id="copy" data-copy='${str}' style="position: absolute; right: 10px; top: 5px; color: #fff;cursor: pointer;">复制</div>`;
|
||||
return `<pre style="position: relative;">${copyHtml}<code class="hljs">${hljs.highlight(lang, str, true).value}</code></pre>`;
|
||||
} catch {}
|
||||
}
|
||||
return ``;
|
||||
},
|
||||
});
|
||||
|
||||
/** 渲染 markdown */
|
||||
const renderedMarkdown = computed(() => {
|
||||
return md.render(props.content);
|
||||
});
|
||||
|
||||
/** 初始化 */
|
||||
onMounted(async () => {
|
||||
// 添加 copy 监听
|
||||
contentRef.value?.addEventListener('click', (e: any) => {
|
||||
if (e.target.id === 'copy') {
|
||||
copy(e.target?.dataset?.copy);
|
||||
message.success('复制成功!');
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div ref="contentRef" class="markdown-view" v-html="renderedMarkdown"></div>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.markdown-view {
|
||||
max-width: 100%;
|
||||
font-family: 'PingFang SC';
|
||||
font-size: 0.95rem;
|
||||
font-weight: 400;
|
||||
line-height: 1.6rem;
|
||||
color: #3b3e55;
|
||||
text-align: left;
|
||||
letter-spacing: 0;
|
||||
|
||||
pre {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
pre code.hljs {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
code.hljs {
|
||||
width: auto;
|
||||
padding-top: 20px;
|
||||
border-radius: 6px;
|
||||
|
||||
@media screen and (min-width: 1536px) {
|
||||
width: 960px;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1536px) and (min-width: 1024px) {
|
||||
width: calc(100vw - 400px - 64px - 32px * 2);
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1024px) and (min-width: 768px) {
|
||||
width: calc(100vw - 32px * 2);
|
||||
}
|
||||
|
||||
@media screen and (max-width: 768px) {
|
||||
width: calc(100vw - 16px * 2);
|
||||
}
|
||||
}
|
||||
|
||||
p,
|
||||
code.hljs {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
p {
|
||||
//margin-bottom: 1rem !important;
|
||||
margin: 0;
|
||||
margin-bottom: 3px;
|
||||
}
|
||||
|
||||
/* 标题通用格式 */
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
margin: 24px 0 8px;
|
||||
font-weight: 600;
|
||||
color: #3b3e55;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 22px;
|
||||
line-height: 32px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 20px;
|
||||
line-height: 30px;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 18px;
|
||||
line-height: 28px;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: 16px;
|
||||
line-height: 26px;
|
||||
}
|
||||
|
||||
h5 {
|
||||
font-size: 16px;
|
||||
line-height: 24px;
|
||||
}
|
||||
|
||||
h6 {
|
||||
font-size: 16px;
|
||||
line-height: 24px;
|
||||
}
|
||||
|
||||
/* 列表(有序,无序) */
|
||||
ul,
|
||||
ol {
|
||||
padding: 0;
|
||||
margin: 0 0 8px;
|
||||
font-size: 16px;
|
||||
line-height: 24px;
|
||||
color: #3b3e55; // var(--color-CG600);
|
||||
}
|
||||
|
||||
li {
|
||||
margin: 4px 0 0 20px;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
ol > li {
|
||||
margin-bottom: 1rem;
|
||||
list-style-type: decimal;
|
||||
// 表达式,修复有序列表序号展示不全的问题
|
||||
// &:nth-child(n + 10) {
|
||||
// margin-left: 30px;
|
||||
// }
|
||||
|
||||
// &:nth-child(n + 100) {
|
||||
// margin-left: 30px;
|
||||
// }
|
||||
}
|
||||
|
||||
ul > li {
|
||||
margin-right: 11px;
|
||||
margin-bottom: 1rem;
|
||||
font-size: 16px;
|
||||
line-height: 24px;
|
||||
color: #3b3e55; // var(--color-G900);
|
||||
list-style-type: disc;
|
||||
}
|
||||
|
||||
ol ul,
|
||||
ol ul > li,
|
||||
ul ul,
|
||||
ul ul li {
|
||||
margin-bottom: 1rem;
|
||||
margin-left: 6px;
|
||||
// list-style: circle;
|
||||
font-size: 16px;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
ul ul ul,
|
||||
ul ul ul li,
|
||||
ol ol,
|
||||
ol ol > li,
|
||||
ol ul ul,
|
||||
ol ul ul > li,
|
||||
ul ol,
|
||||
ul ol > li {
|
||||
list-style: square;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
3
apps/web-antd/src/components/markdown-view/typing.ts
Normal file
3
apps/web-antd/src/components/markdown-view/typing.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export type MarkdownViewProps = {
|
||||
content: string;
|
||||
};
|
||||
@@ -177,7 +177,7 @@ defineExpose({ open }); // 提供 open 方法,用于打开弹窗
|
||||
@click="clickIcon()"
|
||||
>
|
||||
{{ currentNode.name }}
|
||||
<IconifyIcon class="ml-1" icon="ep:edit-pen" />
|
||||
<IconifyIcon class="ml-1" icon="lucide:edit-3" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -222,7 +222,7 @@ defineExpose({ showCopyTaskNodeConfig }); // 暴露方法给父组件
|
||||
/>
|
||||
<div v-else class="node-name">
|
||||
{{ nodeName }}
|
||||
<IconifyIcon class="ml-1" icon="ep:edit-pen" @click="clickIcon()" />
|
||||
<IconifyIcon class="ml-1" icon="lucide:edit-3" @click="clickIcon()" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -171,7 +171,7 @@ defineExpose({ openDrawer }); // 暴露方法给父组件
|
||||
@click="clickIcon()"
|
||||
>
|
||||
{{ nodeName }}
|
||||
<IconifyIcon class="ml-1" icon="ep:edit-pen" :size="16" />
|
||||
<IconifyIcon class="ml-1" icon="lucide:edit-3" :size="16" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -188,7 +188,7 @@ defineExpose({ validate });
|
||||
>
|
||||
<IconifyIcon
|
||||
color="#0089ff"
|
||||
icon="ep:circle-close-filled"
|
||||
icon="lucide:circle-x"
|
||||
class="size-4"
|
||||
@click="
|
||||
deleteConditionGroup(condition.conditionGroups.conditions, cIdx)
|
||||
|
||||
@@ -219,7 +219,7 @@ defineExpose({ openDrawer }); // 暴露方法给父组件
|
||||
@click="clickIcon()"
|
||||
>
|
||||
{{ nodeName }}
|
||||
<IconifyIcon class="ml-1" icon="ep:edit-pen" />
|
||||
<IconifyIcon class="ml-1" icon="lucide:edit-3" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -266,7 +266,7 @@ defineExpose({ openDrawer }); // 暴露方法给父组件
|
||||
@click="deleteRouterGroup(index)"
|
||||
>
|
||||
<template #icon>
|
||||
<IconifyIcon icon="ep:close" />
|
||||
<IconifyIcon icon="lucide:x" />
|
||||
</template>
|
||||
</Button>
|
||||
</div>
|
||||
@@ -287,7 +287,7 @@ defineExpose({ openDrawer }); // 暴露方法给父组件
|
||||
@click="addRouterGroup"
|
||||
>
|
||||
<template #icon>
|
||||
<IconifyIcon icon="ep:setting" />
|
||||
<IconifyIcon icon="lucide:settings" />
|
||||
</template>
|
||||
新增路由分支
|
||||
</Button>
|
||||
|
||||
@@ -158,7 +158,7 @@ defineExpose({ showStartUserNodeConfig });
|
||||
{{ nodeName }}
|
||||
<IconifyIcon
|
||||
class="ml-1"
|
||||
icon="ep:edit-pen"
|
||||
icon="lucide:edit-3"
|
||||
:size="16"
|
||||
@click="clickIcon()"
|
||||
/>
|
||||
|
||||
@@ -399,7 +399,7 @@ onMounted(() => {
|
||||
/>
|
||||
<div v-else class="node-name">
|
||||
{{ nodeName }}
|
||||
<IconifyIcon class="ml-1" icon="ep:edit-pen" @click="clickIcon()" />
|
||||
<IconifyIcon class="ml-1" icon="lucide:edit-3" @click="clickIcon()" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -456,7 +456,7 @@ onMounted(() => {
|
||||
@click="deleteFormSetting(index)"
|
||||
>
|
||||
<template #icon>
|
||||
<IconifyIcon icon="ep:close" />
|
||||
<IconifyIcon icon="lucide:x" />
|
||||
</template>
|
||||
</Button>
|
||||
</div>
|
||||
@@ -486,7 +486,7 @@ onMounted(() => {
|
||||
@click="addFormSettingCondition(index, formSetting)"
|
||||
>
|
||||
<template #icon>
|
||||
<IconifyIcon icon="ep:link" />
|
||||
<IconifyIcon icon="lucide:link" />
|
||||
</template>
|
||||
添加条件
|
||||
</Button>
|
||||
@@ -561,7 +561,7 @@ onMounted(() => {
|
||||
@click="addFormFieldSetting(formSetting)"
|
||||
>
|
||||
<template #icon>
|
||||
<IconifyIcon icon="ep:memo" />
|
||||
<IconifyIcon icon="lucide:file-cog" />
|
||||
</template>
|
||||
添加修改字段
|
||||
</Button>
|
||||
@@ -579,7 +579,7 @@ onMounted(() => {
|
||||
@click="addFormSetting"
|
||||
>
|
||||
<template #icon>
|
||||
<IconifyIcon icon="ep:setting" />
|
||||
<IconifyIcon icon="lucide:settings" />
|
||||
</template>
|
||||
添加设置
|
||||
</Button>
|
||||
@@ -604,7 +604,7 @@ onMounted(() => {
|
||||
@click="deleteFormSetting(index)"
|
||||
>
|
||||
<template #icon>
|
||||
<IconifyIcon icon="ep:close" />
|
||||
<IconifyIcon icon="lucide:x" />
|
||||
</template>
|
||||
</Button>
|
||||
</div>
|
||||
@@ -635,7 +635,7 @@ onMounted(() => {
|
||||
@click="addFormSettingCondition(index, formSetting)"
|
||||
>
|
||||
<template #icon>
|
||||
<IconifyIcon icon="ep:link" />
|
||||
<IconifyIcon icon="lucide:link" />
|
||||
</template>
|
||||
添加条件
|
||||
</Button>
|
||||
@@ -673,7 +673,7 @@ onMounted(() => {
|
||||
@click="addFormSetting"
|
||||
>
|
||||
<template #icon>
|
||||
<IconifyIcon icon="ep:setting" />
|
||||
<IconifyIcon icon="lucide:settings" />
|
||||
</template>
|
||||
添加设置
|
||||
</Button>
|
||||
|
||||
@@ -595,7 +595,7 @@ onMounted(() => {
|
||||
/>
|
||||
<div v-else class="node-name">
|
||||
{{ nodeName }}
|
||||
<IconifyIcon class="ml-1" icon="ep:edit-pen" @click="clickIcon()" />
|
||||
<IconifyIcon class="ml-1" icon="lucide:edit-3" @click="clickIcon()" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -1135,7 +1135,7 @@ onMounted(() => {
|
||||
<Button v-else text @click="changeBtnDisplayName(index)">
|
||||
<div class="flex items-center">
|
||||
{{ item.displayName }}
|
||||
<IconifyIcon icon="ep:edit" class="ml-2" />
|
||||
<IconifyIcon icon="lucide:edit" class="ml-2" />
|
||||
</div>
|
||||
</Button>
|
||||
</Col>
|
||||
|
||||
@@ -91,13 +91,13 @@ function deleteNode() {
|
||||
<div class="node-text" v-else>
|
||||
{{ NODE_DEFAULT_TEXT.get(BpmNodeTypeEnum.COPY_TASK_NODE) }}
|
||||
</div>
|
||||
<IconifyIcon v-if="!readonly" icon="ep:arrow-right-bold" />
|
||||
<IconifyIcon v-if="!readonly" icon="lucide:chevron-right" />
|
||||
</div>
|
||||
<div v-if="!readonly" class="node-toolbar">
|
||||
<div class="toolbar-icon">
|
||||
<IconifyIcon
|
||||
color="#0089ff"
|
||||
icon="ep:circle-close-filled"
|
||||
icon="lucide:circle-x"
|
||||
:size="18"
|
||||
@click="deleteNode"
|
||||
/>
|
||||
|
||||
@@ -88,13 +88,13 @@ function deleteNode() {
|
||||
<div class="node-text" v-else>
|
||||
{{ NODE_DEFAULT_TEXT.get(BpmNodeTypeEnum.DELAY_TIMER_NODE) }}
|
||||
</div>
|
||||
<IconifyIcon v-if="!readonly" icon="ep:arrow-right-bold" />
|
||||
<IconifyIcon v-if="!readonly" icon="lucide:chevron-right" />
|
||||
</div>
|
||||
<div v-if="!readonly" class="node-toolbar">
|
||||
<div class="toolbar-icon">
|
||||
<IconifyIcon
|
||||
color="#0089ff"
|
||||
icon="ep:circle-close-filled"
|
||||
icon="lucide:circle-x"
|
||||
:size="18"
|
||||
@click="deleteNode"
|
||||
/>
|
||||
|
||||
@@ -248,7 +248,7 @@ function recursiveFindParentNode(
|
||||
<div class="toolbar-icon">
|
||||
<IconifyIcon
|
||||
color="#0089ff"
|
||||
icon="ep:circle-close-filled"
|
||||
icon="lucide:circle-x"
|
||||
:size="18"
|
||||
@click="deleteCondition(index)"
|
||||
/>
|
||||
@@ -263,7 +263,7 @@ function recursiveFindParentNode(
|
||||
"
|
||||
@click="moveNode(index, -1)"
|
||||
>
|
||||
<IconifyIcon icon="ep:arrow-left" />
|
||||
<IconifyIcon icon="lucide:chevron-left" />
|
||||
</div>
|
||||
|
||||
<div
|
||||
@@ -275,7 +275,7 @@ function recursiveFindParentNode(
|
||||
"
|
||||
@click="moveNode(index, 1)"
|
||||
>
|
||||
<IconifyIcon icon="ep:arrow-right" />
|
||||
<IconifyIcon icon="lucide:chevron-right" />
|
||||
</div>
|
||||
</div>
|
||||
<NodeHandler
|
||||
|
||||
@@ -250,7 +250,7 @@ function recursiveFindParentNode(
|
||||
<div class="toolbar-icon">
|
||||
<IconifyIcon
|
||||
color="#0089ff"
|
||||
icon="ep:circle-close-filled"
|
||||
icon="lucide:circle-x"
|
||||
:size="18"
|
||||
@click="deleteCondition(index)"
|
||||
/>
|
||||
@@ -265,7 +265,7 @@ function recursiveFindParentNode(
|
||||
"
|
||||
@click="moveNode(index, -1)"
|
||||
>
|
||||
<IconifyIcon icon="ep:arrow-left" />
|
||||
<IconifyIcon icon="lucide:chevron-left" />
|
||||
</div>
|
||||
|
||||
<div
|
||||
@@ -277,7 +277,7 @@ function recursiveFindParentNode(
|
||||
"
|
||||
@click="moveNode(index, 1)"
|
||||
>
|
||||
<IconifyIcon icon="ep:arrow-right" />
|
||||
<IconifyIcon icon="lucide:chevron-right" />
|
||||
</div>
|
||||
</div>
|
||||
<NodeHandler
|
||||
|
||||
@@ -344,7 +344,7 @@ function addNode(type: number) {
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<div class="add-icon"><IconifyIcon icon="ep:plus" /></div>
|
||||
<div class="add-icon"><IconifyIcon icon="lucide:plus" /></div>
|
||||
</Popover>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -201,7 +201,7 @@ function recursiveFindParentNode(
|
||||
<div class="toolbar-icon">
|
||||
<IconifyIcon
|
||||
color="#0089ff"
|
||||
icon="ep:circle-close-filled"
|
||||
icon="lucide:circle-x"
|
||||
@click="deleteCondition(index)"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -91,13 +91,13 @@ function deleteNode() {
|
||||
<div class="node-text" v-else>
|
||||
{{ NODE_DEFAULT_TEXT.get(BpmNodeTypeEnum.ROUTER_BRANCH_NODE) }}
|
||||
</div>
|
||||
<IconifyIcon v-if="!readonly" icon="ep:arrow-right-bold" />
|
||||
<IconifyIcon v-if="!readonly" icon="lucide:chevron-right" />
|
||||
</div>
|
||||
<div v-if="!readonly" class="node-toolbar">
|
||||
<div class="toolbar-icon">
|
||||
<IconifyIcon
|
||||
color="#0089ff"
|
||||
icon="ep:circle-close-filled"
|
||||
icon="lucide:circle-x"
|
||||
@click="deleteNode"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -105,7 +105,7 @@ function nodeClick() {
|
||||
<div class="node-text" v-else>
|
||||
{{ NODE_DEFAULT_TEXT.get(BpmNodeTypeEnum.START_USER_NODE) }}
|
||||
</div>
|
||||
<IconifyIcon icon="ep:arrow-right-bold" v-if="!readonly" />
|
||||
<IconifyIcon icon="lucide:chevron-right" v-if="!readonly" />
|
||||
</div>
|
||||
</div>
|
||||
<!-- 传递子节点给添加节点组件。会在子节点前面添加节点 -->
|
||||
|
||||
@@ -93,13 +93,13 @@ function deleteNode() {
|
||||
<div class="node-text" v-else>
|
||||
{{ NODE_DEFAULT_TEXT.get(BpmNodeTypeEnum.TRIGGER_NODE) }}
|
||||
</div>
|
||||
<IconifyIcon v-if="!readonly" icon="ep:arrow-right-bold" />
|
||||
<IconifyIcon v-if="!readonly" icon="lucide:chevron-right" />
|
||||
</div>
|
||||
<div v-if="!readonly" class="node-toolbar">
|
||||
<div class="toolbar-icon">
|
||||
<IconifyIcon
|
||||
color="#0089ff"
|
||||
icon="ep:circle-close-filled"
|
||||
icon="lucide:circle-x"
|
||||
:size="18"
|
||||
@click="deleteNode"
|
||||
/>
|
||||
|
||||
@@ -111,13 +111,13 @@ function findReturnTaskNodes(
|
||||
<div class="node-text" v-else>
|
||||
{{ NODE_DEFAULT_TEXT.get(currentNode.type) }}
|
||||
</div>
|
||||
<IconifyIcon icon="ep:arrow-right-bold" v-if="!readonly" />
|
||||
<IconifyIcon icon="lucide:chevron-right" v-if="!readonly" />
|
||||
</div>
|
||||
<div v-if="!readonly" class="node-toolbar">
|
||||
<div class="toolbar-icon">
|
||||
<IconifyIcon
|
||||
color="#0089ff"
|
||||
icon="ep:circle-close-filled"
|
||||
icon="lucide:circle-x"
|
||||
:size="18"
|
||||
@click="deleteNode"
|
||||
/>
|
||||
|
||||
@@ -97,7 +97,7 @@ const postOptions = ref<SystemPostApi.Post[]>([]); // 岗位列表
|
||||
const userOptions = ref<SystemUserApi.User[]>([]); // 用户列表
|
||||
const deptOptions = ref<SystemDeptApi.Dept[]>([]); // 部门列表
|
||||
const deptTreeOptions = ref();
|
||||
const userGroupOptions = ref<BpmUserGroupApi.UserGroupVO[]>([]); // 用户组列表
|
||||
const userGroupOptions = ref<BpmUserGroupApi.UserGroup[]>([]); // 用户组列表
|
||||
|
||||
provide('formFields', formFields);
|
||||
provide('formType', formType);
|
||||
|
||||
@@ -205,10 +205,10 @@ onMounted(() => {
|
||||
<Row type="flex" justify="end">
|
||||
<ButtonGroup key="scale-control">
|
||||
<Button v-if="!readonly" @click="exportJson">
|
||||
<IconifyIcon icon="ep:download" /> 导出
|
||||
<IconifyIcon icon="lucide:download" /> 导出
|
||||
</Button>
|
||||
<Button v-if="!readonly" @click="importJson">
|
||||
<IconifyIcon icon="ep:upload" />导入
|
||||
<IconifyIcon icon="lucide:upload" />导入
|
||||
</Button>
|
||||
<!-- 用于打开本地文件-->
|
||||
<input
|
||||
@@ -221,14 +221,14 @@ onMounted(() => {
|
||||
@change="importLocalFile"
|
||||
/>
|
||||
<Button @click="processReZoom()">
|
||||
<IconifyIcon icon="tabler:relation-one-to-one" />
|
||||
<IconifyIcon icon="lucide:table-columns-split" />
|
||||
</Button>
|
||||
<Button :plain="true" @click="zoomOut()">
|
||||
<IconifyIcon icon="tabler:zoom-out" />
|
||||
<IconifyIcon icon="lucide:zoom-out" />
|
||||
</Button>
|
||||
<Button class="w-80px"> {{ scaleValue }}% </Button>
|
||||
<Button :plain="true" @click="zoomIn()">
|
||||
<IconifyIcon icon="tabler:zoom-in" />
|
||||
<IconifyIcon icon="lucide:zoom-in" />
|
||||
</Button>
|
||||
<Button @click="resetPosition">重置</Button>
|
||||
</ButtonGroup>
|
||||
|
||||
@@ -260,7 +260,7 @@ export function useNodeForm(nodeType: BpmNodeTypeEnum) {
|
||||
const postOptions = inject<Ref<SystemPostApi.Post[]>>('postList', ref([])); // 岗位列表
|
||||
const userOptions = inject<Ref<SystemUserApi.User[]>>('userList', ref([])); // 用户列表
|
||||
const deptOptions = inject<Ref<SystemDeptApi.Dept[]>>('deptList', ref([])); // 部门列表
|
||||
const userGroupOptions = inject<Ref<BpmUserGroupApi.UserGroupVO[]>>(
|
||||
const userGroupOptions = inject<Ref<BpmUserGroupApi.UserGroup[]>>(
|
||||
'userGroupList',
|
||||
ref([]),
|
||||
); // 用户组列表
|
||||
|
||||
@@ -25,7 +25,10 @@ defineProps<SummaryCardProps>();
|
||||
<div class="flex items-center gap-1">
|
||||
<span class="text-3.5">{{ title }}</span>
|
||||
<Tooltip :content="tooltip" placement="topLeft" v-if="tooltip">
|
||||
<IconifyIcon icon="ep:warning" class="item-center !text-3 flex" />
|
||||
<IconifyIcon
|
||||
icon="lucide:circle-alert"
|
||||
class="item-center !text-3 flex"
|
||||
/>
|
||||
</Tooltip>
|
||||
</div>
|
||||
<div class="flex flex-row items-baseline gap-2">
|
||||
@@ -42,7 +45,9 @@ defineProps<SummaryCardProps>();
|
||||
>
|
||||
<span class="text-sm">{{ Math.abs(Number(percent)) }}%</span>
|
||||
<IconifyIcon
|
||||
:icon="Number(percent) > 0 ? 'ep:caret-top' : 'ep:caret-bottom'"
|
||||
:icon="
|
||||
Number(percent) > 0 ? 'lucide:chevron-up' : 'lucide:chevron-down'
|
||||
"
|
||||
class="!text-3 ml-0.5"
|
||||
/>
|
||||
</span>
|
||||
|
||||
@@ -136,7 +136,7 @@ export function getUploadUrl(): string {
|
||||
* @param file 文件
|
||||
*/
|
||||
function createFile0(
|
||||
vo: InfraFileApi.FilePresignedUrlRespVO,
|
||||
vo: InfraFileApi.FilePresignedUrlResp,
|
||||
file: File,
|
||||
): InfraFileApi.File {
|
||||
const fileVO = {
|
||||
|
||||
@@ -21,10 +21,11 @@ const accessStore = useAccessStore();
|
||||
|
||||
const tenantEnable = isTenantEnable();
|
||||
|
||||
const value = ref<number>(accessStore.visitTenantId ?? undefined); // 当前访问的租户 ID
|
||||
const tenants = ref<SystemTenantApi.Tenant[]>([]); // 租户列表
|
||||
// 当前访问的租户 ID
|
||||
const value = ref<number | undefined>(accessStore.visitTenantId ?? undefined);
|
||||
// 租户列表
|
||||
const tenants = ref<SystemTenantApi.Tenant[]>([]);
|
||||
|
||||
// TODO @xingyu:这个有可能 3 端复用么?
|
||||
async function handleChange(id: SelectValue) {
|
||||
// 设置访问租户 ID
|
||||
accessStore.setVisitTenantId(id as number);
|
||||
|
||||
113
apps/web-antd/src/router/routes/modules/ai.ts
Normal file
113
apps/web-antd/src/router/routes/modules/ai.ts
Normal file
@@ -0,0 +1,113 @@
|
||||
import type { RouteRecordRaw } from 'vue-router';
|
||||
|
||||
const routes: RouteRecordRaw[] = [
|
||||
{
|
||||
path: '/ai',
|
||||
name: 'Ai',
|
||||
meta: {
|
||||
title: 'Ai',
|
||||
hideInMenu: true,
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: 'image/square',
|
||||
component: () => import('#/views/ai/image/square/index.vue'),
|
||||
name: 'AiImageSquare',
|
||||
meta: {
|
||||
noCache: true,
|
||||
hidden: true,
|
||||
canTo: true,
|
||||
title: '绘图作品',
|
||||
activePath: '/ai/image',
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'knowledge/document',
|
||||
component: () => import('#/views/ai/knowledge/document/index.vue'),
|
||||
name: 'AiKnowledgeDocument',
|
||||
meta: {
|
||||
noCache: true,
|
||||
hidden: true,
|
||||
canTo: true,
|
||||
title: '知识库文档',
|
||||
activePath: '/ai/knowledge',
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'knowledge/document/create',
|
||||
component: () => import('#/views/ai/knowledge/document/form/index.vue'),
|
||||
name: 'AiKnowledgeDocumentCreate',
|
||||
meta: {
|
||||
noCache: true,
|
||||
hidden: true,
|
||||
canTo: true,
|
||||
title: '创建文档',
|
||||
activePath: '/ai/knowledge',
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'knowledge/document/update',
|
||||
component: () => import('#/views/ai/knowledge/document/form/index.vue'),
|
||||
name: 'AiKnowledgeDocumentUpdate',
|
||||
meta: {
|
||||
noCache: true,
|
||||
hidden: true,
|
||||
canTo: true,
|
||||
title: '修改文档',
|
||||
activePath: '/ai/knowledge',
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'knowledge/retrieval',
|
||||
component: () =>
|
||||
import('#/views/ai/knowledge/knowledge/retrieval/index.vue'),
|
||||
name: 'AiKnowledgeRetrieval',
|
||||
meta: {
|
||||
noCache: true,
|
||||
hidden: true,
|
||||
canTo: true,
|
||||
title: '文档召回测试',
|
||||
activePath: '/ai/knowledge',
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'knowledge/segment',
|
||||
component: () => import('#/views/ai/knowledge/segment/index.vue'),
|
||||
name: 'AiKnowledgeSegment',
|
||||
meta: {
|
||||
noCache: true,
|
||||
hidden: true,
|
||||
canTo: true,
|
||||
title: '知识库分段',
|
||||
activePath: '/ai/knowledge',
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'console/workflow/create',
|
||||
component: () => import('#/views/ai/workflow/form/index.vue'),
|
||||
name: 'AiWorkflowCreate',
|
||||
meta: {
|
||||
noCache: true,
|
||||
hidden: true,
|
||||
canTo: true,
|
||||
title: '设计 AI 工作流',
|
||||
activePath: '/ai/workflow',
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'console/workflow/:type/:id',
|
||||
component: () => import('#/views/ai/workflow/form/index.vue'),
|
||||
name: 'AiWorkflowUpdate',
|
||||
meta: {
|
||||
noCache: true,
|
||||
hidden: true,
|
||||
canTo: true,
|
||||
title: '设计 AI 工作流',
|
||||
activePath: '/ai/workflow',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
export default routes;
|
||||
@@ -5,6 +5,244 @@
|
||||
* 枚举类
|
||||
*/
|
||||
|
||||
/**
|
||||
* AI 平台的枚举
|
||||
*/
|
||||
export const AiPlatformEnum = {
|
||||
TONG_YI: 'TongYi', // 阿里
|
||||
YI_YAN: 'YiYan', // 百度
|
||||
DEEP_SEEK: 'DeepSeek', // DeepSeek
|
||||
ZHI_PU: 'ZhiPu', // 智谱 AI
|
||||
XING_HUO: 'XingHuo', // 讯飞
|
||||
SiliconFlow: 'SiliconFlow', // 硅基流动
|
||||
OPENAI: 'OpenAI',
|
||||
Ollama: 'Ollama',
|
||||
STABLE_DIFFUSION: 'StableDiffusion', // Stability AI
|
||||
MIDJOURNEY: 'Midjourney', // Midjourney
|
||||
SUNO: 'Suno', // Suno AI
|
||||
};
|
||||
|
||||
export const AiModelTypeEnum = {
|
||||
CHAT: 1, // 聊天
|
||||
IMAGE: 2, // 图像
|
||||
VOICE: 3, // 音频
|
||||
VIDEO: 4, // 视频
|
||||
EMBEDDING: 5, // 向量
|
||||
RERANK: 6, // 重排
|
||||
};
|
||||
export interface ImageModelVO {
|
||||
key: string;
|
||||
name: string;
|
||||
image?: string;
|
||||
}
|
||||
export const OtherPlatformEnum: ImageModelVO[] = [
|
||||
{
|
||||
key: AiPlatformEnum.TONG_YI,
|
||||
name: '通义万相',
|
||||
},
|
||||
{
|
||||
key: AiPlatformEnum.YI_YAN,
|
||||
name: '百度千帆',
|
||||
},
|
||||
{
|
||||
key: AiPlatformEnum.ZHI_PU,
|
||||
name: '智谱 AI',
|
||||
},
|
||||
{
|
||||
key: AiPlatformEnum.SiliconFlow,
|
||||
name: '硅基流动',
|
||||
},
|
||||
];
|
||||
/**
|
||||
* AI 图像生成状态的枚举
|
||||
*/
|
||||
export const AiImageStatusEnum = {
|
||||
IN_PROGRESS: 10, // 进行中
|
||||
SUCCESS: 20, // 已完成
|
||||
FAIL: 30, // 已失败
|
||||
};
|
||||
/**
|
||||
* AI 音乐生成状态的枚举
|
||||
*/
|
||||
export const AiMusicStatusEnum = {
|
||||
IN_PROGRESS: 10, // 进行中
|
||||
SUCCESS: 20, // 已完成
|
||||
FAIL: 30, // 已失败
|
||||
};
|
||||
|
||||
/**
|
||||
* AI 写作类型的枚举
|
||||
*/
|
||||
export enum AiWriteTypeEnum {
|
||||
WRITING = 1, // 撰写
|
||||
REPLY, // 回复
|
||||
}
|
||||
|
||||
// ========== 【图片 UI】相关的枚举 ==========
|
||||
|
||||
export const ImageHotWords = [
|
||||
'中国旗袍',
|
||||
'古装美女',
|
||||
'卡通头像',
|
||||
'机甲战士',
|
||||
'童话小屋',
|
||||
'中国长城',
|
||||
]; // 图片热词
|
||||
|
||||
export const ImageHotEnglishWords = [
|
||||
'Chinese Cheongsam',
|
||||
'Ancient Beauty',
|
||||
'Cartoon Avatar',
|
||||
'Mech Warrior',
|
||||
'Fairy Tale Cottage',
|
||||
'The Great Wall of China',
|
||||
]; // 图片热词(英文)
|
||||
|
||||
export const StableDiffusionSamplers: ImageModelVO[] = [
|
||||
{
|
||||
key: 'DDIM',
|
||||
name: 'DDIM',
|
||||
},
|
||||
{
|
||||
key: 'DDPM',
|
||||
name: 'DDPM',
|
||||
},
|
||||
{
|
||||
key: 'K_DPMPP_2M',
|
||||
name: 'K_DPMPP_2M',
|
||||
},
|
||||
{
|
||||
key: 'K_DPMPP_2S_ANCESTRAL',
|
||||
name: 'K_DPMPP_2S_ANCESTRAL',
|
||||
},
|
||||
{
|
||||
key: 'K_DPM_2',
|
||||
name: 'K_DPM_2',
|
||||
},
|
||||
{
|
||||
key: 'K_DPM_2_ANCESTRAL',
|
||||
name: 'K_DPM_2_ANCESTRAL',
|
||||
},
|
||||
{
|
||||
key: 'K_EULER',
|
||||
name: 'K_EULER',
|
||||
},
|
||||
{
|
||||
key: 'K_EULER_ANCESTRAL',
|
||||
name: 'K_EULER_ANCESTRAL',
|
||||
},
|
||||
{
|
||||
key: 'K_HEUN',
|
||||
name: 'K_HEUN',
|
||||
},
|
||||
{
|
||||
key: 'K_LMS',
|
||||
name: 'K_LMS',
|
||||
},
|
||||
];
|
||||
|
||||
export const StableDiffusionStylePresets: ImageModelVO[] = [
|
||||
{
|
||||
key: '3d-model',
|
||||
name: '3d-model',
|
||||
},
|
||||
{
|
||||
key: 'analog-film',
|
||||
name: 'analog-film',
|
||||
},
|
||||
{
|
||||
key: 'anime',
|
||||
name: 'anime',
|
||||
},
|
||||
{
|
||||
key: 'cinematic',
|
||||
name: 'cinematic',
|
||||
},
|
||||
{
|
||||
key: 'comic-book',
|
||||
name: 'comic-book',
|
||||
},
|
||||
{
|
||||
key: 'digital-art',
|
||||
name: 'digital-art',
|
||||
},
|
||||
{
|
||||
key: 'enhance',
|
||||
name: 'enhance',
|
||||
},
|
||||
{
|
||||
key: 'fantasy-art',
|
||||
name: 'fantasy-art',
|
||||
},
|
||||
{
|
||||
key: 'isometric',
|
||||
name: 'isometric',
|
||||
},
|
||||
{
|
||||
key: 'line-art',
|
||||
name: 'line-art',
|
||||
},
|
||||
{
|
||||
key: 'low-poly',
|
||||
name: 'low-poly',
|
||||
},
|
||||
{
|
||||
key: 'modeling-compound',
|
||||
name: 'modeling-compound',
|
||||
},
|
||||
// neon-punk origami photographic pixel-art tile-texture
|
||||
{
|
||||
key: 'neon-punk',
|
||||
name: 'neon-punk',
|
||||
},
|
||||
{
|
||||
key: 'origami',
|
||||
name: 'origami',
|
||||
},
|
||||
{
|
||||
key: 'photographic',
|
||||
name: 'photographic',
|
||||
},
|
||||
{
|
||||
key: 'pixel-art',
|
||||
name: 'pixel-art',
|
||||
},
|
||||
{
|
||||
key: 'tile-texture',
|
||||
name: 'tile-texture',
|
||||
},
|
||||
];
|
||||
|
||||
export const StableDiffusionClipGuidancePresets: ImageModelVO[] = [
|
||||
{
|
||||
key: 'NONE',
|
||||
name: 'NONE',
|
||||
},
|
||||
{
|
||||
key: 'FAST_BLUE',
|
||||
name: 'FAST_BLUE',
|
||||
},
|
||||
{
|
||||
key: 'FAST_GREEN',
|
||||
name: 'FAST_GREEN',
|
||||
},
|
||||
{
|
||||
key: 'SIMPLE',
|
||||
name: 'SIMPLE',
|
||||
},
|
||||
{
|
||||
key: 'SLOW',
|
||||
name: 'SLOW',
|
||||
},
|
||||
{
|
||||
key: 'SLOWER',
|
||||
name: 'SLOWER',
|
||||
},
|
||||
{
|
||||
key: 'SLOWEST',
|
||||
name: 'SLOWEST',
|
||||
},
|
||||
];
|
||||
// ========== COMMON 模块 ==========
|
||||
// 全局通用状态枚举
|
||||
export const CommonStatusEnum = {
|
||||
@@ -92,7 +330,136 @@ export const InfraApiErrorLogProcessStatusEnum = {
|
||||
DONE: 1, // 已处理
|
||||
IGNORE: 2, // 已忽略
|
||||
};
|
||||
export interface ImageSizeVO {
|
||||
key: string;
|
||||
name?: string;
|
||||
style: string;
|
||||
width: string;
|
||||
height: string;
|
||||
}
|
||||
export const Dall3SizeList: ImageSizeVO[] = [
|
||||
{
|
||||
key: '1024x1024',
|
||||
name: '1:1',
|
||||
width: '1024',
|
||||
height: '1024',
|
||||
style: 'width: 30px; height: 30px;background-color: #dcdcdc;',
|
||||
},
|
||||
{
|
||||
key: '1024x1792',
|
||||
name: '3:5',
|
||||
width: '1024',
|
||||
height: '1792',
|
||||
style: 'width: 30px; height: 50px;background-color: #dcdcdc;',
|
||||
},
|
||||
{
|
||||
key: '1792x1024',
|
||||
name: '5:3',
|
||||
width: '1792',
|
||||
height: '1024',
|
||||
style: 'width: 50px; height: 30px;background-color: #dcdcdc;',
|
||||
},
|
||||
];
|
||||
|
||||
export const Dall3Models: ImageModelVO[] = [
|
||||
{
|
||||
key: 'dall-e-3',
|
||||
name: 'DALL·E 3',
|
||||
image: `/static/imgs/ai/dall2.jpg`,
|
||||
},
|
||||
{
|
||||
key: 'dall-e-2',
|
||||
name: 'DALL·E 2',
|
||||
image: `/static/imgs/ai/dall3.jpg`,
|
||||
},
|
||||
];
|
||||
|
||||
export const Dall3StyleList: ImageModelVO[] = [
|
||||
{
|
||||
key: 'vivid',
|
||||
name: '清晰',
|
||||
image: `/static/imgs/ai/qingxi.jpg`,
|
||||
},
|
||||
{
|
||||
key: 'natural',
|
||||
name: '自然',
|
||||
image: `/static/imgs/ai/ziran.jpg`,
|
||||
},
|
||||
];
|
||||
export const MidjourneyModels: ImageModelVO[] = [
|
||||
{
|
||||
key: 'midjourney',
|
||||
name: 'MJ',
|
||||
image: 'https://bigpt8.com/pc/_nuxt/mj.34a61377.png',
|
||||
},
|
||||
{
|
||||
key: 'niji',
|
||||
name: 'NIJI',
|
||||
image: 'https://bigpt8.com/pc/_nuxt/nj.ca79b143.png',
|
||||
},
|
||||
];
|
||||
export const MidjourneyVersions = [
|
||||
{
|
||||
value: '6.0',
|
||||
label: 'v6.0',
|
||||
},
|
||||
{
|
||||
value: '5.2',
|
||||
label: 'v5.2',
|
||||
},
|
||||
{
|
||||
value: '5.1',
|
||||
label: 'v5.1',
|
||||
},
|
||||
{
|
||||
value: '5.0',
|
||||
label: 'v5.0',
|
||||
},
|
||||
{
|
||||
value: '4.0',
|
||||
label: 'v4.0',
|
||||
},
|
||||
];
|
||||
|
||||
export const NijiVersionList = [
|
||||
{
|
||||
value: '5',
|
||||
label: 'v5',
|
||||
},
|
||||
];
|
||||
|
||||
export const MidjourneySizeList: ImageSizeVO[] = [
|
||||
{
|
||||
key: '1:1',
|
||||
width: '1',
|
||||
height: '1',
|
||||
style: 'width: 30px; height: 30px;background-color: #dcdcdc;',
|
||||
},
|
||||
{
|
||||
key: '3:4',
|
||||
width: '3',
|
||||
height: '4',
|
||||
style: 'width: 30px; height: 40px;background-color: #dcdcdc;',
|
||||
},
|
||||
{
|
||||
key: '4:3',
|
||||
width: '4',
|
||||
height: '3',
|
||||
style: 'width: 40px; height: 30px;background-color: #dcdcdc;',
|
||||
},
|
||||
{
|
||||
key: '9:16',
|
||||
width: '9',
|
||||
height: '16',
|
||||
style: 'width: 30px; height: 50px;background-color: #dcdcdc;',
|
||||
},
|
||||
{
|
||||
key: '16:9',
|
||||
width: '16',
|
||||
height: '9',
|
||||
style: 'width: 50px; height: 30px;background-color: #dcdcdc;',
|
||||
},
|
||||
];
|
||||
// ========== PAY 模块 ==========
|
||||
/**
|
||||
* 支付渠道枚举
|
||||
@@ -743,3 +1110,81 @@ export enum ProcessVariableEnum {
|
||||
*/
|
||||
START_USER_ID = 'PROCESS_START_USER_ID',
|
||||
}
|
||||
// ========== 【写作 UI】相关的枚举 ==========
|
||||
|
||||
/** 写作点击示例时的数据 */
|
||||
export const WriteExample = {
|
||||
write: {
|
||||
prompt: 'vue',
|
||||
data: 'Vue.js 是一种用于构建用户界面的渐进式 JavaScript 框架。它的核心库只关注视图层,易于上手,同时也便于与其他库或已有项目整合。\n\nVue.js 的特点包括:\n- 响应式的数据绑定:Vue.js 会自动将数据与 DOM 同步,使得状态管理变得更加简单。\n- 组件化:Vue.js 允许开发者通过小型、独立和通常可复用的组件构建大型应用。\n- 虚拟 DOM:Vue.js 使用虚拟 DOM 实现快速渲染,提高了性能。\n\n在 Vue.js 中,一个典型的应用结构可能包括:\n1. 根实例:每个 Vue 应用都需要一个根实例作为入口点。\n2. 组件系统:可以创建自定义的可复用组件。\n3. 指令:特殊的带有前缀 v- 的属性,为 DOM 元素提供特殊的行为。\n4. 插值:用于文本内容,将数据动态地插入到 HTML。\n5. 计算属性和侦听器:用于处理数据的复杂逻辑和响应数据变化。\n6. 条件渲染:根据条件决定元素的渲染。\n7. 列表渲染:用于显示列表数据。\n8. 事件处理:响应用户交互。\n9. 表单输入绑定:处理表单输入和验证。\n10. 组件生命周期钩子:在组件的不同阶段执行特定的函数。\n\nVue.js 还提供了官方的路由器 Vue Router 和状态管理库 Vuex,以支持构建复杂的单页应用(SPA)。\n\n在开发过程中,开发者通常会使用 Vue CLI,这是一个强大的命令行工具,用于快速生成 Vue 项目脚手架,集成了诸如 Babel、Webpack 等现代前端工具,以及热重载、代码检测等开发体验优化功能。\n\nVue.js 的生态系统还包括大量的第三方库和插件,如 Vuetify(UI 组件库)、Vue Test Utils(测试工具)等,这些都极大地丰富了 Vue.js 的开发生态。\n\n总的来说,Vue.js 是一个灵活、高效的前端框架,适合从小型项目到大型企业级应用的开发。它的易用性、灵活性和强大的社区支持使其成为许多开发者的首选框架之一。',
|
||||
},
|
||||
reply: {
|
||||
originalContent: '领导,我想请假',
|
||||
prompt: '不批',
|
||||
data: '您的请假申请已收悉,经核实和考虑,暂时无法批准您的请假申请。\n\n如有特殊情况或紧急事务,请及时与我联系。\n\n祝工作顺利。\n\n谢谢。',
|
||||
},
|
||||
};
|
||||
|
||||
// ========== 【思维导图 UI】相关的枚举 ==========
|
||||
|
||||
/** 思维导图已有内容生成示例 */
|
||||
export const MindMapContentExample = `# Java 技术栈
|
||||
|
||||
## 核心技术
|
||||
### Java SE
|
||||
### Java EE
|
||||
|
||||
## 框架
|
||||
### Spring
|
||||
#### Spring Boot
|
||||
#### Spring MVC
|
||||
#### Spring Data
|
||||
### Hibernate
|
||||
### MyBatis
|
||||
|
||||
## 构建工具
|
||||
### Maven
|
||||
### Gradle
|
||||
|
||||
## 版本控制
|
||||
### Git
|
||||
### SVN
|
||||
|
||||
## 测试工具
|
||||
### JUnit
|
||||
### Mockito
|
||||
### Selenium
|
||||
|
||||
## 应用服务器
|
||||
### Tomcat
|
||||
### Jetty
|
||||
### WildFly
|
||||
|
||||
## 数据库
|
||||
### MySQL
|
||||
### PostgreSQL
|
||||
### Oracle
|
||||
### MongoDB
|
||||
|
||||
## 消息队列
|
||||
### Kafka
|
||||
### RabbitMQ
|
||||
### ActiveMQ
|
||||
|
||||
## 微服务
|
||||
### Spring Cloud
|
||||
### Dubbo
|
||||
|
||||
## 容器化
|
||||
### Docker
|
||||
### Kubernetes
|
||||
|
||||
## 云服务
|
||||
### AWS
|
||||
### Azure
|
||||
### Google Cloud
|
||||
|
||||
## 开发工具
|
||||
### IntelliJ IDEA
|
||||
### Eclipse
|
||||
### Visual Studio Code`;
|
||||
|
||||
@@ -143,10 +143,10 @@ export const getBoolDictOptions = (dictType: string) => {
|
||||
enum DICT_TYPE {
|
||||
AI_GENERATE_MODE = 'ai_generate_mode', // AI 生成模式
|
||||
AI_IMAGE_STATUS = 'ai_image_status', // AI 图片状态
|
||||
AI_MODEL_TYPE = 'ai_model_type', // AI 模型类型
|
||||
AI_MUSIC_STATUS = 'ai_music_status', // AI 音乐状态
|
||||
// ========== AI - 人工智能模块 ==========
|
||||
AI_PLATFORM = 'ai_platform', // AI 平台
|
||||
|
||||
AI_WRITE_FORMAT = 'ai_write_format', // AI 写作格式
|
||||
AI_WRITE_LANGUAGE = 'ai_write_language', // AI 写作语言
|
||||
AI_WRITE_LENGTH = 'ai_write_length', // AI 写作长度
|
||||
|
||||
@@ -1,215 +0,0 @@
|
||||
/**
|
||||
* 下载工具模块
|
||||
* 提供多种文件格式的下载功能
|
||||
*/
|
||||
// TODO @ziye:请使用 @vben/utils/download 代替 packages/@core/base/shared/src/utils/download.ts
|
||||
|
||||
/**
|
||||
* 图片下载配置接口
|
||||
*/
|
||||
interface ImageDownloadOptions {
|
||||
/** 图片 URL */
|
||||
url: string;
|
||||
/** 指定画布宽度 */
|
||||
canvasWidth?: number;
|
||||
/** 指定画布高度 */
|
||||
canvasHeight?: number;
|
||||
/** 将图片绘制在画布上时带上图片的宽高值,默认为 true */
|
||||
drawWithImageSize?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* 基础文件下载函数
|
||||
* @param data - 文件数据 Blob
|
||||
* @param fileName - 文件名
|
||||
* @param mimeType - MIME 类型
|
||||
*/
|
||||
export const download0 = (data: Blob, fileName: string, mimeType: string) => {
|
||||
try {
|
||||
// 创建 blob
|
||||
const blob = new Blob([data], { type: mimeType });
|
||||
// 创建 href 超链接,点击进行下载
|
||||
window.URL = window.URL || window.webkitURL;
|
||||
const href = URL.createObjectURL(blob);
|
||||
const downA = document.createElement('a');
|
||||
downA.href = href;
|
||||
downA.download = fileName;
|
||||
downA.click();
|
||||
// 销毁超链接
|
||||
window.URL.revokeObjectURL(href);
|
||||
} catch (error) {
|
||||
console.error('文件下载失败:', error);
|
||||
throw new Error(
|
||||
`文件下载失败: ${error instanceof Error ? error.message : '未知错误'}`,
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 触发文件下载的通用方法
|
||||
* @param url - 下载链接
|
||||
* @param fileName - 文件名
|
||||
*/
|
||||
const triggerDownload = (url: string, fileName: string) => {
|
||||
const a = document.createElement('a');
|
||||
a.href = url;
|
||||
a.download = fileName;
|
||||
a.click();
|
||||
};
|
||||
|
||||
export const download = {
|
||||
/**
|
||||
* 下载 Excel 文件
|
||||
* @param data - 文件数据 Blob
|
||||
* @param fileName - 文件名
|
||||
*/
|
||||
excel: (data: Blob, fileName: string) => {
|
||||
download0(data, fileName, 'application/vnd.ms-excel');
|
||||
},
|
||||
|
||||
/**
|
||||
* 下载 Word 文件
|
||||
* @param data - 文件数据 Blob
|
||||
* @param fileName - 文件名
|
||||
*/
|
||||
word: (data: Blob, fileName: string) => {
|
||||
download0(data, fileName, 'application/msword');
|
||||
},
|
||||
|
||||
/**
|
||||
* 下载 Zip 文件
|
||||
* @param data - 文件数据 Blob
|
||||
* @param fileName - 文件名
|
||||
*/
|
||||
zip: (data: Blob, fileName: string) => {
|
||||
download0(data, fileName, 'application/zip');
|
||||
},
|
||||
|
||||
/**
|
||||
* 下载 HTML 文件
|
||||
* @param data - 文件数据 Blob
|
||||
* @param fileName - 文件名
|
||||
*/
|
||||
html: (data: Blob, fileName: string) => {
|
||||
download0(data, fileName, 'text/html');
|
||||
},
|
||||
|
||||
/**
|
||||
* 下载 Markdown 文件
|
||||
* @param data - 文件数据 Blob
|
||||
* @param fileName - 文件名
|
||||
*/
|
||||
markdown: (data: Blob, fileName: string) => {
|
||||
download0(data, fileName, 'text/markdown');
|
||||
},
|
||||
|
||||
/**
|
||||
* 下载 JSON 文件
|
||||
* @param data - 文件数据 Blob
|
||||
* @param fileName - 文件名
|
||||
*/
|
||||
json: (data: Blob, fileName: string) => {
|
||||
download0(data, fileName, 'application/json');
|
||||
},
|
||||
|
||||
/**
|
||||
* 下载图片(允许跨域)
|
||||
* @param options - 图片下载配置
|
||||
*/
|
||||
image: (options: ImageDownloadOptions) => {
|
||||
const {
|
||||
url,
|
||||
canvasWidth,
|
||||
canvasHeight,
|
||||
drawWithImageSize = true,
|
||||
} = options;
|
||||
|
||||
const image = new Image();
|
||||
// image.setAttribute('crossOrigin', 'anonymous')
|
||||
image.src = url;
|
||||
image.addEventListener('load', () => {
|
||||
try {
|
||||
const canvas = document.createElement('canvas');
|
||||
canvas.width = canvasWidth || image.width;
|
||||
canvas.height = canvasHeight || image.height;
|
||||
const ctx = canvas.getContext('2d') as CanvasRenderingContext2D;
|
||||
ctx?.clearRect(0, 0, canvas.width, canvas.height);
|
||||
|
||||
if (drawWithImageSize) {
|
||||
ctx.drawImage(image, 0, 0, image.width, image.height);
|
||||
} else {
|
||||
ctx.drawImage(image, 0, 0);
|
||||
}
|
||||
|
||||
const dataUrl = canvas.toDataURL('image/png');
|
||||
triggerDownload(dataUrl, 'image.png');
|
||||
} catch (error) {
|
||||
console.error('图片下载失败:', error);
|
||||
throw new Error(
|
||||
`图片下载失败: ${error instanceof Error ? error.message : '未知错误'}`,
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
image.addEventListener('error', () => {
|
||||
throw new Error('图片加载失败');
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* 将 Base64 字符串转换为文件对象
|
||||
* @param base64 - Base64 字符串
|
||||
* @param fileName - 文件名
|
||||
* @returns File 对象
|
||||
*/
|
||||
base64ToFile: (base64: string, fileName: string): File => {
|
||||
// 输入验证
|
||||
if (!base64 || typeof base64 !== 'string') {
|
||||
throw new Error('base64 参数必须是非空字符串');
|
||||
}
|
||||
|
||||
// 将 base64 按照逗号进行分割,将前缀与后续内容分隔开
|
||||
const data = base64.split(',');
|
||||
if (data.length !== 2 || !data[0] || !data[1]) {
|
||||
throw new Error('无效的 base64 格式');
|
||||
}
|
||||
|
||||
// 利用正则表达式从前缀中获取类型信息(image/png、image/jpeg、image/webp等)
|
||||
const typeMatch = data[0].match(/:(.*?);/);
|
||||
if (!typeMatch || !typeMatch[1]) {
|
||||
throw new Error('无法解析 base64 类型信息');
|
||||
}
|
||||
const type = typeMatch[1];
|
||||
|
||||
// 从类型信息中获取具体的文件格式后缀(png、jpeg、webp)
|
||||
const typeParts = type.split('/');
|
||||
if (typeParts.length !== 2 || !typeParts[1]) {
|
||||
throw new Error('无效的 MIME 类型格式');
|
||||
}
|
||||
const suffix = typeParts[1];
|
||||
|
||||
try {
|
||||
// 使用 atob() 对 base64 数据进行解码,结果是一个文件数据流以字符串的格式输出
|
||||
const bstr = window.atob(data[1]);
|
||||
|
||||
// 获取解码结果字符串的长度
|
||||
const n = bstr.length;
|
||||
// 根据解码结果字符串的长度创建一个等长的整型数字数组
|
||||
const u8arr = new Uint8Array(n);
|
||||
|
||||
// 优化的 Uint8Array 填充逻辑
|
||||
for (let i = 0; i < n; i++) {
|
||||
// 使用 charCodeAt() 获取字符对应的字节值(Base64 解码后的字符串是字节级别的)
|
||||
// eslint-disable-next-line unicorn/prefer-code-point
|
||||
u8arr[i] = bstr.charCodeAt(i);
|
||||
}
|
||||
|
||||
// 返回 File 文件对象
|
||||
return new File([u8arr], `${fileName}.${suffix}`, { type });
|
||||
} catch (error) {
|
||||
throw new Error(
|
||||
`Base64 解码失败: ${error instanceof Error ? error.message : '未知错误'}`,
|
||||
);
|
||||
}
|
||||
},
|
||||
};
|
||||
@@ -1,6 +1,5 @@
|
||||
export * from './constants';
|
||||
export * from './dict';
|
||||
export * from './download';
|
||||
export * from './formCreate';
|
||||
export * from './rangePickerProps';
|
||||
export * from './routerHelper';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { defineAsyncComponent } from 'vue';
|
||||
|
||||
const modules = import.meta.glob('../views/**/*.{vue,tsx}');
|
||||
// TODO @xingyu:这个要不要融合到哪个 router util 里? utils 里面没有引入 vue 使用不了 defineAsyncComponent
|
||||
|
||||
/**
|
||||
* 注册一个异步组件
|
||||
* @param componentPath 例:/bpm/oa/leave/detail
|
||||
|
||||
@@ -19,7 +19,7 @@ const authStore = useAuthStore();
|
||||
const activeName = ref('basicInfo');
|
||||
|
||||
/** 加载个人信息 */
|
||||
const profile = ref<SystemUserProfileApi.UserProfileRespVO>();
|
||||
const profile = ref<SystemUserProfileApi.UserProfileResp>();
|
||||
async function loadProfile() {
|
||||
profile.value = await getUserProfile();
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ import { updateUserProfile } from '#/api/system/user/profile';
|
||||
import { DICT_TYPE, getDictOptions } from '#/utils';
|
||||
|
||||
const props = defineProps<{
|
||||
profile?: SystemUserProfileApi.UserProfileRespVO;
|
||||
profile?: SystemUserProfileApi.UserProfileResp;
|
||||
}>();
|
||||
const emit = defineEmits<{
|
||||
(e: 'success'): void;
|
||||
@@ -77,7 +77,7 @@ async function handleSubmit(values: Recordable<any>) {
|
||||
try {
|
||||
formApi.setLoading(true);
|
||||
// 提交表单
|
||||
await updateUserProfile(values as SystemUserProfileApi.UpdateProfileReqVO);
|
||||
await updateUserProfile(values as SystemUserProfileApi.UpdateProfileReq);
|
||||
// 关闭并提示
|
||||
emit('success');
|
||||
message.success($t('ui.actionMessage.operationSuccess'));
|
||||
|
||||
@@ -14,7 +14,7 @@ import { CropperAvatar } from '#/components/cropper';
|
||||
import { useUpload } from '#/components/upload/use-upload';
|
||||
|
||||
const props = defineProps<{
|
||||
profile?: SystemUserProfileApi.UserProfileRespVO;
|
||||
profile?: SystemUserProfileApi.UserProfileResp;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
|
||||
@@ -0,0 +1,445 @@
|
||||
<script setup lang="ts">
|
||||
import type { PropType } from 'vue';
|
||||
|
||||
import type { AiChatConversationApi } from '#/api/ai/chat/conversation';
|
||||
|
||||
import { h, onMounted, ref, toRefs, watch } from 'vue';
|
||||
|
||||
import { confirm, prompt, useVbenDrawer } from '@vben/common-ui';
|
||||
import { IconifyIcon } from '@vben/icons';
|
||||
|
||||
import { Button, Empty, Input, Layout, message } from 'ant-design-vue';
|
||||
|
||||
import {
|
||||
createChatConversationMy,
|
||||
deleteChatConversationMy,
|
||||
deleteChatConversationMyByUnpinned,
|
||||
getChatConversationMyList,
|
||||
updateChatConversationMy,
|
||||
} from '#/api/ai/chat/conversation';
|
||||
|
||||
import RoleRepository from '../role/RoleRepository.vue';
|
||||
|
||||
// 加载中定时器
|
||||
// 定义组件 props
|
||||
const props = defineProps({
|
||||
activeId: {
|
||||
type: [Number, null] as PropType<null | number>,
|
||||
default: null,
|
||||
},
|
||||
});
|
||||
|
||||
// 定义钩子
|
||||
const emits = defineEmits([
|
||||
'onConversationCreate',
|
||||
'onConversationClick',
|
||||
'onConversationClear',
|
||||
'onConversationDelete',
|
||||
]);
|
||||
|
||||
const [Drawer, drawerApi] = useVbenDrawer({
|
||||
connectedComponent: RoleRepository,
|
||||
});
|
||||
|
||||
// 定义属性
|
||||
const searchName = ref<string>(''); // 对话搜索
|
||||
const activeConversationId = ref<null | number>(null); // 选中的对话,默认为 null
|
||||
const hoverConversationId = ref<null | number>(null); // 悬浮上去的对话
|
||||
const conversationList = ref([] as AiChatConversationApi.ChatConversationVO[]); // 对话列表
|
||||
const conversationMap = ref<any>({}); // 对话分组 (置顶、今天、三天前、一星期前、一个月前)
|
||||
const loading = ref<boolean>(false); // 加载中
|
||||
const loadingTime = ref<any>();
|
||||
|
||||
/** 搜索对话 */
|
||||
async function searchConversation() {
|
||||
// 恢复数据
|
||||
if (searchName.value.trim().length === 0) {
|
||||
conversationMap.value = await getConversationGroupByCreateTime(
|
||||
conversationList.value,
|
||||
);
|
||||
} else {
|
||||
// 过滤
|
||||
const filterValues = conversationList.value.filter((item) => {
|
||||
return item.title.includes(searchName.value.trim());
|
||||
});
|
||||
conversationMap.value =
|
||||
await getConversationGroupByCreateTime(filterValues);
|
||||
}
|
||||
}
|
||||
|
||||
/** 点击对话 */
|
||||
async function handleConversationClick(id: number) {
|
||||
// 过滤出选中的对话
|
||||
const filterConversation = conversationList.value.find((item) => {
|
||||
return item.id === id;
|
||||
});
|
||||
// 回调 onConversationClick
|
||||
// noinspection JSVoidFunctionReturnValueUsed
|
||||
const success = emits('onConversationClick', filterConversation) as any;
|
||||
// 切换对话
|
||||
if (success) {
|
||||
activeConversationId.value = id;
|
||||
}
|
||||
}
|
||||
|
||||
/** 获取对话列表 */
|
||||
async function getChatConversationList() {
|
||||
try {
|
||||
// 加载中
|
||||
loadingTime.value = setTimeout(() => {
|
||||
loading.value = true;
|
||||
}, 50);
|
||||
|
||||
// 1.1 获取 对话数据
|
||||
conversationList.value = await getChatConversationMyList();
|
||||
// 1.2 排序
|
||||
conversationList.value.sort((a, b) => {
|
||||
return Number(b.createTime) - Number(a.createTime);
|
||||
});
|
||||
// 1.3 没有任何对话情况
|
||||
if (conversationList.value.length === 0) {
|
||||
activeConversationId.value = null;
|
||||
conversationMap.value = {};
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. 对话根据时间分组(置顶、今天、一天前、三天前、七天前、30 天前)
|
||||
conversationMap.value = await getConversationGroupByCreateTime(
|
||||
conversationList.value,
|
||||
);
|
||||
} finally {
|
||||
// 清理定时器
|
||||
if (loadingTime.value) {
|
||||
clearTimeout(loadingTime.value);
|
||||
}
|
||||
// 加载完成
|
||||
loading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
/** 按照 creteTime 创建时间,进行分组 */
|
||||
async function getConversationGroupByCreateTime(
|
||||
list: AiChatConversationApi.ChatConversationVO[],
|
||||
) {
|
||||
// 排序、指定、时间分组(今天、一天前、三天前、七天前、30天前)
|
||||
// noinspection NonAsciiCharacters
|
||||
const groupMap: any = {
|
||||
置顶: [],
|
||||
今天: [],
|
||||
一天前: [],
|
||||
三天前: [],
|
||||
七天前: [],
|
||||
三十天前: [],
|
||||
};
|
||||
// 当前时间的时间戳
|
||||
const now = Date.now();
|
||||
// 定义时间间隔常量(单位:毫秒)
|
||||
const oneDay = 24 * 60 * 60 * 1000;
|
||||
const threeDays = 3 * oneDay;
|
||||
const sevenDays = 7 * oneDay;
|
||||
const thirtyDays = 30 * oneDay;
|
||||
for (const conversation of list) {
|
||||
// 置顶
|
||||
if (conversation.pinned) {
|
||||
groupMap['置顶'].push(conversation);
|
||||
continue;
|
||||
}
|
||||
// 计算时间差(单位:毫秒)
|
||||
const diff = now - Number(conversation.createTime);
|
||||
// 根据时间间隔判断
|
||||
if (diff < oneDay) {
|
||||
groupMap['今天'].push(conversation);
|
||||
} else if (diff < threeDays) {
|
||||
groupMap['一天前'].push(conversation);
|
||||
} else if (diff < sevenDays) {
|
||||
groupMap['三天前'].push(conversation);
|
||||
} else if (diff < thirtyDays) {
|
||||
groupMap['七天前'].push(conversation);
|
||||
} else {
|
||||
groupMap['三十天前'].push(conversation);
|
||||
}
|
||||
}
|
||||
return groupMap;
|
||||
}
|
||||
|
||||
async function createConversation() {
|
||||
// 1. 新建对话
|
||||
const conversationId = await createChatConversationMy(
|
||||
{} as unknown as AiChatConversationApi.ChatConversationVO,
|
||||
);
|
||||
// 2. 获取对话内容
|
||||
await getChatConversationList();
|
||||
// 3. 选中对话
|
||||
await handleConversationClick(conversationId);
|
||||
// 4. 回调
|
||||
emits('onConversationCreate');
|
||||
}
|
||||
|
||||
/** 修改对话的标题 */
|
||||
async function updateConversationTitle(
|
||||
conversation: AiChatConversationApi.ChatConversationVO,
|
||||
) {
|
||||
// 1. 二次确认
|
||||
prompt({
|
||||
async beforeClose(scope) {
|
||||
if (scope.isConfirm) {
|
||||
if (scope.value) {
|
||||
try {
|
||||
// 2. 发起修改
|
||||
await updateChatConversationMy({
|
||||
id: conversation.id,
|
||||
title: scope.value,
|
||||
} as AiChatConversationApi.ChatConversationVO);
|
||||
message.success('重命名成功');
|
||||
// 3. 刷新列表
|
||||
await getChatConversationList();
|
||||
// 4. 过滤当前切换的
|
||||
const filterConversationList = conversationList.value.filter(
|
||||
(item) => {
|
||||
return item.id === conversation.id;
|
||||
},
|
||||
);
|
||||
if (
|
||||
filterConversationList.length > 0 &&
|
||||
filterConversationList[0] && // tip:避免切换对话
|
||||
activeConversationId.value === filterConversationList[0].id
|
||||
) {
|
||||
emits('onConversationClick', filterConversationList[0]);
|
||||
}
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
message.error('请输入标题');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
},
|
||||
component: () => {
|
||||
return h(Input, {
|
||||
placeholder: '请输入标题',
|
||||
allowClear: true,
|
||||
defaultValue: conversation.title,
|
||||
rules: [{ required: true, message: '请输入标题' }],
|
||||
});
|
||||
},
|
||||
content: '请输入标题',
|
||||
title: '修改标题',
|
||||
modelPropName: 'value',
|
||||
});
|
||||
}
|
||||
|
||||
/** 删除聊天对话 */
|
||||
async function deleteChatConversation(
|
||||
conversation: AiChatConversationApi.ChatConversationVO,
|
||||
) {
|
||||
try {
|
||||
// 删除的二次确认
|
||||
await confirm(`是否确认删除对话 - ${conversation.title}?`);
|
||||
// 发起删除
|
||||
await deleteChatConversationMy(conversation.id);
|
||||
message.success('对话已删除');
|
||||
// 刷新列表
|
||||
await getChatConversationList();
|
||||
// 回调
|
||||
emits('onConversationDelete', conversation);
|
||||
} catch {}
|
||||
}
|
||||
|
||||
async function handleClearConversation() {
|
||||
try {
|
||||
await confirm('确认后对话会全部清空,置顶的对话除外。');
|
||||
await deleteChatConversationMyByUnpinned();
|
||||
message.success('操作成功!');
|
||||
// 清空 对话 和 对话内容
|
||||
activeConversationId.value = null;
|
||||
// 获取 对话列表
|
||||
await getChatConversationList();
|
||||
// 回调 方法
|
||||
emits('onConversationClear');
|
||||
} catch {}
|
||||
}
|
||||
|
||||
/** 对话置顶 */
|
||||
async function handleTop(
|
||||
conversation: AiChatConversationApi.ChatConversationVO,
|
||||
) {
|
||||
// 更新对话置顶
|
||||
conversation.pinned = !conversation.pinned;
|
||||
await updateChatConversationMy(conversation);
|
||||
// 刷新对话
|
||||
await getChatConversationList();
|
||||
}
|
||||
|
||||
// ============ 角色仓库 ============
|
||||
|
||||
/** 角色仓库抽屉 */
|
||||
const handleRoleRepository = async () => {
|
||||
drawerApi.open();
|
||||
};
|
||||
|
||||
/** 监听选中的对话 */
|
||||
const { activeId } = toRefs(props);
|
||||
watch(activeId, async (newValue) => {
|
||||
activeConversationId.value = newValue;
|
||||
});
|
||||
|
||||
// 定义 public 方法
|
||||
defineExpose({ createConversation });
|
||||
|
||||
/** 初始化 */
|
||||
onMounted(async () => {
|
||||
// 获取 对话列表
|
||||
await getChatConversationList();
|
||||
// 默认选中
|
||||
if (props.activeId) {
|
||||
activeConversationId.value = props.activeId;
|
||||
} else {
|
||||
// 首次默认选中第一个
|
||||
if (conversationList.value.length > 0 && conversationList.value[0]) {
|
||||
activeConversationId.value = conversationList.value[0].id;
|
||||
// 回调 onConversationClick
|
||||
await emits('onConversationClick', conversationList.value[0]);
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Layout.Sider
|
||||
width="260px"
|
||||
class="conversation-container relative flex h-full flex-col justify-between overflow-hidden bg-[hsl(var(--primary-foreground))!important] p-[10px_10px_0]"
|
||||
>
|
||||
<Drawer />
|
||||
<!-- 左顶部:对话 -->
|
||||
<div class="flex h-full flex-col">
|
||||
<Button
|
||||
class="btn-new-conversation h-[38px] w-full"
|
||||
type="primary"
|
||||
@click="createConversation"
|
||||
>
|
||||
<IconifyIcon icon="lucide:plus" class="mr-[5px]" />
|
||||
新建对话
|
||||
</Button>
|
||||
|
||||
<Input
|
||||
v-model:value="searchName"
|
||||
size="large"
|
||||
class="search-input mt-[20px]"
|
||||
placeholder="搜索历史记录"
|
||||
@keyup="searchConversation"
|
||||
>
|
||||
<template #prefix>
|
||||
<IconifyIcon icon="lucide:search" />
|
||||
</template>
|
||||
</Input>
|
||||
|
||||
<!-- 左中间:对话列表 -->
|
||||
<div class="conversation-list mt-[10px] flex-1 overflow-auto">
|
||||
<!-- 情况一:加载中 -->
|
||||
<Empty v-if="loading" description="." v-loading="loading" />
|
||||
|
||||
<!-- 情况二:按照 group 分组 -->
|
||||
<div
|
||||
v-for="conversationKey in Object.keys(conversationMap)"
|
||||
:key="conversationKey"
|
||||
class=""
|
||||
>
|
||||
<div
|
||||
v-if="conversationMap[conversationKey].length > 0"
|
||||
class="conversation-item classify-title pt-[10px]"
|
||||
>
|
||||
<b class="mx-[4px]">
|
||||
{{ conversationKey }}
|
||||
</b>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-for="conversation in conversationMap[conversationKey]"
|
||||
:key="conversation.id"
|
||||
@click="handleConversationClick(conversation.id)"
|
||||
@mouseover="hoverConversationId = conversation.id"
|
||||
@mouseout="hoverConversationId = null"
|
||||
class="conversation-item mt-[5px]"
|
||||
>
|
||||
<div
|
||||
class="conversation flex cursor-pointer flex-row items-center justify-between rounded-[5px] px-[5px] leading-[30px]"
|
||||
:class="[
|
||||
conversation.id === activeConversationId ? 'bg-[#e6e6e6]' : '',
|
||||
]"
|
||||
>
|
||||
<div class="title-wrapper flex items-center">
|
||||
<img
|
||||
class="avatar h-[25px] w-[25px] rounded-[5px]"
|
||||
:src="conversation.roleAvatar ?? '/static/gpt.svg'"
|
||||
/>
|
||||
<span
|
||||
class="title text-black/77 max-w-[150px] overflow-hidden text-ellipsis whitespace-nowrap px-[10px] py-[2px] text-[14px] font-normal"
|
||||
>
|
||||
{{ conversation.title }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-show="hoverConversationId === conversation.id"
|
||||
class="button-wrapper relative right-[2px] flex items-center text-[#606266]"
|
||||
>
|
||||
<Button
|
||||
class="btn mr-0 px-[5px]"
|
||||
type="link"
|
||||
@click.stop="handleTop(conversation)"
|
||||
>
|
||||
<IconifyIcon
|
||||
v-if="!conversation.pinned"
|
||||
icon="lucide:arrow-up"
|
||||
/>
|
||||
<IconifyIcon
|
||||
v-if="conversation.pinned"
|
||||
icon="lucide:arrow-down"
|
||||
/>
|
||||
</Button>
|
||||
<Button
|
||||
class="btn mr-0 px-[5px]"
|
||||
type="link"
|
||||
@click.stop="updateConversationTitle(conversation)"
|
||||
>
|
||||
<IconifyIcon icon="lucide:edit" />
|
||||
</Button>
|
||||
<Button
|
||||
class="btn mr-0 px-[5px]"
|
||||
type="link"
|
||||
@click.stop="deleteChatConversation(conversation)"
|
||||
>
|
||||
<IconifyIcon icon="lucide:trash" />
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 底部占位 -->
|
||||
<div class="h-[50px] w-full"></div>
|
||||
</div>
|
||||
|
||||
<!-- 左底部:工具栏 -->
|
||||
<div
|
||||
class="tool-box absolute bottom-0 left-0 right-0 flex items-center justify-between bg-[#f4f4f4] px-[20px] leading-[35px] text-[var(--el-text-color)] shadow-[0_0_1px_1px_rgba(228,228,228,0.8)]"
|
||||
>
|
||||
<div
|
||||
class="flex cursor-pointer items-center text-[#606266]"
|
||||
@click="handleRoleRepository"
|
||||
>
|
||||
<IconifyIcon icon="lucide:user" />
|
||||
<span class="ml-[5px]">角色仓库</span>
|
||||
</div>
|
||||
<div
|
||||
class="flex cursor-pointer items-center text-[#606266]"
|
||||
@click="handleClearConversation"
|
||||
>
|
||||
<IconifyIcon icon="lucide:trash" />
|
||||
<span class="ml-[5px]">清空未置顶对话</span>
|
||||
</div>
|
||||
</div>
|
||||
</Layout.Sider>
|
||||
</template>
|
||||
@@ -0,0 +1,82 @@
|
||||
<script lang="ts" setup>
|
||||
import type { AiChatConversationApi } from '#/api/ai/chat/conversation';
|
||||
|
||||
import { ref } from 'vue';
|
||||
|
||||
import { useVbenModal } from '@vben/common-ui';
|
||||
|
||||
import { message } from 'ant-design-vue';
|
||||
|
||||
import { useVbenForm } from '#/adapter/form';
|
||||
import {
|
||||
getChatConversationMy,
|
||||
updateChatConversationMy,
|
||||
} from '#/api/ai/chat/conversation';
|
||||
import { $t } from '#/locales';
|
||||
|
||||
import { useFormSchema } from '../../data';
|
||||
|
||||
const emit = defineEmits(['success']);
|
||||
const formData = ref<AiChatConversationApi.ChatConversationVO>();
|
||||
|
||||
const [Form, formApi] = useVbenForm({
|
||||
commonConfig: {
|
||||
componentProps: {
|
||||
class: 'w-full',
|
||||
},
|
||||
formItemClass: 'col-span-2',
|
||||
labelWidth: 140,
|
||||
},
|
||||
layout: 'horizontal',
|
||||
schema: useFormSchema(),
|
||||
showDefaultActions: false,
|
||||
});
|
||||
|
||||
const [Modal, modalApi] = useVbenModal({
|
||||
async onConfirm() {
|
||||
const { valid } = await formApi.validate();
|
||||
if (!valid) {
|
||||
return;
|
||||
}
|
||||
modalApi.lock();
|
||||
// 提交表单
|
||||
const data =
|
||||
(await formApi.getValues()) as AiChatConversationApi.ChatConversationVO;
|
||||
try {
|
||||
await updateChatConversationMy(data);
|
||||
|
||||
// 关闭并提示
|
||||
await modalApi.close();
|
||||
emit('success');
|
||||
message.success($t('ui.actionMessage.operationSuccess'));
|
||||
} finally {
|
||||
modalApi.unlock();
|
||||
}
|
||||
},
|
||||
async onOpenChange(isOpen: boolean) {
|
||||
if (!isOpen) {
|
||||
formData.value = undefined;
|
||||
return;
|
||||
}
|
||||
// 加载数据
|
||||
const data = modalApi.getData<AiChatConversationApi.ChatConversationVO>();
|
||||
if (!data || !data.id) {
|
||||
return;
|
||||
}
|
||||
modalApi.lock();
|
||||
try {
|
||||
formData.value = await getChatConversationMy(data.id as number);
|
||||
// 设置到 values
|
||||
await formApi.setValues(formData.value);
|
||||
} finally {
|
||||
modalApi.unlock();
|
||||
}
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Modal class="w-[600px]" title="设定">
|
||||
<Form class="mx-4" />
|
||||
</Modal>
|
||||
</template>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user