33 changed files with 6017 additions and 1106 deletions
File diff suppressed because it is too large
@ -0,0 +1,156 @@ |
|||||
|
import type { BaseResponse } from '@/utils/request'; |
||||
|
import { request } from '@/utils/request'; |
||||
|
|
||||
|
/** |
||||
|
* @description 查询类别列表 |
||||
|
* @param {SearchPageListParams} data |
||||
|
* @returns |
||||
|
*/ |
||||
|
export function fetchDictList() { |
||||
|
return request<BaseResponse<API.SearchPageListResult>>({ |
||||
|
url: `/fieldType/list`, |
||||
|
method: 'post', |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @description 新增单条 |
||||
|
* @param {DictType} data |
||||
|
* @returns |
||||
|
*/ |
||||
|
export function createDict(data: API.DictType) { |
||||
|
return request({ |
||||
|
url: `/fieldType/create`, |
||||
|
method: 'post', |
||||
|
data, |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @description 修改单条 |
||||
|
* @param {DictType} data |
||||
|
* @returns |
||||
|
*/ |
||||
|
export function updateDict(data: API.DictType) { |
||||
|
return request({ |
||||
|
url: `/fieldType/update`, |
||||
|
method: 'put', |
||||
|
data, |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @description 删除多条 |
||||
|
*/ |
||||
|
export function deleteBatchDictById(data: API.DeleteBatchDictParams) { |
||||
|
return request({ |
||||
|
url: `/fieldType/deleteBatch`, |
||||
|
method: 'delete', |
||||
|
data, |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @description 根据字典类型查询字典值列表 |
||||
|
* @param { fieldTypeId:string} data |
||||
|
* @returns |
||||
|
*/ |
||||
|
export function fetchDictValueListByType(data: { fieldTypeName: string }) { |
||||
|
return request({ |
||||
|
url: `/dict/query`, |
||||
|
method: 'post', |
||||
|
data, |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @description 根据字典类型查询字典值分页列表 |
||||
|
* @param {SearchPageListParams} data |
||||
|
* @returns |
||||
|
*/ |
||||
|
export function fetchDictValuePageList(data: API.SearchPageListParams) { |
||||
|
return request<BaseResponse<API.SearchPageListResult>>( |
||||
|
{ |
||||
|
url: `/dict/page`, |
||||
|
method: 'post', |
||||
|
data, |
||||
|
}, |
||||
|
{ |
||||
|
isGetDataDirectly: false, |
||||
|
}, |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @description 新增单条 |
||||
|
* @param {DictValueType} data |
||||
|
* @returns |
||||
|
*/ |
||||
|
export function createDictValue(data: API.DictValueType) { |
||||
|
return request({ |
||||
|
url: `/dict/create`, |
||||
|
method: 'post', |
||||
|
data, |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @description 启用 |
||||
|
* @param {id: string } data |
||||
|
* @returns |
||||
|
*/ |
||||
|
export function enableDictValue(data: { id: string }) { |
||||
|
return request({ |
||||
|
url: `/dict/enable`, |
||||
|
method: 'post', |
||||
|
params: data, |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @description 禁用 |
||||
|
* @param {id: string } data |
||||
|
* @returns |
||||
|
*/ |
||||
|
export function disableDictValue(data: { id: string }) { |
||||
|
return request({ |
||||
|
url: `/dict/disable`, |
||||
|
method: 'post', |
||||
|
params: data, |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @description 修改单条 |
||||
|
* @param {DictValueType} data |
||||
|
* @returns |
||||
|
*/ |
||||
|
export function updateDictValue(data: API.DictValueType) { |
||||
|
return request({ |
||||
|
url: `/dict/update`, |
||||
|
method: 'put', |
||||
|
data, |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @description 删除单条 |
||||
|
*/ |
||||
|
export function deleteDictValueById(params: API.DeleteDictValueParams) { |
||||
|
return request({ |
||||
|
url: `/dict/delete`, |
||||
|
method: 'delete', |
||||
|
params: params, |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @description 删除多条 |
||||
|
*/ |
||||
|
export function deleteBatchDictValueById(data: API.DeleteBatchDictValueParams) { |
||||
|
return request({ |
||||
|
url: `/dict/deleteBatch`, |
||||
|
method: 'delete', |
||||
|
data, |
||||
|
}); |
||||
|
} |
||||
@ -0,0 +1,26 @@ |
|||||
|
declare namespace API { |
||||
|
type DictType = { |
||||
|
id?: string; |
||||
|
name: string; |
||||
|
}; |
||||
|
|
||||
|
type DeleteDictParams = { |
||||
|
id: string; |
||||
|
}; |
||||
|
|
||||
|
type DeleteBatchDictParams = string[]; |
||||
|
|
||||
|
type DictValueType = { |
||||
|
id?: string; |
||||
|
fieldTypeId: string; |
||||
|
fieldValue: string; |
||||
|
enable: string; |
||||
|
pendingStatus?: boolean; |
||||
|
}; |
||||
|
|
||||
|
type DeleteDictValueParams = { |
||||
|
id: string; |
||||
|
}; |
||||
|
|
||||
|
type DeleteBatchDictValueParams = string[]; |
||||
|
} |
||||
@ -0,0 +1,769 @@ |
|||||
|
<!-- |
||||
|
* @Author: AaronWu 2463371514@qq.com |
||||
|
* @Date: 2025-04-01 10:28:36 |
||||
|
* @LastEditors: AaronWu 2463371514@qq.com |
||||
|
* @LastEditTime: 2025-04-01 16:51:20 |
||||
|
* @FilePath: /IssueSupportManage/src/assets/DTO.md |
||||
|
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE |
||||
|
--> |
||||
|
|
||||
|
# 接口文档 |
||||
|
|
||||
|
<details open> |
||||
|
<summary><h2>用户认证模块</h2></summary> |
||||
|
|
||||
|
<details open> |
||||
|
<summary><h3>1. 用户登录</h3></summary> |
||||
|
|
||||
|
#### 接口说明 |
||||
|
|
||||
|
- 接口描述:用户登录接口,用于验证用户身份并获取访问令牌 |
||||
|
- 请求方式:POST |
||||
|
- 接口路径:/api/login |
||||
|
|
||||
|
#### 请求参数 |
||||
|
|
||||
|
##### LoginParams |
||||
|
|
||||
|
| 参数名 | 类型 | 必填 | 说明 | |
||||
|
| -------- | ------ | ---- | ------ | |
||||
|
| username | string | 是 | 用户名 | |
||||
|
| password | string | 是 | 密码 | |
||||
|
|
||||
|
#### 响应结果 |
||||
|
|
||||
|
##### LoginResult |
||||
|
|
||||
|
| 参数名 | 类型 | 说明 | |
||||
|
| ------------ | ------ | -------- | |
||||
|
| accessToken | string | 访问令牌 | |
||||
|
| expiresTime | string | 过期时间 | |
||||
|
| refreshToken | string | 刷新令牌 | |
||||
|
| userId | string | 用户 ID | |
||||
|
|
||||
|
#### 响应示例 |
||||
|
|
||||
|
```json |
||||
|
{ |
||||
|
"code": 200, |
||||
|
"message": "登录成功", |
||||
|
"data": { |
||||
|
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", |
||||
|
"expiresTime": "2024-04-01 11:30:00", |
||||
|
"refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", |
||||
|
"userId": "12345" |
||||
|
} |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
### 2. 用户登出 |
||||
|
|
||||
|
#### 接口说明 |
||||
|
|
||||
|
- 接口描述:用户登出接口,用于注销当前用户的登录状态 |
||||
|
- 请求方式:POST |
||||
|
- 接口路径:/api/logout |
||||
|
|
||||
|
#### 请求参数 |
||||
|
|
||||
|
无 |
||||
|
|
||||
|
#### 响应结果 |
||||
|
|
||||
|
| 参数名 | 类型 | 说明 | |
||||
|
| ------- | ------ | -------- | |
||||
|
| code | number | 状态码 | |
||||
|
| message | string | 响应消息 | |
||||
|
|
||||
|
#### 响应示例 |
||||
|
|
||||
|
```json |
||||
|
{ |
||||
|
"code": 200, |
||||
|
"message": "登出成功" |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
<details open> |
||||
|
<summary><h2>用户管理模块</h2></summary> |
||||
|
|
||||
|
<details open> |
||||
|
<summary><h3>1. 用户列表查询</h3></summary> |
||||
|
|
||||
|
#### 接口说明 |
||||
|
|
||||
|
- 接口描述:查询用户列表数据,支持条件搜索 |
||||
|
- 请求方式:POST |
||||
|
- 接口路径:/api/user/list |
||||
|
|
||||
|
#### 请求参数 |
||||
|
|
||||
|
##### SearchListParams |
||||
|
|
||||
|
| 参数名 | 类型 | 必填 | 说明 | |
||||
|
| ------- | ------ | ---- | ---------------------------------------- | |
||||
|
| keyword | string | 否 | 搜索关键词(支持用户名、手机号模糊搜索) | |
||||
|
| state | number | 否 | 用户状态(0:禁用,1:启用) | |
||||
|
| sex | string | 否 | 性别 | |
||||
|
|
||||
|
#### 响应结果 |
||||
|
|
||||
|
##### SearchListResult |
||||
|
|
||||
|
| 参数名 | 类型 | 说明 | |
||||
|
| ------ | --------------- | ------------ | |
||||
|
| list | Array<UserInfo> | 用户列表数据 | |
||||
|
|
||||
|
##### UserInfo |
||||
|
|
||||
|
| 参数名 | 类型 | 说明 | |
||||
|
| ---------- | ------- | ------------------------ | |
||||
|
| id | string | 用户 ID | |
||||
|
| account | string | 账号 | |
||||
|
| username | string | 用户名 | |
||||
|
| mobile | string | 手机号 | |
||||
|
| sex | string | 性别 | |
||||
|
| state | number | 状态(0:禁用,1:启用) | |
||||
|
| remark | string | 备注 | |
||||
|
| createTime | string | 创建时间 | |
||||
|
| isAdmin | boolean | 是否管理员 | |
||||
|
|
||||
|
#### 响应示例 |
||||
|
|
||||
|
```json |
||||
|
{ |
||||
|
"code": 200, |
||||
|
"message": "操作成功", |
||||
|
"data": { |
||||
|
"list": [ |
||||
|
{ |
||||
|
"id": "1", |
||||
|
"username": "zhangsan", |
||||
|
"mobile": "13800138000", |
||||
|
"sex": "男", |
||||
|
"state": 1, |
||||
|
"remark": "技术部员工", |
||||
|
"createTime": "2024-04-01 10:00:00", |
||||
|
"isAdmin": false |
||||
|
} |
||||
|
] |
||||
|
} |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
<details open> |
||||
|
<summary><h3>2. 用户分页列表</h3></summary> |
||||
|
|
||||
|
#### 接口说明 |
||||
|
|
||||
|
- 接口描述:分页查询用户列表数据 |
||||
|
- 请求方式:POST |
||||
|
- 接口路径:/api/user/page |
||||
|
|
||||
|
#### 请求参数 |
||||
|
|
||||
|
##### SearchPageListParams |
||||
|
| 参数名 | 类型 | 必填 | 说明 | |
||||
|
|-------|------|------|------| |
||||
|
| name | string | 否 | 搜索关键词 | |
||||
|
| keyword | string | 否 | 搜索关键词(支持用户名、手机号模糊搜索) | |
||||
|
| state | number | 否 | 用户状态(0:禁用,1:启用) | |
||||
|
| sex | string | 否 | 性别 | |
||||
|
| current | number | 是 | 当前页码 | |
||||
|
| size | number | 是 | 每页条数 | |
||||
|
| sort | string | 否 | 排序字段 | |
||||
|
| order | string | 否 | 排序方式(asc:升序,desc:降序) | |
||||
|
|
||||
|
##### SearchListParams |
||||
|
|
||||
|
| 参数名 | 类型 | 必填 | 说明 | |
||||
|
| --------- | ------ | ---- | ---------------------------------------- | |
||||
|
| name | string | 否 | 搜索关键词 | |
||||
|
| keyword | string | 否 | 搜索关键词(支持用户名、手机号模糊搜索) | |
||||
|
| state | number | 否 | 用户状态(0:禁用,1:启用) | |
||||
|
| sex | string | 否 | 性别 | |
||||
|
| pageSize | number | 是 | 每页条数 | |
||||
|
| pageNum | number | 是 | 当前页码 | |
||||
|
| sortField | string | 否 | 排序字段(默认:createTime) | |
||||
|
| sortOrder | string | 否 | 排序方式(asc:升序,desc:降序) | |
||||
|
|
||||
|
#### 响应结果 |
||||
|
|
||||
|
##### SearchPageListResult |
||||
|
|
||||
|
| 参数名 | 类型 | 说明 | |
||||
|
| -------- | --------------- | ------------ | |
||||
|
| list | Array<UserInfo> | 用户列表数据 | |
||||
|
| total | number | 总记录数 | |
||||
|
| pageSize | number | 每页条数 | |
||||
|
| pageNum | number | 当前页码 | |
||||
|
|
||||
|
##### UserInfo |
||||
|
|
||||
|
| 参数名 | 类型 | 说明 | |
||||
|
| ---------- | ------- | ------------------------ | |
||||
|
| id | string | 用户 ID | |
||||
|
| account | string | 账号 | |
||||
|
| username | string | 用户名 | |
||||
|
| mobile | string | 手机号 | |
||||
|
| sex | string | 性别 | |
||||
|
| state | number | 状态(0:禁用,1:启用) | |
||||
|
| remark | string | 备注 | |
||||
|
| createTime | string | 创建时间 | |
||||
|
| isAdmin | boolean | 是否管理员 | |
||||
|
|
||||
|
#### 响应示例 |
||||
|
|
||||
|
```json |
||||
|
{ |
||||
|
"code": 200, |
||||
|
"message": "操作成功", |
||||
|
"data": { |
||||
|
"list": [ |
||||
|
{ |
||||
|
"id": "1", |
||||
|
"username": "zhangsan", |
||||
|
"mobile": "13800138000", |
||||
|
"sex": "男", |
||||
|
"state": 1, |
||||
|
"remark": "技术部员工", |
||||
|
"createTime": "2024-04-01 10:00:00", |
||||
|
"isAdmin": false |
||||
|
} |
||||
|
], |
||||
|
"total": 100, |
||||
|
"pageSize": 10, |
||||
|
"pageNum": 1 |
||||
|
} |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
<details open> |
||||
|
<summary><h3>3. 新增用户</h3></summary> |
||||
|
|
||||
|
#### 接口说明 |
||||
|
|
||||
|
- 接口描述:新增用户信息 |
||||
|
- 请求方式:POST |
||||
|
- 接口路径:/api/user/create |
||||
|
|
||||
|
#### 请求参数 |
||||
|
|
||||
|
##### UserInfoType |
||||
|
|
||||
|
| 参数名 | 类型 | 必填 | 说明 | |
||||
|
| -------- | ------- | ---- | ------------------------ | |
||||
|
| account | string |是 | 账号 | |
||||
|
| username | string | 是 | 用户名 | |
||||
|
| mobile | string | 是 | 手机号 | |
||||
|
| sex | string | 是 | 性别 | |
||||
|
| state | number | 是 | 状态(0:禁用,1:启用) | |
||||
|
| remark | string | 是 | 备注 | |
||||
|
| isAdmin | boolean | 否 | 是否管理员 | |
||||
|
|
||||
|
#### 响应结果 |
||||
|
|
||||
|
| 参数名 | 类型 | 说明 | |
||||
|
| ------- | ------ | -------- | |
||||
|
| code | number | 状态码 | |
||||
|
| message | string | 响应消息 | |
||||
|
|
||||
|
#### 响应示例 |
||||
|
|
||||
|
```json |
||||
|
{ |
||||
|
"code": 200, |
||||
|
"message": "创建成功" |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
<details open> |
||||
|
<summary><h3>4. 修改用户</h3></summary> |
||||
|
|
||||
|
#### 接口说明 |
||||
|
|
||||
|
- 接口描述:修改用户信息 |
||||
|
- 请求方式:POST |
||||
|
- 接口路径:/api/user/update |
||||
|
|
||||
|
#### 请求参数 |
||||
|
|
||||
|
##### UserInfoType |
||||
|
|
||||
|
| 参数名 | 类型 | 必填 | 说明 | |
||||
|
| -------- | ------- | ---- | ------------------------ | |
||||
|
| id | string | 是 | 用户 ID | |
||||
|
| account | string | 是 | 账号 | |
||||
|
| username | string | 是 | 用户名 | |
||||
|
| mobile | string | 是 | 手机号 | |
||||
|
| sex | string | 是 | 性别 | |
||||
|
| state | number | 是 | 状态(0:禁用,1:启用) | |
||||
|
| remark | string | 是 | 备注 | |
||||
|
| isAdmin | boolean | 否 | 是否管理员 | |
||||
|
|
||||
|
#### 响应结果 |
||||
|
|
||||
|
| 参数名 | 类型 | 说明 | |
||||
|
| ------- | ------ | -------- | |
||||
|
| code | number | 状态码 | |
||||
|
| message | string | 响应消息 | |
||||
|
|
||||
|
#### 响应示例 |
||||
|
|
||||
|
```json |
||||
|
{ |
||||
|
"code": 200, |
||||
|
"message": "修改成功" |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
<details open> |
||||
|
<summary><h3>5. 查询用户详情</h3></summary> |
||||
|
|
||||
|
#### 接口说明 |
||||
|
|
||||
|
- 接口描述:根据 ID 查询用户详细信息 |
||||
|
- 请求方式:GET |
||||
|
- 接口路径:/api/user/getById |
||||
|
|
||||
|
#### 请求参数 |
||||
|
|
||||
|
| 参数名 | 类型 | 必填 | 说明 | |
||||
|
| ------ | ------ | ---- | ------- | |
||||
|
| id | string | 是 | 用户 ID | |
||||
|
|
||||
|
#### 响应结果 |
||||
|
|
||||
|
##### UserInfo |
||||
|
|
||||
|
| 参数名 | 类型 | 说明 | |
||||
|
| ---------- | ------- | ------------------------ | |
||||
|
| id | string | 用户 ID | |
||||
|
| account | string | 账号 | |
||||
|
| username | string | 用户名 | |
||||
|
| mobile | string | 手机号 | |
||||
|
| sex | string | 性别 | |
||||
|
| state | number | 状态(0:禁用,1:启用) | |
||||
|
| remark | string | 备注 | |
||||
|
| createTime | string | 创建时间 | |
||||
|
| isAdmin | boolean | 是否管理员 | |
||||
|
|
||||
|
#### 响应示例 |
||||
|
|
||||
|
```json |
||||
|
{ |
||||
|
"code": 200, |
||||
|
"message": "操作成功", |
||||
|
"data": { |
||||
|
"id": "1", |
||||
|
"username": "zhangsan", |
||||
|
"mobile": "13800138000", |
||||
|
"sex": "男", |
||||
|
"state": 1, |
||||
|
"remark": "技术部员工", |
||||
|
"createTime": "2024-04-01 10:00:00", |
||||
|
"isAdmin": false |
||||
|
} |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
<details open> |
||||
|
<summary><h2>字典管理模块</h2></summary> |
||||
|
|
||||
|
<details open> |
||||
|
<summary><h3>1. 字典类别列表查询</h3></summary> |
||||
|
|
||||
|
#### 接口说明 |
||||
|
|
||||
|
- 接口描述:查询所有字典类别列表 |
||||
|
- 请求方式:POST |
||||
|
- 接口路径:/api/fieldType/list |
||||
|
|
||||
|
#### 请求参数 |
||||
|
|
||||
|
无 |
||||
|
|
||||
|
#### 响应结果 |
||||
|
|
||||
|
##### SearchPageListResult |
||||
|
|
||||
|
| 参数名 | 类型 | 说明 | |
||||
|
| ------ | --------------- | ------------ | |
||||
|
| list | Array<DictType> | 字典类别列表 | |
||||
|
|
||||
|
##### DictType |
||||
|
|
||||
|
| 参数名 | 类型 | 必填 | 说明 | |
||||
|
| ------ | ------ | ---- | -------- | |
||||
|
| id | string | 否 | 类别 ID | |
||||
|
| name | string | 是 | 类别名称 | |
||||
|
|
||||
|
#### 响应示例 |
||||
|
|
||||
|
```json |
||||
|
{ |
||||
|
"code": 200, |
||||
|
"message": "操作成功", |
||||
|
"data": { |
||||
|
"list": [ |
||||
|
{ |
||||
|
"id": "1", |
||||
|
"name": "性别" |
||||
|
} |
||||
|
] |
||||
|
} |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
<details open> |
||||
|
<summary><h3>2. 新增字典类别</h3></summary> |
||||
|
|
||||
|
#### 接口说明 |
||||
|
|
||||
|
- 接口描述:新增字典类别信息 |
||||
|
- 请求方式:POST |
||||
|
- 接口路径:/api/fieldType/create |
||||
|
|
||||
|
#### 请求参数 |
||||
|
|
||||
|
##### DictType |
||||
|
|
||||
|
| 参数名 | 类型 | 必填 | 说明 | |
||||
|
| ------ | ------ | ---- | -------- | |
||||
|
| id | string | 否 | 类别 ID | |
||||
|
| name | string | 是 | 类别名称 | |
||||
|
|
||||
|
#### 响应结果 |
||||
|
|
||||
|
| 参数名 | 类型 | 说明 | |
||||
|
| ------- | ------ | -------- | |
||||
|
| code | number | 状态码 | |
||||
|
| message | string | 响应消息 | |
||||
|
|
||||
|
#### 响应示例 |
||||
|
|
||||
|
```json |
||||
|
{ |
||||
|
"code": 200, |
||||
|
"message": "创建成功" |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
<details open> |
||||
|
<summary><h3>3. 修改字典类别</h3></summary> |
||||
|
|
||||
|
#### 接口说明 |
||||
|
|
||||
|
- 接口描述:修改字典类别信息 |
||||
|
- 请求方式:PUT |
||||
|
- 接口路径:/api/fieldType/update |
||||
|
|
||||
|
#### 请求参数 |
||||
|
|
||||
|
##### DictType |
||||
|
|
||||
|
| 参数名 | 类型 | 必填 | 说明 | |
||||
|
| ------ | ------ | ---- | -------- | |
||||
|
| id | string | 是 | 类别 ID | |
||||
|
| name | string | 是 | 类别名称 | |
||||
|
|
||||
|
#### 响应结果 |
||||
|
|
||||
|
| 参数名 | 类型 | 说明 | |
||||
|
| ------- | ------ | -------- | |
||||
|
| code | number | 状态码 | |
||||
|
| message | string | 响应消息 | |
||||
|
|
||||
|
#### 响应示例 |
||||
|
|
||||
|
```json |
||||
|
{ |
||||
|
"code": 200, |
||||
|
"message": "修改成功" |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
<details open> |
||||
|
<summary><h3>4. 批量删除字典类别</h3></summary> |
||||
|
|
||||
|
#### 接口说明 |
||||
|
|
||||
|
- 接口描述:批量删除字典类别信息 |
||||
|
- 请求方式:DELETE |
||||
|
- 接口路径:/api/fieldType/deleteBatch |
||||
|
|
||||
|
#### 请求参数 |
||||
|
|
||||
|
##### DeleteBatchDictParams |
||||
|
|
||||
|
| 参数名 | 类型 | 必填 | 说明 | |
||||
|
| ------ | -------- | ---- | ---------------- | |
||||
|
| - | string[] | 是 | 字典类别 ID 数组 | |
||||
|
|
||||
|
#### 请求示例 |
||||
|
|
||||
|
```json |
||||
|
["1", "2", "3"] |
||||
|
``` |
||||
|
|
||||
|
<details open> |
||||
|
<summary><h3>5. 根据字典类型查询字典值列表</h3></summary> |
||||
|
|
||||
|
#### 接口说明 |
||||
|
|
||||
|
- 接口描述:根据字典类型名称查询对应的字典值列表 |
||||
|
- 请求方式:POST |
||||
|
- 接口路径:/api/dict/query |
||||
|
|
||||
|
#### 请求参数 |
||||
|
|
||||
|
| 参数名 | 类型 | 必填 | 说明 | |
||||
|
| ------------- | ------ | ---- | ------------ | |
||||
|
| fieldTypeName | string | 是 | 字典类型名称 | |
||||
|
|
||||
|
#### 响应结果 |
||||
|
|
||||
|
| 参数名 | 类型 | 说明 | |
||||
|
| ------ | -------------------- | ---------- | |
||||
|
| list | Array<DictValueType> | 字典值列表 | |
||||
|
|
||||
|
##### DictValueType |
||||
|
|
||||
|
| 参数名 | 类型 | 说明 | |
||||
|
| ------------- | ------- | ----------- | |
||||
|
| id | string | 字典值 ID | |
||||
|
| fieldTypeId | string | 字典类型 ID | |
||||
|
| fieldValue | string | 字典值 | |
||||
|
| enable | string | 启用状态 | |
||||
|
| pendingStatus | boolean | 待处理状态 | |
||||
|
|
||||
|
#### 响应示例 |
||||
|
|
||||
|
```json |
||||
|
{ |
||||
|
"code": 200, |
||||
|
"message": "操作成功", |
||||
|
"data": { |
||||
|
"list": [ |
||||
|
{ |
||||
|
"id": "1", |
||||
|
"fieldTypeId": "type_1", |
||||
|
"fieldValue": "男", |
||||
|
"enable": "1", |
||||
|
"pendingStatus": false |
||||
|
}, |
||||
|
{ |
||||
|
"id": "2", |
||||
|
"fieldTypeId": "type_1", |
||||
|
"fieldValue": "女", |
||||
|
"enable": "1", |
||||
|
"pendingStatus": false |
||||
|
} |
||||
|
] |
||||
|
} |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
<details open> |
||||
|
<summary><h3>6. 字典值分页列表查询</h3></summary> |
||||
|
|
||||
|
#### 接口说明 |
||||
|
|
||||
|
- 接口描述:分页查询字典值列表数据 |
||||
|
- 请求方式:POST |
||||
|
- 接口路径:/api/dict/page |
||||
|
|
||||
|
#### 请求参数 |
||||
|
|
||||
|
##### SearchPageListParams |
||||
|
| 参数名 | 类型 | 必填 | 说明 | |
||||
|
|-------|------|------|------| |
||||
|
| fieldValue | string | 否 | 字典值 | |
||||
|
| current | number | 是 | 当前页码 | |
||||
|
| size | number | 是 | 每页条数 | |
||||
|
| sort | string | 否 | 排序字段 | |
||||
|
| order | string | 否 | 排序方式(asc:升序,desc:降序) | |
||||
|
|
||||
|
##### SearchListParams |
||||
|
|
||||
|
| 参数名 | 类型 | 必填 | 说明 | |
||||
|
| ---------- | ------ | ---- | --------------------------------- | |
||||
|
| fieldValue | string | 否 | 字典值 | |
||||
|
| sortField | string | 否 | 排序字段(默认:createTime) | |
||||
|
| sortOrder | string | 否 | 排序方式(asc:升序,desc:降序) | |
||||
|
|
||||
|
#### 响应结果 |
||||
|
|
||||
|
##### SearchPageListResult |
||||
|
|
||||
|
| 参数名 | 类型 | 说明 | |
||||
|
| -------- | -------------------- | ---------- | |
||||
|
| list | Array<DictValueType> | 字典值列表 | |
||||
|
| total | number | 总记录数 | |
||||
|
| pageSize | number | 每页条数 | |
||||
|
| pageNum | number | 当前页码 | |
||||
|
|
||||
|
##### DictValueType |
||||
|
|
||||
|
| 参数名 | 类型 | 说明 | |
||||
|
| ------------- | ------- | ----------- | |
||||
|
| id | string | 字典值 ID | |
||||
|
| fieldTypeId | string | 字典类型 ID | |
||||
|
| fieldValue | string | 字典值 | |
||||
|
| enable | string | 启用状态 | |
||||
|
| pendingStatus | boolean | 待处理状态 | |
||||
|
|
||||
|
#### 响应示例 |
||||
|
|
||||
|
```json |
||||
|
{ |
||||
|
"code": 200, |
||||
|
"message": "操作成功", |
||||
|
"data": { |
||||
|
"list": [ |
||||
|
{ |
||||
|
"id": "1", |
||||
|
"fieldTypeId": "type_1", |
||||
|
"fieldValue": "男", |
||||
|
"enable": "1", |
||||
|
"pendingStatus": false |
||||
|
} |
||||
|
], |
||||
|
"total": 10, |
||||
|
"pageSize": 10, |
||||
|
"pageNum": 1 |
||||
|
} |
||||
|
} |
||||
|
``` |
||||
|
<details open> |
||||
|
<summary><h3>7. 新增字典值</h3></summary> |
||||
|
|
||||
|
#### 接口说明 |
||||
|
- 接口描述:新增字典值信息 |
||||
|
- 请求方式:POST |
||||
|
- 接口路径:/api/dict/create |
||||
|
|
||||
|
#### 请求参数 |
||||
|
##### DictValueType |
||||
|
| 参数名 | 类型 | 必填 | 说明 | |
||||
|
|-------|------|------|------| |
||||
|
| id | string | 否 | 字典值ID | |
||||
|
| fieldTypeId | string | 是 | 字典类型ID | |
||||
|
| fieldValue | string | 是 | 字典值 | |
||||
|
| enable | string | 是 | 启用状态 | |
||||
|
| pendingStatus | boolean | 否 | 待处理状态 | |
||||
|
|
||||
|
#### 响应结果 |
||||
|
| 参数名 | 类型 | 说明 | |
||||
|
|-------|------|------| |
||||
|
| code | number | 状态码 | |
||||
|
| message | string | 响应消息 | |
||||
|
|
||||
|
#### 响应示例 |
||||
|
```json |
||||
|
{ |
||||
|
"code": 200, |
||||
|
"message": "创建成功" |
||||
|
} |
||||
|
``` |
||||
|
<details open> |
||||
|
<summary><h3>8. 修改字典值</h3></summary> |
||||
|
|
||||
|
#### 接口说明 |
||||
|
- 接口描述:修改字典值信息 |
||||
|
- 请求方式:PUT |
||||
|
- 接口路径:/api/dict/update |
||||
|
|
||||
|
#### 请求参数 |
||||
|
##### DictValueType |
||||
|
| 参数名 | 类型 | 必填 | 说明 | |
||||
|
|-------|------|------|------| |
||||
|
| id | string | 是 | 字典值ID | |
||||
|
| fieldTypeId | string | 是 | 字典类型ID | |
||||
|
| fieldValue | string | 是 | 字典值 | |
||||
|
| enable | string | 是 | 启用状态 | |
||||
|
| pendingStatus | boolean | 否 | 待处理状态 | |
||||
|
|
||||
|
#### 响应结果 |
||||
|
| 参数名 | 类型 | 说明 | |
||||
|
|-------|------|------| |
||||
|
| code | number | 状态码 | |
||||
|
| message | string | 响应消息 | |
||||
|
|
||||
|
#### 响应示例 |
||||
|
```json |
||||
|
{ |
||||
|
"code": 200, |
||||
|
"message": "修改成功" |
||||
|
} |
||||
|
``` |
||||
|
<details open> |
||||
|
<summary><h3>9. 启用字典值</h3></summary> |
||||
|
|
||||
|
#### 接口说明 |
||||
|
- 接口描述:启用指定的字典值 |
||||
|
- 请求方式:POST |
||||
|
- 接口路径:/api/dict/enable |
||||
|
|
||||
|
#### 请求参数 |
||||
|
| 参数名 | 类型 | 必填 | 说明 | |
||||
|
|-------|------|------|------| |
||||
|
| id | string | 是 | 字典值ID | |
||||
|
|
||||
|
#### 响应结果 |
||||
|
| 参数名 | 类型 | 说明 | |
||||
|
|-------|------|------| |
||||
|
| code | number | 状态码 | |
||||
|
| message | string | 响应消息 | |
||||
|
|
||||
|
#### 响应示例 |
||||
|
```json |
||||
|
{ |
||||
|
"code": 200, |
||||
|
"message": "启用成功" |
||||
|
} |
||||
|
``` |
||||
|
<details open> |
||||
|
<summary><h3>10. 禁用字典值</h3></summary> |
||||
|
|
||||
|
#### 接口说明 |
||||
|
- 接口描述:禁用指定的字典值 |
||||
|
- 请求方式:POST |
||||
|
- 接口路径:/api/dict/disable |
||||
|
|
||||
|
#### 请求参数 |
||||
|
| 参数名 | 类型 | 必填 | 说明 | |
||||
|
|-------|------|------|------| |
||||
|
| id | string | 是 | 字典值ID | |
||||
|
|
||||
|
#### 响应结果 |
||||
|
| 参数名 | 类型 | 说明 | |
||||
|
|-------|------|------| |
||||
|
| code | number | 状态码 | |
||||
|
| message | string | 响应消息 | |
||||
|
|
||||
|
#### 响应示例 |
||||
|
```json |
||||
|
{ |
||||
|
"code": 200, |
||||
|
"message": "禁用成功" |
||||
|
} |
||||
|
``` |
||||
|
<details open> |
||||
|
<summary><h3>11. 批量删除字典值</h3></summary> |
||||
|
|
||||
|
#### 接口说明 |
||||
|
- 接口描述:批量删除字典值信息 |
||||
|
- 请求方式:DELETE |
||||
|
- 接口路径:/api/dict/deleteBatch |
||||
|
|
||||
|
#### 请求参数 |
||||
|
##### DeleteBatchDictValueParams |
||||
|
| 参数名 | 类型 | 必填 | 说明 | |
||||
|
|-------|------|------|------| |
||||
|
| - | string[] | 是 | 字典值ID数组 | |
||||
|
|
||||
|
#### 请求示例 |
||||
|
```json |
||||
|
["1", "2", "3"] |
||||
|
``` |
||||
@ -0,0 +1,7 @@ |
|||||
|
import { withInstall } from '@/utils' |
||||
|
|
||||
|
import basicDrawer from './src/BasicDrawer.vue'; |
||||
|
|
||||
|
export const BasicDrawer = withInstall(basicDrawer); |
||||
|
export * from './src/typing'; |
||||
|
export { useDrawer, useDrawerInner } from './src/useDrawer'; |
||||
@ -0,0 +1,258 @@ |
|||||
|
<template> |
||||
|
<Drawer :class="prefixCls" @close="onClose" v-bind="getBindValues"> |
||||
|
<template #title v-if="!$slots.title"> |
||||
|
<DrawerHeader |
||||
|
:title="getMergeProps.title" |
||||
|
:isDetail="isDetail" |
||||
|
:showDetailBack="showDetailBack" |
||||
|
@close="onClose" |
||||
|
> |
||||
|
<template #titleToolbar> |
||||
|
<slot name="titleToolbar"></slot> |
||||
|
</template> |
||||
|
</DrawerHeader> |
||||
|
</template> |
||||
|
<template v-else #title> |
||||
|
<slot name="title"></slot> |
||||
|
</template> |
||||
|
|
||||
|
<ScrollContainer |
||||
|
:style="getScrollContentStyle" |
||||
|
:loading-tip="loadingText || t('common.loadingText')" |
||||
|
> |
||||
|
<!-- v-loading="getLoading" --> |
||||
|
|
||||
|
<slot></slot> |
||||
|
</ScrollContainer> |
||||
|
<DrawerFooter v-bind="getProps" @close="onClose" @ok="handleOk" :height="getFooterHeight"> |
||||
|
<template #[item]="data" v-for="item in Object.keys($slots)"> |
||||
|
<slot :name="item" v-bind="data || {}"></slot> |
||||
|
</template> |
||||
|
</DrawerFooter> |
||||
|
</Drawer> |
||||
|
</template> |
||||
|
<script lang="ts"> |
||||
|
import type { DrawerInstance, DrawerProps } from './typing'; |
||||
|
import type { CSSProperties } from 'vue'; |
||||
|
import { |
||||
|
defineComponent, |
||||
|
ref, |
||||
|
computed, |
||||
|
watch, |
||||
|
unref, |
||||
|
nextTick, |
||||
|
toRaw, |
||||
|
getCurrentInstance, |
||||
|
} from 'vue'; |
||||
|
import { Drawer } from 'ant-design-vue'; |
||||
|
import { useI18n } from '@/hooks/useI18n'; |
||||
|
import { isFunction, isNumber } from '@/utils/is'; |
||||
|
import { deepMerge } from '@/utils'; |
||||
|
import DrawerFooter from './components/DrawerFooter.vue'; |
||||
|
import DrawerHeader from './components/DrawerHeader.vue'; |
||||
|
import { ScrollContainer } from '@/components/core/Container'; |
||||
|
import { basicProps } from './props'; |
||||
|
// import { useDesign } from '/@/hooks/web/useDesign'; |
||||
|
import { useAttrs } from '@/hooks/core/useAttrs'; |
||||
|
|
||||
|
export default defineComponent({ |
||||
|
components: { Drawer, ScrollContainer, DrawerFooter, DrawerHeader }, |
||||
|
inheritAttrs: false, |
||||
|
props: basicProps, |
||||
|
emits: ['visible-change', 'ok', 'close', 'register'], |
||||
|
setup(props, { emit }) { |
||||
|
const visibleRef = ref(false); |
||||
|
const attrs = useAttrs(); |
||||
|
const propsRef = ref<Partial<Nullable<DrawerProps>>>(null); |
||||
|
|
||||
|
const { t } = useI18n(); |
||||
|
const prefixVar= 'basic-drawer', |
||||
|
prefixCls ='basic-drawer'; |
||||
|
|
||||
|
const drawerInstance: DrawerInstance = { |
||||
|
setDrawerProps: setDrawerProps, |
||||
|
emitVisible: undefined, |
||||
|
}; |
||||
|
|
||||
|
const instance = getCurrentInstance(); |
||||
|
|
||||
|
instance && emit('register', drawerInstance, instance.uid); |
||||
|
|
||||
|
const getMergeProps = computed((): DrawerProps => { |
||||
|
return deepMerge(toRaw(props), unref(propsRef)); |
||||
|
}); |
||||
|
|
||||
|
const getProps = computed((): DrawerProps => { |
||||
|
const opt = { |
||||
|
placement: 'right', |
||||
|
...unref(attrs), |
||||
|
...unref(getMergeProps), |
||||
|
visible: unref(visibleRef), |
||||
|
}; |
||||
|
opt.title = undefined; |
||||
|
const { isDetail, width, wrapClassName, getContainer } = opt; |
||||
|
if (isDetail) { |
||||
|
if (!width) { |
||||
|
opt.width = '100%'; |
||||
|
} |
||||
|
const detailCls = `${prefixCls}__detail`; |
||||
|
opt.class = wrapClassName ? `${wrapClassName} ${detailCls}` : detailCls; |
||||
|
|
||||
|
if (!getContainer) { |
||||
|
// TODO type error? |
||||
|
opt.getContainer = `.${prefixVar}-layout-content` as any; |
||||
|
} |
||||
|
} |
||||
|
return opt as DrawerProps; |
||||
|
}); |
||||
|
|
||||
|
const getBindValues = computed((): DrawerProps => { |
||||
|
return { |
||||
|
...attrs, |
||||
|
...unref(getProps), |
||||
|
}; |
||||
|
}); |
||||
|
|
||||
|
// Custom implementation of the bottom button, |
||||
|
const getFooterHeight = computed(() => { |
||||
|
const { footerHeight, showFooter } = unref(getProps); |
||||
|
if (showFooter && footerHeight) { |
||||
|
return isNumber(footerHeight) |
||||
|
? `${footerHeight}px` |
||||
|
: `${footerHeight.replace('px', '')}px`; |
||||
|
} |
||||
|
return `0px`; |
||||
|
}); |
||||
|
|
||||
|
const getScrollContentStyle = computed((): CSSProperties => { |
||||
|
const footerHeight = unref(getFooterHeight); |
||||
|
return { |
||||
|
position: 'relative', |
||||
|
height: `calc(100% - ${footerHeight})`, |
||||
|
}; |
||||
|
}); |
||||
|
|
||||
|
const getLoading = computed(() => { |
||||
|
return !!unref(getProps)?.loading; |
||||
|
}); |
||||
|
|
||||
|
watch( |
||||
|
() => props.visible, |
||||
|
(newVal, oldVal) => { |
||||
|
if (newVal !== oldVal) visibleRef.value = newVal; |
||||
|
}, |
||||
|
{ deep: true }, |
||||
|
); |
||||
|
|
||||
|
watch( |
||||
|
() => visibleRef.value, |
||||
|
(visible) => { |
||||
|
nextTick(() => { |
||||
|
emit('visible-change', visible); |
||||
|
instance && drawerInstance.emitVisible?.(visible, instance.uid); |
||||
|
}); |
||||
|
}, |
||||
|
); |
||||
|
|
||||
|
// Cancel event |
||||
|
async function onClose(e: Recordable) { |
||||
|
const { closeFunc } = unref(getProps); |
||||
|
emit('close', e); |
||||
|
if (closeFunc && isFunction(closeFunc)) { |
||||
|
const res = await closeFunc(); |
||||
|
visibleRef.value = !res; |
||||
|
return; |
||||
|
} |
||||
|
visibleRef.value = false; |
||||
|
} |
||||
|
|
||||
|
function setDrawerProps(props: Partial<DrawerProps>): void { |
||||
|
// Keep the last setDrawerProps |
||||
|
propsRef.value = deepMerge(unref(propsRef) || ({} as any), props); |
||||
|
|
||||
|
if (Reflect.has(props, 'visible')) { |
||||
|
visibleRef.value = !!props.visible; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
function handleOk() { |
||||
|
emit('ok'); |
||||
|
} |
||||
|
|
||||
|
return { |
||||
|
onClose, |
||||
|
t, |
||||
|
prefixCls, |
||||
|
getMergeProps: getMergeProps as any, |
||||
|
getScrollContentStyle, |
||||
|
getProps: getProps as any, |
||||
|
getLoading, |
||||
|
getBindValues, |
||||
|
getFooterHeight, |
||||
|
handleOk, |
||||
|
}; |
||||
|
}, |
||||
|
}); |
||||
|
</script> |
||||
|
<style lang="less"> |
||||
|
@header-height: 60px; |
||||
|
@detail-header-height: 40px; |
||||
|
@prefix-cls: ~'basic-drawer'; |
||||
|
@prefix-cls-detail: ~'basic-drawer__detail'; |
||||
|
|
||||
|
.@{prefix-cls} { |
||||
|
.ant-drawer-wrapper-body { |
||||
|
overflow: hidden; |
||||
|
} |
||||
|
|
||||
|
.ant-drawer-close { |
||||
|
&:hover { |
||||
|
color: @error-color; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.ant-drawer-body { |
||||
|
height: calc(100% - @header-height); |
||||
|
padding: 0; |
||||
|
background-color: @component-background; |
||||
|
|
||||
|
.scrollbar__wrap { |
||||
|
padding: 16px !important; |
||||
|
margin-bottom: 0 !important; |
||||
|
} |
||||
|
|
||||
|
> .scrollbar > .scrollbar__bar.is-horizontal { |
||||
|
display: none; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.@{prefix-cls-detail} { |
||||
|
position: absolute; |
||||
|
|
||||
|
.ant-drawer-header { |
||||
|
width: 100%; |
||||
|
height: @detail-header-height; |
||||
|
padding: 0; |
||||
|
border-top: 1px solid @border-color-base; |
||||
|
box-sizing: border-box; |
||||
|
} |
||||
|
|
||||
|
.ant-drawer-title { |
||||
|
height: 100%; |
||||
|
} |
||||
|
|
||||
|
.ant-drawer-close { |
||||
|
height: @detail-header-height; |
||||
|
line-height: @detail-header-height; |
||||
|
} |
||||
|
|
||||
|
.scrollbar__wrap { |
||||
|
padding: 0 !important; |
||||
|
} |
||||
|
|
||||
|
.ant-drawer-body { |
||||
|
height: calc(100% - @detail-header-height); |
||||
|
} |
||||
|
} |
||||
|
</style> |
||||
@ -0,0 +1,82 @@ |
|||||
|
<template> |
||||
|
<div :class="prefixCls" :style="getStyle" v-if="showFooter || $slots.footer"> |
||||
|
<template v-if="!$slots.footer"> |
||||
|
<slot name="insertFooter"></slot> |
||||
|
<a-button v-bind="cancelButtonProps" @click="handleClose" class="mr-2" v-if="showCancelBtn"> |
||||
|
{{ cancelText }} |
||||
|
</a-button> |
||||
|
<slot name="centerFooter"></slot> |
||||
|
<a-button |
||||
|
:type="okType" |
||||
|
@click="handleOk" |
||||
|
v-bind="okButtonProps" |
||||
|
class="mr-2" |
||||
|
:loading="confirmLoading" |
||||
|
v-if="showOkBtn" |
||||
|
> |
||||
|
{{ okText }} |
||||
|
</a-button> |
||||
|
<slot name="appendFooter"></slot> |
||||
|
</template> |
||||
|
|
||||
|
<template v-else> |
||||
|
<slot name="footer"></slot> |
||||
|
</template> |
||||
|
</div> |
||||
|
</template> |
||||
|
<script lang="ts"> |
||||
|
import type { CSSProperties } from 'vue'; |
||||
|
import { defineComponent, computed } from 'vue'; |
||||
|
// import { useDesign } from '/@/hooks/web/useDesign'; |
||||
|
|
||||
|
import { footerProps } from '../props'; |
||||
|
export default defineComponent({ |
||||
|
name: 'BasicDrawerFooter', |
||||
|
props: { |
||||
|
...footerProps, |
||||
|
height: { |
||||
|
type: String, |
||||
|
default: '60px', |
||||
|
}, |
||||
|
}, |
||||
|
emits: ['ok', 'close'], |
||||
|
setup(props, { emit }) { |
||||
|
const prefixCls = 'basic-drawer-footer'; |
||||
|
|
||||
|
const getStyle = computed((): CSSProperties => { |
||||
|
const heightStr = `${props.height}`; |
||||
|
return { |
||||
|
height: heightStr, |
||||
|
lineHeight: `calc(${heightStr} - 1px)`, |
||||
|
}; |
||||
|
}); |
||||
|
|
||||
|
function handleOk() { |
||||
|
emit('ok'); |
||||
|
} |
||||
|
|
||||
|
function handleClose() { |
||||
|
emit('close'); |
||||
|
} |
||||
|
return { handleOk, prefixCls, handleClose, getStyle }; |
||||
|
}, |
||||
|
}); |
||||
|
</script> |
||||
|
|
||||
|
<style lang="less"> |
||||
|
@prefix-cls: ~'basic-drawer-footer'; |
||||
|
@footer-height: 60px; |
||||
|
.@{prefix-cls} { |
||||
|
position: absolute; |
||||
|
bottom: 0; |
||||
|
width: 100%; |
||||
|
padding: 0 12px 0 20px; |
||||
|
text-align: right; |
||||
|
background-color: @component-background; |
||||
|
border-top: 1px solid @border-color-base; |
||||
|
|
||||
|
> * { |
||||
|
margin-right: 8px; |
||||
|
} |
||||
|
} |
||||
|
</style> |
||||
@ -0,0 +1,74 @@ |
|||||
|
<template> |
||||
|
<BasicTitle v-if="!isDetail" :class="prefixCls"> |
||||
|
<slot name="title"></slot> |
||||
|
{{ !$slots.title ? title : '' }} |
||||
|
</BasicTitle> |
||||
|
|
||||
|
<div :class="[prefixCls, `${prefixCls}--detail`]" v-else> |
||||
|
<span :class="`${prefixCls}__twrap`"> |
||||
|
<span @click="handleClose" v-if="showDetailBack"> |
||||
|
<ArrowLeftOutlined :class="`${prefixCls}__back`" /> |
||||
|
</span> |
||||
|
<span v-if="title">{{ title }}</span> |
||||
|
</span> |
||||
|
|
||||
|
<span :class="`${prefixCls}__toolbar`"> |
||||
|
<slot name="titleToolbar"></slot> |
||||
|
</span> |
||||
|
</div> |
||||
|
</template> |
||||
|
<script lang="ts"> |
||||
|
import { defineComponent } from 'vue'; |
||||
|
import BasicTitle from '@/components/basic/basic-title/index.vue'; |
||||
|
import { ArrowLeftOutlined } from '@ant-design/icons-vue'; |
||||
|
|
||||
|
// import { useDesign } from '/@/hooks/web/useDesign'; |
||||
|
|
||||
|
import { propTypes } from '@/utils/propTypes'; |
||||
|
export default defineComponent({ |
||||
|
name: 'BasicDrawerHeader', |
||||
|
components: { BasicTitle, ArrowLeftOutlined }, |
||||
|
props: { |
||||
|
isDetail: propTypes.bool, |
||||
|
showDetailBack: propTypes.bool, |
||||
|
title: propTypes.string, |
||||
|
}, |
||||
|
emits: ['close'], |
||||
|
setup(_, { emit }) { |
||||
|
const prefixCls = 'basic-drawer-header'; |
||||
|
|
||||
|
function handleClose() { |
||||
|
emit('close'); |
||||
|
} |
||||
|
|
||||
|
return { prefixCls, handleClose }; |
||||
|
}, |
||||
|
}); |
||||
|
</script> |
||||
|
|
||||
|
<style lang="less"> |
||||
|
@prefix-cls: ~'basic-drawer-header'; |
||||
|
@footer-height: 60px; |
||||
|
.@{prefix-cls} { |
||||
|
display: flex; |
||||
|
height: 100%; |
||||
|
align-items: center; |
||||
|
|
||||
|
&__back { |
||||
|
padding: 0 12px; |
||||
|
cursor: pointer; |
||||
|
|
||||
|
&:hover { |
||||
|
color: @primary-color; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
&__twrap { |
||||
|
flex: 1; |
||||
|
} |
||||
|
|
||||
|
&__toolbar { |
||||
|
padding-right: 50px; |
||||
|
} |
||||
|
} |
||||
|
</style> |
||||
@ -0,0 +1,44 @@ |
|||||
|
import type { PropType } from 'vue'; |
||||
|
|
||||
|
import { useI18n } from '@/hooks/useI18n'; |
||||
|
const { t } = useI18n(); |
||||
|
|
||||
|
export const footerProps = { |
||||
|
confirmLoading: { type: Boolean }, |
||||
|
/** |
||||
|
* @description: Show close button |
||||
|
*/ |
||||
|
showCancelBtn: { type: Boolean, default: true }, |
||||
|
cancelButtonProps: Object as PropType<Recordable>, |
||||
|
cancelText: { type: String, default: t('common.cancelText') }, |
||||
|
/** |
||||
|
* @description: Show confirmation button |
||||
|
*/ |
||||
|
showOkBtn: { type: Boolean, default: true }, |
||||
|
okButtonProps: Object as PropType<Recordable>, |
||||
|
okText: { type: String, default: t('common.okText') }, |
||||
|
okType: { type: String, default: 'primary' }, |
||||
|
showFooter: { type: Boolean }, |
||||
|
footerHeight: { |
||||
|
type: [String, Number] as PropType<string | number>, |
||||
|
default: 60, |
||||
|
}, |
||||
|
}; |
||||
|
export const basicProps = { |
||||
|
isDetail: { type: Boolean }, |
||||
|
title: { type: String, default: '' }, |
||||
|
loadingText: { type: String }, |
||||
|
showDetailBack: { type: Boolean, default: true }, |
||||
|
visible: { type: Boolean }, |
||||
|
loading: { type: Boolean }, |
||||
|
maskClosable: { type: Boolean, default: true }, |
||||
|
getContainer: { |
||||
|
type: [Object, String] as PropType<any>, |
||||
|
}, |
||||
|
closeFunc: { |
||||
|
type: [Function, Object] as PropType<any>, |
||||
|
default: null, |
||||
|
}, |
||||
|
destroyOnClose: { type: Boolean }, |
||||
|
...footerProps, |
||||
|
}; |
||||
@ -0,0 +1,195 @@ |
|||||
|
import type { ButtonProps } from 'ant-design-vue/lib/button/buttonTypes'; |
||||
|
import type { ScrollContainerOptions } from '@/components/core/Container/index'; |
||||
|
import type { CSSProperties, VNodeChild, ComputedRef } from 'vue'; |
||||
|
|
||||
|
export interface DrawerInstance { |
||||
|
setDrawerProps: (props: Partial<DrawerProps> | boolean) => void; |
||||
|
emitVisible?: (visible: boolean, uid: number) => void; |
||||
|
} |
||||
|
|
||||
|
export interface ReturnMethods extends DrawerInstance { |
||||
|
openDrawer: <T = any>(visible?: boolean, data?: T, openOnSet?: boolean) => void; |
||||
|
closeDrawer: () => void; |
||||
|
getVisible?: ComputedRef<boolean>; |
||||
|
} |
||||
|
|
||||
|
export type RegisterFn = (drawerInstance: DrawerInstance, uuid?: string) => void; |
||||
|
|
||||
|
export interface ReturnInnerMethods extends DrawerInstance { |
||||
|
closeDrawer: () => void; |
||||
|
changeLoading: (loading: boolean) => void; |
||||
|
changeOkLoading: (loading: boolean) => void; |
||||
|
getVisible?: ComputedRef<boolean>; |
||||
|
} |
||||
|
|
||||
|
export type UseDrawerReturnType = [RegisterFn, ReturnMethods]; |
||||
|
|
||||
|
export type UseDrawerInnerReturnType = [RegisterFn, ReturnInnerMethods]; |
||||
|
|
||||
|
|
||||
|
export interface DrawerActionType { |
||||
|
scrollBottom: () => void; |
||||
|
scrollTo: (to: number) => void; |
||||
|
getScrollWrap: () => Element | null; |
||||
|
} |
||||
|
|
||||
|
export interface DrawerFooterProps { |
||||
|
showOkBtn: boolean; |
||||
|
showCancelBtn: boolean; |
||||
|
/** |
||||
|
* Text of the Cancel button |
||||
|
* @default 'cancel' |
||||
|
* @type string |
||||
|
*/ |
||||
|
cancelText: string; |
||||
|
/** |
||||
|
* Text of the OK button |
||||
|
* @default 'OK' |
||||
|
* @type string |
||||
|
*/ |
||||
|
okText: string; |
||||
|
|
||||
|
/** |
||||
|
* Button type of the OK button |
||||
|
* @default 'primary' |
||||
|
* @type string |
||||
|
*/ |
||||
|
okType: 'primary' | 'danger' | 'dashed' | 'ghost' | 'default'; |
||||
|
/** |
||||
|
* The ok button props, follow jsx rules |
||||
|
* @type object |
||||
|
*/ |
||||
|
okButtonProps: { props: ButtonProps; on: {} }; |
||||
|
|
||||
|
/** |
||||
|
* The cancel button props, follow jsx rules |
||||
|
* @type object |
||||
|
*/ |
||||
|
cancelButtonProps: { props: ButtonProps; on: {} }; |
||||
|
/** |
||||
|
* Whether to apply loading visual effect for OK button or not |
||||
|
* @default false |
||||
|
* @type boolean |
||||
|
*/ |
||||
|
confirmLoading: boolean; |
||||
|
|
||||
|
showFooter: boolean; |
||||
|
footerHeight: string | number; |
||||
|
} |
||||
|
export interface DrawerProps extends DrawerFooterProps { |
||||
|
isDetail?: boolean; |
||||
|
loading?: boolean; |
||||
|
showDetailBack?: boolean; |
||||
|
visible?: boolean; |
||||
|
/** |
||||
|
* Built-in ScrollContainer component configuration |
||||
|
* @type ScrollContainerOptions |
||||
|
*/ |
||||
|
scrollOptions?: ScrollContainerOptions; |
||||
|
closeFunc?: () => Promise<any>; |
||||
|
triggerWindowResize?: boolean; |
||||
|
/** |
||||
|
* Whether a close (x) button is visible on top right of the Drawer dialog or not. |
||||
|
* @default true |
||||
|
* @type boolean |
||||
|
*/ |
||||
|
closable?: boolean; |
||||
|
|
||||
|
/** |
||||
|
* Whether to unmount child components on closing drawer or not. |
||||
|
* @default false |
||||
|
* @type boolean |
||||
|
*/ |
||||
|
destroyOnClose?: boolean; |
||||
|
|
||||
|
/** |
||||
|
* Return the mounted node for Drawer. |
||||
|
* @default 'body' |
||||
|
* @type any ( HTMLElement| () => HTMLElement | string) |
||||
|
*/ |
||||
|
getContainer?: () => HTMLElement | string; |
||||
|
|
||||
|
/** |
||||
|
* Whether to show mask or not. |
||||
|
* @default true |
||||
|
* @type boolean |
||||
|
*/ |
||||
|
mask?: boolean; |
||||
|
|
||||
|
/** |
||||
|
* Clicking on the mask (area outside the Drawer) to close the Drawer or not. |
||||
|
* @default true |
||||
|
* @type boolean |
||||
|
*/ |
||||
|
maskClosable?: boolean; |
||||
|
|
||||
|
/** |
||||
|
* Style for Drawer's mask element. |
||||
|
* @default {} |
||||
|
* @type object |
||||
|
*/ |
||||
|
maskStyle?: CSSProperties; |
||||
|
|
||||
|
/** |
||||
|
* The title for Drawer. |
||||
|
* @type any (string | slot) |
||||
|
*/ |
||||
|
title?: VNodeChild | JSX.Element; |
||||
|
/** |
||||
|
* The class name of the container of the Drawer dialog. |
||||
|
* @type string |
||||
|
*/ |
||||
|
wrapClassName?: string; |
||||
|
class?: string; |
||||
|
/** |
||||
|
* Style of wrapper element which **contains mask** compare to `drawerStyle` |
||||
|
* @type object |
||||
|
*/ |
||||
|
wrapStyle?: CSSProperties; |
||||
|
|
||||
|
/** |
||||
|
* Style of the popup layer element |
||||
|
* @type object |
||||
|
*/ |
||||
|
drawerStyle?: CSSProperties; |
||||
|
|
||||
|
/** |
||||
|
* Style of floating layer, typically used for adjusting its position. |
||||
|
* @type object |
||||
|
*/ |
||||
|
bodyStyle?: CSSProperties; |
||||
|
headerStyle?: CSSProperties; |
||||
|
|
||||
|
/** |
||||
|
* Width of the Drawer dialog. |
||||
|
* @default 256 |
||||
|
* @type string | number |
||||
|
*/ |
||||
|
width?: string | number; |
||||
|
|
||||
|
/** |
||||
|
* placement is top or bottom, height of the Drawer dialog. |
||||
|
* @type string | number |
||||
|
*/ |
||||
|
height?: string | number; |
||||
|
|
||||
|
/** |
||||
|
* The z-index of the Drawer. |
||||
|
* @default 1000 |
||||
|
* @type number |
||||
|
*/ |
||||
|
zIndex?: number; |
||||
|
|
||||
|
/** |
||||
|
* The placement of the Drawer. |
||||
|
* @default 'right' |
||||
|
* @type string |
||||
|
*/ |
||||
|
placement?: 'top' | 'right' | 'bottom' | 'left'; |
||||
|
afterVisibleChange?: (visible?: boolean) => void; |
||||
|
keyboard?: boolean; |
||||
|
/** |
||||
|
* Specify a callback that will be called when a user clicks mask, close button or Cancel button. |
||||
|
*/ |
||||
|
onClose?: (e?: Event) => void; |
||||
|
} |
||||
@ -0,0 +1,161 @@ |
|||||
|
import type { |
||||
|
UseDrawerReturnType, |
||||
|
DrawerInstance, |
||||
|
ReturnMethods, |
||||
|
DrawerProps, |
||||
|
UseDrawerInnerReturnType, |
||||
|
} from './typing'; |
||||
|
import { |
||||
|
ref, |
||||
|
getCurrentInstance, |
||||
|
unref, |
||||
|
reactive, |
||||
|
watchEffect, |
||||
|
nextTick, |
||||
|
toRaw, |
||||
|
computed, |
||||
|
} from 'vue'; |
||||
|
import { isProdMode } from '@/utils/env'; |
||||
|
import { isFunction } from '@/utils/is'; |
||||
|
import { tryOnUnmounted } from '@vueuse/core'; |
||||
|
import { isEqual } from 'lodash-es'; |
||||
|
import { error } from '@/utils/log'; |
||||
|
|
||||
|
const dataTransferRef = reactive<any>({}); |
||||
|
|
||||
|
const visibleData = reactive<{ [key: number]: boolean }>({}); |
||||
|
|
||||
|
/** |
||||
|
* @description: Applicable to separate drawer and call outside |
||||
|
*/ |
||||
|
export function useDrawer(): UseDrawerReturnType { |
||||
|
if (!getCurrentInstance()) { |
||||
|
throw new Error('useDrawer() can only be used inside setup() or functional components!'); |
||||
|
} |
||||
|
const drawer = ref<DrawerInstance | null>(null); |
||||
|
const loaded = ref<Nullable<boolean>>(false); |
||||
|
const uid = ref<string>(''); |
||||
|
|
||||
|
function register(drawerInstance: DrawerInstance, uuid: string) { |
||||
|
isProdMode() && |
||||
|
tryOnUnmounted(() => { |
||||
|
drawer.value = null; |
||||
|
loaded.value = null; |
||||
|
dataTransferRef[unref(uid)] = null; |
||||
|
}); |
||||
|
|
||||
|
if (unref(loaded) && isProdMode() && drawerInstance === unref(drawer)) { |
||||
|
return; |
||||
|
} |
||||
|
uid.value = uuid; |
||||
|
drawer.value = drawerInstance; |
||||
|
loaded.value = true; |
||||
|
|
||||
|
drawerInstance.emitVisible = (visible: boolean, uid: number) => { |
||||
|
visibleData[uid] = visible; |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
const getInstance = () => { |
||||
|
const instance = unref(drawer); |
||||
|
if (!instance) { |
||||
|
error('useDrawer instance is undefined!'); |
||||
|
} |
||||
|
return instance; |
||||
|
}; |
||||
|
|
||||
|
const methods: ReturnMethods = { |
||||
|
setDrawerProps: (props: Partial<DrawerProps>): void => { |
||||
|
getInstance()?.setDrawerProps(props); |
||||
|
}, |
||||
|
|
||||
|
getVisible: computed((): boolean => { |
||||
|
return visibleData[~~unref(uid)]; |
||||
|
}), |
||||
|
|
||||
|
openDrawer: <T = any>(visible = true, data?: T, openOnSet = true): void => { |
||||
|
getInstance()?.setDrawerProps({ |
||||
|
visible: visible, |
||||
|
}); |
||||
|
if (!data) return; |
||||
|
|
||||
|
if (openOnSet) { |
||||
|
dataTransferRef[unref(uid)] = null; |
||||
|
dataTransferRef[unref(uid)] = toRaw(data); |
||||
|
return; |
||||
|
} |
||||
|
const equal = isEqual(toRaw(dataTransferRef[unref(uid)]), toRaw(data)); |
||||
|
if (!equal) { |
||||
|
dataTransferRef[unref(uid)] = toRaw(data); |
||||
|
} |
||||
|
}, |
||||
|
closeDrawer: () => { |
||||
|
getInstance()?.setDrawerProps({ visible: false }); |
||||
|
}, |
||||
|
}; |
||||
|
|
||||
|
return [register, methods]; |
||||
|
} |
||||
|
|
||||
|
export const useDrawerInner = (callbackFn?: Fn): UseDrawerInnerReturnType => { |
||||
|
const drawerInstanceRef = ref<Nullable<DrawerInstance>>(null); |
||||
|
const currentInstance = getCurrentInstance(); |
||||
|
const uidRef = ref<string>(''); |
||||
|
|
||||
|
if (!getCurrentInstance()) { |
||||
|
throw new Error('useDrawerInner() can only be used inside setup() or functional components!'); |
||||
|
} |
||||
|
|
||||
|
const getInstance = () => { |
||||
|
const instance = unref(drawerInstanceRef); |
||||
|
if (!instance) { |
||||
|
error('useDrawerInner instance is undefined!'); |
||||
|
return; |
||||
|
} |
||||
|
return instance; |
||||
|
}; |
||||
|
|
||||
|
const register = (modalInstance: DrawerInstance, uuid: string) => { |
||||
|
isProdMode() && |
||||
|
tryOnUnmounted(() => { |
||||
|
drawerInstanceRef.value = null; |
||||
|
}); |
||||
|
|
||||
|
uidRef.value = uuid; |
||||
|
drawerInstanceRef.value = modalInstance; |
||||
|
currentInstance?.emit('register', modalInstance, uuid); |
||||
|
}; |
||||
|
|
||||
|
watchEffect(() => { |
||||
|
const data = dataTransferRef[unref(uidRef)]; |
||||
|
if (!data) return; |
||||
|
if (!callbackFn || !isFunction(callbackFn)) return; |
||||
|
nextTick(() => { |
||||
|
callbackFn(data); |
||||
|
}); |
||||
|
}); |
||||
|
|
||||
|
return [ |
||||
|
register, |
||||
|
{ |
||||
|
changeLoading: (loading = true) => { |
||||
|
getInstance()?.setDrawerProps({ loading }); |
||||
|
}, |
||||
|
|
||||
|
changeOkLoading: (loading = true) => { |
||||
|
getInstance()?.setDrawerProps({ confirmLoading: loading }); |
||||
|
}, |
||||
|
getVisible: computed((): boolean => { |
||||
|
return visibleData[~~unref(uidRef)]; |
||||
|
}), |
||||
|
|
||||
|
closeDrawer: () => { |
||||
|
getInstance()?.setDrawerProps({ visible: false }); |
||||
|
}, |
||||
|
|
||||
|
setDrawerProps: (props: Partial<DrawerProps>) => { |
||||
|
getInstance()?.setDrawerProps(props); |
||||
|
}, |
||||
|
}, |
||||
|
]; |
||||
|
}; |
||||
@ -1,7 +1,21 @@ |
|||||
|
/* |
||||
|
* @Author: AaronWu 2463371514@qq.com |
||||
|
* @Date: 2025-03-31 15:12:17 |
||||
|
* @LastEditors: AaronWu 2463371514@qq.com |
||||
|
* @LastEditTime: 2025-04-01 10:39:52 |
||||
|
* @FilePath: /IssueSupportManage/src/shims-vue.d.ts |
||||
|
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
|
||||
|
*/ |
||||
declare module '*.vue' { |
declare module '*.vue' { |
||||
import type { DefineComponent } from 'vue' |
|
||||
const component: DefineComponent<{}, {}, any> |
|
||||
export default component |
|
||||
|
import type { DefineComponent } from 'vue'; |
||||
|
const component: DefineComponent<{}, {}, any>; |
||||
|
export default component; |
||||
} |
} |
||||
|
|
||||
declare module 'nprogress' |
|
||||
|
declare module '*.md' { |
||||
|
import type { ComponentOptions } from 'vue'; |
||||
|
const Component: ComponentOptions; |
||||
|
export default Component; |
||||
|
} |
||||
|
|
||||
|
declare module 'nprogress'; |
||||
|
|||||
@ -0,0 +1,38 @@ |
|||||
|
|
||||
|
|
||||
|
/** |
||||
|
* @description: Development mode |
||||
|
*/ |
||||
|
export const devMode = 'development'; |
||||
|
|
||||
|
/** |
||||
|
* @description: Production mode |
||||
|
*/ |
||||
|
export const prodMode = 'production'; |
||||
|
|
||||
|
/** |
||||
|
* @description: Get environment variables |
||||
|
* @returns: |
||||
|
* @example: |
||||
|
*/ |
||||
|
export function getEnv(): string { |
||||
|
return import.meta.env.MODE; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @description: Is it a development mode |
||||
|
* @returns: |
||||
|
* @example: |
||||
|
*/ |
||||
|
export function isDevMode(): boolean { |
||||
|
return import.meta.env.DEV; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @description: Is it a production mode |
||||
|
* @returns: |
||||
|
* @example: |
||||
|
*/ |
||||
|
export function isProdMode(): boolean { |
||||
|
return import.meta.env.PROD; |
||||
|
} |
||||
@ -0,0 +1,9 @@ |
|||||
|
const projectName = import.meta.env.VITE_GLOB_APP_TITLE; |
||||
|
|
||||
|
export function warn(message: string) { |
||||
|
console.warn(`[${projectName} warn]:${message}`); |
||||
|
} |
||||
|
|
||||
|
export function error(message: string) { |
||||
|
throw new Error(`[${projectName} error]:${message}`); |
||||
|
} |
||||
@ -1,85 +1,90 @@ |
|||||
<!-- |
<!-- |
||||
功能:功能描述 |
|
||||
作者:Aaron.Wu |
|
||||
时间:2023年05月25日 17:00:26 |
|
||||
版本:v1.0 |
|
||||
修改记录: |
|
||||
修改内容: |
|
||||
修改人员: |
|
||||
修改时间: |
|
||||
|
* @Author: AaronWu 2463371514@qq.com |
||||
|
* @Date: 2025-03-31 15:12:17 |
||||
|
* @LastEditors: AaronWu 2463371514@qq.com |
||||
|
* @LastEditTime: 2025-04-01 10:40:23 |
||||
|
* @FilePath: /IssueSupportManage/src/views/dashboard/welcome/index.vue |
||||
|
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE |
||||
--> |
--> |
||||
<template> |
<template> |
||||
<div class="w-200px"> |
|
||||
<!-- <button @click="handleClick">222</button> |
|
||||
<BasicTree |
|
||||
ref="treeRef" |
|
||||
:clickRowToExpand="false" |
|
||||
:beforeRightClick="getRightMenuList" |
|
||||
:loading="treeLoading" |
|
||||
title="77777" |
|
||||
:treeData="treeData" |
|
||||
checkStrictly |
|
||||
checkable |
|
||||
highlight |
|
||||
search |
|
||||
toolbar |
|
||||
@select="handleSelect" |
|
||||
:checkedKeys="['0-0']" |
|
||||
> |
|
||||
</BasicTree> --> |
|
||||
|
<div class="welcome-container"> |
||||
|
<a-card class="doc-card"> |
||||
|
<template #title> |
||||
|
<div class="card-title"> |
||||
|
<span>接口文档</span> |
||||
|
<a-tag color="blue">DTO</a-tag> |
||||
|
</div> |
||||
|
</template> |
||||
|
<!-- <div class="markdown-body" v-html="mdContent"></div> --> |
||||
|
<DTO></DTO> |
||||
|
</a-card> |
||||
</div> |
</div> |
||||
</template> |
</template> |
||||
|
|
||||
<script lang="ts" setup> |
<script lang="ts" setup> |
||||
import { ContextMenuItem } from '@/components/basic/ContextMenu'; |
|
||||
import { BasicTree } from '@/components/core/Tree'; |
|
||||
import { PlusOutlined } from '@ant-design/icons-vue'; |
|
||||
import { Menu } from 'ant-design-vue'; |
|
||||
import { h, ref } from 'vue'; |
|
||||
|
import { ref, onMounted } from 'vue'; |
||||
|
import DTO from '@/assets/DTO.md'; |
||||
|
// console.log('DTO: ', DTO); |
||||
|
|
||||
const treeRef = ref<Nullable<any>>(null); |
|
||||
const treeData = ref<any[]>([ |
|
||||
{ |
|
||||
title: 'parent 1', |
|
||||
key: '0-0', |
|
||||
children: [ |
|
||||
{ |
|
||||
title: 'parent 1-0', |
|
||||
key: '0-0-0', |
|
||||
disabled: true, |
|
||||
children: [ |
|
||||
{ title: 'leaf', key: '0-0-0-0', disableCheckbox: true }, |
|
||||
{ title: 'leaf', key: '0-0-0-1' }, |
|
||||
], |
|
||||
}, |
|
||||
{ |
|
||||
title: 'parent 1-1', |
|
||||
key: '0-0-1', |
|
||||
children: [{ key: '0-0-1-0', title: 'sss' }], |
|
||||
}, |
|
||||
], |
|
||||
}, |
|
||||
]); |
|
||||
const treeLoading = ref<boolean>(false); |
|
||||
|
// const mdContent = ref(DTO); |
||||
|
</script> |
||||
|
|
||||
|
<style lang="less" scoped> |
||||
|
.welcome-container { |
||||
|
padding: 24px; |
||||
|
|
||||
const handleSelect = (key, row) => { |
|
||||
console.log('row: ', row); |
|
||||
console.log('key: ', key); |
|
||||
}; |
|
||||
|
.doc-card { |
||||
|
background: #fff; |
||||
|
border-radius: 8px; |
||||
|
|
||||
const handleClick = () => { |
|
||||
console.log(treeRef.value.checkAll(true)); |
|
||||
treeRef.value.setCheckedKeys(['0-0']) |
|
||||
}; |
|
||||
|
.card-title { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
gap: 12px; |
||||
|
|
||||
// 右键菜单 |
|
||||
function getRightMenuList(node: any): ContextMenuItem[] { |
|
||||
return [ |
|
||||
{ |
|
||||
label: '新增', |
|
||||
handler: () => {}, |
|
||||
}, |
|
||||
]; |
|
||||
|
span { |
||||
|
font-size: 16px; |
||||
|
font-weight: 500; |
||||
|
} |
||||
|
} |
||||
} |
} |
||||
</script> |
|
||||
<style lang="less" scoped></style> |
|
||||
|
|
||||
|
:deep(.markdown-body) { |
||||
|
padding: 16px 0; |
||||
|
|
||||
|
table { |
||||
|
width: 100%; |
||||
|
border-collapse: collapse; |
||||
|
margin: 16px 0; |
||||
|
|
||||
|
th, |
||||
|
td { |
||||
|
padding: 12px; |
||||
|
border: 1px solid #e8e8e8; |
||||
|
} |
||||
|
|
||||
|
th { |
||||
|
background: #fafafa; |
||||
|
font-weight: 500; |
||||
|
} |
||||
|
|
||||
|
tr:hover { |
||||
|
background: #fafafa; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
h2 { |
||||
|
font-size: 24px; |
||||
|
margin: 24px 0 16px; |
||||
|
padding-bottom: 8px; |
||||
|
border-bottom: 1px solid #eee; |
||||
|
} |
||||
|
|
||||
|
h3 { |
||||
|
font-size: 18px; |
||||
|
margin: 20px 0 12px; |
||||
|
color: #1a1a1a; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
</style> |
||||
|
|||||
@ -1,14 +0,0 @@ |
|||||
<!-- |
|
||||
功能:功能描述 |
|
||||
作者:Aaron |
|
||||
时间:2023年06月16日 14:53:40 |
|
||||
版本:v1.0 |
|
||||
修改记录: |
|
||||
修改内容: |
|
||||
修改人员: |
|
||||
修改时间: |
|
||||
--> |
|
||||
<template> </template> |
|
||||
|
|
||||
<script lang="tsx" setup></script> |
|
||||
<style lang="less" scoped></style> |
|
||||
@ -0,0 +1,330 @@ |
|||||
|
<template> |
||||
|
<div class="bg-white m-4 mr-2 overflow-hidden h-full"> |
||||
|
<BasicTree |
||||
|
ref="treeRef" |
||||
|
:actionList="actionList" |
||||
|
:beforeRightClick="getRightMenuList" |
||||
|
:checkable="!query" |
||||
|
:clickRowToExpand="false" |
||||
|
:treeData="treeData" |
||||
|
checkStrictly |
||||
|
:defaultExpandAll="true" |
||||
|
search |
||||
|
toolbar |
||||
|
:highlight="true" |
||||
|
@select="handleSelect" |
||||
|
:toolbarStrictly="false" |
||||
|
> |
||||
|
<!-- <template #titleBefore="item"> </template> --> |
||||
|
</BasicTree> |
||||
|
<div v-if="query" class="m-4 flex justify-center"> |
||||
|
<a-button class="w-[80%]" type="primary" @click="handleReset()">重置</a-button> |
||||
|
<!-- <Checkbox v-model:checked="recursion" @change="handleQuery()">本级及子级</Checkbox> --> |
||||
|
</div> |
||||
|
<div v-else class="m-4 flex justify-center"> |
||||
|
<a-button |
||||
|
type="primary" |
||||
|
class="w-[80%]" |
||||
|
v-permission="{ action: RoleEnum.DICT_ADD, effect: 'disabled' }" |
||||
|
@click="openTypeModal({})" |
||||
|
> |
||||
|
{{ '新增类型' }} |
||||
|
</a-button> |
||||
|
<!-- <a-button |
||||
|
v-permission="{ action: RoleEnum.DICT_DELETE, effect: 'disabled' }" |
||||
|
class="mr-2" |
||||
|
@click="handleBatchDelete()" |
||||
|
> |
||||
|
{{ '删除' }} |
||||
|
</a-button> --> |
||||
|
</div> |
||||
|
<!-- <OrgRole @register="registerModal" @success="handleSuccess" /> --> |
||||
|
</div> |
||||
|
</template> |
||||
|
<script lang="tsx"> |
||||
|
import { defineComponent, h, onMounted, ref, unref } from 'vue'; |
||||
|
import { Checkbox, message, Tag } from 'ant-design-vue'; // antd组件 |
||||
|
import { useI18n } from '@/hooks/useI18n'; |
||||
|
import { |
||||
|
BasicTree, |
||||
|
ContextMenuItem, |
||||
|
TreeActionItem, |
||||
|
TreeActionType, |
||||
|
TreeItem, |
||||
|
} from '@/components/core/Tree'; |
||||
|
import { eachTree, findChildrenByParentId, findNodeByKey } from '@/utils/helper/treeHelper'; |
||||
|
import { RoleEnum } from '@/enums/roleEnum'; |
||||
|
import { OrgTypeEnum } from '@/enums/biz/base'; |
||||
|
import { useFormModal } from '@/hooks/useModal/index'; |
||||
|
|
||||
|
import { createDict, deleteBatchDictById, fetchDictList, updateDict } from '@/api/dict/index'; |
||||
|
// import { useModal } from '@/components/Modal'; |
||||
|
// import OrgRole from './orgRole/index.vue'; |
||||
|
import { useMessage } from '@/hooks/useMessage'; |
||||
|
import { mockTree } from './mockData'; |
||||
|
import { Nullable } from '@/utils/types'; |
||||
|
import { typeFormSchema } from './formSchemas'; |
||||
|
import { TableListItem } from './columns'; |
||||
|
import { omit } from 'lodash-es'; |
||||
|
import { isArray } from '@/utils/is'; |
||||
|
|
||||
|
export default defineComponent({ |
||||
|
name: 'BaseDictValueManagement', |
||||
|
components: { |
||||
|
BasicTree, |
||||
|
// OrgRole, |
||||
|
Checkbox, |
||||
|
Tag, |
||||
|
}, |
||||
|
props: { |
||||
|
query: { |
||||
|
type: Boolean, |
||||
|
default: false, |
||||
|
}, |
||||
|
}, |
||||
|
emits: ['select', 'add', 'edit', 'change', 'reset'], |
||||
|
setup(props, { emit }) { |
||||
|
const { t } = useI18n(); |
||||
|
const { createMessage, createConfirm } = useMessage(); |
||||
|
|
||||
|
const treeRef = ref<Nullable<TreeActionType>>(null); |
||||
|
const treeData = ref<TreeItem[]>([]); |
||||
|
const recursion = ref<boolean>(false); |
||||
|
// 绑定角色 |
||||
|
// const [registerModal, { openModal }] = useModal(); |
||||
|
|
||||
|
const [showModal] = useFormModal(); |
||||
|
|
||||
|
/** |
||||
|
* @description 打开弹窗 |
||||
|
*/ |
||||
|
const openTypeModal = async (record: Partial<TableListItem> = {}, isReadOnly = false) => { |
||||
|
const [formRef] = await showModal<any>({ |
||||
|
modalProps: { |
||||
|
title: `${isReadOnly ? '查看' : record.id ? '编辑' : '新增'}类型`, |
||||
|
width: 500, |
||||
|
onFinish: async (values) => { |
||||
|
values.id = record.id; |
||||
|
await (record.id ? updateDict : createDict)(values); |
||||
|
message.success(`${record.id ? '编辑' : '新增'}成功`); |
||||
|
fetch(); |
||||
|
}, |
||||
|
}, |
||||
|
formProps: { |
||||
|
labelWidth: 100, |
||||
|
schemas: typeFormSchema, |
||||
|
autoSubmitOnEnter: true, |
||||
|
}, |
||||
|
}); |
||||
|
formRef?.setFieldsValue(record); |
||||
|
}; |
||||
|
|
||||
|
function getTree() { |
||||
|
const tree = unref(treeRef); |
||||
|
if (!tree) { |
||||
|
throw new Error('树结构加载失败,请刷新页面'); |
||||
|
} |
||||
|
return tree; |
||||
|
} |
||||
|
|
||||
|
onMounted(() => { |
||||
|
fetch(); |
||||
|
}); |
||||
|
|
||||
|
// 加载数据 |
||||
|
async function fetch() { |
||||
|
// const types = (await fetchDictList()) as unknown as TreeItem[]; |
||||
|
const types = mockTree; |
||||
|
console.log('types: ', types); |
||||
|
treeData.value = types.map((e) => { |
||||
|
return { |
||||
|
...e, |
||||
|
name: e.name, |
||||
|
editable: true, |
||||
|
}; |
||||
|
}) as unknown as TreeItem[]; |
||||
|
eachTree(treeData.value, (item) => { |
||||
|
item.key = item.id; |
||||
|
item.title = item.name; |
||||
|
item.slots = { titleBefore: 'titleBefore' }; |
||||
|
return item; |
||||
|
}); |
||||
|
console.log('treeData.value: ', treeData.value); |
||||
|
console.log('[treeData.value[0].id]: ', [treeData.value[0].id]); |
||||
|
|
||||
|
if (isArray(treeData.value) && treeData.value.length > 0) { |
||||
|
getTree().setSelectedKeys([treeData.value[0].id]); |
||||
|
handleSelect([treeData.value[0].id]); |
||||
|
} |
||||
|
// setTimeout(() => { |
||||
|
// getTree().filterByLevel(2); |
||||
|
// }, 0); |
||||
|
} |
||||
|
|
||||
|
// 选择节点 |
||||
|
function handleSelect(keys: string[]) { |
||||
|
console.log('keys: ', keys); |
||||
|
if (keys[0]) { |
||||
|
const node = findNodeByKey(keys[0], treeData.value); |
||||
|
const parent = findNodeByKey(node?.parentId, treeData.value); |
||||
|
let childrenIds: string[] = []; |
||||
|
if (recursion.value) { |
||||
|
childrenIds = findChildrenByParentId(keys[0], treeData.value); |
||||
|
} else { |
||||
|
childrenIds = [node.id]; |
||||
|
} |
||||
|
emit('select', parent, node, childrenIds); |
||||
|
} else { |
||||
|
emit('select', {}, {}); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
let actionList: TreeActionItem[] = []; |
||||
|
let getRightMenuList = (_: any): ContextMenuItem[] => { |
||||
|
return []; |
||||
|
}; |
||||
|
if (!props.query) { |
||||
|
// 悬停图标 |
||||
|
actionList = [ |
||||
|
{ |
||||
|
render: (node) => { |
||||
|
if (node.editable) { |
||||
|
return h( |
||||
|
'a', |
||||
|
{ |
||||
|
class: 'ml-2', |
||||
|
onClick: (e: Event) => { |
||||
|
e?.stopPropagation(); |
||||
|
e?.preventDefault(); |
||||
|
const current = findNodeByKey(node?.id, treeData.value); |
||||
|
// const parent = findNodeByKey(node?.parentId, treeData.value); |
||||
|
// emit('edit', parent, current); |
||||
|
openTypeModal(current); |
||||
|
}, |
||||
|
}, |
||||
|
'编辑', |
||||
|
); |
||||
|
} |
||||
|
}, |
||||
|
}, |
||||
|
|
||||
|
{ |
||||
|
render: (node) => { |
||||
|
if (node.editable) { |
||||
|
return h( |
||||
|
'a', |
||||
|
{ |
||||
|
class: 'ml-2', |
||||
|
onClick: (e: Event) => { |
||||
|
e?.stopPropagation(); |
||||
|
e?.preventDefault(); |
||||
|
batchDelete([node.id]); |
||||
|
}, |
||||
|
}, |
||||
|
'删除', |
||||
|
); |
||||
|
} |
||||
|
}, |
||||
|
}, |
||||
|
]; |
||||
|
|
||||
|
// 右键菜单 |
||||
|
// getRightMenuList = (node: any): ContextMenuItem[] => { |
||||
|
// return [ |
||||
|
// { |
||||
|
// label: '编辑', |
||||
|
// auth: RoleEnum.DICT_EDIT, |
||||
|
// handler: () => { |
||||
|
// const current = findNodeByKey(unref(node)?.id, treeData.value); |
||||
|
// const parent = findNodeByKey(unref(node)?.parentId, treeData.value); |
||||
|
// emit('edit', parent, current); |
||||
|
// }, |
||||
|
// }, |
||||
|
// { |
||||
|
// label: '删除', |
||||
|
// auth: RoleEnum.DICT_DELETE, |
||||
|
// handler: () => { |
||||
|
// batchDelete([unref(node).id]); |
||||
|
// }, |
||||
|
// }, |
||||
|
// ]; |
||||
|
// }; |
||||
|
} |
||||
|
|
||||
|
// 执行批量删除 |
||||
|
async function batchDelete(ids: string[]) { |
||||
|
createConfirm({ |
||||
|
iconType: 'warning', |
||||
|
content: '选中节点及其子结点将被永久删除, 是否确定删除?', |
||||
|
onOk: async () => { |
||||
|
try { |
||||
|
await deleteBatchDictById(ids); |
||||
|
createMessage.success(t('common.tips.deleteSuccess')); |
||||
|
fetch(); |
||||
|
} catch (e) {} |
||||
|
}, |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
// 点击树外面的 新增 |
||||
|
function handleAdd() { |
||||
|
emit('add', findNodeByKey('0', treeData.value)); |
||||
|
} |
||||
|
|
||||
|
// 点击树外面的 批量删除 |
||||
|
function handleBatchDelete() { |
||||
|
const { checked } = getTree().getCheckedKeys() as { |
||||
|
checked: string[]; |
||||
|
halfChecked: string[]; |
||||
|
}; |
||||
|
if (!checked || checked.length <= 0) { |
||||
|
createMessage.warning(t('common.tips.pleaseSelectTheData')); |
||||
|
return; |
||||
|
} |
||||
|
batchDelete(checked); |
||||
|
} |
||||
|
|
||||
|
// 切换显示方式 |
||||
|
function changeDisplay() { |
||||
|
emit('change', '2'); |
||||
|
} |
||||
|
|
||||
|
// 重置 |
||||
|
function handleReset() { |
||||
|
getTree().setSelectedKeys([]); |
||||
|
emit('reset'); |
||||
|
} |
||||
|
|
||||
|
// 选择 本级及子级 |
||||
|
function handleQuery() { |
||||
|
handleSelect(getTree().getSelectedKeys() as string[]); |
||||
|
} |
||||
|
|
||||
|
// 新增或编辑成功回调 |
||||
|
function handleSuccess() { |
||||
|
fetch(); |
||||
|
} |
||||
|
|
||||
|
return { |
||||
|
t, |
||||
|
treeRef, |
||||
|
treeData, |
||||
|
fetch, |
||||
|
handleAdd, |
||||
|
handleBatchDelete, |
||||
|
getRightMenuList, |
||||
|
actionList, |
||||
|
handleSelect, |
||||
|
changeDisplay, |
||||
|
handleReset, |
||||
|
handleQuery, |
||||
|
RoleEnum, |
||||
|
// registerModal, |
||||
|
handleSuccess, |
||||
|
recursion, |
||||
|
OrgTypeEnum, |
||||
|
openTypeModal, |
||||
|
}; |
||||
|
}, |
||||
|
}); |
||||
|
</script> |
||||
@ -1,132 +1,80 @@ |
|||||
|
/* |
||||
|
* @Author: AaronWu 2463371514@qq.com |
||||
|
* @Date: 2025-04-01 13:43:34 |
||||
|
* @LastEditors: AaronWu 2463371514@qq.com |
||||
|
* @LastEditTime: 2025-04-01 13:52:02 |
||||
|
* @FilePath: /IssueSupportManage/src/views/system/dictionary/columns.tsx |
||||
|
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
|
||||
|
*/ |
||||
import type { TableColumn } from '@/components/core/dynamic-table'; |
import type { TableColumn } from '@/components/core/dynamic-table'; |
||||
import { formatToDateTime } from '@/utils/dateUtil'; |
|
||||
|
import { h } from 'vue'; |
||||
|
import { Switch } from 'ant-design-vue'; |
||||
|
import { disableDictValue, enableDictValue } from '@/api/dict'; |
||||
|
|
||||
export type TableListItem = API.DictionaryInfoType; |
|
||||
export type DictionaryTableListItem = API.DictionaryItemInfoType; |
|
||||
|
export type TableListItem = API.DictValueType; |
||||
export type TableColumnItem = TableColumn<TableListItem>; |
export type TableColumnItem = TableColumn<TableListItem>; |
||||
export type DictionaryTableColumnItem = TableColumn<DictionaryTableListItem>; |
|
||||
|
|
||||
// 数据项类型
|
// 数据项类型
|
||||
// export type ListItemType = typeof tableData[number];
|
// export type ListItemType = typeof tableData[number];
|
||||
// 使用TableColumn<ListItemType> 将会限制dataIndex的类型,但换来的是dataIndex有类型提示
|
// 使用TableColumn<ListItemType> 将会限制dataIndex的类型,但换来的是dataIndex有类型提示
|
||||
export const baseColumns: TableColumnItem[] = [ |
export const baseColumns: TableColumnItem[] = [ |
||||
{ |
{ |
||||
title: '标识', |
|
||||
|
title: '字段值', |
||||
align: 'center', |
align: 'center', |
||||
dataIndex: 'dictKey', |
|
||||
width: 200, |
|
||||
|
dataIndex: 'fieldValue', |
||||
|
width: 150, |
||||
|
ellipsis: true, |
||||
resizable: true, |
resizable: true, |
||||
// defaultEditable: true,
|
|
||||
// editable: ({ index }) => {
|
|
||||
// // 第一行不允许被编辑
|
|
||||
// return index > 0;
|
|
||||
// },
|
|
||||
formItemProps: { |
formItemProps: { |
||||
defaultValue: '', |
defaultValue: '', |
||||
required: false, |
required: false, |
||||
}, |
}, |
||||
}, |
}, |
||||
{ |
{ |
||||
title: '名称', |
|
||||
|
title: '启用状态', |
||||
align: 'center', |
align: 'center', |
||||
dataIndex: 'name', |
|
||||
width: 200, |
|
||||
|
dataIndex: 'enable', |
||||
|
width: 150, |
||||
|
ellipsis: true, |
||||
resizable: true, |
resizable: true, |
||||
formItemProps: { |
formItemProps: { |
||||
defaultValue: '', |
|
||||
required: false, |
|
||||
|
component: 'Select', |
||||
|
defaultValue: '1', |
||||
|
componentProps: { |
||||
|
options: [ |
||||
|
{ |
||||
|
label: '启用', |
||||
|
value: '1', |
||||
|
}, |
||||
|
{ |
||||
|
label: '禁用', |
||||
|
value: '0', |
||||
|
}, |
||||
|
], |
||||
|
}, |
||||
}, |
}, |
||||
}, |
|
||||
{ |
|
||||
title: '状态', |
|
||||
align: 'center', |
|
||||
dataIndex: 'status', |
|
||||
hideInSearch: true, |
|
||||
width: 100, |
|
||||
customRender: ({ record }) => { |
customRender: ({ record }) => { |
||||
return ( |
|
||||
<a-tag color={record.status ? 'success' : 'error'}>{record.status ? '启用' : '禁用'}</a-tag> |
|
||||
); |
|
||||
}, |
|
||||
}, |
|
||||
|
const onChange = (checked: boolean) => { |
||||
|
record.pendingStatus = true; |
||||
|
const newState = checked ? '1' : '0'; |
||||
|
record.enable = newState; |
||||
|
|
||||
{ |
|
||||
title: '创建时间', |
|
||||
align: 'center', |
|
||||
dataIndex: 'createTime', |
|
||||
width: 200, |
|
||||
formItemProps: { |
|
||||
defaultValue: '', |
|
||||
required: false, |
|
||||
component: 'RangePicker', |
|
||||
}, |
|
||||
customRender: ({ record }) => `${formatToDateTime(record.createTime)}`, |
|
||||
}, |
|
||||
]; |
|
||||
|
(checked ? enableDictValue : disableDictValue)({ id: record.id! }) |
||||
|
.then(() => { |
||||
|
record.enable = newState; |
||||
|
}) |
||||
|
.catch(() => {}) |
||||
|
.finally(() => { |
||||
|
record.pendingStatus = false; |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
export const dictItemColumns: DictionaryTableColumnItem[]=[ |
|
||||
{ |
|
||||
title: '标识', |
|
||||
align: 'center', |
|
||||
dataIndex: 'dictKey', |
|
||||
width: 200, |
|
||||
resizable: true, |
|
||||
defaultEditable: true, |
|
||||
// editable: ({ index }) => {
|
|
||||
// // 第一行不允许被编辑
|
|
||||
// return index > 0;
|
|
||||
// },
|
|
||||
formItemProps: { |
|
||||
defaultValue: '', |
|
||||
required: false, |
|
||||
}, |
|
||||
}, |
|
||||
{ |
|
||||
title: '名称', |
|
||||
align: 'center', |
|
||||
dataIndex: 'name', |
|
||||
width: 200, |
|
||||
resizable: true, |
|
||||
formItemProps: { |
|
||||
defaultValue: '', |
|
||||
required: false, |
|
||||
|
// 渲染函数写法
|
||||
|
return h(Switch, { |
||||
|
checked: record.enable === '1', |
||||
|
loading: record.pendingStatus, |
||||
|
onChange, |
||||
|
}); |
||||
}, |
}, |
||||
}, |
}, |
||||
{ |
|
||||
title: '状态', |
|
||||
align: 'center', |
|
||||
dataIndex: 'status', |
|
||||
hideInSearch: true, |
|
||||
width: 100, |
|
||||
customRender: ({ record }) => { |
|
||||
return ( |
|
||||
<a-tag color={record.status ? 'success' : 'error'}>{record.status ? '启用' : '禁用'}</a-tag> |
|
||||
); |
|
||||
}, |
|
||||
}, |
|
||||
{ |
|
||||
title: '排序', |
|
||||
align: 'center', |
|
||||
dataIndex: 'sortValue', |
|
||||
hideInSearch: true, |
|
||||
width: 200, |
|
||||
resizable: true, |
|
||||
formItemProps: { |
|
||||
defaultValue: '', |
|
||||
required: false, |
|
||||
}, |
|
||||
}, |
|
||||
{ |
|
||||
title: '创建时间', |
|
||||
align: 'center', |
|
||||
dataIndex: 'createTime', |
|
||||
hideInSearch: true, |
|
||||
width: 200, |
|
||||
formItemProps: { |
|
||||
defaultValue: '', |
|
||||
required: false, |
|
||||
component: 'RangePicker', |
|
||||
}, |
|
||||
customRender: ({ record }) => `${formatToDateTime(record.createTime)}`, |
|
||||
}, |
|
||||
] |
|
||||
|
]; |
||||
|
|||||
@ -1,44 +1,62 @@ |
|||||
import type { FormSchema } from '@/components/core/schema-form/'; |
import type { FormSchema } from '@/components/core/schema-form/'; |
||||
|
|
||||
export const schemas: FormSchema[] = [ |
|
||||
|
|
||||
|
// 列表编辑页字段
|
||||
|
export const editFormSchema: FormSchema[] = [ |
||||
{ |
{ |
||||
field: 'dictKey', |
|
||||
|
field: 'id', |
||||
|
label: 'ID', |
||||
component: 'Input', |
component: 'Input', |
||||
label: '标识', |
|
||||
colProps: { |
|
||||
span: 12, |
|
||||
}, |
|
||||
rules: [{ required: true }], |
|
||||
|
vShow: false, |
||||
}, |
}, |
||||
{ |
{ |
||||
field: 'name', |
|
||||
|
label: '字段值', |
||||
|
field: 'fieldValue', |
||||
component: 'Input', |
component: 'Input', |
||||
label: '名称', |
|
||||
colProps: { |
colProps: { |
||||
span: 12, |
|
||||
|
span: 24, |
||||
}, |
}, |
||||
rules: [{ required: true }], |
rules: [{ required: true }], |
||||
}, |
}, |
||||
{ |
{ |
||||
field: 'status', |
|
||||
component: 'Switch', |
|
||||
label: '状态', |
|
||||
|
label: '启用状态', |
||||
|
field: 'enable', |
||||
|
component: 'RadioGroup', |
||||
|
defaultValue: '1', |
||||
colProps: { |
colProps: { |
||||
span: 12, |
span: 12, |
||||
}, |
}, |
||||
|
componentProps: { |
||||
|
options: [ |
||||
|
{ |
||||
|
label: '启用', |
||||
|
value: '1', |
||||
|
}, |
||||
|
{ |
||||
|
label: '禁用', |
||||
|
value: '0', |
||||
|
}, |
||||
|
], |
||||
|
}, |
||||
|
rules: [{ required: true, type: 'string' }], |
||||
|
|
||||
}, |
}, |
||||
|
]; |
||||
|
|
||||
|
// 新增类别表单
|
||||
|
export const typeFormSchema: FormSchema[] = [ |
||||
{ |
{ |
||||
field: 'remark', |
|
||||
component: 'InputTextArea', |
|
||||
label: '备注', |
|
||||
|
field: 'id', |
||||
|
label: 'ID', |
||||
|
component: 'Input', |
||||
|
vShow: false, |
||||
|
}, |
||||
|
{ |
||||
|
label: '名称', |
||||
|
field: 'name', |
||||
|
component: 'Input', |
||||
colProps: { |
colProps: { |
||||
span: 12, |
|
||||
|
span: 24, |
||||
}, |
}, |
||||
}, |
|
||||
{ |
|
||||
field: 'dictItems', |
|
||||
label: '字典条目', |
|
||||
slot: 'dictItems', |
|
||||
|
rules: [{ required: true }], |
||||
}, |
}, |
||||
]; |
]; |
||||
|
|||||
@ -0,0 +1,14 @@ |
|||||
|
/* |
||||
|
* @Author: AaronWu 2463371514@qq.com |
||||
|
* @Date: 2025-04-01 13:24:31 |
||||
|
* @LastEditors: AaronWu 2463371514@qq.com |
||||
|
* @LastEditTime: 2025-04-01 13:25:12 |
||||
|
* @FilePath: /IssueSupportManage/src/views/system/dictionary/mockData.ts |
||||
|
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
|
||||
|
*/ |
||||
|
export const mockTree: any[] = [ |
||||
|
{ |
||||
|
id: 1, |
||||
|
name: '字典类别', |
||||
|
}, |
||||
|
]; |
||||
File diff suppressed because it is too large
Loading…
Reference in new issue