Initial commit: HZHub project setup with RuoYi-AI base

This commit is contained in:
2026-03-26 09:47:46 +00:00
commit 3584e491cc
5005 changed files with 318595 additions and 0 deletions

View File

@@ -0,0 +1,357 @@
# 工作流管理 API 接口文档
## 1. 获取工作流详情
### 基本信息
- **接口URL**: `/workflow/get/{uuid}`
- **请求方式**: `GET`
- **接口描述**: 根据工作流UUID获取工作流的完整信息包括节点、连线、配置等
- **权限要求**: 需要登录,只能获取自己创建的工作流或公开的工作流
### 请求参数
#### 路径参数
| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| uuid | String | 是 | 工作流的唯一标识符 |
#### 请求示例
```http
GET /workflow/get/workflow-1698745623456 HTTP/1.1
Host: api.example.com
Authorization: Bearer {token}
```
### 响应数据
#### 响应结构
```typescript
{
code: number; // 状态码200表示成功
msg: string; // 响应消息
data: {
uuid: string; // 工作流UUID
title: string; // 工作流名称
remark: string; // 备注说明
isPublic: boolean; // 是否公开
nodes: Array<{ // 节点列表
uuid: string; // 节点UUID
title: string; // 节点名称
workflowUuid: string; // 所属工作流UUID
workflowComponentId: number; // 工作流组件ID
wfComponent: { // 工作流组件信息
name: string; // 组件名称Start、Answer等
title: string; // 组件显示名称
remark: string; // 组件说明
isEnable: boolean; // 是否启用
};
inputConfig: { // 输入配置
user_inputs: Array<any>; // 用户输入配置
ref_inputs: Array<any>; // 引用输入配置
};
nodeConfig: { // 节点配置(根据不同组件类型有不同字段)
[key: string]: any;
};
outputConfig: { // 输出配置
[key: string]: any;
};
positionX: number; // 节点X坐标
positionY: number; // 节点Y坐标
}>;
edges: Array<{ // 连线列表
uuid: string; // 连线UUID
source: string; // 源节点UUID
target: string; // 目标节点UUID
sourceHandle?: string; // 源节点连接点ID可选
targetHandle?: string; // 目标节点连接点ID可选
label?: string; // 连线标签(可选)
}>;
createTime: string; // 创建时间ISO 8601格式
updateTime: string; // 更新时间ISO 8601格式
createBy: string; // 创建人
updateBy: string; // 更新人
};
}
```
#### 响应示例
```json
{
"code": 200,
"msg": "操作成功",
"data": {
"uuid": "workflow-1698745623456",
"title": "客服问答工作流",
"remark": "用于处理客户常见问题",
"isPublic": false,
"nodes": [
{
"uuid": "node-start-1",
"title": "开始",
"workflowUuid": "workflow-1698745623456",
"workflowComponentId": 1,
"wfComponent": {
"name": "Start",
"title": "开始",
"remark": "工作流起始节点",
"isEnable": true
},
"inputConfig": {
"user_inputs": [
{
"uuid": "input-1",
"name": "question",
"title": "用户问题",
"type": 1,
"required": true
}
],
"ref_inputs": []
},
"nodeConfig": {
"prologue": "您好,请问有什么可以帮您?"
},
"outputConfig": {},
"positionX": 100,
"positionY": 200
},
{
"uuid": "node-answer-1",
"title": "AI回答",
"workflowUuid": "workflow-1698745623456",
"workflowComponentId": 3,
"wfComponent": {
"name": "Answer",
"title": "回答",
"remark": "AI生成回答",
"isEnable": true
},
"inputConfig": {
"user_inputs": [],
"ref_inputs": [
{
"source": "node-start-1",
"field": "question"
}
]
},
"nodeConfig": {
"model_name": "gpt-4",
"prompt": "请根据用户问题给出专业回答:{{question}}"
},
"outputConfig": {},
"positionX": 400,
"positionY": 200
}
],
"edges": [
{
"uuid": "edge-1",
"source": "node-start-1",
"target": "node-answer-1",
"sourceHandle": "right",
"targetHandle": "left"
}
],
"createTime": "2024-10-30T10:30:00Z",
"updateTime": "2024-10-30T15:45:00Z",
"createBy": "admin",
"updateBy": "admin"
}
}
```
#### 错误响应
```json
{
"code": 404,
"msg": "工作流不存在",
"data": null
}
```
```json
{
"code": 403,
"msg": "无权限访问该工作流",
"data": null
}
```
### 注意事项
1. **权限控制**:
- 用户只能获取自己创建的工作流
- 公开的工作流所有登录用户都可以获取
2. **数据完整性**:
- 返回的工作流包含完整的节点和连线信息
- 节点配置 `nodeConfig` 根据不同组件类型会有不同的字段结构
3. **坐标系统**:
- `positionX``positionY` 是节点在画布上的位置坐标
- 单位为像素px
---
## 2. 分页查询工作流列表
### 基本信息
- **接口URL**: `/workflow/page`
- **请求方式**: `POST`
- **接口描述**: 分页查询工作流列表,支持按标题搜索和类型过滤
- **权限要求**: 需要登录
### 请求参数
#### Body参数JSON格式
| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| pageNum | Integer | 是 | 页码从1开始 |
| pageSize | Integer | 是 | 每页数量建议10-100 |
| title | String | 否 | 工作流名称,支持模糊搜索 |
| type | String | 否 | 类型筛选:空字符串或不传=全部,"my"=我的,"public"=公开 |
#### 请求示例
```http
POST /workflow/page HTTP/1.1
Host: api.example.com
Content-Type: application/json
Authorization: Bearer {token}
```
### 响应数据
#### 响应结构
```typescript
{
code: number; // 状态码200表示成功
msg: string; // 响应消息
data: {
total: number; // 总记录数
rows: Array<{ // 工作流列表
uuid: string; // 工作流UUID
title: string; // 工作流名称
remark: string; // 备注说明
isPublic: boolean; // 是否公开
nodes: Array<any>; // 节点列表(简化版,仅用于统计数量)
edges: Array<any>; // 连线列表(简化版)
createTime: string; // 创建时间
updateTime: string; // 更新时间
createBy: string; // 创建人
updateBy: string; // 更新人
}>;
};
}
```
#### 响应示例
```json
{
"code": 200,
"msg": "操作成功",
"data": {
"total": 25,
"rows": [
{
"uuid": "workflow-1698745623456",
"title": "客服问答工作流",
"remark": "用于处理客户常见问题",
"isPublic": false,
"nodes": [
{ "uuid": "node-start-1" },
{ "uuid": "node-answer-1" },
{ "uuid": "node-end-1" }
],
"edges": [
{ "uuid": "edge-1" },
{ "uuid": "edge-2" }
],
"createTime": "2024-10-30T10:30:00Z",
"updateTime": "2024-10-30T15:45:00Z",
"createBy": "admin",
"updateBy": "admin"
},
{
"uuid": "workflow-1698745623457",
"title": "客服智能路由",
"remark": "根据问题类型自动分配",
"isPublic": true,
"nodes": [
{ "uuid": "node-start-2" },
{ "uuid": "node-classifier-1" },
{ "uuid": "node-switcher-1" }
],
"edges": [
{ "uuid": "edge-3" }
],
"createTime": "2024-10-29T14:20:00Z",
"updateTime": "2024-10-29T14:20:00Z",
"createBy": "admin",
"updateBy": "admin"
}
]
}
}
```
#### 错误响应
```json
{
"code": 400,
"msg": "参数错误pageNum必须大于0",
"data": null
}
```
```json
{
"code": 400,
"msg": "参数错误pageSize必须在1-100之间",
"data": null
}
```
### 注意事项
1. **分页参数**:
- `pageNum` 从1开始不是0
- `pageSize` 建议范围 1-100超出范围应返回400错误
2. **搜索功能**:
- `title` 参数支持模糊搜索LIKE '%title%'
- 搜索不区分大小写
3. **类型过滤**:
- `type` 为空或不传:返回所有工作流(我的+公开)
- `type="my"`:仅返回当前用户创建的工作流
- `type="public"`:仅返回公开的工作流
4. **数据优化**:
- 列表接口中的 `nodes``edges` 为简化版,仅包含基本信息
- 前端会根据数组长度统计节点数量,无需额外返回 `nodeCount` 字段
5. **排序规则**:
- 默认按 `updateTime` 降序排列(最新修改的在前)
- 可根据需求添加其他排序字段
---
5. **排序规则**:
- 默认按 `updateTime` 降序排列(最新修改的在前)
- 可根据需求添加其他排序字段
---

View File

@@ -0,0 +1,19 @@
import { requestClient } from '#/api/request'
export const adapters = {
httpGet<T = any>(url: string, config?: any) {
return requestClient.get<T>(url, config)
},
httpPost<T = any>(url: string, data?: any, config?: any) {
return requestClient.post<T>(url, data, config)
},
httpPut<T = any>(url: string, data?: any, config?: any) {
return requestClient.put<T>(url, data, config)
},
httpDelete<T = any>(url: string, config?: any) {
return requestClient.delete<T>(url, config)
}
}

View File

@@ -0,0 +1,103 @@
import { adapters } from './adapters'
export const workflowApi = {
workflowAdd<T = any>(data: { title: string; remark: string; isPublic: boolean }) {
return adapters.httpPost<T>('/workflow/add', data)
},
workflowCopy<T = any>(wfUuid: string) {
return adapters.httpPost<T>(`/workflow/copy/${wfUuid}`)
},
workflowUpdate<T = any>(data: Workflow.WorkflowUpdateReq) {
return adapters.httpPost<T>('/workflow/update', data)
},
workflowDel<T = any>(uuid: string) {
return adapters.httpPost<T>(`/workflow/del/${uuid}`)
},
workflowSetPublic<T = any>(uuid: string, isPublic?: boolean) {
return adapters.httpPost<T>(`/workflow/set-public/${uuid}?isPublic=${isPublic}`)
},
workflowBaseInfoUpdate<T = any>(data: { uuid: string; title: string; remark: string; isPublic: boolean }) {
return adapters.httpPost<T>('/workflow/base-info/update', data)
},
//新增节点
addNode<T = any>(data: { name: string; title: string }) {
return adapters.httpPost<T>('/admin/workflow/component/addOrUpdate', data)
},
// 上传文件
uploadFile<T = any>(data: File) {
const formData = new FormData();
formData.append('files', data);
return adapters.httpPost<T>('/resource/oss/fileUpload', formData);
},
workflowGet<T = any>(uuid: string) {
return adapters.httpGet<T>(`/workflow/${uuid}`)
},
workflowPage<T = any>(params: {
currentPage: number;
pageSize: number;
wfSearchReq: {
title?: string;
isEnable?: boolean;
isPublic?: boolean;
}
}) {
const { currentPage, pageSize, wfSearchReq } = params
return adapters.httpPost<T>('/admin/workflow/search', wfSearchReq, {
params: { currentPage, pageSize }
})
},
workflowComponents<T = any>() {
return adapters.httpGet<T>('/workflow/public/component/list')
},
workflowSearchMine<T = any>(keyword: string, currentPage: number, pageSize: number) {
const search = keyword === undefined ? '' : `keyword=${keyword}&`
return adapters.httpGet<T>(`/workflow/mine/search?${search}currentPage=${currentPage}&pageSize=${pageSize}`)
},
workflowSearchPublic<T = any>(keyword: string, currentPage: number, pageSize: number) {
const search = keyword === undefined ? '' : `keyword=${keyword}&`
return adapters.httpGet<T>(`/workflow/public/search?${search}currentPage=${currentPage}&pageSize=${pageSize}`)
},
workflowRuntimes<T = any>(wfUuid: string, currentPage: number, pageSize: number) {
return adapters.httpGet<T>(`/workflow/runtime/page?wfUuid=${wfUuid}&currentPage=${currentPage}&pageSize=${pageSize}`)
},
workflowRuntimeNodes<T = any>(wfRuntimeUuid: string) {
return adapters.httpGet<T>(`/workflow/runtime/nodes/${wfRuntimeUuid}`)
},
workflowRuntimesClear<T = any>() {
return adapters.httpPost<T>('/workflow/runtime/clear')
},
workflowOperators<T = any>() {
return adapters.httpGet<T>('/workflow/public/operators')
},
workflowRuntimeDelete<T = any>(wfRuntimeUuid: string) {
return adapters.httpGet<T>(`/workflow/runtime/del/${wfRuntimeUuid}`)
},
workflowRuntimeResume<T = any>(params: {
runtimeUuid: string
feedbackContent: string
}) {
return adapters.httpPost<T>(`/workflow/runtime/resume/${params.runtimeUuid}`, { ...params })
},
}
export default workflowApi
// 运行时能力透出(便于按包内其他接口形式统一从此处导出)
export * from './runtime'

View File

@@ -0,0 +1,167 @@
// 运行时相关接口(提供注入能力,避免与应用层 API 耦合)
import { adapters } from './adapters'
import { useAccessStore } from '@vben/stores'
export interface WorkflowRunParams {
options: { uuid: string; inputs: any[] }
signal?: AbortSignal
startCallback?: (wfRuntimeJson: string) => void
thinkingDataReceived?: (chunk: string) => void
messageReceived?: (chunk: string, event?: string) => void
doneCallback?: (finalChunk: string) => void
errorCallback?: (error: string) => void
}
export interface WorkflowResumeParams {
runtimeUuid: string
feedbackContent: string
}
let workflowRunImpl: ((p: WorkflowRunParams) => Promise<void>) | null = null
let workflowResumeImpl: ((p: WorkflowResumeParams) => Promise<void>) | null = null
export function setWorkflowRunImpl(fn: (p: WorkflowRunParams) => Promise<void>) {
workflowRunImpl = fn
}
export function setWorkflowResumeImpl(fn: (p: WorkflowResumeParams) => Promise<void>) {
workflowResumeImpl = fn
}
export async function workflowRun(p: WorkflowRunParams) {
if (!workflowRunImpl) {
// 默认回退到真实接口(后端改为 body 传 uuid/inputsURL 不再携带 uuid
return commonSseProcess(`/api/workflow/run`, {
options: p.options,
signal: p.signal,
startCallback: p.startCallback || (() => {}),
messageReceived: p.messageReceived || (() => {}),
thinkingDataReceived: p.thinkingDataReceived || (() => {}),
doneCallback: p.doneCallback || (() => {}),
errorCallback: p.errorCallback || (() => {}),
})
}
return workflowRunImpl(p)
}
export async function workflowRuntimeResume(p: WorkflowResumeParams) {
if (!workflowResumeImpl) {
return adapters.httpPost(`/workflow/runtime/resume/${p.runtimeUuid}`, { ...p })
}
return workflowResumeImpl(p)
}
let uploadAction = '/api/file/upload'
export function setUploadAction(url: string) { uploadAction = url }
export function getUploadAction() { return uploadAction }
// 标准化的 SSE 运行器(不包含任何权限处理)
export async function commonSseProcess(
url: string,
params: {
options: any
signal?: AbortSignal
startCallback: (chunk: string) => void
thinkingDataReceived: (chunk: string) => void
messageReceived: (chunk: string, eventName: string) => void
audioDataReceived?: (chunk: string) => void
stateChanged?: (state: string) => void
doneCallback: (chunk: string) => void
errorCallback: (error: string) => void
},
) {
try {
// 使用项目的请求客户端来获取正确的配置
const accessStore = useAccessStore()
const token = accessStore.accessToken ? `Bearer ${accessStore.accessToken}` : ''
console.log('SSE 请求配置:', {
url,
token: token ? '已设置' : '未设置',
options: params.options
})
const res = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': token,
'Accept-Language': 'zh_CN',
'Content-Language': 'zh_CN',
'clientId': 'web'
},
body: JSON.stringify({ ...params.options }),
signal: params.signal,
})
console.log('SSE 响应状态:', {
status: res.status,
statusText: res.statusText,
contentType: res.headers.get('content-type'),
ok: res.ok
})
const contentType = res.headers.get('content-type') || ''
if (!res.ok || !contentType.includes('text/event-stream')) {
throw new Error(`SSE open failed: ${res.status} ${res.statusText}`)
}
const reader = res.body?.getReader()
if (!reader) { throw new Error('ReadableStream not supported') }
const decoder = new TextDecoder('utf-8')
let buffer = ''
while (true) {
const { done, value } = await reader.read()
if (done) break
buffer += decoder.decode(value, { stream: true })
// 按事件块分割(以空行分隔)
const parts = buffer.split('\n\n')
// 最后一段可能是不完整,保留在 buffer
buffer = parts.pop() || ''
for (const part of parts) {
// 解析 sse 行event: xxx / data: yyy
const lines = part.split('\n')
let eventName = ''
const dataLines: string[] = []
for (const line of lines) {
if (line.startsWith('event:')) eventName = line.slice(6).trim()
else if (line.startsWith('data:')) dataLines.push(line.slice(5))
}
let data = dataLines.join('\n')
if (data.indexOf('-_wrap_-') === 0) data = data.replace('-_wrap_-', '\n')
// 分发内置事件
if (eventName === '[START]') { params.startCallback(data); continue }
if (eventName === '[ERROR]') { params.errorCallback(data); continue }
if (eventName === '[DONE]') { params.doneCallback(data); continue }
if (eventName === '[AUDIO]') { params.audioDataReceived && params.audioDataReceived(data); continue }
if (eventName === '[THINKING]') { params.thinkingDataReceived && params.thinkingDataReceived(data); continue }
if (eventName === '[STATE_CHANGED]') { params.stateChanged && params.stateChanged(data); continue }
params.messageReceived(data, eventName)
}
}
} catch (e: any) {
params.errorCallback(e?.message || String(e))
throw e
}
}
// 运行记录相关
export function workflowRuntimes<T = any>(wfUuid: string, currentPage: number, pageSize: number) {
return adapters.httpGet<T>(`/workflow/runtime/page?wfUuid=${wfUuid}&currentPage=${currentPage}&pageSize=${pageSize}`)
}
export function workflowRuntimeNodes<T = any>(wfRuntimeUuid: string) {
return adapters.httpGet<T>(`/workflow/runtime/nodes/${wfRuntimeUuid}`)
}
export function workflowRuntimesClear<T = any>() {
return adapters.httpPost<T>('/workflow/runtime/clear')
}
export function workflowRuntimeDelete<T = any>(uuid: string) {
return adapters.httpPost<T>(`/workflow/runtime/del/${uuid}`)
}

View File

@@ -0,0 +1,65 @@
declare namespace Workflow {
interface WorkflowUpdateReq {
uuid: string
title: string
remark: string
isPublic: boolean
nodes: any[]
edges: any[]
}
interface WorkflowInfo {
uuid: string
title: string
remark: string
isPublic: boolean
nodes: WorkflowNode[]
edges: WorkflowEdge[]
}
interface WorkflowNode {
uuid: string
title: string
workflowUuid: string
wfComponent: WorkflowComponent
inputConfig: any
nodeConfig: any
outputConfig: any
positionX: number
positionY: number
}
interface WorkflowEdge {
id?: string
uuid: string
workflowUuid: string
sourceNodeUuid: string
sourceHandle?: string
targetNodeUuid: string
}
interface WorkflowComponent {
name: string
title: string
remark?: string
isEnable?: boolean
}
interface WorkflowRuntime {
uuid: string
workflowUuid: string
status: string
createTime: string
updateTime: string
}
interface WorkflowRuntimeNode {
uuid: string
runtimeUuid: string
nodeUuid: string
status: string
inputData: any
outputData: any
errorMessage?: string
}
}

View File

@@ -0,0 +1,62 @@
import type { ConfigForm, ConfigQuery, ConfigVO } from './model';
import type { ID, IDS, PageResult } from '#/api/common';
import { commonExport } from '#/api/helper';
import { requestClient } from '#/api/request';
/**
* 查询配置信息列表
* @param params
* @returns 配置信息列表
*/
export function configList(params?: ConfigQuery) {
return requestClient.get<PageResult<ConfigVO>>('/system/config/list', {
params,
});
}
/**
* 导出配置信息列表
* @param params
* @returns 配置信息列表
*/
export function configExport(params?: ConfigQuery) {
return commonExport('/system/config/export', params ?? {});
}
/**
* 查询配置信息详情
* @param id id
* @returns 配置信息详情
*/
export function configInfo(id: ID) {
return requestClient.get<ConfigVO>(`/system/config/${id}`);
}
/**
* 新增配置信息
* @param data
* @returns void
*/
export function configAdd(data: ConfigForm) {
return requestClient.postWithMsg<void>('/system/config', data);
}
/**
* 更新配置信息
* @param data
* @returns void
*/
export function configUpdate(data: ConfigForm) {
return requestClient.putWithMsg<void>('/system/config', data);
}
/**
* 删除配置信息
* @param id id
* @returns void
*/
export function configRemove(id: ID | IDS) {
return requestClient.deleteWithMsg<void>(`/system/config/${id}`);
}

View File

@@ -0,0 +1,107 @@
import type { BaseEntity, PageQuery } from '#/api/common';
export interface ConfigVO {
/**
* 主键
*/
id: number | string;
/**
* 配置类型
*/
category: string;
/**
* 配置名称
*/
configName: string;
/**
* 配置值
*/
configValue: string;
/**
* 说明
*/
configDict: string;
/**
* 备注
*/
remark: string;
/**
* 更新IP
*/
updateIp: string;
}
export interface ConfigForm extends BaseEntity {
/**
* 主键
*/
id?: number | string;
/**
* 配置类型
*/
category?: string;
/**
* 配置名称
*/
configName?: string;
/**
* 配置值
*/
configValue?: string;
/**
* 说明
*/
configDict?: string;
/**
* 备注
*/
remark?: string;
/**
* 更新IP
*/
updateIp?: string;
}
export interface ConfigQuery extends PageQuery {
/**
* 配置类型
*/
category?: string;
/**
* 配置名称
*/
configName?: string;
/**
* 配置值
*/
configValue?: string;
/**
* 说明
*/
configDict?: string;
/**
* 更新IP
*/
updateIp?: string;
/**
* 日期范围参数
*/
params?: any;
}

View File

@@ -0,0 +1,62 @@
import type { MessageForm, MessageQuery, MessageVO } from './model';
import type { ID, IDS, PageResult } from '#/api/common';
import { commonExport } from '#/api/helper';
import { requestClient } from '#/api/request';
/**
* 查询聊天消息列表
* @param params
* @returns 聊天消息列表
*/
export function messageList(params?: MessageQuery) {
return requestClient.get<PageResult<MessageVO>>('/system/message/list', {
params,
});
}
/**
* 导出聊天消息列表
* @param params
* @returns 聊天消息列表
*/
export function messageExport(params?: MessageQuery) {
return commonExport('/system/message/export', params ?? {});
}
/**
* 查询聊天消息详情
* @param id id
* @returns 聊天消息详情
*/
export function messageInfo(id: ID) {
return requestClient.get<MessageVO>(`/system/message/${id}`);
}
/**
* 新增聊天消息
* @param data
* @returns void
*/
export function messageAdd(data: MessageForm) {
return requestClient.postWithMsg<void>('/system/message', data);
}
/**
* 更新聊天消息
* @param data
* @returns void
*/
export function messageUpdate(data: MessageForm) {
return requestClient.putWithMsg<void>('/system/message', data);
}
/**
* 删除聊天消息
* @param id id
* @returns void
*/
export function messageRemove(id: ID | IDS) {
return requestClient.deleteWithMsg<void>(`/system/message/${id}`);
}

View File

@@ -0,0 +1,122 @@
import type { BaseEntity, PageQuery } from '#/api/common';
export interface MessageVO {
/**
* 主键
*/
id: number | string;
/**
* 会话id
*/
sessionId: number | string;
/**
* 用户id
*/
userId: number | string;
/**
* 消息内容
*/
content: string;
/**
* 对话角色
*/
role: string;
/**
* 累计 Tokens
*/
totalTokens: number;
/**
* 模型名称
*/
modelName: string;
/**
* 备注
*/
remark: string;
}
export interface MessageForm extends BaseEntity {
/**
* 主键
*/
id?: number | string;
/**
* 会话id
*/
sessionId?: number | string;
/**
* 用户id
*/
userId?: number | string;
/**
* 消息内容
*/
content?: string;
/**
* 对话角色
*/
role?: string;
/**
* 累计 Tokens
*/
totalTokens?: number;
/**
* 模型名称
*/
modelName?: string;
/**
* 备注
*/
remark?: string;
}
export interface MessageQuery extends PageQuery {
/**
* 会话id
*/
sessionId?: number | string;
/**
* 用户id
*/
userId?: number | string;
/**
* 消息内容
*/
content?: string;
/**
* 对话角色
*/
role?: string;
/**
* 累计 Tokens
*/
totalTokens?: number;
/**
* 模型名称
*/
modelName?: string;
/**
* 日期范围参数
*/
params?: any;
}

View File

@@ -0,0 +1,62 @@
import type { ModelForm, ModelQuery, ModelVO } from './model';
import type { ID, IDS, PageResult } from '#/api/common';
import { commonExport } from '#/api/helper';
import { requestClient } from '#/api/request';
/**
* 查询模型管理列表
* @param params
* @returns 模型管理列表
*/
export function modelList(params?: ModelQuery) {
return requestClient.get<PageResult<ModelVO>>('/system/model/list', {
params,
});
}
/**
* 导出模型管理列表
* @param params
* @returns 模型管理列表
*/
export function modelExport(params?: ModelQuery) {
return commonExport('/system/model/export', params ?? {});
}
/**
* 查询模型管理详情
* @param id id
* @returns 模型管理详情
*/
export function modelInfo(id: ID) {
return requestClient.get<ModelVO>(`/system/model/${id}`);
}
/**
* 新增模型管理
* @param data
* @returns void
*/
export function modelAdd(data: ModelForm) {
return requestClient.postWithMsg<void>('/system/model', data);
}
/**
* 更新模型管理
* @param data
* @returns void
*/
export function modelUpdate(data: ModelForm) {
return requestClient.putWithMsg<void>('/system/model', data);
}
/**
* 删除模型管理
* @param id id
* @returns void
*/
export function modelRemove(id: ID | IDS) {
return requestClient.deleteWithMsg<void>(`/system/model/${id}`);
}

View File

@@ -0,0 +1,152 @@
import type { BaseEntity, PageQuery } from '#/api/common';
export interface ModelVO {
/**
* 主键
*/
id: number | string;
/**
* 模型分类
*/
category: string;
/**
* 模型名称
*/
modelName: string;
/**
* 模型供应商
*/
providerCode: number | string;
/**
* 模型描述
*/
modelDescribe: string;
/**
* 是否显示
*/
modelShow: string;
/**
* 模型维度
*/
modelDimension: number;
/**
* 请求地址
*/
apiHost: string;
/**
* 密钥
*/
apiKey: string;
/**
* 备注
*/
remark: string;
}
export interface ModelForm extends BaseEntity {
/**
* 主键
*/
id?: number | string;
/**
* 模型分类
*/
category?: string;
/**
* 模型名称
*/
modelName?: string;
/**
* 模型供应商
*/
providerCode?: number | string;
/**
* 模型描述
*/
modelDescribe?: string;
/**
* 是否显示
*/
modelShow?: string;
/**
* 模型维度
*/
modelDimension?: number;
/**
* 请求地址
*/
apiHost?: string;
/**
* 密钥
*/
apiKey?: string;
/**
* 备注
*/
remark?: string;
}
export interface ModelQuery extends PageQuery {
/**
* 模型分类
*/
category?: string;
/**
* 模型名称
*/
modelName?: string;
/**
* 模型供应商
*/
providerCode?: number | string;
/**
* 模型描述
*/
modelDescribe?: string;
/**
* 是否显示
*/
modelShow?: string;
/**
* 模型维度
*/
modelDimension?: number;
/**
* 请求地址
*/
apiHost?: string;
/**
* 密钥
*/
apiKey?: string;
/**
* 日期范围参数
*/
params?: any;
}

View File

@@ -0,0 +1,62 @@
import type { ProviderForm, ProviderQuery, ProviderVO } from './model';
import type { ID, IDS, PageResult } from '#/api/common';
import { commonExport } from '#/api/helper';
import { requestClient } from '#/api/request';
/**
* 查询厂商管理列表
* @param params
* @returns 厂商管理列表
*/
export function providerList(params?: ProviderQuery) {
return requestClient.get<PageResult<ProviderVO>>('/system/provider/list', {
params,
});
}
/**
* 导出厂商管理列表
* @param params
* @returns 厂商管理列表
*/
export function providerExport(params?: ProviderQuery) {
return commonExport('/system/provider/export', params ?? {});
}
/**
* 查询厂商管理详情
* @param id id
* @returns 厂商管理详情
*/
export function providerInfo(id: ID) {
return requestClient.get<ProviderVO>(`/system/provider/${id}`);
}
/**
* 新增厂商管理
* @param data
* @returns void
*/
export function providerAdd(data: ProviderForm) {
return requestClient.postWithMsg<void>('/system/provider', data);
}
/**
* 更新厂商管理
* @param data
* @returns void
*/
export function providerUpdate(data: ProviderForm) {
return requestClient.putWithMsg<void>('/system/provider', data);
}
/**
* 删除厂商管理
* @param id id
* @returns void
*/
export function providerRemove(id: ID | IDS) {
return requestClient.deleteWithMsg<void>(`/system/provider/${id}`);
}

View File

@@ -0,0 +1,152 @@
import type { BaseEntity, PageQuery } from '#/api/common';
export interface ProviderVO {
/**
* 主键
*/
id: number | string;
/**
* 厂商名称
*/
providerName: number | string;
/**
* 厂商编码
*/
providerCode: number | string;
/**
* 厂商图标
*/
providerIcon: number | string;
/**
* 厂商描述
*/
providerDesc: number | string;
/**
* API地址
*/
apiHost: string;
/**
* 状态0正常 1停用
*/
status: string;
/**
* 排序
*/
sortOrder: number;
/**
* 备注
*/
remark: string;
/**
* 更新IP
*/
updateIp: string;
}
export interface ProviderForm extends BaseEntity {
/**
* 主键
*/
id?: number | string;
/**
* 厂商名称
*/
providerName?: number | string;
/**
* 厂商编码
*/
providerCode?: number | string;
/**
* 厂商图标
*/
providerIcon?: number | string;
/**
* 厂商描述
*/
providerDesc?: number | string;
/**
* API地址
*/
apiHost?: string;
/**
* 状态0正常 1停用
*/
status?: string;
/**
* 排序
*/
sortOrder?: number;
/**
* 备注
*/
remark?: string;
/**
* 更新IP
*/
updateIp?: string;
}
export interface ProviderQuery extends PageQuery {
/**
* 厂商名称
*/
providerName?: number | string;
/**
* 厂商编码
*/
providerCode?: number | string;
/**
* 厂商图标
*/
providerIcon?: number | string;
/**
* 厂商描述
*/
providerDesc?: number | string;
/**
* API地址
*/
apiHost?: string;
/**
* 状态0正常 1停用
*/
status?: string;
/**
* 排序
*/
sortOrder?: number;
/**
* 更新IP
*/
updateIp?: string;
/**
* 日期范围参数
*/
params?: any;
}

View File

@@ -0,0 +1,42 @@
export type ID = number | string;
export type IDS = (number | string)[];
export interface BaseEntity {
createBy?: string;
createDept?: string;
createTime?: string;
updateBy?: string;
updateTime?: string;
}
/**
* 分页信息
* @param rows 结果集
* @param total 总数
*/
export interface PageResult<T = any> {
rows: T[];
total: number;
}
/**
* 分页查询参数
*
* 排序支持的用法如下:
* {isAsc:"asc",orderByColumn:"id"} order by id asc
* {isAsc:"asc",orderByColumn:"id,createTime"} order by id asc,create_time asc
* {isAsc:"desc",orderByColumn:"id,createTime"} order by id desc,create_time desc
* {isAsc:"asc,desc",orderByColumn:"id,createTime"} order by id asc,create_time desc
*
* @param pageNum 当前页
* @param pageSize 每页大小
* @param orderByColumn 排序字段
* @param isAsc 是否升序
*/
export interface PageQuery {
isAsc?: string;
orderByColumn?: string;
pageNum?: number;
pageSize?: number;
[key: string]: any;
}

View File

@@ -0,0 +1,176 @@
import type { GrantType } from '@vben/common-ui';
import type { HttpResponse } from '@vben/request';
import { useAppConfig } from '@vben/hooks';
import { requestClient } from '#/api/request';
const { clientId, sseEnable } = useAppConfig(
import.meta.env,
import.meta.env.PROD,
);
export namespace AuthApi {
/**
* @description: 所有登录类型都需要用到的
* @param clientId 客户端ID 这里为必填项 但是在loginApi内部处理了 所以为可选
* @param grantType 授权/登录类型
* @param tenantId 租户id
*/
export interface BaseLoginParams {
clientId?: string;
grantType: GrantType;
tenantId: string;
}
/**
* @description: oauth登录需要用到的参数
* @param socialCode 第三方参数
* @param socialState 第三方参数
* @param source 与后端的 justauth.type.xxx的回调地址的source对应
*/
export interface OAuthLoginParams extends BaseLoginParams {
socialCode: string;
socialState: string;
source: string;
}
/**
* @description: 验证码登录需要用到的参数
* @param code 验证码 可选(未开启验证码情况)
* @param uuid 验证码ID 可选(未开启验证码情况)
* @param username 用户名
* @param password 密码
*/
export interface SimpleLoginParams extends BaseLoginParams {
code?: string;
uuid?: string;
username: string;
password: string;
}
export type LoginParams = OAuthLoginParams | SimpleLoginParams;
// /** 登录接口参数 */
// export interface LoginParams {
// code?: string;
// grantType: string;
// password: string;
// tenantId: string;
// username: string;
// uuid?: string;
// }
/** 登录接口返回值 */
export interface LoginResult {
access_token: string;
client_id: string;
expire_in: number;
}
export interface RefreshTokenResult {
data: string;
status: number;
}
}
/**
* 登录
*/
export async function loginApi(data: AuthApi.LoginParams) {
return requestClient.post<AuthApi.LoginResult>(
'/auth/login',
{ ...data, clientId },
{
encrypt: true,
},
);
}
/**
* 用户登出
* @returns void
*/
export function doLogout() {
return requestClient.post<HttpResponse<void>>('/auth/logout');
}
/**
* 关闭sse连接
* @returns void
*/
export function seeConnectionClose() {
/**
* 未开启sse 不需要处理
*/
if (!sseEnable) {
return;
}
return requestClient.get<void>('/resource/sse/close');
}
/**
* @param companyName 租户/公司名称
* @param domain 绑定域名(不带http(s)://) 可选
* @param tenantId 租户id
*/
export interface TenantOption {
companyName: string;
domain?: string;
tenantId: string;
}
/**
* @param tenantEnabled 是否启用租户
* @param voList 租户列表
*/
export interface TenantResp {
tenantEnabled: boolean;
voList: TenantOption[];
}
/**
* 获取租户列表 下拉框使用
*/
export function tenantList() {
return requestClient.get<TenantResp>('/auth/tenant/list');
}
/**
* vben的 先不删除
* @returns string[]
*/
export async function getAccessCodesApi() {
return requestClient.get<string[]>('/auth/codes');
}
/**
* 绑定第三方账号
* @param source 绑定的来源
* @returns 跳转url
*/
export function authBinding(source: string, tenantId: string) {
return requestClient.get<string>(`/auth/binding/${source}`, {
params: {
domain: window.location.host,
tenantId,
},
});
}
/**
* 取消绑定
* @param id id
*/
export function authUnbinding(id: string) {
return requestClient.deleteWithMsg<void>(`/auth/unlock/${id}`);
}
/**
* oauth授权回调
* @param data oauth授权
* @returns void
*/
export function authCallback(data: AuthApi.OAuthLoginParams) {
return requestClient.post<void>('/auth/social/callback', data);
}

View File

@@ -0,0 +1,42 @@
import { requestClient } from '#/api/request';
/**
* 发送短信验证码
* @param phonenumber 手机号
* @returns void
*/
export function sendSmsCode(phonenumber: string) {
return requestClient.get<void>('/resource/sms/code', {
params: { phonenumber },
});
}
/**
* 发送邮件验证码
* @param email 邮箱
* @returns void
*/
export function sendEmailCode(email: string) {
return requestClient.get<void>('/resource/email/code', {
params: { email },
});
}
/**
* @param img 图片验证码 需要和base64拼接
* @param captchaEnabled 是否开启
* @param uuid 验证码ID
*/
export interface CaptchaResponse {
captchaEnabled: boolean;
img: string;
uuid: string;
}
/**
* 图片验证码
* @returns resp
*/
export function captchaImage() {
return requestClient.get<CaptchaResponse>('/auth/code');
}

View File

@@ -0,0 +1,4 @@
export * from './auth';
export * from './menu';
export * from './upload';
export * from './user';

View File

@@ -0,0 +1,45 @@
import { requestClient } from '#/api/request';
/**
* @description: 菜单meta
* @param title 菜单名
* @param icon 菜单图标
* @param noCache 是否不缓存
* @param link 外链链接
*/
export interface MenuMeta {
icon: string;
link?: string;
noCache: boolean;
title: string;
}
/**
* @description: 菜单
* @param name 菜单名
* @param path 菜单路径
* @param hidden 是否隐藏
* @param component 组件名称 Layout
* @param alwaysShow 总是显示
* @param query 路由参数(json形式)
* @param meta 路由信息
* @param children 子路由信息
*/
export interface Menu {
alwaysShow?: boolean;
children: Menu[];
component: string;
hidden: boolean;
meta: MenuMeta;
name: string;
path: string;
query?: string;
redirect?: string;
}
/**
* 获取用户所有菜单
*/
export async function getAllMenusApi() {
return requestClient.get<Menu[]>('/system/menu/getRouters');
}

View File

@@ -0,0 +1,47 @@
import type { AxiosRequestConfig } from '@vben/request';
import { requestClient } from '#/api/request';
/**
* Axios上传进度事件
*/
export type AxiosProgressEvent = AxiosRequestConfig['onUploadProgress'];
/**
* 默认上传结果
*/
export interface UploadResult {
url: string;
fileName: string;
ossId: string;
}
/**
* 通过单文件上传接口
* @param file 上传的文件
* @param options 一些配置项
* @param options.onUploadProgress 上传进度事件
* @param options.signal 上传取消信号
* @param options.otherData 其他请求参数 后端拓展可能会用到
* @returns 上传结果
*/
export function uploadApi(
file: Blob | File,
options?: {
onUploadProgress?: AxiosProgressEvent;
otherData?: Record<string, any>;
signal?: AbortSignal;
},
) {
const { onUploadProgress, signal, otherData = {} } = options ?? {};
return requestClient.upload<UploadResult>(
'/resource/oss/upload',
{ file, ...otherData },
{ onUploadProgress, signal, timeout: 60_000 },
);
}
/**
* 上传api type
*/
export type UploadApi = typeof uploadApi;

View File

@@ -0,0 +1,46 @@
import { requestClient } from '#/api/request';
export interface Role {
dataScope: string;
flag: boolean;
roleId: number;
roleKey: string;
roleName: string;
roleSort: number;
status: string;
superAdmin: boolean;
}
export interface User {
avatar: string;
createTime: string;
deptId: number;
deptName: string;
email: string;
loginDate: string;
loginIp: string;
nickName: string;
phonenumber: string;
remark: string;
roles: Role[];
sex: string;
status: string;
tenantId: string;
userId: number;
userName: string;
userType: string;
}
export interface UserInfoResp {
permissions: string[];
roles: string[];
user: User;
}
/**
* 获取用户信息
* 存在返回null的情况(401) 不会抛出异常 需要手动抛异常
*/
export async function getUserInfoApi() {
return requestClient.get<null | UserInfoResp>('/system/user/getInfo');
}

View File

@@ -0,0 +1,161 @@
import { requestClient } from '#/api/request';
import type {
ExtractParams,
GraphData,
GraphInstance,
GraphStats,
IngestParams,
NeighborQueryParams,
PathQueryParams,
RetrieveParams,
SearchParams,
ExtractionResult,
GraphRetrievalResult,
GraphPath,
GraphNode,
GraphBuildTask,
} from './model';
/**
* 知识图谱API接口
*/
// ==================== 图谱实例管理 ====================
/**
* 获取图谱实例列表
*/
export function graphInstanceList(params?: any) {
return requestClient.get<any>('/graph/instance/list', { params });
}
/**
* 创建图谱实例
*/
export function graphInstanceAdd(data: Partial<GraphInstance>) {
return requestClient.post<any>('/graph/instance', data);
}
/**
* 更新图谱实例
*/
export function graphInstanceUpdate(data: Partial<GraphInstance>) {
return requestClient.put<any>('/graph/instance', data);
}
/**
* 删除图谱实例
*/
export function graphInstanceRemove(id: string | string[]) {
if (Array.isArray(id)) {
return requestClient.delete<any>('/graph/instance/batch', { data: { ids: id } });
}
return requestClient.delete<any>(`/graph/instance/${id}`);
}
/**
* 获取图谱实例详情
*/
export function graphInstanceInfo(id: string) {
return requestClient.get<GraphInstance>(`/graph/instance/${id}`);
}
/**
* 构建图谱
*/
export function graphInstanceBuild(id: string) {
return requestClient.post<any>(`/graph/instance/build/${id}`);
}
/**
* 重建图谱
*/
export function graphInstanceRebuild(id: string) {
return requestClient.post<any>(`/graph/instance/rebuild/${id}`);
}
/**
* 获取构建状态
*/
export function graphInstanceStatus(id: string) {
return requestClient.get<any>(`/graph/instance/status/${id}`);
}
/**
* 导出图谱实例数据
*/
export function graphInstanceExport(params?: any) {
return requestClient.post<Blob>('/graph/instance/export', params, {
responseType: 'blob',
});
}
// ==================== 图谱查询 ====================
/**
* 获取知识库的图谱数据
*/
export function graphQueryByKnowledge(knowledgeId: string, limit?: number) {
return requestClient.get<GraphData>(`/graph/query/knowledge/${knowledgeId}`, {
params: { limit },
});
}
/**
* 搜索实体
*/
export function graphSearchEntity(params: SearchParams) {
return requestClient.get<GraphNode[]>('/graph/query/search/entity', { params }); // ⭐ 修复路径
}
/**
* 获取邻居节点
*/
export function graphGetNeighbors(params: NeighborQueryParams) {
return requestClient.get<GraphData>('/graph/query/neighbors', { params });
}
/**
* 查找路径
*/
export function graphFindPath(params: PathQueryParams) {
return requestClient.get<GraphPath[]>('/graph/query/path', { params });
}
/**
* 获取图谱统计信息
*/
export function graphGetStats(knowledgeId: string) {
return requestClient.get<GraphStats>(`/graph/query/stats/${knowledgeId}`);
}
/**
* 删除图谱数据
*/
export function graphDeleteData(knowledgeId: string) {
return requestClient.delete<any>(`/graph/query/delete/${knowledgeId}`);
}
// ==================== 图谱RAG ====================
/**
* 实体抽取
*/
export function graphExtractEntities(data: ExtractParams) {
return requestClient.post<ExtractionResult>('/graph/query/extract', data);
}
/**
* 文本入库
*/
export function graphIngestText(data: IngestParams) {
return requestClient.post<ExtractionResult>('/graph/query/ingest', data);
}
/**
* 图谱检索
*/
export function graphRetrieve(data: RetrieveParams) {
return requestClient.post<GraphRetrievalResult>('/graph/query/retrieve', data);
}

View File

@@ -0,0 +1,166 @@
/**
* 知识图谱相关类型定义
*/
// 图谱实例
export interface GraphInstance {
id?: string;
instanceName: string;
knowledgeId: string;
knowledgeName?: string;
modelName?: string;
status?: string; // NOT_BUILT, BUILDING, COMPLETED, FAILED
nodeCount?: number;
edgeCount?: number;
entityTypes?: string;
relationTypes?: string;
createTime?: string;
updateTime?: string;
remark?: string;
}
// 图谱构建任务
export interface GraphBuildTask {
id?: string;
instanceId?: string;
taskType?: string; // FULL_BUILD, INCREMENTAL_BUILD, DOCUMENT_BUILD
status?: string; // PENDING, RUNNING, COMPLETED, FAILED, CANCELLED
taskStatus?: number; // 任务状态码(后端枚举值)
graphStatus?: number; // 图谱状态码(后端枚举值)
progress?: number;
totalDocuments?: number;
processedDocuments?: number;
nodeCount?: number;
relationshipCount?: number;
errorMessage?: string;
startTime?: string;
endTime?: string;
createTime?: string;
}
// 图谱节点
export interface GraphNode {
id?: string;
nodeId: string;
name: string;
label: string; // 实体类型
description?: string;
confidence?: number;
properties?: string; // JSON字符串
knowledgeId?: string;
}
// 图谱边
export interface GraphEdge {
id?: string;
edgeId: string;
sourceNodeId: string;
targetNodeId: string;
label: string; // 关系类型
confidence?: number;
weight?: number;
properties?: string; // JSON字符串
knowledgeId?: string;
}
// 图谱数据
export interface GraphData {
vertices: GraphNode[];
edges: GraphEdge[];
}
// 图谱统计
export interface GraphStats {
totalNodes: number;
totalEdges: number;
entityTypes: Record<string, number>;
relationTypes: Record<string, number>;
}
// 实体抽取结果
export interface ExtractedEntity {
name: string;
type: string;
description?: string;
}
export interface ExtractedRelation {
source: string;
target: string;
type: string;
description?: string;
}
export interface ExtractionResult {
entities: ExtractedEntity[];
relations: ExtractedRelation[];
}
// 图谱检索结果
export interface GraphRetrievalResult {
content: string;
relevantEntities: GraphNode[];
relevantRelations: GraphEdge[];
}
// 路径查询结果
export interface GraphPath {
nodes: GraphNode[];
edges: GraphEdge[];
length: number;
}
// 邻居查询参数
export interface NeighborQueryParams {
nodeId: string;
knowledgeId: string;
depth?: number;
}
// 路径查询参数
export interface PathQueryParams {
startNodeId: string;
endNodeId: string;
knowledgeId: string;
maxDepth?: number;
}
// 搜索参数
export interface SearchParams {
keyword: string;
knowledgeId: string;
limit?: number;
}
// 实体抽取参数
export interface ExtractParams {
text: string;
modelName?: string;
}
// 文本入库参数
export interface IngestParams {
text: string;
knowledgeId: string;
modelName?: string;
metadata?: Record<string, any>;
}
// 检索参数
export interface RetrieveParams {
query: string;
knowledgeId: string;
topK?: number;
}
// 图谱实例表单
export interface GraphInstanceForm {
id?: string;
instanceName: string;
knowledgeId: string;
modelName?: string;
entityTypes?: string[];
relationTypes?: string[];
remark?: string;
}

View File

@@ -0,0 +1,101 @@
import { $t } from '@vben/locales';
import { message, Modal } from 'ant-design-vue';
import { useAuthStore } from '#/store';
import { requestClient } from './request';
/**
* @description: contentType
*/
export const ContentTypeEnum = {
// form-data upload
FORM_DATA: 'multipart/form-data;charset=UTF-8',
// form-data qs
FORM_URLENCODED: 'application/x-www-form-urlencoded;charset=UTF-8',
// json
JSON: 'application/json;charset=UTF-8',
} as const;
/**
* 通用下载接口 封装一层
* @param url 请求地址
* @param data 请求参数
* @returns blob二进制
*/
export function commonExport(url: string, data: Record<string, any>) {
return requestClient.post<Blob>(url, data, {
data,
headers: { 'Content-Type': ContentTypeEnum.FORM_URLENCODED },
isTransformResponse: false,
responseType: 'blob',
});
}
/**
* 定义一个401专用异常 用于可能会用到的区分场景?
*/
export class UnauthorizedException extends Error {}
/**
* logout这种接口都返回401 抛出这个异常
*/
export class ImpossibleReturn401Exception extends Error {}
/**
* 是否已经处在登出过程中了 一个标志位
* 主要是防止一个页面会请求多个api 都401 会导致登出执行多次
*/
let isLogoutProcessing = false;
/**
* 防止 调用logout接口 logout又返回401 然后又走到Logout逻辑死循环
*/
let lockLogoutRequest = false;
/**
* 登出逻辑 两个地方用到 提取出来
* @throws UnauthorizedException 抛出特定的异常
*/
export function handleUnauthorizedLogout() {
const timeoutMsg = $t('http.loginTimeout');
/**
* lock 不再请求logout接口
* 这里已经算异常情况了
*/
if (lockLogoutRequest) {
throw new UnauthorizedException(timeoutMsg);
}
// 已经在登出过程中 不再执行
if (isLogoutProcessing) {
throw new UnauthorizedException(timeoutMsg);
}
isLogoutProcessing = true;
const userStore = useAuthStore();
userStore
.logout()
.catch((error) => {
/**
* logout接口返回了401
* 做Lock处理 且 该标志位不会复位(因为这种场景出现 系统已经算故障了)
* 因为这已经不符合正常的逻辑了
*/
if (error instanceof ImpossibleReturn401Exception) {
lockLogoutRequest = true;
if (import.meta.env.DEV) {
Modal.error({
title: '提示',
centered: true,
content:
'检测到你的logout接口返回了401, 去检查你的后端配置 这已经不符合正常逻辑(该提示不会在非dev环境弹出)',
});
}
}
})
.finally(() => {
message.error(timeoutMsg);
isLogoutProcessing = false;
});
// 不再执行下面逻辑
throw new UnauthorizedException(timeoutMsg);
}

View File

@@ -0,0 +1 @@
export * from './core';

View File

@@ -0,0 +1,61 @@
import type { AttachVO, AttachForm, AttachQuery } from './model';
import type { ID, IDS } from '#/api/common';
import type { PageResult } from '#/api/common';
import { commonExport } from '#/api/helper';
import { requestClient } from '#/api/request';
/**
* 查询知识库附件列表
* @param params
* @returns 知识库附件列表
*/
export function attachList(params?: AttachQuery) {
return requestClient.get<PageResult<AttachVO>>('/system/attach/list', { params });
}
/**
* 导出知识库附件列表
* @param params
* @returns 知识库附件列表
*/
export function attachExport(params?: AttachQuery) {
return commonExport('/system/attach/export', params ?? {});
}
/**
* 查询知识库附件详情
* @param id id
* @returns 知识库附件详情
*/
export function attachInfo(id: ID) {
return requestClient.get<AttachVO>(`/system/attach/${id}`);
}
/**
* 新增知识库附件
* @param data
* @returns void
*/
export function attachAdd(data: AttachForm) {
return requestClient.postWithMsg<void>('/system/attach', data);
}
/**
* 更新知识库附件
* @param data
* @returns void
*/
export function attachUpdate(data: AttachForm) {
return requestClient.putWithMsg<void>('/system/attach', data);
}
/**
* 删除知识库附件
* @param id id
* @returns void
*/
export function attachRemove(id: ID | IDS) {
return requestClient.deleteWithMsg<void>(`/system/attach/${id}`);
}

View File

@@ -0,0 +1,109 @@
import type { PageQuery, BaseEntity } from '#/api/common';
export interface AttachVO {
/**
*
*/
id: string | number;
/**
* 知识库ID
*/
knowledgeId: string | number;
/**
* 附件名称
*/
name: string;
/**
* 附件类型
*/
type: string;
/**
* 对象存储ID
*/
ossId: string | number;
/**
* 文档内容
*/
content: string;
/**
* 备注
*/
remark: string;
}
export interface AttachForm extends BaseEntity {
/**
*
*/
id?: string | number;
/**
* 知识库ID
*/
knowledgeId?: string | number;
/**
* 附件名称
*/
name?: string;
/**
* 附件类型
*/
type?: string;
/**
* 对象存储ID
*/
ossId?: string | number;
/**
* 文档内容
*/
content?: string;
/**
* 备注
*/
remark?: string;
}
export interface AttachQuery extends PageQuery {
/**
* 知识库ID
*/
knowledgeId?: string | number;
/**
* 附件名称
*/
name?: string;
/**
* 附件类型
*/
type?: string;
/**
* 对象存储ID
*/
ossId?: string | number;
/**
* 文档内容
*/
content?: string;
/**
* 日期范围参数
*/
params?: any;
}

View File

@@ -0,0 +1,61 @@
import type { FragmentVO, FragmentForm, FragmentQuery } from './model';
import type { ID, IDS } from '#/api/common';
import type { PageResult } from '#/api/common';
import { commonExport } from '#/api/helper';
import { requestClient } from '#/api/request';
/**
* 查询知识片段列表
* @param params
* @returns 知识片段列表
*/
export function fragmentList(params?: FragmentQuery) {
return requestClient.get<PageResult<FragmentVO>>('/system/fragment/list', { params });
}
/**
* 导出知识片段列表
* @param params
* @returns 知识片段列表
*/
export function fragmentExport(params?: FragmentQuery) {
return commonExport('/system/fragment/export', params ?? {});
}
/**
* 查询知识片段详情
* @param id id
* @returns 知识片段详情
*/
export function fragmentInfo(id: ID) {
return requestClient.get<FragmentVO>(`/system/fragment/${id}`);
}
/**
* 新增知识片段
* @param data
* @returns void
*/
export function fragmentAdd(data: FragmentForm) {
return requestClient.postWithMsg<void>('/system/fragment', data);
}
/**
* 更新知识片段
* @param data
* @returns void
*/
export function fragmentUpdate(data: FragmentForm) {
return requestClient.putWithMsg<void>('/system/fragment', data);
}
/**
* 删除知识片段
* @param id id
* @returns void
*/
export function fragmentRemove(id: ID | IDS) {
return requestClient.deleteWithMsg<void>(`/system/fragment/${id}`);
}

View File

@@ -0,0 +1,79 @@
import type { PageQuery, BaseEntity } from '#/api/common';
export interface FragmentVO {
/**
*
*/
id: string | number;
/**
* 附件ID
*/
attachId: string | number;
/**
* 片段索引下标
*/
idx: string | number;
/**
* 文档内容
*/
content: string;
/**
* 备注
*/
remark: string;
}
export interface FragmentForm extends BaseEntity {
/**
*
*/
id?: string | number;
/**
* 附件ID
*/
attachId?: string | number;
/**
* 片段索引下标
*/
idx?: string | number;
/**
* 文档内容
*/
content?: string;
/**
* 备注
*/
remark?: string;
}
export interface FragmentQuery extends PageQuery {
/**
* 附件ID
*/
attachId?: string | number;
/**
* 片段索引下标
*/
idx?: string | number;
/**
* 文档内容
*/
content?: string;
/**
* 日期范围参数
*/
params?: any;
}

View File

@@ -0,0 +1,61 @@
import type { InfoVO, InfoForm, InfoQuery } from './model';
import type { ID, IDS } from '#/api/common';
import type { PageResult } from '#/api/common';
import { commonExport } from '#/api/helper';
import { requestClient } from '#/api/request';
/**
* 查询知识库列表
* @param params
* @returns 知识库列表
*/
export function infoList(params?: InfoQuery) {
return requestClient.get<PageResult<InfoVO>>('/system/info/list', { params });
}
/**
* 导出知识库列表
* @param params
* @returns 知识库列表
*/
export function infoExport(params?: InfoQuery) {
return commonExport('/system/info/export', params ?? {});
}
/**
* 查询知识库详情
* @param id id
* @returns 知识库详情
*/
export function infoInfo(id: ID) {
return requestClient.get<InfoVO>(`/system/info/${id}`);
}
/**
* 新增知识库
* @param data
* @returns void
*/
export function infoAdd(data: InfoForm) {
return requestClient.postWithMsg<void>('/system/info', data);
}
/**
* 更新知识库
* @param data
* @returns void
*/
export function infoUpdate(data: InfoForm) {
return requestClient.putWithMsg<void>('/system/info', data);
}
/**
* 删除知识库
* @param id id
* @returns void
*/
export function infoRemove(id: ID | IDS) {
return requestClient.deleteWithMsg<void>(`/system/info/${id}`);
}

View File

@@ -0,0 +1,184 @@
import type { PageQuery, BaseEntity } from '#/api/common';
export interface InfoVO {
/**
* 主键
*/
id: string | number;
/**
* 用户ID
*/
userId: string | number;
/**
* 知识库名称
*/
name: string;
/**
* 是否公开知识库0 否 1是
*/
share: number;
/**
* 知识库描述
*/
description: string;
/**
* 知识分隔符
*/
separator: string;
/**
* 重叠字符数
*/
overlapChar: number;
/**
* 知识库中检索的条数
*/
retrieveLimit: number;
/**
* 文本块大小
*/
textBlockSize: number;
/**
* 向量库
*/
vectorModel: string;
/**
* 向量模型
*/
embeddingModel: string;
/**
* 备注
*/
remark: string;
}
export interface InfoForm extends BaseEntity {
/**
* 主键
*/
id?: string | number;
/**
* 用户ID
*/
userId?: string | number;
/**
* 知识库名称
*/
name?: string;
/**
* 是否公开知识库0 否 1是
*/
share?: number;
/**
* 知识库描述
*/
description?: string;
/**
* 知识分隔符
*/
separator?: string;
/**
* 重叠字符数
*/
overlapChar?: number;
/**
* 知识库中检索的条数
*/
retrieveLimit?: number;
/**
* 文本块大小
*/
textBlockSize?: number;
/**
* 向量库
*/
vectorModel?: string;
/**
* 向量模型
*/
embeddingModel?: string;
/**
* 备注
*/
remark?: string;
}
export interface InfoQuery extends PageQuery {
/**
* 用户ID
*/
userId?: string | number;
/**
* 知识库名称
*/
name?: string;
/**
* 是否公开知识库0 否 1是
*/
share?: number;
/**
* 知识库描述
*/
description?: string;
/**
* 知识分隔符
*/
separator?: string;
/**
* 重叠字符数
*/
overlapChar?: number;
/**
* 知识库中检索的条数
*/
retrieveLimit?: number;
/**
* 文本块大小
*/
textBlockSize?: number;
/**
* 向量库
*/
vectorModel?: string;
/**
* 向量模型
*/
embeddingModel?: string;
/**
* 日期范围参数
*/
params?: any;
}

View File

@@ -0,0 +1,113 @@
import type { McpMarket, McpMarketRefreshResult, McpMarketTool } from './model';
import type { ID, IDS, PageQuery, PageResult } from '#/api/common';
import { commonExport } from '#/api/helper';
import { requestClient } from '#/api/request';
enum Api {
mcpMarketExport = '/mcp/market/export',
mcpMarketList = '/mcp/market/list',
mcpMarketAll = '/mcp/market/all',
root = '/mcp/market',
}
/**
* 查询MCP市场分页列表
* @param params 请求参数
* @returns 列表
*/
export function mcpMarketList(params?: PageQuery) {
return requestClient.get<PageResult<McpMarket>>(Api.mcpMarketList, { params });
}
/**
* 查询所有MCP市场不分页
* @returns 列表
*/
export function mcpMarketAll() {
return requestClient.get<McpMarket[]>(Api.mcpMarketAll);
}
/**
* 导出MCP市场excel
* @param data 请求参数
*/
export function mcpMarketExport(data: Partial<McpMarket>) {
return commonExport(Api.mcpMarketExport, data);
}
/**
* MCP市场详情
* @param id id
* @returns 详情
*/
export function mcpMarketInfo(id: ID) {
return requestClient.get<McpMarket>(`${Api.root}/${id}`);
}
/**
* MCP市场新增
* @param data 参数
*/
export function mcpMarketAdd(data: Partial<McpMarket>) {
return requestClient.postWithMsg<void>(Api.root, data);
}
/**
* MCP市场修改
* @param data 参数
*/
export function mcpMarketUpdate(data: Partial<McpMarket>) {
return requestClient.putWithMsg<void>(Api.root, data);
}
/**
* MCP市场状态修改
* @param data 状态
*/
export function mcpMarketChangeStatus(data: any) {
return requestClient.putWithMsg<void>(
`${Api.root}/${data.id}/status?status=${data.status}`,
);
}
/**
* MCP市场删除
* @param ids id集合
*/
export function mcpMarketRemove(ids: IDS) {
return requestClient.deleteWithMsg<void>(`${Api.root}/${ids}`);
}
/**
* 刷新市场工具列表
* @param marketId 市场ID
*/
export function mcpMarketRefresh(marketId: ID) {
return requestClient.postWithMsg<McpMarketRefreshResult>(`${Api.root}/${marketId}/refresh`);
}
/**
* 加载单个工具到本地
* @param toolId 工具ID
*/
export function mcpMarketLoadTool(toolId: ID) {
return requestClient.postWithMsg<void>(`${Api.root}/tools/${toolId}/load`);
}
/**
* 批量加载工具到本地
* @param toolIds 工具ID列表
*/
export function mcpMarketBatchLoadTools(toolIds: ID[]) {
return requestClient.postWithMsg<void>(`${Api.root}/tools/batch-load`, toolIds);
}
/**
* 获取市场工具列表
* @param marketId 市场ID
*/
export function mcpMarketToolList(marketId: ID) {
return requestClient.get<McpMarketTool[]>(`${Api.root}/${marketId}/tools`);
}

View File

@@ -0,0 +1,28 @@
export interface McpMarket {
id: number;
name: string;
url: string;
description: string;
authConfig: string;
status: string;
createTime: string;
updateTime: string;
}
export interface McpMarketTool {
id: number;
marketId: number;
toolName: string;
toolDescription: string;
toolVersion: string;
toolMetadata: string;
isLoaded: boolean;
localToolId: number;
}
export interface McpMarketRefreshResult {
success: boolean;
message: string;
addedCount: number;
updatedCount: number;
}

View File

@@ -0,0 +1,90 @@
import type { McpTool, McpToolTestResult } from './model';
import type { ID, IDS, PageQuery, PageResult } from '#/api/common';
import { commonExport } from '#/api/helper';
import { requestClient } from '#/api/request';
enum Api {
mcpToolTest = '/mcp/tool',
mcpToolExport = '/mcp/tool/export',
mcpToolList = '/mcp/tool/list',
mcpToolAll = '/mcp/tool/all',
root = '/mcp/tool',
}
/**
* 查询MCP工具分页列表
* @param params 请求参数
* @returns 列表
*/
export function mcpToolList(params?: PageQuery) {
return requestClient.get<PageResult<McpTool>>(Api.mcpToolList, { params });
}
/**
* 查询所有MCP工具不分页
* @returns 列表
*/
export function mcpToolAll() {
return requestClient.get<McpTool[]>(Api.mcpToolAll);
}
/**
* 导出MCP工具excel
* @param data 请求参数
*/
export function mcpToolExport(data: Partial<McpTool>) {
return commonExport(Api.mcpToolExport, data);
}
/**
* MCP工具详情
* @param id id
* @returns 详情
*/
export function mcpToolInfo(id: ID) {
return requestClient.get<McpTool>(`${Api.root}/${id}`);
}
/**
* MCP工具新增
* @param data 参数
*/
export function mcpToolAdd(data: Partial<McpTool>) {
return requestClient.postWithMsg<void>(Api.root, data);
}
/**
* MCP工具修改
* @param data 参数
*/
export function mcpToolUpdate(data: Partial<McpTool>) {
return requestClient.putWithMsg<void>(Api.root, data);
}
/**
* MCP工具状态修改
* @param data 状态
*/
export function mcpToolChangeStatus(data: any) {
return requestClient.putWithMsg<void>(
`${Api.root}/${data.id}/status?status=${data.status}`,
);
}
/**
* MCP工具删除
* @param ids id集合
*/
export function mcpToolRemove(ids: IDS) {
return requestClient.deleteWithMsg<void>(`${Api.root}/${ids}`);
}
/**
* MCP工具测试
* @param id 工具ID
*/
export function mcpToolTest(id: ID) {
return requestClient.post<McpToolTestResult>(`${Api.root}/${id}/test`);
}

View File

@@ -0,0 +1,16 @@
export interface McpTool {
id: number;
name: string;
description: string;
type: string;
status: string;
configJson: string;
createTime: string;
updateTime: string;
}
export interface McpToolTestResult {
success: boolean;
message: string;
data?: any;
}

View File

@@ -0,0 +1,24 @@
import { requestClient } from '#/api/request';
export interface CommandStats {
name: string;
value: string;
}
export interface RedisInfo {
[key: string]: string;
}
export interface CacheInfo {
commandStats: CommandStats[];
dbSize: number;
info: RedisInfo;
}
/**
*
* @returns redis信息
*/
export function redisCacheInfo() {
return requestClient.get<CacheInfo>('/monitor/cache');
}

View File

@@ -0,0 +1,60 @@
import type { LoginLog } from './model';
import type { IDS, PageQuery, PageResult } from '#/api/common';
import { commonExport } from '#/api/helper';
import { requestClient } from '#/api/request';
enum Api {
loginInfoClean = '/monitor/logininfor/clean',
loginInfoExport = '/monitor/logininfor/export',
loginInfoList = '/monitor/logininfor/list',
root = '/monitor/logininfor',
userUnlock = '/monitor/logininfor/unlock',
}
/**
* 登录日志列表
* @param params 查询参数
* @returns list[]
*/
export function loginInfoList(params?: PageQuery) {
return requestClient.get<PageResult<LoginLog>>(Api.loginInfoList, { params });
}
/**
* 导出登录日志
* @param data 表单参数
* @returns excel
*/
export function loginInfoExport(data: any) {
return commonExport(Api.loginInfoExport, data);
}
/**
* 移除登录日志
* @param infoIds 登录日志id数组
* @returns void
*/
export function loginInfoRemove(infoIds: IDS) {
return requestClient.deleteWithMsg<void>(`${Api.root}/${infoIds}`);
}
/**
* 账号解锁
* @param username 用户名(账号)
* @returns void
*/
export function userUnlock(username: string) {
return requestClient.get<void>(`${Api.userUnlock}/${username}`, {
successMessageMode: 'message',
});
}
/**
* 清空全部登录日志
* @returns void
*/
export function loginInfoClean() {
return requestClient.deleteWithMsg<void>(Api.loginInfoClean);
}

View File

@@ -0,0 +1,13 @@
export interface LoginLog {
infoId: string;
tenantId: string;
userName: string;
status: string;
ipaddr: string;
loginLocation: string;
browser: string;
os: string;
msg: string;
loginTime: string;
clientKey: string;
}

View File

@@ -0,0 +1,45 @@
import type { OnlineUser } from './model';
import type { PageQuery, PageResult } from '#/api/common';
import { requestClient } from '#/api/request';
enum Api {
onlineList = '/monitor/online/list',
root = '/monitor/online',
}
/**
* 当前账号的在线设备 个人中心使用
* @returns OnlineUser[]
*/
export function onlineDeviceList() {
return requestClient.get<PageResult<OnlineUser>>(Api.root);
}
/**
* 这里的分页参数无效 返回的是全部的分页
* @param params 请求参数
* @returns 结果
*/
export function onlineList(params?: PageQuery) {
return requestClient.get<PageResult<OnlineUser>>(Api.onlineList, { params });
}
/**
* 强制下线
* @param tokenId 用户token
* @returns void
*/
export function forceLogout(tokenId: string) {
return requestClient.deleteWithMsg<void>(`${Api.root}/${tokenId}`);
}
/**
* 个人中心用的 跟上面的不同是用的Post
* @param tokenId 用户token
* @returns void
*/
export function forceLogout2(tokenId: string) {
return requestClient.deleteWithMsg<void>(`${Api.root}/myself/${tokenId}`);
}

View File

@@ -0,0 +1,11 @@
export interface OnlineUser {
tokenId: string;
deptName: string;
userName: string;
ipaddr: string;
loginLocation: string;
browser: string;
os: string;
loginTime: number;
deviceType: string;
}

View File

@@ -0,0 +1,47 @@
import type { OperationLog } from './model';
import type { IDS, PageQuery, PageResult } from '#/api/common';
import { commonExport } from '#/api/helper';
import { requestClient } from '#/api/request';
enum Api {
operLogClean = '/monitor/operlog/clean',
operLogExport = '/monitor/operlog/export',
operLogList = '/monitor/operlog/list',
root = '/monitor/operlog',
}
/**
* 操作日志分页
* @param params 查询参数
* @returns 分页结果
*/
export function operLogList(params?: PageQuery) {
return requestClient.get<PageResult<OperationLog>>(Api.operLogList, {
params,
});
}
/**
* 删除操作日志
* @param operIds id/ids
*/
export function operLogDelete(operIds: IDS) {
return requestClient.deleteWithMsg<void>(`${Api.root}/${operIds}`);
}
/**
* 清空全部分页日志
*/
export function operLogClean() {
return requestClient.deleteWithMsg<void>(Api.operLogClean);
}
/**
* 导出操作日志
* @param data 查询参数
*/
export function operLogExport(data: Partial<OperationLog>) {
return commonExport(Api.operLogExport, data);
}

View File

@@ -0,0 +1,21 @@
export interface OperationLog {
operId: string;
tenantId: string;
title: string;
businessType: string;
businessTypes?: any;
method: string;
requestMethod: string;
operatorType: number;
operName: string;
deptName: string;
operUrl: string;
operIp: string;
operLocation: string;
operParam: string;
jsonResult: string;
status: string;
errorMsg: string;
operTime: string;
costTime: number;
}

View File

@@ -0,0 +1,14 @@
import { requestClient } from '#/api/request';
enum Api {
addConfig = '/chat/config/saveOrUpdate',
listConfig = '/chat/config/list',
}
export function listConfig() {
return requestClient.get<any>(Api.listConfig);
}
export function addConfig(data: any) {
return requestClient.post<any>(Api.addConfig, data);
}

View File

@@ -0,0 +1,329 @@
/**
* 该文件可自行根据业务逻辑进行调整
*/
import type { HttpResponse } from '@vben/request';
import type {
BaseAsymmetricEncryption,
BaseSymmetricEncryption,
} from '@vben/utils';
import { BUSINESS_SUCCESS_CODE, UNAUTHORIZED_CODE } from '@vben/constants';
import { useAppConfig } from '@vben/hooks';
import { $t } from '@vben/locales';
import { preferences } from '@vben/preferences';
import {
authenticateResponseInterceptor,
errorMessageResponseInterceptor,
RequestClient,
stringify,
} from '@vben/request';
import { useAccessStore } from '@vben/stores';
import {
AesEncryption,
decodeBase64,
encodeBase64,
randomStr,
RsaEncryption,
} from '@vben/utils';
import { message, Modal } from 'ant-design-vue';
import { isEmpty, isNull } from 'lodash-es';
import { useAuthStore } from '#/store';
import { handleUnauthorizedLogout } from './helper';
const { apiURL, clientId, enableEncrypt, rsaPublicKey, rsaPrivateKey } =
useAppConfig(import.meta.env, import.meta.env.PROD);
/**
* 使用非对称加密的实现 前端已经实现RSA/SM2
*
* 你可以使用Sm2Encryption来替换 后端也需要同步替换公私钥对
*
* 后端文件位置: ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/filter/DecryptRequestBodyWrapper.java
*
* 注意前端sm-crypto库只能支持04开头的公钥! 否则加密会有问题 你可以使用前端的import { logSm2KeyPair } from '@vben/utils';方法来生成
* 如果你生成的公钥开头不是04 那么不能正常加密
* 或者使用这个网站来生成: https://tool.hiofd.com/sm2-key-gen/
*/
const asymmetricEncryption: BaseAsymmetricEncryption = new RsaEncryption({
publicKey: rsaPublicKey,
privateKey: rsaPrivateKey,
});
/**
* 对称加密的实现 AES/SM4
*/
const symmetricEncryption: BaseSymmetricEncryption = new AesEncryption();
function createRequestClient(baseURL: string) {
const client = new RequestClient({
// 后端地址
baseURL,
// 消息提示类型
errorMessageMode: 'message',
// 是否返回原生响应 比如:需要获取响应头时使用该属性
isReturnNativeResponse: false,
// 需要对返回数据进行处理
isTransformResponse: true,
});
/**
* 重新认证逻辑
*/
async function doReAuthenticate() {
console.warn('Access token or refresh token is invalid or expired. ');
const accessStore = useAccessStore();
const authStore = useAuthStore();
accessStore.setAccessToken(null);
if (
preferences.app.loginExpiredMode === 'modal' &&
accessStore.isAccessChecked
) {
accessStore.setLoginExpired(true);
} else {
await authStore.logout();
}
}
/**
* 刷新token逻辑
*/
async function doRefreshToken() {
// 不需要
// 保留此方法只是为了合并方便
return '';
}
function formatToken(token: null | string) {
return token ? `Bearer ${token}` : null;
}
client.addRequestInterceptor({
fulfilled: (config) => {
const accessStore = useAccessStore();
// 添加token
config.headers.Authorization = formatToken(accessStore.accessToken);
const isFileUpload =
config.data instanceof FormData ||
config.data instanceof File ||
config.data instanceof Blob;
if (isFileUpload) {
delete config.headers['Content-Type'];
}
/**
* locale跟后台不一致 需要转换
*/
const language = preferences.app.locale.replace('-', '_');
config.headers['Accept-Language'] = language;
config.headers['Content-Language'] = language;
/**
* 添加全局clientId
* 关于header的clientId被错误绑定到实体类
* https://gitee.com/dapppp/ruoyi-plus-vben5/issues/IC0BDS
*/
config.headers.ClientID = clientId;
/**
* 格式化get/delete参数
* 如果包含自定义的paramsSerializer则不走此逻辑
*/
if (
['DELETE', 'GET'].includes(config.method?.toUpperCase() || '') &&
config.params &&
!config.paramsSerializer
) {
/**
* 1. 格式化参数 微服务在传递区间时间选择(后端的params Map类型参数)需要格式化key 否则接收不到
* 2. 数组参数需要格式化 后端才能正常接收 会变成arr=1&arr=2&arr=3的格式来接收
*/
config.paramsSerializer = (params) =>
stringify(params, { arrayFormat: 'repeat' });
}
const { encrypt } = config;
// 全局开启请求加密功能 && 该请求开启 && 是post/put请求
if (
!isFileUpload &&
enableEncrypt &&
encrypt &&
['POST', 'PUT'].includes(config.method?.toUpperCase() || '')
) {
// sm4这里改为randomStr(16)
const key = randomStr(32);
const keyWithBase64 = encodeBase64(key);
config.headers['encrypt-key'] =
asymmetricEncryption.encrypt(keyWithBase64);
/**
* axios会默认给字符串前后加上引号 RSA可以正常解密(加不加都能解密) 但是SM2不行(大坑!!!)
* 这里通过transformRequest强制返回原始内容
*/
config.transformRequest = (data) => data;
config.data =
typeof config.data === 'object'
? symmetricEncryption.encrypt(JSON.stringify(config.data), key)
: symmetricEncryption.encrypt(config.data, key);
}
return config;
},
});
// 通用的错误处理, 如果没有进入上面的错误处理逻辑,就会进入这里
// 主要处理http状态码不为200(如网络异常/离线)的情况 必须放在在下面的响应拦截器之前
client.addResponseInterceptor(
errorMessageResponseInterceptor((msg: string) => message.error(msg)),
);
client.addResponseInterceptor<HttpResponse>({
fulfilled: async (response) => {
const encryptKey = (response.headers ?? {})['encrypt-key'];
if (encryptKey) {
/** RSA私钥解密 拿到解密秘钥的base64 */
const base64Str = asymmetricEncryption.decrypt(encryptKey);
/** base64 解码 得到请求头的 AES 秘钥 */
const secret = decodeBase64(base64Str);
/** 使用aesKey解密 responseData */
const decryptData = symmetricEncryption.decrypt(
response.data as unknown as string,
secret,
);
/** 赋值 需要转为对象 */
response.data = JSON.parse(decryptData);
}
const { isReturnNativeResponse, isTransformResponse } = response.config;
// 是否返回原生响应 比如:需要获取响应时使用该属性
if (isReturnNativeResponse) {
return response;
}
// 不进行任何处理,直接返回
// 用于页面代码可能需要直接获取codedatamessage这些信息时开启
if (!isTransformResponse) {
/**
* @warning 注意 微服务版本在401(网关)会返回text/plain的头 所以这里代码会无效
* 我建议你改后端而不是前端来做兼容
*/
// json数据的判断
if (response.headers['content-type']?.includes?.('application/json')) {
/**
* 需要判断是否登录超时/401
* 执行登出操作
*/
const resp = response.data as unknown as HttpResponse;
// 抛出异常 不再执行
if (
typeof resp === 'object' &&
Reflect.has(resp, 'code') &&
resp.code === UNAUTHORIZED_CODE
) {
handleUnauthorizedLogout();
}
/**
* 需要判断下载二进制的情况 正常是返回二进制 报错会返回json
* 当type为blob且content-type为application/json时 则判断已经下载出错
*/
if (response.config.responseType === 'blob') {
// 这时候的data为blob类型
const blob = response.data as unknown as Blob;
// 拿到字符串转json对象
response.data = JSON.parse(await blob.text());
// 然后按正常逻辑执行下面的代码(判断业务状态码)
} else {
// 其他类型数据 直接返回
return response.data;
}
} else {
// 非json数据 直接返回 不做校验
return response.data;
}
}
const axiosResponseData = response.data;
if (!axiosResponseData) {
throw new Error($t('http.apiRequestFailed'));
}
// 后端并没有采用严格的{code, msg, data}模式
const { code, data, msg, ...other } = axiosResponseData;
// 业务状态码为200 则请求成功
const hasSuccess =
Reflect.has(axiosResponseData, 'code') &&
code === BUSINESS_SUCCESS_CODE;
if (hasSuccess) {
let successMsg = msg;
if (isNull(successMsg) || isEmpty(successMsg)) {
successMsg = $t(`http.operationSuccess`);
}
if (response.config.successMessageMode === 'modal') {
Modal.success({
content: successMsg,
title: $t('http.successTip'),
});
} else if (response.config.successMessageMode === 'message') {
message.success(successMsg);
}
// 分页情况下为code msg rows total 并没有data字段
// 如果有data 直接返回data 没有data将剩余参数(...other)封装为data返回
// 需要考虑data为null的情况(比如查询为空) 所以这里直接判断undefined
if (data !== undefined) {
return data;
}
// 没有data 将其他参数包装为data
return other;
}
// 在此处根据自己项目的实际情况对不同的code执行不同的操作
// 如果不希望中断当前请求请return数据否则直接抛出异常即可
let timeoutMsg = '';
switch (code) {
// 登录超时
case UNAUTHORIZED_CODE: {
handleUnauthorizedLogout();
break;
}
default: {
if (msg) {
timeoutMsg = msg;
}
}
}
// errorMessageMode='modal'的时候会显示modal错误弹窗而不是消息提示用于一些比较重要的错误
// errorMessageMode='none' 一般是调用时明确表示不希望自动弹出错误提示
if (response.config.errorMessageMode === 'modal') {
Modal.error({
content: timeoutMsg,
title: $t('http.errorTip'),
});
} else if (response.config.errorMessageMode === 'message') {
message.error(timeoutMsg);
}
throw new Error(timeoutMsg || $t('http.apiRequestFailed'));
},
});
// token过期的处理
client.addResponseInterceptor(
authenticateResponseInterceptor({
client,
doReAuthenticate,
doRefreshToken,
enableRefreshToken: preferences.app.enableRefreshToken,
formatToken,
}),
);
return client;
}
export const requestClient = createRequestClient(apiURL);
export const baseRequestClient = new RequestClient({ baseURL: apiURL });

View File

@@ -0,0 +1,75 @@
import type { Client } from './model';
import type { ID, IDS, PageQuery, PageResult } from '#/api/common';
import { commonExport } from '#/api/helper';
import { requestClient } from '#/api/request';
enum Api {
clientChangeStatus = '/system/client/changeStatus',
clientExport = '/system/client/export',
clientList = '/system/client/list',
root = '/system/client',
}
/**
* 查询客户端分页列表
* @param params 请求参数
* @returns 列表
*/
export function clientList(params?: PageQuery) {
return requestClient.get<PageResult<Client>>(Api.clientList, { params });
}
/**
* 导出客户端excel
* @param data 请求参数
*/
export function clientExport(data: Partial<Client>) {
return commonExport(Api.clientExport, data);
}
/**
* 客户端详情
* @param id id
* @returns 详情
*/
export function clientInfo(id: ID) {
return requestClient.get<Client>(`${Api.root}/${id}`);
}
/**
* 客户端新增
* @param data 参数
*/
export function clientAdd(data: Partial<Client>) {
return requestClient.postWithMsg<void>(Api.root, data);
}
/**
* 客户端修改
* @param data 参数
*/
export function clientUpdate(data: Partial<Client>) {
return requestClient.putWithMsg<void>(Api.root, data);
}
/**
* 客户端状态修改
* @param data 状态
*/
export function clientChangeStatus(data: any) {
const requestData = {
clientId: data.clientId,
status: data.status,
};
return requestClient.putWithMsg<void>(Api.clientChangeStatus, requestData);
}
/**
* 客户端删除
* @param ids id集合
*/
export function clientRemove(ids: IDS) {
return requestClient.deleteWithMsg<void>(`${Api.root}/${ids}`);
}

View File

@@ -0,0 +1,12 @@
export interface Client {
id: number;
clientId: string;
clientKey: string;
clientSecret: string;
grantTypeList: string[];
grantType: string;
deviceType: string;
activeTimeout: number;
timeout: number;
status: string;
}

View File

@@ -0,0 +1,76 @@
import type { SysConfig } from './model';
import type { ID, IDS, PageQuery, PageResult } from '#/api/common';
import { commonExport } from '#/api/helper';
import { requestClient } from '#/api/request';
enum Api {
configExport = '/system/config/export',
configInfoByKey = '/system/config/configKey',
configList = '/system/config/list',
configRefreshCache = '/system/config/refreshCache',
root = '/system/config',
}
/**
* 系统参数分页列表
* @param params 请求参数
* @returns 列表
*/
export function configList(params?: PageQuery) {
return requestClient.get<PageResult<SysConfig>>(Api.configList, { params });
}
export function configInfo(configId: ID) {
return requestClient.get<SysConfig>(`${Api.root}/${configId}`);
}
/**
* 导出
* @param data 参数
*/
export function configExport(data: Partial<SysConfig>) {
return commonExport(Api.configExport, data);
}
/**
* 刷新缓存
* @returns void
*/
export function configRefreshCache() {
return requestClient.deleteWithMsg<void>(Api.configRefreshCache);
}
/**
* 更新系统配置
* @param data 参数
*/
export function configUpdate(data: Partial<SysConfig>) {
return requestClient.putWithMsg<void>(Api.root, data);
}
/**
* 新增系统配置
* @param data 参数
*/
export function configAdd(data: Partial<SysConfig>) {
return requestClient.postWithMsg<void>(Api.root, data);
}
/**
* 删除配置
* @param configIds ids
*/
export function configRemove(configIds: IDS) {
return requestClient.deleteWithMsg<void>(`${Api.root}/${configIds}`);
}
/**
* 获取配置信息
* @param configKey configKey
* @returns value
*/
export function configInfoByKey(configKey: string) {
return requestClient.get<string>(`${Api.configInfoByKey}/${configKey}`);
}

View File

@@ -0,0 +1,9 @@
export interface SysConfig {
configId: number;
configName: string;
configKey: string;
configValue: string;
configType: string;
remark: string;
createTime: string;
}

View File

@@ -0,0 +1,62 @@
import type { Dept } from './model';
import type { ID } from '#/api/common';
import { requestClient } from '#/api/request';
enum Api {
deptList = '/system/dept/list',
deptNodeInfo = '/system/dept/list/exclude',
root = '/system/dept',
}
/**
* 部门列表
* @returns list
*/
export function deptList(params?: { deptName?: string; status?: string }) {
return requestClient.get<Dept[]>(Api.deptList, { params });
}
/**
* 查询部门列表(排除节点)
* @param deptId 部门ID
* @returns void
*/
export function deptNodeList(deptId: ID) {
return requestClient.get<Dept[]>(`${Api.deptNodeInfo}/${deptId}`);
}
/**
* 部门详情
* @param deptId 部门id
* @returns 部门信息
*/
export function deptInfo(deptId: ID) {
return requestClient.get<Dept>(`${Api.root}/${deptId}`);
}
/**
* 部门新增
* @param data 参数
*/
export function deptAdd(data: Partial<Dept>) {
return requestClient.postWithMsg<void>(Api.root, data);
}
/**
* 部门更新
* @param data 参数
*/
export function deptUpdate(data: Partial<Dept>) {
return requestClient.putWithMsg<void>(Api.root, data);
}
/**
* 注意这里只允许单删除
* @param deptId ID
* @returns void
*/
export function deptRemove(deptId: ID) {
return requestClient.deleteWithMsg<void>(`${Api.root}/${deptId}`);
}

View File

@@ -0,0 +1,19 @@
export interface Dept {
createBy: string;
createTime: string;
updateBy?: string;
updateTime?: string;
remark?: string;
deptId: number;
parentId: number;
ancestors: string;
deptName: string;
orderNum: number;
leader: string;
phone: string;
email: string;
status: string;
delFlag: string;
parentName?: string;
children?: Dept[];
}

View File

@@ -0,0 +1,17 @@
export interface DictData {
createBy: string;
createTime: string;
cssClass: string;
default: boolean;
dictCode: number;
dictLabel: string;
dictSort: number;
dictType: string;
dictValue: string;
isDefault: string;
listClass: string;
remark: string;
status: string;
updateBy?: any;
updateTime?: any;
}

View File

@@ -0,0 +1,75 @@
import type { DictData } from './dict-data-model';
import type { ID, IDS, PageQuery } from '#/api/common';
import { commonExport } from '#/api/helper';
import { requestClient } from '#/api/request';
enum Api {
dictDataExport = '/system/dict/data/export',
dictDataList = '/system/dict/data/list',
root = '/system/dict/data',
}
/**
* 主要是DictTag组件使用
* @param dictType 字典类型
* @returns 字典数据
*/
export function dictDataInfo(dictType: string) {
return requestClient.get<DictData[]>(`${Api.root}/type/${dictType}`);
}
/**
* 字典数据
* @param params 查询参数
* @returns 字典数据列表
*/
export function dictDataList(params?: PageQuery) {
return requestClient.get<DictData[]>(Api.dictDataList, { params });
}
/**
* 导出字典数据
* @param data 表单参数
* @returns blob
*/
export function dictDataExport(data: Partial<DictData>) {
return commonExport(Api.dictDataExport, data);
}
/**
* 删除
* @param dictIds 字典ID Array
* @returns void
*/
export function dictDataRemove(dictIds: IDS) {
return requestClient.deleteWithMsg<void>(`${Api.root}/${dictIds}`);
}
/**
* 新增
* @param data 表单参数
* @returns void
*/
export function dictDataAdd(data: Partial<DictData>) {
return requestClient.postWithMsg<void>(Api.root, data);
}
/**
* 修改
* @param data 表单参数
* @returns void
*/
export function dictDataUpdate(data: Partial<DictData>) {
return requestClient.putWithMsg<void>(Api.root, data);
}
/**
* 查询字典数据详细
* @param dictCode 字典编码
* @returns 字典数据
*/
export function dictDetailInfo(dictCode: ID) {
return requestClient.get<DictData>(`${Api.root}/${dictCode}`);
}

View File

@@ -0,0 +1,8 @@
export interface DictType {
createTime: string;
dictId: number;
dictName: string;
dictType: string;
remark: string;
status: string;
}

View File

@@ -0,0 +1,85 @@
import type { DictType } from './dict-type-model';
import type { ID, IDS, PageQuery, PageResult } from '#/api/common';
import { commonExport } from '#/api/helper';
import { requestClient } from '#/api/request';
enum Api {
dictOptionSelectList = '/system/dict/type/optionselect',
dictTypeExport = '/system/dict/type/export',
dictTypeList = '/system/dict/type/list',
dictTypeRefreshCache = '/system/dict/type/refreshCache',
root = '/system/dict/type',
}
/**
* 获取字典类型列表
* @param params 请求参数
* @returns list
*/
export function dictTypeList(params?: PageQuery) {
return requestClient.get<PageResult<DictType>>(Api.dictTypeList, { params });
}
/**
* 导出字典类型列表
* @param data 表单参数
* @returns blob
*/
export function dictTypeExport(data: Partial<DictType>) {
return commonExport(Api.dictTypeExport, data);
}
/**
* 删除字典类型
* @param dictIds 字典类型id数组
* @returns void
*/
export function dictTypeRemove(dictIds: IDS) {
return requestClient.deleteWithMsg<void>(`${Api.root}/${dictIds}`);
}
/**
* 刷新字典缓存
* @returns void
*/
export function refreshDictTypeCache() {
return requestClient.deleteWithMsg<void>(Api.dictTypeRefreshCache);
}
/**
* 新增
* @param data 表单参数
* @returns void
*/
export function dictTypeAdd(data: Partial<DictType>) {
return requestClient.postWithMsg<void>(Api.root, data);
}
/**
* 修改
* @param data 表单参数
* @returns void
*/
export function dictTypeUpdate(data: Partial<DictType>) {
return requestClient.putWithMsg<void>(Api.root, data);
}
/**
* 查询详情
* @param dictId 字典类型id
* @returns 信息
*/
export function dictTypeInfo(dictId: ID) {
return requestClient.get<DictType>(`${Api.root}/${dictId}`);
}
/**
* 这个在ele用到 v5用不上
* 下拉框 返回值和list一样
* @returns options
*/
export function dictOptionSelectList() {
return requestClient.get<DictType[]>(Api.dictOptionSelectList);
}

View File

@@ -0,0 +1,35 @@
import type { DictData } from './dict-data-model';
import type { DictType } from './dict-type-model';
import { dictDataInfo } from './dict-data';
export type { DictData, DictType };
export {
dictDataInfo,
dictDataList,
dictDataExport,
dictDataRemove,
dictDataAdd,
dictDataUpdate,
dictDetailInfo,
} from './dict-data';
export {
dictTypeList,
dictTypeExport,
dictTypeRemove,
refreshDictTypeCache,
dictTypeAdd,
dictTypeUpdate,
dictTypeInfo,
dictOptionSelectList,
} from './dict-type';
/**
* 获取字典数据项 (dictDataInfo的别名)
* @param dictType 字典类型
* @returns 字典数据
*/
export function getDictItems(dictType: string) {
return dictDataInfo(dictType);
}

View File

@@ -0,0 +1,92 @@
import type { Menu, MenuOption, MenuQuery, MenuResp } from './model';
import type { ID, IDS } from '#/api/common';
import { requestClient } from '#/api/request';
enum Api {
menuList = '/system/menu/list',
menuTreeSelect = '/system/menu/treeselect',
roleMenuTree = '/system/menu/roleMenuTreeselect',
root = '/system/menu',
tenantPackageMenuTreeselect = '/system/menu/tenantPackageMenuTreeselect',
}
/**
* 菜单列表
* @param params 参数
* @returns 列表
*/
export function menuList(params?: MenuQuery) {
return requestClient.get<Menu[]>(Api.menuList, { params });
}
/**
* 菜单详情
* @param menuId 菜单id
* @returns 菜单详情
*/
export function menuInfo(menuId: ID) {
return requestClient.get<Menu>(`${Api.root}/${menuId}`);
}
/**
* 菜单新增
* @param data 参数
*/
export function menuAdd(data: Partial<Menu>) {
return requestClient.postWithMsg<void>(Api.root, data);
}
/**
* 菜单更新
* @param data 参数
*/
export function menuUpdate(data: Partial<Menu>) {
return requestClient.putWithMsg<void>(Api.root, data);
}
/**
* 菜单删除
* @param menuIds ids
*/
export function menuRemove(menuIds: IDS) {
return requestClient.deleteWithMsg<void>(`${Api.root}/${menuIds}`);
}
/**
* 返回对应角色的菜单
* @param roleId id
* @returns resp
*/
export function roleMenuTreeSelect(roleId: ID) {
return requestClient.get<MenuResp>(`${Api.roleMenuTree}/${roleId}`);
}
/**
* 下拉框使用 返回所有的菜单
* @returns []
*/
export function menuTreeSelect() {
return requestClient.get<MenuOption[]>(Api.menuTreeSelect);
}
/**
* 租户套餐使用
* @param packageId packageId
* @returns resp
*/
export function tenantPackageMenuTreeSelect(packageId: ID) {
return requestClient.get<MenuResp>(
`${Api.tenantPackageMenuTreeselect}/${packageId}`,
);
}
/**
* 批量删除菜单
* @param menuIds 菜单ids
* @returns void
*/
export function menuCascadeRemove(menuIds: IDS) {
return requestClient.deleteWithMsg<void>(`${Api.root}/cascade/${menuIds}`);
}

View File

@@ -0,0 +1,57 @@
export interface Menu {
createBy?: any;
createTime: string;
updateBy?: any;
updateTime?: any;
remark?: any;
menuId: number;
menuName: string;
parentName?: string;
parentId: number;
orderNum: number;
path: string;
component?: string;
query: string;
isFrame: string;
isCache: string;
menuType: string;
visible: string;
status: string;
perms: string;
icon: string;
children: Menu[];
}
/**
* @description 菜单信息
* @param label 菜单名称
*/
export interface MenuOption {
id: number;
parentId: number;
label: string;
weight: number;
children: MenuOption[];
key: string; // 实际上不存在 ide报错
menuType: string;
icon: string;
}
/**
* @description 菜单返回
* @param checkedKeys 选中的菜单id
* @param menus 菜单信息
*/
export interface MenuResp {
checkedKeys: number[];
menus: MenuOption[];
}
/**
* 菜单表单查询
*/
export interface MenuQuery {
menuName?: string;
visible?: string;
status?: string;
}

View File

@@ -0,0 +1,52 @@
import type { Notice } from './model';
import type { ID, IDS, PageQuery } from '#/api/common';
import { requestClient } from '#/api/request';
enum Api {
noticeList = '/system/notice/list',
root = '/system/notice',
}
/**
* 通知公告分页
* @param params 分页参数
* @returns 分页结果
*/
export function noticeList(params?: PageQuery) {
return requestClient.get<Notice[]>(Api.noticeList, { params });
}
/**
* 通知公告详情
* @param noticeId id
* @returns 详情
*/
export function noticeInfo(noticeId: ID) {
return requestClient.get<Notice>(`${Api.root}/${noticeId}`);
}
/**
* 通知公告新增
* @param data 参数
*/
export function noticeAdd(data: Partial<Notice>) {
return requestClient.postWithMsg<void>(Api.root, data);
}
/**
* 通知公告更新
* @param data 参数
*/
export function noticeUpdate(data: any) {
return requestClient.putWithMsg<void>(Api.root, data);
}
/**
* 通知公告删除
* @param noticeIds ids
*/
export function noticeRemove(noticeIds: IDS) {
return requestClient.deleteWithMsg<void>(`${Api.root}/${noticeIds}`);
}

View File

@@ -0,0 +1,11 @@
export interface Notice {
noticeId: number;
noticeTitle: string;
noticeType: string;
noticeContent: string;
status: string;
remark: string;
createBy: number;
createByName: string;
createTime: string;
}

View File

@@ -0,0 +1,46 @@
import type { OssConfig } from './model';
import type { ID, IDS, PageQuery } from '#/api/common';
import { requestClient } from '#/api/request';
enum Api {
ossConfigChangeStatus = '/resource/oss/config/changeStatus',
ossConfigList = '/resource/oss/config/list',
root = '/resource/oss/config',
}
// 获取OSS配置列表
export function ossConfigList(params?: PageQuery) {
return requestClient.get<OssConfig[]>(Api.ossConfigList, { params });
}
// 获取OSS配置的信息
export function ossConfigInfo(ossConfigId: ID) {
return requestClient.get<OssConfig>(`${Api.root}/${ossConfigId}`);
}
// 添加新的OSS配置
export function ossConfigAdd(data: Partial<OssConfig>) {
return requestClient.postWithMsg<void>(Api.root, data);
}
// 更新现有的OSS配置
export function ossConfigUpdate(data: Partial<OssConfig>) {
return requestClient.putWithMsg<void>(Api.root, data);
}
// 删除OSS配置
export function ossConfigRemove(ossConfigIds: IDS) {
return requestClient.deleteWithMsg<void>(`${Api.root}/${ossConfigIds}`);
}
// 更改OSS配置的状态
export function ossConfigChangeStatus(data: any) {
const requestData: Partial<OssConfig> = {
ossConfigId: data.ossConfigId,
status: data.status,
configKey: data.configKey,
};
return requestClient.putWithMsg(Api.ossConfigChangeStatus, requestData);
}

View File

@@ -0,0 +1,16 @@
export interface OssConfig {
ossConfigId: number;
configKey: string;
accessKey: string;
secretKey: string;
bucketName: string;
prefix: string;
endpoint: string;
domain: string;
isHttps: string;
region: string;
status: string;
ext1: string;
remark: string;
accessPolicy: string;
}

View File

@@ -0,0 +1,89 @@
import type { AxiosRequestConfig } from '@vben/request';
import type { OssFile } from './model';
import type { ID, IDS, PageQuery, PageResult } from '#/api/common';
import { ContentTypeEnum } from '#/api/helper';
import { requestClient } from '#/api/request';
enum Api {
ossDownload = '/resource/oss/download',
ossInfo = '/resource/oss/listByIds',
ossList = '/resource/oss/list',
ossUpload = '/resource/oss/upload',
root = '/resource/oss',
}
/**
* 文件list
* @param params 参数
* @returns 分页
*/
export function ossList(params?: PageQuery) {
return requestClient.get<PageResult<OssFile>>(Api.ossList, { params });
}
/**
* 查询文件信息 返回为数组
* @param ossIds id数组
* @returns 信息数组
*/
export function ossInfo(ossIds: ID | IDS) {
return requestClient.get<OssFile[]>(`${Api.ossInfo}/${ossIds}`);
}
/**
* @deprecated 使用apps/web-antd/src/api/core/upload.ts uploadApi方法
* @param file 文件
* @returns void
*/
export function ossUpload(file: Blob | File) {
const formData = new FormData();
formData.append('file', file);
return requestClient.postWithMsg(Api.ossUpload, formData, {
headers: { 'Content-Type': ContentTypeEnum.FORM_DATA },
timeout: 30 * 1000,
});
}
/**
* 下载文件 返回为二进制
* @param ossId ossId
* @param onDownloadProgress 下载进度(可选)
* @returns blob
*/
export function ossDownload(
ossId: ID,
onDownloadProgress?: AxiosRequestConfig['onDownloadProgress'],
) {
return requestClient.get<Blob>(`${Api.ossDownload}/${ossId}`, {
responseType: 'blob',
timeout: 30 * 1000,
isTransformResponse: false,
onDownloadProgress,
});
}
/**
* 在使用浏览器原生下载前检测是否登录
* 这里的方案为请求一次接口 如果登录超时会走到response的401逻辑
* 如果没有listByIds的权限 也不会弹出无权限提示
* 仅仅是为了检测token是否有效使用
*
* @returns void
*/
export function checkLoginBeforeDownload() {
return requestClient.get<OssFile[]>(`${Api.ossInfo}/1`, {
errorMessageMode: 'none',
});
}
/**
* 删除文件
* @param ossIds id数组
* @returns void
*/
export function ossRemove(ossIds: IDS) {
return requestClient.deleteWithMsg<void>(`${Api.root}/${ossIds}`);
}

View File

@@ -0,0 +1,28 @@
export interface OssFile {
ossId: string;
fileName: string;
originalName: string;
fileSuffix: string;
url: string;
createTime: string;
createBy: number;
createByName: string;
service: string;
}
export interface OssConfig {
ossConfigId: number;
configKey: string;
accessKey: string;
secretKey: string;
bucketName: string;
prefix: string;
endpoint: string;
domain: string;
isHttps: string;
region: string;
status: string;
ext1: string;
remark: string;
accessPolicy: string;
}

View File

@@ -0,0 +1,85 @@
import type { DeptTree } from '../user/model';
import type { Post } from './model';
import type { ID, IDS, PageQuery } from '#/api/common';
import { commonExport } from '#/api/helper';
import { requestClient } from '#/api/request';
enum Api {
postExport = '/system/post/export',
postList = '/system/post/list',
postSelect = '/system/post/optionselect',
root = '/system/post',
}
/**
* 获取岗位列表
* @param params 参数
* @returns Post[]
*/
export function postList(params?: PageQuery) {
return requestClient.get<Post[]>(Api.postList, { params });
}
/**
* 导出岗位信息
* @param data 请求参数
* @returns blob
*/
export function postExport(data: Partial<Post>) {
return commonExport(Api.postExport, data);
}
/**
* 查询岗位信息
* @param postId id
* @returns 岗位信息
*/
export function postInfo(postId: ID) {
return requestClient.get<Post>(`${Api.root}/${postId}`);
}
/**
* 岗位新增
* @param data 参数
* @returns void
*/
export function postAdd(data: Partial<Post>) {
return requestClient.postWithMsg<void>(Api.root, data);
}
/**
* 岗位更新
* @param data 参数
* @returns void
*/
export function postUpdate(data: Partial<Post>) {
return requestClient.putWithMsg<void>(Api.root, data);
}
/**
* 岗位删除
* @param postIds ids
* @returns void
*/
export function postRemove(postIds: IDS) {
return requestClient.deleteWithMsg<void>(`${Api.root}/${postIds}`);
}
/**
* 根据部门id获取岗位下拉列表
* @param deptId 部门id
* @returns 岗位
*/
export function postOptionSelect(deptId: ID) {
return requestClient.get<Post[]>(Api.postSelect, { params: { deptId } });
}
/**
* 岗位专用 - 获取部门树
* @returns 部门树
*/
export function postDeptTreeSelect() {
return requestClient.get<DeptTree[]>('/system/post/deptTree');
}

View File

@@ -0,0 +1,12 @@
/**
* @description: Post interface
*/
export interface Post {
postId: number;
postCode: string;
postName: string;
postSort: number;
status: string;
remark: string;
createTime: string;
}

View File

@@ -0,0 +1,65 @@
import type { FileCallBack, UpdatePasswordParam, UserProfile } from './model';
import { buildUUID } from '@vben/utils';
import { requestClient } from '#/api/request';
enum Api {
root = '/system/user/profile',
updateAvatar = '/system/user/profile/avatar',
updatePassword = '/system/user/profile/updatePwd',
}
/**
* 用户个人主页信息
* @returns userInformation
*/
export function userProfile() {
return requestClient.get<UserProfile>(Api.root);
}
/**
* 更新用户个人主页信息
* @param data
* @returns void
*/
export function userProfileUpdate(data: any) {
return requestClient.putWithMsg<void>(Api.root, data);
}
/**
* 用户修改密码 (需要加密)
* @param data
* @returns void
*/
export function userUpdatePassword(data: UpdatePasswordParam) {
return requestClient.putWithMsg<void>(Api.updatePassword, data, {
encrypt: true,
});
}
/**
* 用户更新个人头像
* @param fileCallback data
* @returns void
*/
export function userUpdateAvatar(fileCallback: FileCallBack) {
/** 直接点击头像上传 filename为空 由于后台通过拓展名判断(默认文件名blob) 会上传失败 */
let { file } = fileCallback;
const { filename } = fileCallback;
/**
* Blob转File类型
* 1. 在直接点击确认 filename为空 取uuid作为文件名
* 2. 选择上传必须转为File类型 Blob类型上传后台获取文件名为空
*/
file = filename
? new File([file], filename)
: new File([file], `${buildUUID()}.png`);
return requestClient.post(
Api.updateAvatar,
{
avatarfile: file,
},
{ headers: { 'Content-Type': 'multipart/form-data' } },
);
}

View File

@@ -0,0 +1,75 @@
export interface Dept {
deptId: number;
parentId: number;
parentName?: any;
ancestors: string;
deptName: string;
orderNum: number;
leader: string;
phone?: any;
email: string;
status: string;
createTime?: any;
}
export interface Role {
roleId: number;
roleName: string;
roleKey: string;
roleSort: number;
dataScope: string;
menuCheckStrictly?: any;
deptCheckStrictly?: any;
status: string;
remark: string;
createTime?: any;
flag: boolean;
superAdmin: boolean;
}
export interface User {
userId: number;
tenantId: string;
deptId: number;
userName: string;
nickName: string;
userType: string;
email: string;
phonenumber: string;
sex: string;
avatar: string;
status: string;
loginIp: string;
loginDate: string;
remark: string;
createTime: string;
dept: Dept;
roles: Role[];
roleIds?: string[];
postIds?: string[];
roleId: number;
deptName: string;
}
/**
* @description 用户个人主页信息
* @param user 用户信息
* @param roleGroup 角色名称
* @param postGroup 岗位名称
*/
export interface UserProfile {
user: User;
roleGroup: string;
postGroup: string;
}
export interface UpdatePasswordParam {
oldPassword: string;
newPassword: string;
}
interface FileCallBack {
name: string;
file: Blob;
filename: string;
}

View File

@@ -0,0 +1,166 @@
import type { User } from '../user/model';
import type { DeptResp, Role } from './model';
import type { ID, IDS, PageQuery, PageResult } from '#/api/common';
import { commonExport } from '#/api/helper';
import { requestClient } from '#/api/request';
enum Api {
roleAllocatedList = '/system/role/authUser/allocatedList',
roleAuthCancel = '/system/role/authUser/cancel',
roleAuthCancelAll = '/system/role/authUser/cancelAll',
roleAuthSelectAll = '/system/role/authUser/selectAll',
roleChangeStatus = '/system/role/changeStatus',
roleDataScope = '/system/role/dataScope',
roleDeptTree = '/system/role/deptTree',
roleExport = '/system/role/export',
roleList = '/system/role/list',
roleOptionSelect = '/system/role/optionselect',
roleUnallocatedList = '/system/role/authUser/unallocatedList',
root = '/system/role',
}
/**
* 查询角色分页列表
* @param params 搜索条件
* @returns 分页列表
*/
export function roleList(params?: PageQuery) {
return requestClient.get<PageResult<Role>>(Api.roleList, { params });
}
/**
* 导出角色信息
* @param data 查询参数
* @returns blob
*/
export function roleExport(data: Partial<Role>) {
return commonExport(Api.roleExport, data);
}
/**
* 查询角色信息
* @param roleId 角色id
* @returns 角色信息
*/
export function roleInfo(roleId: ID) {
return requestClient.get<Role>(`${Api.root}/${roleId}`);
}
/**
* 角色新增
* @param data 参数
* @returns void
*/
export function roleAdd(data: Partial<Role>) {
return requestClient.postWithMsg<void>(Api.root, data);
}
/**
* 角色更新
* @param data 参数
* @returns void
*/
export function roleUpdate(data: Partial<Role>) {
return requestClient.putWithMsg<void>(Api.root, data);
}
/**
* 修改角色状态
* @param data 参数
* @returns void
*/
export function roleChangeStatus(data: Partial<Role>) {
const requestData = {
roleId: data.roleId,
status: data.status,
};
return requestClient.putWithMsg<void>(Api.roleChangeStatus, requestData);
}
/**
* 角色删除
* @param roleIds ids
* @returns void
*/
export function roleRemove(roleIds: IDS) {
return requestClient.deleteWithMsg<void>(`${Api.root}/${roleIds}`);
}
/**
* 更新数据权限
* @param data
* @returns void
*/
export function roleDataScope(data: any) {
return requestClient.putWithMsg<void>(Api.roleDataScope, data);
}
/**
* @deprecated 全局并没有用到这个方法
*/
export function roleOptionSelect(params?: any) {
return requestClient.get(Api.roleOptionSelect, { params });
}
/**
* 已分配角色的用户分页
* @param params 请求参数
* @returns 分页
*/
export function roleAllocatedList(params?: PageQuery) {
return requestClient.get<PageResult<User>>(Api.roleAllocatedList, { params });
}
/**
* 未授权的用户
* @param params
* @returns void
*/
export function roleUnallocatedList(params: any) {
return requestClient.get<PageResult<User>>(Api.roleUnallocatedList, {
params,
});
}
/**
* 取消用户角色授权
* @returns void
*/
export function roleAuthCancel(data: { roleId: ID; userId: ID }) {
return requestClient.putWithMsg<void>(Api.roleAuthCancel, data);
}
/**
* 批量取消授权
* @param roleId 角色ID
* @param userIds 用户ID集合
* @returns void
*/
export function roleAuthCancelAll(roleId: ID, userIds: IDS) {
return requestClient.putWithMsg<void>(
`${Api.roleAuthCancelAll}?roleId=${roleId}&userIds=${userIds.join(',')}`,
);
}
/**
* 批量授权用户
* @param roleId 角色ID
* @param userIds 用户ID集合
* @returns void
*/
export function roleSelectAll(roleId: ID, userIds: IDS) {
return requestClient.putWithMsg<void>(
`${Api.roleAuthSelectAll}?roleId=${roleId}&userIds=${userIds.join(',')}`,
);
}
/**
* 根据角色id获取部门树
* @param roleId 角色id
* @returns DeptResp
*/
export function roleDeptTree(roleId: ID) {
return requestClient.get<DeptResp>(`${Api.roleDeptTree}/${roleId}`);
}

View File

@@ -0,0 +1,29 @@
export interface Role {
roleId: number;
roleName: string;
roleKey: string;
roleSort: number;
dataScope: string;
menuCheckStrictly: boolean;
deptCheckStrictly: boolean;
status: string;
remark: string;
createTime: string;
// 用户是否存在此角色标识 默认不存在
flag: boolean;
superAdmin: boolean;
}
export interface DeptOption {
id: number;
parentId: number;
label: string;
weight: number;
children: DeptOption[];
key: string; // 实际上不存在 ide报错
}
export interface DeptResp {
checkedKeys: number[];
depts: DeptOption[];
}

View File

@@ -0,0 +1,25 @@
import type { SocialInfo } from './model';
import type { ID } from '#/api/common';
import { requestClient } from '#/api/request';
enum Api {
root = '/system/social',
socialList = '/system/social/list',
}
/**
* 获取绑定的社交信息列表
* @returns info
*/
export function socialList() {
return requestClient.get<SocialInfo[]>(Api.socialList);
}
/**
* @deprecated 并没有用到这个方法
*/
export function socialInfo(id: ID) {
return requestClient.get(`${Api.root}/${id}`);
}

View File

@@ -0,0 +1,26 @@
export interface SocialInfo {
id: string;
userId: number;
tenantId: string;
authId: string;
source: string;
accessToken: string;
expireIn: number;
refreshToken: string;
openId: string;
userName: string;
nickName: string;
email: string;
avatar: string;
accessCode?: any;
unionId?: any;
scope: string;
tokenType: string;
idToken?: any;
macAlgorithm?: any;
macKey?: any;
code?: any;
oauthToken?: any;
oauthTokenSecret?: any;
createTime: string;
}

View File

@@ -0,0 +1,91 @@
import type { TenantPackage } from './model';
import type { ID, IDS, PageQuery, PageResult } from '#/api/common';
import { commonExport } from '#/api/helper';
import { requestClient } from '#/api/request';
enum Api {
packageChangeStatus = '/system/tenant/package/changeStatus',
packageExport = '/system/tenant/package/export',
packageList = '/system/tenant/package/list',
packageSelectList = '/system/tenant/package/selectList',
root = '/system/tenant/package',
}
/**
* 租户套餐分页列表
* @param params 请求参数
* @returns 分页列表
*/
export function packageList(params?: PageQuery) {
return requestClient.get<PageResult<TenantPackage>>(Api.packageList, {
params,
});
}
/**
* 租户套餐下拉框
* @returns 下拉框
*/
export function packageSelectList() {
return requestClient.get<TenantPackage[]>(Api.packageSelectList);
}
/**
* 租户套餐导出
* @param data 参数
* @returns blob
*/
export function packageExport(data: Partial<TenantPackage>) {
return commonExport(Api.packageExport, data);
}
/**
* 租户套餐信息
* @param id id
* @returns 信息
*/
export function packageInfo(id: ID) {
return requestClient.get<TenantPackage>(`${Api.root}/${id}`);
}
/**
* 租户套餐新增
* @param data data
* @returns void
*/
export function packageAdd(data: Partial<TenantPackage>) {
return requestClient.postWithMsg<void>(Api.root, data);
}
/**
* 租户套餐更新
* @param data data
* @returns void
*/
export function packageUpdate(data: Partial<TenantPackage>) {
return requestClient.putWithMsg<void>(Api.root, data);
}
/**
* 租户套餐状态变更
* @param data data
* @returns void
*/
export function packageChangeStatus(data: Partial<TenantPackage>) {
const packageId = {
packageId: data.packageId,
status: data.status,
};
return requestClient.putWithMsg<void>(Api.packageChangeStatus, packageId);
}
/**
* 租户套餐移除
* @param ids ids
* @returns void
*/
export function packageRemove(ids: IDS) {
return requestClient.deleteWithMsg<void>(`${Api.root}/${ids}`);
}

View File

@@ -0,0 +1,17 @@
/**
* @description 租户套餐
* @param packageId id
* @param packageName 名称
* @param menuIds 菜单id 格式为[1,2,3] 返回为string 提交为数组
* @param remark 备注
* @param menuCheckStrictly 是否关联父节点
* @param status 状态
*/
export interface TenantPackage {
packageId: string;
packageName: string;
menuIds: number[] | string;
remark: string;
menuCheckStrictly: boolean;
status: string;
}

View File

@@ -0,0 +1,137 @@
import type { Tenant } from './model';
import type { ID, IDS, PageQuery } from '#/api/common';
import { commonExport } from '#/api/helper';
import { requestClient } from '#/api/request';
enum Api {
dictSync = '/system/tenant/syncTenantDict',
root = '/system/tenant',
tenantDynamic = '/system/tenant/dynamic',
tenantDynamicClear = '/system/tenant/dynamic/clear',
tenantExport = '/system/tenant/export',
tenantList = '/system/tenant/list',
tenantStatus = '/system/tenant/changeStatus',
tenantSyncPackage = '/system/tenant/syncTenantPackage',
}
/**
* 查询租户分页列表
* @param params 参数
* @returns 分页
*/
export function tenantList(params?: PageQuery) {
return requestClient.get<Tenant[]>(Api.tenantList, { params });
}
/**
* 租户导出
* @param data data
* @returns void
*/
export function tenantExport(data: Partial<Tenant>) {
return commonExport(Api.tenantExport, data);
}
/**
* 查询租户信息
* @param id id
* @returns 租户信息
*/
export function tenantInfo(id: ID) {
return requestClient.get<Tenant>(`${Api.root}/${id}`);
}
/**
* 新增租户 必须开启加密
* @param data data
* @returns void
*/
export function tenantAdd(data: Partial<Tenant>) {
return requestClient.postWithMsg<void>(Api.root, data, { encrypt: true });
}
/**
* 租户更新
* @param data data
* @returns void
*/
export function tenantUpdate(data: Partial<Tenant>) {
return requestClient.putWithMsg<void>(Api.root, data);
}
/**
* 租户状态更新
* @param data data
* @returns void
*/
export function tenantStatusChange(data: Partial<Tenant>) {
const requestData = {
id: data.id,
tenantId: data.tenantId,
status: data.status,
};
return requestClient.putWithMsg(Api.tenantStatus, requestData);
}
/**
* 租户删除
* @param ids ids
* @returns void
*/
export function tenantRemove(ids: IDS) {
return requestClient.deleteWithMsg(`${Api.root}/${ids}`);
}
/**
* 动态切换租户
* @param tenantId 租户ID
* @returns void
*/
export function tenantDynamicToggle(tenantId: string) {
return requestClient.get<void>(`${Api.tenantDynamic}/${tenantId}`);
}
/**
* 清除 动态切换租户
* @returns void
*/
export function tenantDynamicClear() {
return requestClient.get<void>(Api.tenantDynamicClear);
}
/**
* 租户套餐同步
* @param tenantId 租户id
* @param packageId 套餐id
* @returns void
*/
export function tenantSyncPackage(tenantId: string, packageId: string) {
return requestClient.get<void>(Api.tenantSyncPackage, {
params: { packageId, tenantId },
successMessageMode: 'message',
});
}
/**
* 同步租户字典
* @param tenantId 租户ID
* @returns void
*/
export function dictSyncTenant(tenantId?: string) {
return requestClient.get<void>(Api.dictSync, {
params: { tenantId },
successMessageMode: 'message',
});
}
/**
* 同步租户配置
* @returns void
*/
export function syncTenantConfig() {
return requestClient.get<void>('/system/tenant/syncTenantConfig', {
successMessageMode: 'message',
});
}

View File

@@ -0,0 +1,16 @@
export interface Tenant {
accountCount: number;
address?: string;
companyName: string;
contactPhone: string;
contactUserName: string;
domain?: string;
expireTime?: string;
id: number;
intro: string;
licenseNumber?: any;
packageId: string;
remark?: string;
status: string;
tenantId: string;
}

View File

@@ -0,0 +1,171 @@
import type {
DeptTree,
ResetPwdParam,
User,
UserImportParam,
UserInfoResponse,
} from './model';
import type { ID, IDS, PageQuery, PageResult } from '#/api/common';
import { commonExport, ContentTypeEnum } from '#/api/helper';
import { requestClient } from '#/api/request';
enum Api {
deptTree = '/system/user/deptTree',
listDeptUsers = '/system/user/list/dept',
root = '/system/user',
userAuthRole = '/system/user/authRole',
userExport = '/system/user/export',
userImport = '/system/user/importData',
userImportTemplate = '/system/user/importTemplate',
userList = '/system/user/list',
userResetPassword = '/system/user/resetPwd',
userStatusChange = '/system/user/changeStatus',
}
/**
* 获取用户列表
* @param params
* @returns User
*/
export function userList(params?: PageQuery) {
return requestClient.get<PageResult<User>>(Api.userList, { params });
}
/**
* 导出excel
* @param data data
* @returns blob
*/
export function userExport(data: Partial<User>) {
return commonExport(Api.userExport, data);
}
/**
* 从excel导入用户
* @param data
* @returns void
*/
export function userImportData(data: UserImportParam) {
return requestClient.post<{ code: number; msg: string }>(
Api.userImport,
data,
{
headers: {
'Content-Type': ContentTypeEnum.FORM_DATA,
},
isTransformResponse: false,
},
);
}
/**
* 下载用户导入模板
* @returns blob
*/
export function downloadImportTemplate() {
return requestClient.post<Blob>(
Api.userImportTemplate,
{},
{
isTransformResponse: false,
responseType: 'blob',
},
);
}
/**
* 可以不传ID 返回部门和角色options 需要获得原始数据
* 不传ID时一定要带最后的/
* @param userId 用户ID
* @returns 用户信息
*/
export function findUserInfo(userId?: ID) {
const url = userId ? `${Api.root}/${userId}` : `${Api.root}/`;
return requestClient.get<UserInfoResponse>(url);
}
/**
* 新增用户
* @param data data
* @returns void
*/
export function userAdd(data: Partial<User>) {
return requestClient.postWithMsg<void>(Api.root, data);
}
/**
* 更新用户
* @param data data
* @returns void
*/
export function userUpdate(data: Partial<User>) {
return requestClient.putWithMsg<void>(Api.root, data);
}
/**
* 更新用户状态
* @param data data
* @returns void
*/
export function userStatusChange(data: Partial<User>) {
const requestData = {
userId: data.userId,
status: data.status,
};
return requestClient.putWithMsg<void>(Api.userStatusChange, requestData);
}
/**
* 删除用户
* @param userIds 用户ID数组
* @returns void
*/
export function userRemove(userIds: IDS) {
return requestClient.deleteWithMsg<void>(`${Api.root}/${userIds}`);
}
/**
* 重置用户密码 需要加密
* @param data
* @returns void
*/
export function userResetPassword(data: ResetPwdParam) {
return requestClient.putWithMsg<void>(Api.userResetPassword, data, {
encrypt: true,
});
}
/**
* 这个方法未调用过
* @param userId
* @returns void
*/
export function getUserAuthRole(userId: ID) {
return requestClient.get(`${Api.userAuthRole}/${userId}`);
}
/**
* 这个方法未调用过
* @param userId
* @returns void
*/
export function userAuthRoleUpdate(userId: ID, roleIds: number[]) {
return requestClient.putWithMsg(Api.userAuthRole, { roleIds, userId });
}
/**
* 获取部门树
* @returns 部门树数组
*/
export function getDeptTree() {
return requestClient.get<DeptTree[]>(Api.deptTree);
}
/**
* 获取部门下的所有用户信息
*/
export function listUserByDeptId(deptId: ID) {
return requestClient.get<User[]>(`${Api.listDeptUsers}/${deptId}`);
}

View File

@@ -0,0 +1,117 @@
/**
* @description: 用户导入
* @param updateSupport 是否覆盖数据
* @param file excel文件
*/
export interface UserImportParam {
updateSupport: boolean;
file: Blob | File;
}
/**
* @description: 重置密码
*/
export interface ResetPwdParam {
userId: string;
password: string;
}
export interface Dept {
deptId: number;
parentId: number;
parentName?: string;
ancestors: string;
deptName: string;
orderNum: number;
leader: string;
phone?: string;
email?: string;
status: string;
createTime?: string;
}
export interface Role {
roleId: string;
roleName: string;
roleKey: string;
roleSort: number;
dataScope: string;
menuCheckStrictly?: boolean;
deptCheckStrictly?: boolean;
status: string;
remark: string;
createTime?: string;
flag: boolean;
superAdmin: boolean;
}
export interface User {
userId: string;
tenantId: string;
deptId: number;
userName: string;
nickName: string;
userType: string;
email: string;
phonenumber: string;
sex: string;
avatar?: string;
status: string;
loginIp: string;
loginDate: string;
remark: string;
createTime: string;
dept: Dept;
roles: Role[];
roleIds?: string[];
postIds?: number[];
roleId: string;
deptName: string;
}
export interface Post {
postId: number;
postCode: string;
postName: string;
postSort: number;
status: string;
remark: string;
createTime: string;
}
/**
* @description 用户信息
* @param user 用户个人信息
* @param roleIds 角色IDS 不传id为空
* @param roles 所有的角色
* @param postIds 岗位IDS 不传id为空
* @param posts 所有的岗位
*/
export interface UserInfoResponse {
user?: User;
roleIds?: string[];
roles: Role[];
postIds?: number[];
posts?: Post[];
}
/**
* @description: 部门树
*/
export interface DeptTree {
id: number;
/**
* antd组件必须要这个属性 实际是没有这个属性的
*/
key: string;
parentId: number;
label: string;
weight: number;
children?: DeptTree[];
}
export interface DeptTreeData {
id: number;
label: string;
children?: DeptTreeData[];
}

View File

@@ -0,0 +1,103 @@
import type { GenInfo } from './model';
import type { ID, IDS, PageQuery } from '#/api/common';
import { ContentTypeEnum } from '#/api/helper';
import { requestClient } from '#/api/request';
enum Api {
batchGenCode = '/tool/gen/batchGenCode',
columnList = '/tool/gen/column',
dataSourceNames = '/tool/gen/getDataNames',
download = '/tool/gen/download',
genCode = '/tool/gen/genCode',
generatedList = '/tool/gen/list',
importTable = '/tool/gen/importTable',
preview = '/tool/gen/preview',
readyToGenList = '/tool/gen/db/list',
root = '/tool/gen',
syncDb = '/tool/gen/synchDb',
}
// 查询代码生成列表
export function generatedList(params?: PageQuery) {
return requestClient.get(Api.generatedList, { params });
}
// 修改代码生成业务
export function genInfo(tableId: ID) {
return requestClient.get<GenInfo>(`${Api.root}/${tableId}`);
}
// 查询数据库列表
export function readyToGenList(params?: PageQuery) {
return requestClient.get(Api.readyToGenList, { params });
}
// 查询数据表字段列表
export function columnList(tableId: ID) {
return requestClient.get(`${Api.columnList}/${tableId}`);
}
/**
* 导入表结构(保存)
* @param tables table名称数组 如sys_a, sys_b
* @param dataName 数据源名称
* @returns ret
*/
export function importTable(tables: string | string[], dataName: string) {
return requestClient.postWithMsg(
Api.importTable,
{ dataName, tables },
{
headers: { 'Content-Type': ContentTypeEnum.FORM_URLENCODED },
},
);
}
// 修改保存代码生成业务
export function editSave(data: any) {
return requestClient.putWithMsg(Api.root, data);
}
// 删除代码生成
export function genRemove(tableIds: IDS) {
return requestClient.deleteWithMsg(`${Api.root}/${tableIds}`);
}
// 预览代码
export function previewCode(tableId: ID) {
return requestClient.get<{ [key: string]: string }>(
`${Api.preview}/${tableId}`,
);
}
// 生成代码(下载方式)
export function genDownload(tableId: ID) {
return requestClient.get<Blob>(`${Api.download}/${tableId}`);
}
// 生成代码(自定义路径)
export function genWithPath(tableId: ID) {
return requestClient.get<void>(`${Api.genCode}/${tableId}`);
}
// 同步数据库
export function syncDb(tableId: ID) {
return requestClient.get(`${Api.syncDb}/${tableId}`, {
successMessageMode: 'message',
});
}
// 批量生成代码
export function batchGenCode(tableIdStr: ID | IDS) {
return requestClient.get<Blob>(Api.batchGenCode, {
isTransformResponse: false,
params: { tableIdStr },
responseType: 'blob',
});
}
// 查询数据源名称列表
export function getDataSourceNames() {
return requestClient.get<string[]>(Api.dataSourceNames);
}

View File

@@ -0,0 +1,187 @@
export interface Column {
createDept?: any;
createBy?: any;
createTime?: any;
updateBy?: any;
updateTime?: any;
columnId: string;
tableId: string;
columnName: string;
columnComment: string;
columnType: string;
javaType: string;
javaField: string;
isPk: string;
isIncrement: string;
isRequired: string;
isInsert?: any;
isEdit: string;
isList: string;
isQuery?: any;
queryType: string;
htmlType: string;
dictType: string;
sort: number;
list: boolean;
required: boolean;
pk: boolean;
insert: boolean;
edit: boolean;
usableColumn: boolean;
superColumn: boolean;
increment: boolean;
query: boolean;
capJavaField: string;
}
export interface Table {
createDept?: any;
createBy?: any;
createTime?: any;
updateBy?: any;
updateTime?: any;
tableId: string;
dataName: string;
tableName: string;
tableComment: string;
subTableName?: any;
subTableFkName?: any;
className: string;
tplCategory: string;
packageName: string;
moduleName: string;
businessName: string;
functionName: string;
functionAuthor: string;
genType?: any;
genPath?: any;
pkColumn?: any;
columns: Column[];
options?: any;
remark?: any;
treeCode?: any;
treeParentCode?: any;
treeName?: any;
menuIds?: any;
parentMenuId?: any;
parentMenuName?: any;
tree: boolean;
crud: boolean;
}
export interface Row {
createDept: number;
createBy: number;
createTime: string;
updateBy: number;
updateTime: string;
columnId: string;
tableId: string;
columnName: string;
columnComment: string;
columnType: string;
javaType: string;
javaField: string;
isPk: string;
isIncrement: string;
isRequired: string;
isInsert?: any;
isEdit: string;
isList: string;
isQuery?: any;
queryType: string;
htmlType: string;
dictType: string;
sort: number;
list: boolean;
required: boolean;
pk: boolean;
insert: boolean;
edit: boolean;
usableColumn: boolean;
superColumn: boolean;
increment: boolean;
query: boolean;
capJavaField: string;
}
export interface Column {
createDept?: any;
createBy?: any;
createTime?: any;
updateBy?: any;
updateTime?: any;
columnId: string;
tableId: string;
columnName: string;
columnComment: string;
columnType: string;
javaType: string;
javaField: string;
isPk: string;
isIncrement: string;
isRequired: string;
isInsert?: any;
isEdit: string;
isList: string;
isQuery?: any;
queryType: string;
htmlType: string;
dictType: string;
sort: number;
list: boolean;
required: boolean;
pk: boolean;
insert: boolean;
edit: boolean;
usableColumn: boolean;
superColumn: boolean;
increment: boolean;
query: boolean;
capJavaField: string;
}
export interface Info {
createDept?: any;
createBy?: any;
createTime?: any;
updateBy?: any;
updateTime?: any;
tableId: string;
dataName: string;
tableName: string;
tableComment: string;
subTableName?: any;
subTableFkName?: any;
className: string;
tplCategory: string;
packageName: string;
moduleName: string;
businessName: string;
functionName: string;
functionAuthor: string;
genType: string;
genPath: string;
pkColumn?: any;
columns: Column[];
options?: any;
remark?: any;
treeCode?: any;
treeParentCode?: any;
treeName?: any;
menuIds?: any;
parentMenuId?: any;
parentMenuName?: any;
tree: boolean;
crud: boolean;
// 树表需要添加此属性
params?: any;
popupComponent?: string;
formComponent?: string;
}
export interface GenInfo {
tables: Table[];
rows: Row[];
info: Info;
}

View File

@@ -0,0 +1,63 @@
import type {
CategoryForm,
CategoryQuery,
CategoryTree,
CategoryVO,
} from './model';
import type { ID, IDS } from '#/api/common';
import { requestClient } from '#/api/request';
/**
* 获取流程分类树列表
* @returns tree
*/
export function categoryTree() {
return requestClient.get<CategoryTree[]>('/workflow/category/categoryTree');
}
/**
* 查询流程分类列表
* @param params
* @returns 流程分类列表
*/
export function categoryList(params?: CategoryQuery) {
return requestClient.get<CategoryVO[]>(`/workflow/category/list`, { params });
}
/**
* 查询流程分类详情
* @param id id
* @returns 流程分类详情
*/
export function categoryInfo(id: ID) {
return requestClient.get<CategoryVO>(`/workflow/category/${id}`);
}
/**
* 新增流程分类
* @param data
* @returns void
*/
export function categoryAdd(data: CategoryForm) {
return requestClient.postWithMsg<void>('/workflow/category', data);
}
/**
* 更新流程分类
* @param data
* @returns void
*/
export function categoryUpdate(data: CategoryForm) {
return requestClient.putWithMsg<void>('/workflow/category', data);
}
/**
* 删除流程分类
* @param id id
* @returns void
*/
export function categoryRemove(id: ID | IDS) {
return requestClient.deleteWithMsg<void>(`/workflow/category/${id}`);
}

View File

@@ -0,0 +1,97 @@
import type { BaseEntity } from '#/api/common';
export interface CategoryVO {
/**
* 主键
*/
id: number | string;
/**
* 分类名称
*/
categoryName: string;
/**
* 分类编码
*/
categoryCode: string;
/**
* 父级id
*/
parentId: number | string;
/**
* 排序
*/
sortNum: number;
/**
* 子对象
*/
children: CategoryVO[];
key: string;
}
export interface CategoryForm extends BaseEntity {
/**
* 主键
*/
id?: number | string;
/**
* 分类名称
*/
categoryName?: string;
/**
* 分类编码
*/
categoryCode?: string;
/**
* 父级id
*/
parentId?: number | string;
/**
* 排序
*/
sortNum?: number;
}
export interface CategoryQuery {
/**
* 分类名称
*/
categoryName?: string;
/**
* 分类编码
*/
categoryCode?: string;
/**
* 父级id
*/
parentId?: number | string;
/**
* 排序
*/
sortNum?: number;
/**
* 日期范围参数
*/
params?: any;
}
export interface CategoryTree {
id: number;
parentId: number;
label: string;
weight: number;
children: CategoryTree[];
key: string;
}

View File

@@ -0,0 +1,155 @@
import type { ProcessDefinition } from './model';
import type { ID, IDS, PageQuery, PageResult } from '#/api/common';
import { requestClient } from '#/api/request';
/**
* 全部的流程定义
* @param params 查询参数
* @returns 分页
*/
export function workflowDefinitionList(params?: PageQuery) {
return requestClient.get<PageResult<ProcessDefinition>>(
'/workflow/definition/list',
{ params },
);
}
/**
* 未发布的流程定义
* @param params 查询参数
* @returns 分页
*/
export function unPublishList(params?: PageQuery) {
return requestClient.get<PageResult<ProcessDefinition>>(
'/workflow/definition/unPublishList',
{ params },
);
}
/**
* 获取历史流程定义列表
* @param flowCode
* @returns ProcessDefinition[]
*/
export function getHisListByKey(flowCode: string) {
return requestClient.get<ProcessDefinition[]>(
`/workflow/definition/getHisListByKey/${flowCode}`,
);
}
/**
* 获取流程定义详细信息
* @param id id
* @returns ProcessDefinition
*/
export function workflowDefinitionInfo(id: ID) {
return requestClient.get<ProcessDefinition>(`/workflow/definition/${id}`);
}
/**
* 新增流程定义
* @param data
*/
export function workflowDefinitionAdd(data: any) {
return requestClient.postWithMsg<void>('/workflow/definition', data);
}
/**
* 更新流程定义
* @param data
*/
export function workflowDefinitionUpdate(data: any) {
return requestClient.putWithMsg<void>('/workflow/definition', data);
}
/**
* 发布流程定义
* @param id id
* @returns boolean
*/
export function workflowDefinitionPublish(id: ID) {
return requestClient.putWithMsg<boolean>(
`/workflow/definition/publish/${id}`,
);
}
/**
* 取消发布流程定义
* @param id id
* @returns boolean
*/
export function workflowDefinitionUnPublish(id: ID) {
return requestClient.putWithMsg<boolean>(
`/workflow/definition/unPublish/${id}`,
);
}
/**
* 删除流程定义
* @param ids idList
*/
export function workflowDefinitionDelete(ids: IDS) {
return requestClient.deleteWithMsg<void>(`/workflow/definition/${ids}`);
}
/**
* 复制流程定义
* @param id id
*/
export function workflowDefinitionCopy(id: ID) {
return requestClient.postWithMsg<void>(`/workflow/definition/copy/${id}`);
}
/**
* 导入流程定义
* @returns boolean
*/
export function workflowDefinitionImport(data: {
category: ID;
file: Blob | File;
}) {
return requestClient.postWithMsg<boolean>(
'/workflow/definition/importDef',
data,
{ headers: { 'Content-Type': 'multipart/form-data' } },
);
}
/**
* 导出流程定义
* @param id id
* @returns blob
*/
export function workflowDefinitionExport(id: ID) {
return requestClient.postWithMsg<Blob>(
`/workflow/definition/exportDef/${id}`,
{},
{
responseType: 'blob',
isTransformResponse: false,
},
);
}
/**
* 获取流程定义xml字符串
* @param id id
* @returns xml
*/
export function workflowDefinitionXml(id: ID) {
return requestClient.get<string>(`/workflow/definition/xmlString/${id}`);
}
/**
* 激活/挂起流程定义
* @param id 流程定义id
* @param active 激活/挂起
* @returns boolean
*/
export function workflowDefinitionActive(id: ID, active: boolean) {
return requestClient.putWithMsg<boolean>(
`/workflow/definition/active/${id}?active=${active}`,
);
}

View File

@@ -0,0 +1,19 @@
export interface ProcessDefinition {
id: string;
createTime: string;
updateTime: string;
tenantId: string;
delFlag: string;
flowCode: string;
flowName: string;
category: string;
categoryName: string;
version: string;
isPublish: number;
formCustom: string;
formPath: string;
activityStatus: number;
listenerType?: any;
listenerPath?: any;
ext?: any;
}

View File

@@ -0,0 +1,139 @@
import type { TaskInfo } from '../task/model';
import type { FlowInfoResponse, FlowInstanceVariableResp } from './model';
import type { ID, IDS, PageQuery, PageResult } from '#/api/common';
import { requestClient } from '#/api/request';
/**
* @param businessId 业务ID
* @returns TaskInfo
*/
export function getTaskByBusinessId(businessId: string) {
return requestClient.get<TaskInfo>(
`/workflow/instance/getInfo/${businessId}`,
);
}
/**
* 分页查询正在运行的流程实例
* @param params
* @returns
*/
export function pageByRunning(params?: PageQuery) {
return requestClient.get('/workflow/instance/pageByRunning', { params });
}
/**
* pageByFinish
* @param params
* @returns
*/
export function pageByFinish(params?: PageQuery) {
return requestClient.get('/workflow/instance/pageByFinish', { params });
}
/**
* 按照业务id删除流程实例
* @param businessIds 业务id
*/
export function deleteByBusinessIds(businessIds: IDS) {
return requestClient.deleteWithMsg<void>(
`/workflow/instance/deleteByBusinessIds${businessIds}`,
);
}
/**
* 按照实例id删除流程实例
* @param instanceIds 实例id
*/
export function deleteByInstanceIds(instanceIds: IDS) {
return requestClient.deleteWithMsg<void>(
`/workflow/instance/deleteByInstanceIds/${instanceIds}`,
);
}
/**
* 撤销流程
* @param data
*/
export function cancelProcessApply(data: { businessId: ID; message?: string }) {
return requestClient.putWithMsg<void>(
'/workflow/instance/cancelProcessApply',
data,
);
}
/**
* 激活/挂起流程实例
* @param instanceId
* @param active
*/
export function workflowInstanceActive(instanceId: ID, active: boolean) {
return requestClient.putWithMsg<void>(
`/workflow/instance/active/${instanceId}?active=${active}`,
);
}
/**
* 获取当前登录人发起的流程实例
* @param params
* @returns PageResult<Flow>
*/
export function pageByCurrent(params?: PageQuery) {
return requestClient.get<PageResult<TaskInfo>>(
'/workflow/instance/pageByCurrent',
{ params },
);
}
/**
* 获取流程图,流程记录
* @param businessId 业务标识
* @returns 流程图,流程记录
*/
export function flowInfo(businessId: string) {
return requestClient.get<FlowInfoResponse>(
`/workflow/instance/flowHisTaskList/${businessId}`,
);
}
/**
* 获取流程变量
* @param instanceId
* @returns Map<string,any>
*/
export function instanceVariable(instanceId: string) {
return requestClient.get<FlowInstanceVariableResp>(
`/workflow/instance/instanceVariable/${instanceId}`,
);
}
/**
* 作废流程
*/
export function workflowInstanceInvalid(data: {
comment?: string;
id: string;
}) {
return requestClient.postWithMsg<void>('/workflow/instance/invalid', data);
}
/**
* 修改流程参数
* @param data 参数
* @param data.instanceId 实例ID
* @param data.key 参数key
* @param data.value 值
* @returns void
*/
export function updateFlowVariable(data: {
instanceId: string;
key: string;
value: any;
}) {
return requestClient.putWithMsg<void>(
'/workflow/instance/updateVariable',
data,
);
}

View File

@@ -0,0 +1,54 @@
export {};
export interface Flow {
id: string;
createTime: string;
updateTime: string;
tenantId: string;
delFlag: string;
definitionId: string;
flowName?: any;
instanceId: string;
taskId: string;
cooperateType: number;
cooperateTypeName: string;
businessId?: any;
nodeCode: string;
nodeName: string;
nodeType: number;
targetNodeCode: string;
targetNodeName: string;
approver: string;
approveName: string;
collaborator?: any;
permissionList?: any;
skipType: string;
flowStatus: string;
flowTaskStatus?: any;
flowStatusName?: any;
message: string;
ext: null | string;
createBy?: any;
formCustom: string;
formPath: string;
flowCode?: any;
version?: any;
runDuration: string;
nickName?: any;
}
export interface FlowInfoResponse {
instanceId: string;
list: Flow[];
}
export interface FlowInstanceVariableResp {
/**
* json字符串 流程变量
*/
variable: string;
variableList: {
key: string;
value: any;
}[];
}

View File

@@ -0,0 +1,25 @@
import type { Spel } from './model';
import type { ID, PageQuery, PageResult } from '#/api/common';
import { requestClient } from '#/api/request';
export function spelList(params?: PageQuery) {
return requestClient.get<PageResult<Spel>>('/workflow/spel/list', { params });
}
export function spelInfo(id: ID) {
return requestClient.get<Spel>(`/workflow/spel/${id}`);
}
export function spelAdd(data: Partial<Spel>) {
return requestClient.postWithMsg<Spel>('/workflow/spel', data);
}
export function spelUpdate(data: Partial<Spel>) {
return requestClient.putWithMsg<Spel>('/workflow/spel', data);
}
export function spelDelete(ids: ID[]) {
return requestClient.deleteWithMsg<Spel>(`/workflow/spel/${ids}`);
}

View File

@@ -0,0 +1,10 @@
export interface Spel {
id: number;
componentName: string;
methodName: string;
methodParams: string;
viewSpel: string;
status: string;
remark: string;
createTime: string;
}

View File

@@ -0,0 +1,172 @@
import type {
CompleteTaskReqData,
NextNodeInfo,
StartWorkFlowReqData,
TaskInfo,
TaskOperationData,
TaskOperationType,
} from './model';
import type { ID, IDS, PageQuery, PageResult } from '#/api/common';
import { requestClient } from '#/api/request';
/**
* 启动任务
* @param data
*/
export function startWorkFlow(data: StartWorkFlowReqData) {
return requestClient.post<{
processInstanceId: string;
taskId: string;
}>('/workflow/task/startWorkFlow', data);
}
/**
* 办理任务
* @param data
*/
export function completeTask(data: CompleteTaskReqData) {
return requestClient.postWithMsg<void>('/workflow/task/completeTask', data);
}
/**
* 查询当前用户的待办任务
* @param params
*/
export function pageByTaskWait(params?: PageQuery) {
return requestClient.get<PageResult<TaskInfo>>(
'/workflow/task/pageByTaskWait',
{ params },
);
}
/**
* 查询当前用户的已办任务
* @param params
*/
export function pageByTaskFinish(params?: PageQuery) {
return requestClient.get<PageResult<TaskInfo>>(
'/workflow/task/pageByTaskFinish',
{ params },
);
}
/**
* 查询所有待办任务
* @param params
*/
export function pageByAllTaskWait(params?: PageQuery) {
return requestClient.get<PageResult<TaskInfo>>(
'/workflow/task/pageByAllTaskWait',
{ params },
);
}
/**
* 查询已办任务
* @param params
*/
export function pageByAllTaskFinish(params?: PageQuery) {
return requestClient.get<PageResult<TaskInfo>>(
'/workflow/task/pageByAllTaskFinish',
{ params },
);
}
/**
* 查询当前用户的抄送
* @param params
*/
export function pageByTaskCopy(params?: PageQuery) {
return requestClient.get<PageResult<TaskInfo>>(
'/workflow/task/pageByTaskCopy',
{ params },
);
}
/**
* 根据taskId查询代表任务
* @param taskId 任务id
* @returns info
*/
export function getTaskByTaskId(taskId: string) {
return requestClient.get<TaskInfo>(`/workflow/task/getTask/${taskId}`);
}
/**
* 终止任务
*/
export function terminationTask(data: { comment?: string; taskId: string }) {
return requestClient.postWithMsg<void>(
'/workflow/task/terminationTask',
data,
);
}
/**
* 任务操作
* @param taskOperationData 参数
* @param taskOperation 操作类型,委派 delegateTask、转办 transferTask、加签 addSignature、减签 reductionSignature
*/
export function taskOperation(
taskOperationData: TaskOperationData,
taskOperation: TaskOperationType,
) {
return requestClient.postWithMsg<void>(
`/workflow/task/taskOperation/${taskOperation}`,
taskOperationData,
);
}
/**
* 修改任务办理人
* @param taskIdList 任务id
* @param userId 办理人id
*/
export function updateAssignee(taskIdList: IDS, userId: ID) {
return requestClient.putWithMsg<void>(
`/workflow/task/updateAssignee/${userId}`,
taskIdList,
);
}
/**
* 驳回审批
* @param data 参数
*/
export function backProcess(data: any) {
return requestClient.postWithMsg<void>('/workflow/task/backProcess', data);
}
/**
* 获取可驳回节点
* @param taskId 任务ID
* @param nodeCode 当前节点编码
*/
export function getBackTaskNode(taskId: string, nodeCode: string) {
return requestClient.get<{ nodeCode: string; nodeName: string }[]>(
`/workflow/task/getBackTaskNode/${taskId}/${nodeCode}`,
);
}
/**
* 获取当前任务的所有办理人
* @param taskId 任务id
*/
export function currentTaskAllUser(taskId: ID) {
return requestClient.get<any>(`/workflow/task/currentTaskAllUser/${taskId}`);
}
/**
* 获取下一节点
* @param data data
* @param data.taskId taskId
* @returns NextNodeInfo
*/
export function getNextNodeList(data: { taskId: string }) {
return requestClient.post<NextNodeInfo[]>(
'/workflow/task/getNextNodeList',
data,
);
}

View File

@@ -0,0 +1,116 @@
export interface ButtonWithPermission {
code: string;
value: null | string;
show: boolean;
}
export interface TaskInfo {
id: string;
categoryName: string;
createTime: string;
updateTime: string;
tenantId: string;
delFlag?: any;
definitionId: string;
instanceId: string;
flowName: string;
businessId: string;
nodeCode: string;
nodeName: string;
/**
* >5.5.0版本才有自定义标题
*/
businessTitle?: string;
nodeType: number;
permissionList?: any;
userList?: any;
formCustom: string;
formPath: string;
flowCode: string;
version: string;
flowStatus: string;
flowStatusName: string;
assigneeIds: string;
assigneeNames: string;
processedBy: string;
type: string;
nodeRatio?: string;
createBy: string;
createByName: string;
targetNodeName?: string;
buttonList: ButtonWithPermission[];
}
export interface CompleteTaskReqData {
messageType: string[];
flowCopyList: { userId: string; userName: string }[];
taskId: ID;
taskVariables: Record<string, any>;
variables: any;
// 附件ID 1,2,3,4形式
fileId?: string;
// 选人 key为节点code value为用户ID join(,)
assigneeMap: { [key: string]: string };
}
export interface StartWorkFlowReqData {
/**
* 业务ID
*/
businessId: ID;
/**
* flowCode
*/
flowCode: string;
/**
* 流程变量
*/
variables: Record<string, any>;
/**
* 流程实例业务扩展业务对象 必须要有不能为null 可以为空对象
*/
flowInstanceBizExtBo: Record<string, any>;
}
export interface TaskOperationData {
message?: string;
taskId: ID;
// 单个操作人
userId?: ID;
// 多个操作人
userIds?: IDS;
}
/**
* 操作类型,委派 delegateTask、转办 transferTask、加签 addSignature、减签 reductionSignature
*/
export type TaskOperationType =
| 'addSignature'
| 'delegateTask'
| 'reductionSignature'
| 'transferTask';
export interface NextNodeInfo {
skipList: string[];
id: string;
createTime: string;
updateTime: string;
tenantId: string;
delFlag: string;
nodeType: number;
definitionId: string;
nodeCode: string;
nodeName: string;
permissionFlag: string;
nodeRatio: string;
coordinate: string;
version: string;
anyNodeSkip: any;
listenerType: any;
listenerPath: any;
handlerType: any;
handlerPath: any;
formCustom: string;
formPath: any;
ext: string;
}