create-jnrs-vue 1.2.21 → 1.2.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/jnrs-vue/.env.development +1 -1
- package/jnrs-vue/README.md +1 -1
- package/{bin → jnrs-vue/bin}/upgrade.mjs +2 -2
- package/jnrs-vue/package.json +6 -3
- package/jnrs-vue/src/api/common/index.ts +2 -2
- package/jnrs-vue/src/api/demos/index.ts +73 -32
- package/jnrs-vue/src/api/request.ts +10 -11
- package/jnrs-vue/src/api/system/index.ts +27 -26
- package/jnrs-vue/src/components/common/CardTable.vue +3 -3
- package/jnrs-vue/src/components/common/DictTag.vue +1 -1
- package/jnrs-vue/src/components/common/ImageView.vue +4 -4
- package/jnrs-vue/src/components/common/PdfView.vue +4 -4
- package/jnrs-vue/src/components/select/SelectManager.vue +2 -2
- package/jnrs-vue/src/composables/useCrud.ts +29 -10
- package/jnrs-vue/src/layout/RouterTabs.vue +6 -6
- package/jnrs-vue/src/layout/SideMenuItem.vue +2 -2
- package/jnrs-vue/src/layout/TopHeader.vue +2 -1
- package/jnrs-vue/src/layout/index.vue +2 -1
- package/jnrs-vue/src/locales/en.ts +1 -1
- package/jnrs-vue/src/main.ts +2 -7
- package/jnrs-vue/src/router/index.ts +5 -4
- package/jnrs-vue/src/stores/index.ts +8 -0
- package/jnrs-vue/src/stores/system/auth.ts +67 -0
- package/jnrs-vue/src/types/index.ts +2 -81
- package/jnrs-vue/src/types/system.d.ts +115 -0
- package/jnrs-vue/src/types/system.js +1 -0
- package/jnrs-vue/src/types/system.ts +124 -0
- package/jnrs-vue/src/types/webSocket.ts +4 -4
- package/jnrs-vue/src/utils/dict.ts +59 -0
- package/jnrs-vue/src/utils/file.ts +1 -1
- package/jnrs-vue/src/utils/index.ts +4 -0
- package/jnrs-vue/src/utils/packages.ts +6 -65
- package/jnrs-vue/src/utils/permissions.ts +1 -1
- package/jnrs-vue/src/views/demos/crud/index.vue +29 -17
- package/jnrs-vue/src/views/demos/simpleTable/index.vue +2 -2
- package/jnrs-vue/src/views/demos/unitTest/RequestPage.vue +30 -7
- package/jnrs-vue/src/views/demos/unitTest/index.vue +2 -2
- package/jnrs-vue/src/views/home/index.vue +1 -1
- package/jnrs-vue/src/views/login/index.vue +2 -2
- package/jnrs-vue/src/views/system/dict/index.vue +4 -4
- package/jnrs-vue/src/views/system/mine/baseInfo.vue +2 -2
- package/jnrs-vue/src/views/system/mine/securitySettings.vue +1 -1
- package/jnrs-vue/src/views/visual/index.vue +3 -4
- package/jnrs-vue/vite.config.ts +2 -2
- package/jnrs-vue/viteMockServe/fail.ts +3 -3
- package/jnrs-vue/viteMockServe/file.ts +1 -1
- package/jnrs-vue/viteMockServe/index.ts +7 -16
- package/jnrs-vue/viteMockServe/json/loginRes_user.json +21 -1
- package/jnrs-vue/viteMockServe/success.ts +5 -5
- package/package.json +2 -3
- package/jnrs-vue/src/api/user/index.ts +0 -12
package/README.md
CHANGED
package/jnrs-vue/README.md
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import { execSync } from 'child_process'
|
|
10
|
-
import { cpSync, readFileSync, writeFileSync } from 'fs'
|
|
10
|
+
import { cpSync, readFileSync, writeFileSync, rmSync } from 'fs'
|
|
11
11
|
import { join } from 'path'
|
|
12
12
|
|
|
13
13
|
console.log('🔄 正在拉取最新模板...')
|
|
@@ -37,4 +37,4 @@ console.log(' - 检查 package.json 差异')
|
|
|
37
37
|
console.log(' - src/ 目录未自动更新,请手动合并新功能')
|
|
38
38
|
|
|
39
39
|
// 4. 清理临时目录
|
|
40
|
-
|
|
40
|
+
rmSync('_temp_new', { recursive: true, force: true })
|
package/jnrs-vue/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jnrs-vue",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.23",
|
|
4
4
|
"description": "JNRS 信息化管理系统",
|
|
5
5
|
"author": "talia_tan",
|
|
6
6
|
"private": true,
|
|
@@ -8,6 +8,9 @@
|
|
|
8
8
|
"engines": {
|
|
9
9
|
"node": "^20.19.0 || >=22.12.0"
|
|
10
10
|
},
|
|
11
|
+
"bin": {
|
|
12
|
+
"upgrade-jnrs-vue": "./bin/upgrade.mjs"
|
|
13
|
+
},
|
|
11
14
|
"scripts": {
|
|
12
15
|
"dev": "vite",
|
|
13
16
|
"build": "run-p type-check \"build-only {@}\" --",
|
|
@@ -19,8 +22,8 @@
|
|
|
19
22
|
},
|
|
20
23
|
"dependencies": {
|
|
21
24
|
"@element-plus/icons-vue": "^2.3.2",
|
|
22
|
-
"@jnrs/shared": "1.1.
|
|
23
|
-
"@jnrs/vue-core": "1.2.
|
|
25
|
+
"@jnrs/shared": "1.1.16",
|
|
26
|
+
"@jnrs/vue-core": "1.2.11",
|
|
24
27
|
"@jnrs/lingshu-smart": "2.2.4",
|
|
25
28
|
"@vueuse/core": "^14.1.0",
|
|
26
29
|
"element-plus": "^2.13.3",
|
|
@@ -7,7 +7,7 @@ import { axiosRequest } from '../request'
|
|
|
7
7
|
*/
|
|
8
8
|
export const FileApi = (uniqueFileName: string): Promise<Blob> => {
|
|
9
9
|
return axiosRequest({
|
|
10
|
-
url: '/
|
|
10
|
+
url: '/files/' + uniqueFileName,
|
|
11
11
|
method: 'get',
|
|
12
12
|
responseType: 'blob',
|
|
13
13
|
showErrorMsg: false
|
|
@@ -19,7 +19,7 @@ export const FileApi = (uniqueFileName: string): Promise<Blob> => {
|
|
|
19
19
|
*/
|
|
20
20
|
// import { useFetch } from '@vueuse/core'
|
|
21
21
|
// export const FileApi = (uniqueFileName: string) => {
|
|
22
|
-
// return useFetch(`/
|
|
22
|
+
// return useFetch(`/files/${uniqueFileName}`, {
|
|
23
23
|
// method: 'get',
|
|
24
24
|
// headers: {
|
|
25
25
|
// responseType: 'blob'
|
|
@@ -1,12 +1,20 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* @Author : TanRui
|
|
3
|
+
* @WeChat : Tan578853789
|
|
4
|
+
* @File : demos/index.ts
|
|
5
|
+
* @Date : 2026/03/01
|
|
6
|
+
* @Desc. : 示例模块接口文档(可作为 AI Agent 上下文来源)
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import type { IBusinessResponse } from '@jnrs/shared'
|
|
10
|
+
import type { IPagination, IPageTableData, IFile, IUser } from '@/types'
|
|
2
11
|
import { axiosRequest } from '../request'
|
|
3
|
-
import {
|
|
4
|
-
import { objectToFormData } from '@/utils/packages'
|
|
12
|
+
import { objectToFormData } from '@/utils'
|
|
5
13
|
|
|
6
14
|
/**
|
|
7
|
-
* 项目
|
|
15
|
+
* 项目 - 详情
|
|
8
16
|
*/
|
|
9
|
-
export interface
|
|
17
|
+
export interface Project extends IFile {
|
|
10
18
|
id: string
|
|
11
19
|
programCode: string
|
|
12
20
|
program: string
|
|
@@ -23,9 +31,9 @@ export interface ProjectItem extends FileContainer {
|
|
|
23
31
|
}
|
|
24
32
|
|
|
25
33
|
/**
|
|
26
|
-
*
|
|
34
|
+
* 新增项目 - 忽略字段
|
|
27
35
|
*/
|
|
28
|
-
type
|
|
36
|
+
type CreateProjectOmit =
|
|
29
37
|
| 'id'
|
|
30
38
|
| 'programCode'
|
|
31
39
|
| 'program'
|
|
@@ -37,28 +45,54 @@ type AddProjectOmitKeys =
|
|
|
37
45
|
| 'imageDocument'
|
|
38
46
|
| 'attachmentDocument'
|
|
39
47
|
|
|
40
|
-
|
|
48
|
+
/**
|
|
49
|
+
* 项目 - 创建
|
|
50
|
+
*/
|
|
51
|
+
export type EditProject = Omit<Project, CreateProjectOmit> & {
|
|
41
52
|
id?: string
|
|
42
|
-
managerId?: Record<string, unknown> |
|
|
53
|
+
managerId?: Record<string, unknown> | number
|
|
43
54
|
newAttachmentFile: []
|
|
44
55
|
newImageFiles: []
|
|
45
56
|
}
|
|
46
57
|
|
|
47
58
|
/**
|
|
48
|
-
* 查询
|
|
59
|
+
* 项目 - 查询
|
|
49
60
|
*/
|
|
50
|
-
export interface ProjectQuery extends
|
|
61
|
+
export interface ProjectQuery extends IPagination {
|
|
51
62
|
code?: string
|
|
52
63
|
projectType?: '敏捷型' | '瀑布型' | '混合型'
|
|
53
64
|
manager?: string
|
|
54
65
|
}
|
|
55
66
|
|
|
67
|
+
// 测试 获取数据
|
|
68
|
+
export const DataApiTest = (id: string): Promise<IUser> => {
|
|
69
|
+
return axiosRequest({
|
|
70
|
+
url: '/auth/user-info',
|
|
71
|
+
method: 'get',
|
|
72
|
+
params: {
|
|
73
|
+
id
|
|
74
|
+
}
|
|
75
|
+
})
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// 测试 获取全量数据
|
|
79
|
+
export const FullDataApiTest = (id: string): Promise<IBusinessResponse<IUser>> => {
|
|
80
|
+
return axiosRequest({
|
|
81
|
+
url: '/auth/user-info',
|
|
82
|
+
method: 'get',
|
|
83
|
+
params: {
|
|
84
|
+
id
|
|
85
|
+
},
|
|
86
|
+
returnFullResponse: true // 需要返回完整响应数据时使用该选项
|
|
87
|
+
})
|
|
88
|
+
}
|
|
89
|
+
|
|
56
90
|
/**
|
|
57
91
|
* 测试 404 错误
|
|
58
92
|
*/
|
|
59
93
|
export const NotFoundApi = () => {
|
|
60
94
|
return axiosRequest({
|
|
61
|
-
url: '/
|
|
95
|
+
url: '/notFound',
|
|
62
96
|
method: 'get'
|
|
63
97
|
})
|
|
64
98
|
}
|
|
@@ -68,7 +102,7 @@ export const NotFoundApi = () => {
|
|
|
68
102
|
*/
|
|
69
103
|
export const NoNeedAuthApi = () => {
|
|
70
104
|
return axiosRequest({
|
|
71
|
-
url: '/
|
|
105
|
+
url: '/auth/no',
|
|
72
106
|
method: 'post',
|
|
73
107
|
noAuth: true
|
|
74
108
|
})
|
|
@@ -80,7 +114,7 @@ export const NoNeedAuthApi = () => {
|
|
|
80
114
|
*/
|
|
81
115
|
export const NoAuthApi = (showErrorMsg: boolean) => {
|
|
82
116
|
return axiosRequest({
|
|
83
|
-
url: '/
|
|
117
|
+
url: '/auth/no',
|
|
84
118
|
method: 'post',
|
|
85
119
|
showErrorMsg
|
|
86
120
|
})
|
|
@@ -89,43 +123,50 @@ export const NoAuthApi = (showErrorMsg: boolean) => {
|
|
|
89
123
|
/**
|
|
90
124
|
* 数据详情
|
|
91
125
|
*/
|
|
92
|
-
export const DetailsApi = (): Promise<
|
|
126
|
+
export const DetailsApi = (): Promise<IFile> => {
|
|
93
127
|
return axiosRequest({
|
|
94
|
-
url: '/
|
|
128
|
+
url: '/details',
|
|
95
129
|
method: 'get'
|
|
96
130
|
})
|
|
97
131
|
}
|
|
98
132
|
|
|
99
133
|
/**
|
|
100
|
-
*
|
|
134
|
+
* 项目 - 编辑
|
|
101
135
|
*/
|
|
102
|
-
export const
|
|
103
|
-
const formData = objectToFormData({
|
|
104
|
-
...data,
|
|
105
|
-
managerId: extractFieldId(data.managerId, 'managerId')
|
|
106
|
-
})
|
|
136
|
+
export const EditProjectApi = (data: EditProject) => {
|
|
107
137
|
return axiosRequest({
|
|
108
|
-
url: '/
|
|
138
|
+
url: '/demos/save',
|
|
109
139
|
method: 'post',
|
|
110
|
-
data: formData
|
|
140
|
+
data: objectToFormData(data) // 包含文件上传类需使用 formData 类型
|
|
141
|
+
})
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* 项目 - 更新
|
|
146
|
+
*/
|
|
147
|
+
export const UpdateProjectApi = (data: Project) => {
|
|
148
|
+
return axiosRequest({
|
|
149
|
+
url: '/demos/update',
|
|
150
|
+
method: 'put',
|
|
151
|
+
data
|
|
111
152
|
})
|
|
112
153
|
}
|
|
113
154
|
|
|
114
155
|
/**
|
|
115
156
|
* 删除数据
|
|
116
157
|
*/
|
|
117
|
-
export const
|
|
158
|
+
export const DeleteProjectApi = (id: string) => {
|
|
118
159
|
return axiosRequest({
|
|
119
|
-
url: `/
|
|
160
|
+
url: `/demos/delete/${id}`,
|
|
120
161
|
method: 'delete'
|
|
121
162
|
})
|
|
122
163
|
}
|
|
123
164
|
/**
|
|
124
165
|
* 列表数据
|
|
125
166
|
*/
|
|
126
|
-
export const
|
|
167
|
+
export const ProjectListApi = (data?: ProjectQuery): Promise<IPageTableData<Project>> => {
|
|
127
168
|
return axiosRequest({
|
|
128
|
-
url: '/
|
|
169
|
+
url: '/demos/table',
|
|
129
170
|
method: 'get',
|
|
130
171
|
data
|
|
131
172
|
})
|
|
@@ -134,9 +175,9 @@ export const ListApi = (data?: ProjectQuery): Promise<PageTableData<ProjectItem>
|
|
|
134
175
|
/**
|
|
135
176
|
* 下载数据导入模板
|
|
136
177
|
*/
|
|
137
|
-
export const
|
|
178
|
+
export const DownloadTemplateApi = (): Promise<Blob> => {
|
|
138
179
|
return axiosRequest({
|
|
139
|
-
url: '/
|
|
180
|
+
url: '/project/template',
|
|
140
181
|
method: 'post'
|
|
141
182
|
})
|
|
142
183
|
}
|
|
@@ -146,7 +187,7 @@ export const ImportTemplateApi = (): Promise<Blob> => {
|
|
|
146
187
|
*/
|
|
147
188
|
export const ImportDataApi = (data: FormData) => {
|
|
148
189
|
return axiosRequest({
|
|
149
|
-
url: '/
|
|
190
|
+
url: '/project/import',
|
|
150
191
|
method: 'post',
|
|
151
192
|
data
|
|
152
193
|
})
|
|
@@ -157,7 +198,7 @@ export const ImportDataApi = (data: FormData) => {
|
|
|
157
198
|
*/
|
|
158
199
|
export const ExportApi = (data: Record<string, unknown>): Promise<Blob> => {
|
|
159
200
|
return axiosRequest({
|
|
160
|
-
url: '/
|
|
201
|
+
url: '/project/export',
|
|
161
202
|
method: 'post',
|
|
162
203
|
data
|
|
163
204
|
})
|
|
@@ -6,9 +6,10 @@
|
|
|
6
6
|
* @Desc. : axios 网络请求实例
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import type {
|
|
9
|
+
import type { IBusinessRequest, IBusinessResponse } from '@jnrs/shared'
|
|
10
10
|
import { createAxiosInstance } from '@jnrs/shared/request'
|
|
11
|
-
import { useMockStore
|
|
11
|
+
import { useMockStore } from '@jnrs/vue-core/pinia'
|
|
12
|
+
import { useAuthStore } from '@/stores'
|
|
12
13
|
import { handleRouter } from '@jnrs/vue-core/router'
|
|
13
14
|
import { ElMessage } from 'element-plus'
|
|
14
15
|
|
|
@@ -31,20 +32,18 @@ const axiosInstance = createAxiosInstance({
|
|
|
31
32
|
* @param options 请求配置项
|
|
32
33
|
* @returns Promise<T> 响应数据
|
|
33
34
|
*/
|
|
34
|
-
const axiosRequest = <T =
|
|
35
|
+
const axiosRequest = <T = IBusinessResponse>(options: IBusinessRequest): Promise<T> => {
|
|
35
36
|
if (!axiosInstance) {
|
|
36
37
|
throw new Error('请先调用 createRequest 初始化 axios 实例')
|
|
37
38
|
}
|
|
38
39
|
|
|
39
|
-
|
|
40
|
-
const { isMock } = useMockStore()
|
|
40
|
+
const { useMockServe } = useMockStore()
|
|
41
41
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
: '/mock' + options.url
|
|
42
|
+
// 如果开启 mock 模式,则将请求地址改为 mock 地址,否则使用 api 地址
|
|
43
|
+
if (useMockServe) {
|
|
44
|
+
options.url = '/api/mock' + options.url
|
|
45
|
+
} else {
|
|
46
|
+
options.url = '/api' + options.url
|
|
48
47
|
}
|
|
49
48
|
|
|
50
49
|
return axiosInstance(options)
|
|
@@ -1,16 +1,17 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type {
|
|
1
|
+
import type { IDict, IDictItem, IRole } from '@/types'
|
|
2
|
+
import type { IMenuItem } from '@jnrs/vue-core'
|
|
3
|
+
import type { IUser } from '@/types'
|
|
3
4
|
import { axiosRequest } from '../request'
|
|
4
|
-
import { objectToFormData } from '@/utils
|
|
5
|
+
import { objectToFormData } from '@/utils'
|
|
5
6
|
|
|
6
7
|
// 菜单
|
|
7
|
-
export const MenuApi = (): Promise<
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
8
|
+
export const MenuApi = async (): Promise<IMenuItem[]> => {
|
|
9
|
+
const response = await fetch('/system/menu.json')
|
|
10
|
+
if (!response.ok) {
|
|
11
|
+
throw new Error(`Failed to load menu.json: ${response.status} ${response.statusText}`)
|
|
12
|
+
}
|
|
13
|
+
const data = await response.json()
|
|
14
|
+
return data.data
|
|
14
15
|
}
|
|
15
16
|
|
|
16
17
|
// 登录
|
|
@@ -22,16 +23,16 @@ interface LoginParams {
|
|
|
22
23
|
/**
|
|
23
24
|
* 登录结果
|
|
24
25
|
*/
|
|
25
|
-
export interface LoginResult extends
|
|
26
|
+
export interface LoginResult extends IUser {
|
|
26
27
|
token: string
|
|
27
|
-
dict:
|
|
28
|
+
dict: IDict
|
|
28
29
|
}
|
|
29
30
|
|
|
30
31
|
export const LoginApi = (data: LoginParams): Promise<LoginResult> => {
|
|
31
32
|
return axiosRequest({
|
|
32
|
-
url: '/
|
|
33
|
+
url: '/auth/login',
|
|
33
34
|
method: 'post',
|
|
34
|
-
data,
|
|
35
|
+
data: objectToFormData(data),
|
|
35
36
|
noAuth: true
|
|
36
37
|
})
|
|
37
38
|
}
|
|
@@ -39,15 +40,15 @@ export const LoginApi = (data: LoginParams): Promise<LoginResult> => {
|
|
|
39
40
|
// 退出登录
|
|
40
41
|
export const LogoutApi = () => {
|
|
41
42
|
return axiosRequest({
|
|
42
|
-
url: '/
|
|
43
|
+
url: '/auth/logout',
|
|
43
44
|
method: 'get'
|
|
44
45
|
})
|
|
45
46
|
}
|
|
46
47
|
|
|
47
48
|
// 获取用户信息
|
|
48
|
-
export const UserInfoApi = (): Promise<
|
|
49
|
+
export const UserInfoApi = (): Promise<IUser> => {
|
|
49
50
|
return axiosRequest({
|
|
50
|
-
url: '/
|
|
51
|
+
url: '/auth/user-info',
|
|
51
52
|
method: 'get'
|
|
52
53
|
})
|
|
53
54
|
}
|
|
@@ -55,7 +56,7 @@ export const UserInfoApi = (): Promise<User> => {
|
|
|
55
56
|
// 修改头像
|
|
56
57
|
export const AvatarChangeApi = (data: File) => {
|
|
57
58
|
return axiosRequest({
|
|
58
|
-
url: '/
|
|
59
|
+
url: '/user/avatar',
|
|
59
60
|
method: 'post',
|
|
60
61
|
data: objectToFormData({ file: data })
|
|
61
62
|
})
|
|
@@ -69,16 +70,16 @@ interface PasswordChange {
|
|
|
69
70
|
|
|
70
71
|
export const PasswordChangeApi = (data: PasswordChange) => {
|
|
71
72
|
return axiosRequest({
|
|
72
|
-
url: '/
|
|
73
|
+
url: '/auth/change-password',
|
|
73
74
|
method: 'post',
|
|
74
75
|
data
|
|
75
76
|
})
|
|
76
77
|
}
|
|
77
78
|
|
|
78
79
|
// 获取字典列表
|
|
79
|
-
export const DictApi = (): Promise<
|
|
80
|
+
export const DictApi = (): Promise<IDictItem[]> => {
|
|
80
81
|
return axiosRequest({
|
|
81
|
-
url: '/
|
|
82
|
+
url: '/dict-manager',
|
|
82
83
|
method: 'get'
|
|
83
84
|
})
|
|
84
85
|
}
|
|
@@ -86,24 +87,24 @@ export const DictApi = (): Promise<DictItem[]> => {
|
|
|
86
87
|
// 获取单个字典
|
|
87
88
|
export const DictDetailApi = (id: string) => {
|
|
88
89
|
return axiosRequest({
|
|
89
|
-
url: `/
|
|
90
|
+
url: `/dict-manager/detail/${id}`,
|
|
90
91
|
method: 'get'
|
|
91
92
|
})
|
|
92
93
|
}
|
|
93
94
|
|
|
94
95
|
// 修改单个字典
|
|
95
|
-
export const DictChangeApi = (data:
|
|
96
|
+
export const DictChangeApi = (data: IDictItem) => {
|
|
96
97
|
return axiosRequest({
|
|
97
|
-
url: '/
|
|
98
|
+
url: '/dict-manager/detail',
|
|
98
99
|
method: 'post',
|
|
99
100
|
data
|
|
100
101
|
})
|
|
101
102
|
}
|
|
102
103
|
|
|
103
104
|
// 获取角色列表
|
|
104
|
-
export const RoleApi = (): Promise<
|
|
105
|
+
export const RoleApi = (): Promise<IRole[]> => {
|
|
105
106
|
return axiosRequest({
|
|
106
|
-
url: '/
|
|
107
|
+
url: '/role-manager',
|
|
107
108
|
method: 'get',
|
|
108
109
|
noAuth: true
|
|
109
110
|
})
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
-->
|
|
8
8
|
|
|
9
9
|
<script setup lang="ts">
|
|
10
|
-
import type {
|
|
10
|
+
import type { IPagination, IPageTableData } from '@/types'
|
|
11
11
|
import { ref, onActivated } from 'vue'
|
|
12
12
|
import { JnPagination, JnTable } from '@jnrs/vue-core/components'
|
|
13
13
|
import { debounce } from '@jnrs/shared/lodash'
|
|
@@ -17,7 +17,7 @@ export interface Props {
|
|
|
17
17
|
* 获取数据表格 api 函数
|
|
18
18
|
*/
|
|
19
19
|
// eslint-disable-next-line
|
|
20
|
-
getTableDataApi?: (data?:
|
|
20
|
+
getTableDataApi?: (data?: IPagination) => Promise<IPageTableData<any>>
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
const { getTableDataApi } = defineProps<Props>()
|
|
@@ -25,7 +25,7 @@ const { getTableDataApi } = defineProps<Props>()
|
|
|
25
25
|
const loading = ref(false)
|
|
26
26
|
const tableData = ref()
|
|
27
27
|
const total = ref(0)
|
|
28
|
-
const pagination = ref<
|
|
28
|
+
const pagination = ref<IPagination>({ pageNo: 1, pageSize: 20 })
|
|
29
29
|
|
|
30
30
|
const getTable = debounce(async () => {
|
|
31
31
|
if (!getTableDataApi) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
|
-
import type {
|
|
3
|
-
import type {
|
|
2
|
+
import type { IFileItem } from '@jnrs/shared'
|
|
3
|
+
import type { IAttachment } from '@/types'
|
|
4
4
|
import { ref, watch, onActivated, onDeactivated, onBeforeUnmount } from 'vue'
|
|
5
5
|
import { blobToUrl } from '@jnrs/shared'
|
|
6
6
|
import { debounce } from '@jnrs/shared/lodash'
|
|
@@ -12,7 +12,7 @@ export interface Props {
|
|
|
12
12
|
/**
|
|
13
13
|
* 要加载的文件列表 | 文件名唯一标识 uniqueFileName
|
|
14
14
|
*/
|
|
15
|
-
loadKeys:
|
|
15
|
+
loadKeys: IAttachment[] | string | undefined
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
18
|
* 是否清理文件副作用
|
|
@@ -26,7 +26,7 @@ const { loadKeys, clearSideEffects = false } = defineProps<Props>()
|
|
|
26
26
|
const posterUrl = ref('')
|
|
27
27
|
|
|
28
28
|
// 存储每个 URL 对应的 URL 对象
|
|
29
|
-
const fileList = ref<
|
|
29
|
+
const fileList = ref<IFileItem[]>([])
|
|
30
30
|
|
|
31
31
|
// 存储每个 URL 对应的 revoke 函数用于副作用清理
|
|
32
32
|
const revokeFns = ref<(() => void)[]>([])
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
|
-
import type {
|
|
3
|
-
import type {
|
|
2
|
+
import type { IFileItem } from '@jnrs/shared'
|
|
3
|
+
import type { IAttachment } from '@/types'
|
|
4
4
|
import { ref, watch, onActivated, onDeactivated, onBeforeUnmount } from 'vue'
|
|
5
5
|
import { blobToUrl } from '@jnrs/shared'
|
|
6
6
|
import { FileApi } from '@/api/common'
|
|
@@ -11,7 +11,7 @@ export interface Props {
|
|
|
11
11
|
/**
|
|
12
12
|
* 要加载的文件列表 | 文件名唯一标识 uniqueFileName
|
|
13
13
|
*/
|
|
14
|
-
loadKeys:
|
|
14
|
+
loadKeys: IAttachment[] | string | undefined
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
17
|
* 是否清理文件副作用
|
|
@@ -22,7 +22,7 @@ export interface Props {
|
|
|
22
22
|
const { loadKeys, clearSideEffects = false } = defineProps<Props>()
|
|
23
23
|
|
|
24
24
|
// 存储每个 URL 对应的 URL 对象
|
|
25
|
-
const fileList = ref<
|
|
25
|
+
const fileList = ref<IFileItem[]>([])
|
|
26
26
|
|
|
27
27
|
// 存储每个 URL 对应的 revoke 函数用于副作用清理
|
|
28
28
|
const revokeFns = ref<(() => void)[]>([])
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
-->
|
|
8
8
|
|
|
9
9
|
<script setup lang="ts">
|
|
10
|
-
import {
|
|
10
|
+
import { ProjectListApi } from '@/api/demos/index'
|
|
11
11
|
import { JnSelectTemplate } from '@jnrs/vue-core/components'
|
|
12
12
|
</script>
|
|
13
13
|
|
|
@@ -15,8 +15,8 @@ import { JnSelectTemplate } from '@jnrs/vue-core/components'
|
|
|
15
15
|
<JnSelectTemplate
|
|
16
16
|
tableName="项目经理"
|
|
17
17
|
:keyValue="{ name: 'manager', id: 'managerId', code: 'code' }"
|
|
18
|
+
:listApi="ProjectListApi"
|
|
18
19
|
optionSecondaryField="code"
|
|
19
|
-
:listApi="ListApi"
|
|
20
20
|
>
|
|
21
21
|
<template #table>
|
|
22
22
|
<el-table-column prop="manager" label="项目经理" align="center" sortable />
|
|
@@ -3,14 +3,14 @@ import type { FormInstance } from 'element-plus'
|
|
|
3
3
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
|
4
4
|
import { debounce } from '@jnrs/shared/lodash'
|
|
5
5
|
import { objectMatchAssign } from '@jnrs/shared'
|
|
6
|
-
import type {
|
|
6
|
+
import type { IPagination, IPageTableData } from '@/types'
|
|
7
7
|
|
|
8
8
|
interface CrudOptions<TItem, TForm, TQuery> {
|
|
9
9
|
// 初始值
|
|
10
10
|
defaultForm: () => TForm
|
|
11
11
|
defaultQuery?: () => TQuery
|
|
12
12
|
// API
|
|
13
|
-
listApi: (params: Partial<
|
|
13
|
+
listApi: (params: Partial<IPagination> & TQuery) => Promise<IPageTableData<TItem> | TItem[]>
|
|
14
14
|
saveApi: (data: TForm) => Promise<unknown>
|
|
15
15
|
deleteApi?: (id: number) => Promise<unknown>
|
|
16
16
|
// 可选:是否启用分页,默认 true
|
|
@@ -21,13 +21,22 @@ interface CrudOptions<TItem, TForm, TQuery> {
|
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
export function useCrud<TItem, TForm, TQuery = object>(options: CrudOptions<TItem, TForm, TQuery>) {
|
|
24
|
-
const {
|
|
24
|
+
const {
|
|
25
|
+
defaultForm,
|
|
26
|
+
defaultQuery,
|
|
27
|
+
listApi,
|
|
28
|
+
saveApi,
|
|
29
|
+
deleteApi,
|
|
30
|
+
pagination: enablePagination = true,
|
|
31
|
+
transformItem,
|
|
32
|
+
beforeEdit
|
|
33
|
+
} = options
|
|
25
34
|
|
|
26
35
|
// 列表状态
|
|
27
36
|
const loading = ref(false)
|
|
28
37
|
const tableData = ref<TItem[]>([]) as Ref<TItem[]>
|
|
29
38
|
const total = ref(0)
|
|
30
|
-
const pagination = ref<
|
|
39
|
+
const pagination = ref<IPagination>({ pageNo: 1, pageSize: 20 })
|
|
31
40
|
const queryForm = ref(defaultQuery?.() ?? {}) as Ref<TQuery>
|
|
32
41
|
|
|
33
42
|
// 表单状态
|
|
@@ -42,7 +51,7 @@ export function useCrud<TItem, TForm, TQuery = object>(options: CrudOptions<TIte
|
|
|
42
51
|
const params = {
|
|
43
52
|
...(enablePagination ? pagination.value : {}),
|
|
44
53
|
...queryForm.value
|
|
45
|
-
} as Partial<
|
|
54
|
+
} as Partial<IPagination> & TQuery
|
|
46
55
|
const res = await listApi(params)
|
|
47
56
|
// 支持返回数组或 { list, count } 格式
|
|
48
57
|
if (Array.isArray(res)) {
|
|
@@ -74,7 +83,7 @@ export function useCrud<TItem, TForm, TQuery = object>(options: CrudOptions<TIte
|
|
|
74
83
|
queueMicrotask(() => {
|
|
75
84
|
formRef.value?.resetFields()
|
|
76
85
|
const matched = objectMatchAssign(
|
|
77
|
-
defaultForm() as Record<string, unknown>,
|
|
86
|
+
defaultForm() as Record<string, unknown>,
|
|
78
87
|
row as Record<string, unknown>
|
|
79
88
|
) as TForm
|
|
80
89
|
form.value = (beforeEdit ? beforeEdit(row, matched) : matched) as TForm
|
|
@@ -124,8 +133,18 @@ export function useCrud<TItem, TForm, TQuery = object>(options: CrudOptions<TIte
|
|
|
124
133
|
}
|
|
125
134
|
|
|
126
135
|
return {
|
|
127
|
-
loading,
|
|
128
|
-
|
|
129
|
-
|
|
136
|
+
loading,
|
|
137
|
+
tableData,
|
|
138
|
+
total,
|
|
139
|
+
pagination,
|
|
140
|
+
queryForm,
|
|
141
|
+
dialogRef,
|
|
142
|
+
formRef,
|
|
143
|
+
form,
|
|
144
|
+
getList,
|
|
145
|
+
openCreate,
|
|
146
|
+
openEdit,
|
|
147
|
+
submitForm,
|
|
148
|
+
handleDelete
|
|
130
149
|
}
|
|
131
|
-
}
|
|
150
|
+
}
|