@xmszm/core 0.0.2 → 0.0.3
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 +10 -1
- package/dist/index.cjs +2 -2
- package/dist/index.mjs +1296 -1285
- package/dist/plugin/vite/initRouteMeta.cjs +1 -0
- package/dist/plugin/vite/initRouteMeta.mjs +13 -0
- package/dist/style.css +1 -1
- package/docs/.vitepress/config.mjs +10 -1
- package/docs/components/config-options.md +125 -0
- package/docs/components/dataform.md +175 -22
- package/docs/components/datatable.md +21 -39
- package/docs/components/dialog.md +155 -16
- package/docs/components/options.md +43 -14
- package/docs/components/query.md +20 -12
- package/docs/components/utils.md +118 -10
- package/docs/guide/changelog.md +81 -0
- package/docs/guide/config.md +241 -4
- package/docs/guide/quickstart.md +27 -2
- package/docs/index.md +1 -1
- package/docs/usage.md +16 -3
- package/examples/README.md +46 -0
- package/examples/index.html +14 -0
- package/examples/package.json +25 -0
- package/examples/pnpm-lock.yaml +1569 -0
- package/examples/pnpm-workspace.yaml +3 -0
- package/examples/src/AdminSystem.vue +870 -0
- package/examples/src/App.vue +330 -0
- package/examples/src/Introduction.vue +307 -0
- package/examples/src/main.js +22 -0
- package/examples/src/utils/permission.js +16 -0
- package/examples/src/utils/request.js +10 -0
- package/examples/vite.config.js +41 -0
- package/package.json +10 -4
- package/src/dialog/commonDialog.tsx +285 -0
- package/src/dialog/utils/{dialog.js → dialog.ts} +2 -0
- package/src/enum/sort.tsx +45 -0
- package/src/form/DataForm.vue +26 -52
- package/src/{index.js → index.ts} +7 -6
- package/src/list/{useList.jsx → useList.tsx} +49 -14
- package/src/options/{Options.jsx → Options.tsx} +37 -36
- package/src/options/defaultOptions.tsx +656 -0
- package/src/query/CommonQuery.vue +57 -89
- package/src/table/DataTable.vue +60 -94
- package/src/table/opr/{DataColumnCollet.jsx → DataColumnCollet.tsx} +18 -8
- package/src/table/opr/{useDataColumn.jsx → useDataColumn.tsx} +43 -48
- package/src/table/opr/{useDataColumnButton.jsx → useDataColumnButton.tsx} +13 -6
- package/src/table/opr/{useDataColumnPop.jsx → useDataColumnPop.tsx} +13 -5
- package/src/utils/{array.js → array.ts} +4 -6
- package/src/utils/{config.js → config.ts} +16 -2
- package/src/utils/{dialog.js → dialog.ts} +2 -2
- package/src/utils/{object.js → object.ts} +1 -0
- package/src/utils/{upload.js → upload.ts} +3 -3
- package/types/components.d.ts +402 -0
- package/types/index.d.ts +145 -7
- package/types/plugin/vite/initRouteMeta.d.ts +23 -0
- package/types/src.d.ts +55 -0
- package/types/vue-shim.d.ts +9 -0
- package/examples/demo.vue +0 -224
- package/src/dialog/commonDialog.jsx +0 -262
- package/src/enum/sort.jsx +0 -31
- package/src/options/defaultOptions.jsx +0 -580
- /package/src/dialog/{useCommonDialog.js → useCommonDialog.ts} +0 -0
- /package/src/directives/{auto-register.js → auto-register.ts} +0 -0
- /package/src/directives/{permission.js → permission.ts} +0 -0
- /package/src/enum/{options.js → options.ts} +0 -0
- /package/src/plugin/{index.js → index.ts} +0 -0
- /package/src/plugin/vite/{initRouteMeta.js → initRouteMeta.ts} +0 -0
- /package/src/store/utils/{index.js → index.ts} +0 -0
- /package/src/table/opr/{useQRCode.js → useQRCode.ts} +0 -0
- /package/src/table/utils/{ellipsis.js → ellipsis.ts} +0 -0
- /package/src/utils/{auth.js → auth.ts} +0 -0
- /package/src/utils/{time.js → time.ts} +0 -0
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { defineConfig } from 'vite'
|
|
2
|
+
import vue from '@vitejs/plugin-vue'
|
|
3
|
+
import vueJsx from '@vitejs/plugin-vue-jsx'
|
|
4
|
+
import path from 'path'
|
|
5
|
+
|
|
6
|
+
// 插件:重定向 @xmszm/core 中的 @/ 路径到项目 src
|
|
7
|
+
const redirectExternalImports = () => {
|
|
8
|
+
return {
|
|
9
|
+
name: 'redirect-external-imports',
|
|
10
|
+
resolveId(id, importer) {
|
|
11
|
+
// 如果是从 @xmszm/core 导入的 @/ 路径,重定向到项目 src
|
|
12
|
+
if (importer && importer.includes('@xmszm/core') && id.startsWith('@/')) {
|
|
13
|
+
const resolvedPath = path.resolve(__dirname, 'src', id.replace('@/', ''))
|
|
14
|
+
return resolvedPath
|
|
15
|
+
}
|
|
16
|
+
return null
|
|
17
|
+
},
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export default defineConfig({
|
|
22
|
+
base: '/core/examples/',
|
|
23
|
+
plugins: [vue(), vueJsx(), redirectExternalImports()],
|
|
24
|
+
resolve: {
|
|
25
|
+
alias: {
|
|
26
|
+
'@': path.resolve(__dirname, 'src'),
|
|
27
|
+
'@xmszm/core': path.resolve(__dirname, '..'),
|
|
28
|
+
'@xmszm/core/dist/style.css': path.resolve(__dirname, '../dist/style.css'),
|
|
29
|
+
},
|
|
30
|
+
dedupe: ['vue'],
|
|
31
|
+
},
|
|
32
|
+
build: {
|
|
33
|
+
outDir: 'dist',
|
|
34
|
+
assetsDir: 'assets',
|
|
35
|
+
},
|
|
36
|
+
server: {
|
|
37
|
+
port: 3000,
|
|
38
|
+
open: true
|
|
39
|
+
}
|
|
40
|
+
})
|
|
41
|
+
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xmszm/core",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.3",
|
|
4
4
|
"description": "naiveui core 组件与工具库",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -21,6 +21,11 @@
|
|
|
21
21
|
"style": "./dist/style.css",
|
|
22
22
|
"types": "./types/index.d.ts"
|
|
23
23
|
},
|
|
24
|
+
"./plugin/vite/initRouteMeta": {
|
|
25
|
+
"import": "./dist/plugin/vite/initRouteMeta.mjs",
|
|
26
|
+
"require": "./dist/plugin/vite/initRouteMeta.cjs",
|
|
27
|
+
"types": "./types/plugin/vite/initRouteMeta.d.ts"
|
|
28
|
+
},
|
|
24
29
|
"./dist/style.css": "./dist/style.css",
|
|
25
30
|
"./package.json": "./package.json"
|
|
26
31
|
},
|
|
@@ -47,6 +52,8 @@
|
|
|
47
52
|
"vue-router": "^4.2.0"
|
|
48
53
|
},
|
|
49
54
|
"devDependencies": {
|
|
55
|
+
"@types/node": "^20.0.0",
|
|
56
|
+
"@unocss/vite": "^66.5.10",
|
|
50
57
|
"@vicons/ionicons5": "^0.13.0",
|
|
51
58
|
"@vitejs/plugin-vue": "^5.1.2",
|
|
52
59
|
"@vitejs/plugin-vue-jsx": "^4.0.1",
|
|
@@ -55,13 +62,12 @@
|
|
|
55
62
|
"lodash-es": "^4.17.21",
|
|
56
63
|
"naive-ui": "^2.38.0",
|
|
57
64
|
"rimraf": "^6.0.1",
|
|
65
|
+
"typescript": "^5.0.0",
|
|
66
|
+
"unocss": "^66.5.10",
|
|
58
67
|
"unplugin-auto-import": "^20.3.0",
|
|
59
68
|
"vite": "^5.4.0",
|
|
60
69
|
"vitepress": "^1.2.3",
|
|
61
70
|
"vue": "^3.3.0",
|
|
62
71
|
"vue-router": "^4.2.0"
|
|
63
|
-
},
|
|
64
|
-
"dependencies": {
|
|
65
|
-
"npm": "^11.7.0"
|
|
66
72
|
}
|
|
67
73
|
}
|
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
import { NButton, NSpace, useDialog, createDiscreteApi } from 'naive-ui'
|
|
2
|
+
import type { DialogApi } from 'naive-ui'
|
|
3
|
+
import { reactive, ref, unref, defineComponent } from 'vue'
|
|
4
|
+
import type { Ref, VNode } from 'vue'
|
|
5
|
+
import type { CommonDialogOptions, DialogAction } from '../../types/components'
|
|
6
|
+
import type { CommonDialogResult } from '../../types'
|
|
7
|
+
import DataForm from '../form/DataForm.vue'
|
|
8
|
+
import { dialogDefaultOption } from './utils/dialog'
|
|
9
|
+
import './style/commonDialog.less'
|
|
10
|
+
|
|
11
|
+
// 声明全局 $dialog 变量(外部可能注入)
|
|
12
|
+
declare global {
|
|
13
|
+
// eslint-disable-next-line no-var
|
|
14
|
+
var $dialog: DialogApi | undefined
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// 全局缓存 dialog 实例,避免重复创建离散 API
|
|
18
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
19
|
+
let globalDialogInstance: any = null
|
|
20
|
+
let discreteDialogFactory: { dialog: any } | null = null
|
|
21
|
+
|
|
22
|
+
function getDialogInstanceOnce(): any {
|
|
23
|
+
if (globalDialogInstance)
|
|
24
|
+
return globalDialogInstance
|
|
25
|
+
|
|
26
|
+
// 1. 检查全局 $dialog
|
|
27
|
+
if (typeof $dialog !== 'undefined' && $dialog) {
|
|
28
|
+
globalDialogInstance = $dialog
|
|
29
|
+
return globalDialogInstance
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// 2. 组件上下文中尝试 useDialog(若无上下文会抛错)
|
|
33
|
+
try {
|
|
34
|
+
const dialog = useDialog()
|
|
35
|
+
if (dialog) {
|
|
36
|
+
globalDialogInstance = dialog
|
|
37
|
+
return globalDialogInstance
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
catch (e) {
|
|
41
|
+
// 忽略,继续尝试离散 API
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// 3. 使用离散 API,且只创建一次
|
|
45
|
+
if (!discreteDialogFactory) {
|
|
46
|
+
const { dialog } = createDiscreteApi(['dialog'])
|
|
47
|
+
discreteDialogFactory = { dialog }
|
|
48
|
+
}
|
|
49
|
+
globalDialogInstance = discreteDialogFactory.dialog
|
|
50
|
+
return globalDialogInstance
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* 集成填写表单功能的弹窗
|
|
55
|
+
* @param param - 弹窗配置选项
|
|
56
|
+
* @param dialogProps - 传递给 NDialog 的属性
|
|
57
|
+
* @returns 弹窗控制对象 {cancel, setValue, model, modeEnum}
|
|
58
|
+
*/
|
|
59
|
+
export function commonDialogMethod(
|
|
60
|
+
{
|
|
61
|
+
title = '',
|
|
62
|
+
noTitle = false,
|
|
63
|
+
titleFull = null,
|
|
64
|
+
options = [],
|
|
65
|
+
mode = 'add',
|
|
66
|
+
modeEnum = {},
|
|
67
|
+
labelField = 'label',
|
|
68
|
+
isNo = true,
|
|
69
|
+
formProps = {},
|
|
70
|
+
interfaceFn = null,
|
|
71
|
+
interfaceFnCancel = null,
|
|
72
|
+
valueData,
|
|
73
|
+
read,
|
|
74
|
+
isRead,
|
|
75
|
+
action = null,
|
|
76
|
+
contentStyle = {},
|
|
77
|
+
actionProps = {},
|
|
78
|
+
}: CommonDialogOptions = {
|
|
79
|
+
title: '自定义弹窗',
|
|
80
|
+
noTitle: false,
|
|
81
|
+
action: [],
|
|
82
|
+
options: [],
|
|
83
|
+
read: false,
|
|
84
|
+
isRead: false,
|
|
85
|
+
valueData: {},
|
|
86
|
+
},
|
|
87
|
+
dialogProps: Record<string, any> | null = null,
|
|
88
|
+
): CommonDialogResult {
|
|
89
|
+
// 优先使用外部注册的 $dialog;再尝试组件上下文 useDialog;再退回离散 API(仅全局创建一次)
|
|
90
|
+
const dialogInstance = getDialogInstanceOnce()
|
|
91
|
+
|
|
92
|
+
const defaultModeEnum: Record<string, { sub?: string; read?: boolean }> = {
|
|
93
|
+
none: { sub: '', read: false },
|
|
94
|
+
create: { sub: '创建', read: false },
|
|
95
|
+
add: { sub: '添加', read: false },
|
|
96
|
+
edit: { sub: '编辑', read: false },
|
|
97
|
+
view: { sub: '查看', read: true },
|
|
98
|
+
export: { sub: '导出', read: false },
|
|
99
|
+
import: { sub: '导入', read: false },
|
|
100
|
+
delete: { sub: '删除', read: false },
|
|
101
|
+
copy: { sub: '复制', read: false },
|
|
102
|
+
...modeEnum,
|
|
103
|
+
}
|
|
104
|
+
const formRef: Ref<any> = ref()
|
|
105
|
+
const actionLoading = reactive<boolean[]>([])
|
|
106
|
+
const model = ref({ ...valueData })
|
|
107
|
+
const defaultActionProps = {
|
|
108
|
+
justify: 'end' as 'end',
|
|
109
|
+
wrapItem: false,
|
|
110
|
+
style: {
|
|
111
|
+
width: '100%',
|
|
112
|
+
},
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const defaultButtonStyle = {
|
|
116
|
+
width: '120px',
|
|
117
|
+
}
|
|
118
|
+
const defaultAction: DialogAction[] = [
|
|
119
|
+
{
|
|
120
|
+
label: '取消',
|
|
121
|
+
props: {
|
|
122
|
+
type: 'primary',
|
|
123
|
+
ghost: true,
|
|
124
|
+
},
|
|
125
|
+
onClick: ({ cancel }) => {
|
|
126
|
+
if (interfaceFnCancel) {
|
|
127
|
+
interfaceFnCancel(unref(model), {
|
|
128
|
+
close: cancel,
|
|
129
|
+
})
|
|
130
|
+
} else {
|
|
131
|
+
cancel()
|
|
132
|
+
}
|
|
133
|
+
},
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
label: '确定',
|
|
137
|
+
valid: true,
|
|
138
|
+
onClick: async ({ cancel, hideLoading }) =>
|
|
139
|
+
interfaceFn
|
|
140
|
+
? await interfaceFn(unref(model), {
|
|
141
|
+
close: cancel,
|
|
142
|
+
hideLoading,
|
|
143
|
+
})
|
|
144
|
+
: cancel(),
|
|
145
|
+
},
|
|
146
|
+
];
|
|
147
|
+
|
|
148
|
+
(Array.isArray(action) ? action : defaultAction).forEach((v, i) => {
|
|
149
|
+
actionLoading[i] = false
|
|
150
|
+
})
|
|
151
|
+
const titleRender = typeof titleFull === 'function'
|
|
152
|
+
? () => titleFull(defaultModeEnum[mode]?.sub || '')
|
|
153
|
+
: titleFull
|
|
154
|
+
|
|
155
|
+
// 使用 ref 存储 dialog 实例,以便在函数中访问
|
|
156
|
+
const dialogRef: Ref<any> = ref()
|
|
157
|
+
|
|
158
|
+
function cancel(): void {
|
|
159
|
+
console.log('取消', model.value)
|
|
160
|
+
dialogRef.value?.destroy()
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
async function validate(arr: string[] = []): Promise<void> {
|
|
164
|
+
console.log('开启验证')
|
|
165
|
+
await formRef.value?.valid()
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
async function comfirm(fn?: () => any): Promise<any> {
|
|
169
|
+
return fn && fn()
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
const renderAction = !(read ?? isRead)
|
|
173
|
+
? typeof action === 'function'
|
|
174
|
+
? () => action({ formRef, data: unref(model), d: dialogRef.value, close: cancel })
|
|
175
|
+
: () => (
|
|
176
|
+
<NSpace
|
|
177
|
+
{...defaultActionProps}
|
|
178
|
+
{...actionProps}
|
|
179
|
+
style={{
|
|
180
|
+
...defaultActionProps?.style,
|
|
181
|
+
...(actionProps?.style || {}),
|
|
182
|
+
}}
|
|
183
|
+
>
|
|
184
|
+
{(Array.isArray(action) ? action : defaultAction).map((v, i) =>
|
|
185
|
+
v?.render
|
|
186
|
+
? (
|
|
187
|
+
v?.render?.()
|
|
188
|
+
)
|
|
189
|
+
: (
|
|
190
|
+
<NButton
|
|
191
|
+
type="primary"
|
|
192
|
+
ghost={v.mode === 'cancel'}
|
|
193
|
+
{...(v?.props || {})}
|
|
194
|
+
{...(actionProps?.buttonProps || {})}
|
|
195
|
+
style={{ ...defaultButtonStyle, ...(v?.style || {}) }}
|
|
196
|
+
loading={actionLoading[i]}
|
|
197
|
+
onClick={async () => {
|
|
198
|
+
if (v.mode === 'cancel') {
|
|
199
|
+
dialogRef.value?.destroy()
|
|
200
|
+
}
|
|
201
|
+
else {
|
|
202
|
+
const showLoading = () => (actionLoading[i] = true)
|
|
203
|
+
const hideLoading = () => (actionLoading[i] = false)
|
|
204
|
+
if (v?.loading)
|
|
205
|
+
showLoading()
|
|
206
|
+
try {
|
|
207
|
+
console.log('model', unref(model))
|
|
208
|
+
|
|
209
|
+
if (v?.valid)
|
|
210
|
+
await validate()
|
|
211
|
+
console.log(v?.valid)
|
|
212
|
+
if (v?.valid || v?.loading)
|
|
213
|
+
showLoading()
|
|
214
|
+
await v?.onClick?.({
|
|
215
|
+
model: unref(model),
|
|
216
|
+
comfirm,
|
|
217
|
+
cancel,
|
|
218
|
+
validate,
|
|
219
|
+
showLoading,
|
|
220
|
+
hideLoading,
|
|
221
|
+
})
|
|
222
|
+
}
|
|
223
|
+
catch (e) {
|
|
224
|
+
console.log(e)
|
|
225
|
+
}
|
|
226
|
+
finally {
|
|
227
|
+
if (v?.valid || v?.loading)
|
|
228
|
+
hideLoading()
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}}
|
|
232
|
+
>
|
|
233
|
+
{v.label || ''}
|
|
234
|
+
</NButton>
|
|
235
|
+
),
|
|
236
|
+
)}
|
|
237
|
+
</NSpace>
|
|
238
|
+
)
|
|
239
|
+
: null
|
|
240
|
+
|
|
241
|
+
const d = dialogInstance.create({
|
|
242
|
+
type: 'info',
|
|
243
|
+
...dialogDefaultOption,
|
|
244
|
+
...(!noTitle
|
|
245
|
+
? { title: titleRender || (defaultModeEnum[mode]?.sub ?? '') + title }
|
|
246
|
+
: {}),
|
|
247
|
+
style: {
|
|
248
|
+
width: '500px',
|
|
249
|
+
},
|
|
250
|
+
content: () => (
|
|
251
|
+
<DataForm
|
|
252
|
+
ref={(v: any) => {
|
|
253
|
+
formRef.value = v
|
|
254
|
+
}}
|
|
255
|
+
options={options}
|
|
256
|
+
v-model:value={model}
|
|
257
|
+
isNo={isNo}
|
|
258
|
+
read={read ?? isRead}
|
|
259
|
+
labelField={labelField}
|
|
260
|
+
formProps={formProps}
|
|
261
|
+
contentStyle={contentStyle}
|
|
262
|
+
dialog
|
|
263
|
+
/>
|
|
264
|
+
),
|
|
265
|
+
action: renderAction,
|
|
266
|
+
// ...readButton.value,
|
|
267
|
+
...dialogProps,
|
|
268
|
+
class: `core-dialog ${(read ?? isRead) ? 'core-dialog-read' : ''} ${dialogProps?.class || ''}`,
|
|
269
|
+
})
|
|
270
|
+
|
|
271
|
+
// 将 dialog 实例存储到 ref 中
|
|
272
|
+
dialogRef.value = d
|
|
273
|
+
|
|
274
|
+
// onBeforeUnmount(() => {
|
|
275
|
+
// console.log('commomDialog end')
|
|
276
|
+
// cancel()
|
|
277
|
+
// })
|
|
278
|
+
|
|
279
|
+
return {
|
|
280
|
+
cancel,
|
|
281
|
+
setValue: (v: any, str?: string) => str ? (model.value[str] = v) : (model.value = { ...model.value, ...v }),
|
|
282
|
+
model: unref(model),
|
|
283
|
+
modeEnum: defaultModeEnum
|
|
284
|
+
};
|
|
285
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { h } from 'vue'
|
|
2
|
+
import { ChevronDown, ChevronUp, Code } from '@vicons/ionicons5'
|
|
3
|
+
|
|
4
|
+
interface OrderEnumItem {
|
|
5
|
+
title: string
|
|
6
|
+
value: boolean | null
|
|
7
|
+
Icon: any
|
|
8
|
+
fn: (listQuery: any, key?: string) => void
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
interface OrderEnum {
|
|
12
|
+
ascend: OrderEnumItem
|
|
13
|
+
descend: OrderEnumItem
|
|
14
|
+
false: OrderEnumItem
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export const orderEnum: OrderEnum = {
|
|
18
|
+
ascend: {
|
|
19
|
+
title: '升序',
|
|
20
|
+
value: true,
|
|
21
|
+
Icon: h(ChevronUp),
|
|
22
|
+
fn: (listQuery: any, key: string) => {
|
|
23
|
+
listQuery.desc = true
|
|
24
|
+
listQuery.sortFieldName = key
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
descend: {
|
|
28
|
+
title: '降序',
|
|
29
|
+
value: false,
|
|
30
|
+
Icon: h(ChevronDown),
|
|
31
|
+
fn: (listQuery: any) => {
|
|
32
|
+
listQuery.sortFieldName = ''
|
|
33
|
+
listQuery.desc = true
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
false: {
|
|
37
|
+
title: '默认',
|
|
38
|
+
value: null,
|
|
39
|
+
Icon: h(Code, { style: 'transform:rotateZ(90deg)' }),
|
|
40
|
+
fn: (listQuery: any) => {
|
|
41
|
+
listQuery.desc = false
|
|
42
|
+
listQuery.sortFieldName = ''
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
}
|
package/src/form/DataForm.vue
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
<script setup>
|
|
1
|
+
<script setup lang="ts">
|
|
2
2
|
import { NForm } from 'naive-ui'
|
|
3
|
-
import { ref, unref } from 'vue'
|
|
3
|
+
import { ref, unref, computed } from 'vue'
|
|
4
|
+
import type { DataFormProps, DataFormExpose } from '../../types/components'
|
|
4
5
|
|
|
5
|
-
import Options from '../options/Options
|
|
6
|
-
import {initRules} from '../dialog/utils/dialog
|
|
7
|
-
import { toArray } from '
|
|
6
|
+
import Options from '../options/Options'
|
|
7
|
+
import { initRules } from '../dialog/utils/dialog'
|
|
8
|
+
import { toArray } from '../utils/array'
|
|
8
9
|
import { registerDirectives } from '../directives/auto-register'
|
|
9
10
|
import { getCurrentInstance } from 'vue'
|
|
10
11
|
|
|
@@ -13,43 +14,16 @@ const instance = getCurrentInstance()
|
|
|
13
14
|
if (instance?.appContext?.app) {
|
|
14
15
|
registerDirectives(instance.appContext.app)
|
|
15
16
|
}
|
|
16
|
-
const props = defineProps({
|
|
17
|
-
isNo:
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
},
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
},
|
|
25
|
-
|
|
26
|
-
type: String,
|
|
27
|
-
default: () => 'label'
|
|
28
|
-
},
|
|
29
|
-
contentStyle: {
|
|
30
|
-
type: Object,
|
|
31
|
-
default: () => ({})
|
|
32
|
-
},
|
|
33
|
-
options: {
|
|
34
|
-
type: Array,
|
|
35
|
-
default: () => []
|
|
36
|
-
},
|
|
37
|
-
rules: {
|
|
38
|
-
type: Object,
|
|
39
|
-
default: () => ({})
|
|
40
|
-
},
|
|
41
|
-
formProps: {
|
|
42
|
-
type: Object,
|
|
43
|
-
default: () => ({})
|
|
44
|
-
},
|
|
45
|
-
formItemProps: {
|
|
46
|
-
type: Object,
|
|
47
|
-
default: () => ({})
|
|
48
|
-
},
|
|
49
|
-
dialog: {
|
|
50
|
-
type: Boolean,
|
|
51
|
-
default: () => false
|
|
52
|
-
}
|
|
17
|
+
const props = withDefaults(defineProps<DataFormProps>(), {
|
|
18
|
+
isNo: true,
|
|
19
|
+
read: false,
|
|
20
|
+
labelField: 'label',
|
|
21
|
+
contentStyle: () => ({}),
|
|
22
|
+
options: () => [],
|
|
23
|
+
rules: () => ({}),
|
|
24
|
+
formProps: () => ({}),
|
|
25
|
+
formItemProps: () => ({}),
|
|
26
|
+
dialog: false,
|
|
53
27
|
})
|
|
54
28
|
const _options = computed(() => props.options)
|
|
55
29
|
// ====== 复制 initRules 逻辑 ======
|
|
@@ -76,27 +50,27 @@ const autoRules = computed(() => {
|
|
|
76
50
|
})
|
|
77
51
|
console.log(autoRules.value);
|
|
78
52
|
|
|
79
|
-
defineExpose({
|
|
53
|
+
defineExpose<DataFormExpose>({
|
|
80
54
|
formRef,
|
|
81
55
|
getRule: () => autoRules.value,
|
|
82
|
-
valid: (keyCode = []) =>{
|
|
83
|
-
console.log('?? valid',keyCode)
|
|
84
|
-
return new Promise((resolve, reject) => {
|
|
56
|
+
valid: (keyCode: string[] = []) => {
|
|
57
|
+
console.log('?? valid', keyCode)
|
|
58
|
+
return new Promise<void>((resolve, reject) => {
|
|
85
59
|
const arrCode = toArray(keyCode)
|
|
86
|
-
formRef.value?.validate((v) => {
|
|
60
|
+
formRef.value?.validate((v: any) => {
|
|
87
61
|
if (v) return reject(v)
|
|
88
62
|
resolve()
|
|
89
|
-
},(v)=> arrCode.length ?
|
|
63
|
+
}, (v: any) => arrCode.length ? arrCode.includes(v?.key) : true)
|
|
90
64
|
})
|
|
91
65
|
},
|
|
92
|
-
confirm: (fn) =>
|
|
93
|
-
new Promise((resolve, reject) => {
|
|
94
|
-
formRef.value?.validate((v) => {
|
|
66
|
+
confirm: (fn?: (model: any) => void) =>
|
|
67
|
+
new Promise<any>((resolve, reject) => {
|
|
68
|
+
formRef.value?.validate((v: any) => {
|
|
95
69
|
if (v) return reject(v)
|
|
96
70
|
fn && fn(unref(_model))
|
|
97
71
|
resolve(unref(_model))
|
|
98
72
|
})
|
|
99
|
-
})
|
|
73
|
+
}),
|
|
100
74
|
})
|
|
101
75
|
</script>
|
|
102
76
|
|
|
@@ -7,15 +7,15 @@ export {
|
|
|
7
7
|
getOptions,
|
|
8
8
|
setupOptions,
|
|
9
9
|
} from './options/defaultOptions'
|
|
10
|
-
export { default as Options } from './options/Options
|
|
10
|
+
export { default as Options } from './options/Options'
|
|
11
11
|
export { default as CommonQuery } from './query/CommonQuery.vue'
|
|
12
12
|
|
|
13
13
|
export { createActionColumnJsx, createQRCode } from './table/opr/useDataColumn'
|
|
14
14
|
export { useQRCode } from './table/opr/useQRCode'
|
|
15
15
|
|
|
16
|
-
export { default as OprButton } from './table/opr/useDataColumnButton
|
|
16
|
+
export { default as OprButton } from './table/opr/useDataColumnButton'
|
|
17
17
|
|
|
18
|
-
export { default as Pop } from './table/opr/useDataColumnPop
|
|
18
|
+
export { default as Pop } from './table/opr/useDataColumnPop'
|
|
19
19
|
|
|
20
20
|
export { toArray } from './utils/array'
|
|
21
21
|
|
|
@@ -23,6 +23,7 @@ export {
|
|
|
23
23
|
cellectChildenPermission,
|
|
24
24
|
handleParams,
|
|
25
25
|
useApiConfig,
|
|
26
|
+
useAuthPermission,
|
|
26
27
|
} from './utils/auth'
|
|
27
28
|
|
|
28
29
|
export { ObjectToArray } from './utils/object'
|
|
@@ -41,9 +42,9 @@ export { default as DataTable } from './table/DataTable.vue'
|
|
|
41
42
|
export { labelField as globalLabelField, valueField as globalValueField } from './enum/options'
|
|
42
43
|
|
|
43
44
|
|
|
44
|
-
export { initRules } from './dialog/utils/dialog
|
|
45
|
+
export { initRules } from './dialog/utils/dialog'
|
|
45
46
|
|
|
46
|
-
export { ellipsis } from './table/utils/ellipsis
|
|
47
|
+
export { ellipsis } from './table/utils/ellipsis'
|
|
47
48
|
|
|
48
49
|
export { initRouteMeta } from './plugin/vite/initRouteMeta'
|
|
49
50
|
|
|
@@ -54,4 +55,4 @@ import CorePluginDefault from './plugin/index'
|
|
|
54
55
|
export { CorePluginDefault as CorePlugin }
|
|
55
56
|
export { install } from './plugin/index'
|
|
56
57
|
export { permissionDirective } from './directives/permission'
|
|
57
|
-
export { registerDirectives, autoRegisterDirectives, getGlobalApp } from './directives/auto-register'
|
|
58
|
+
export { registerDirectives, autoRegisterDirectives, getGlobalApp } from './directives/auto-register'
|
|
@@ -1,11 +1,36 @@
|
|
|
1
|
-
import { computed, ref, unref, watch } from 'vue'
|
|
1
|
+
import { computed, ref, unref, watch, type Ref, type ComputedRef } from 'vue'
|
|
2
|
+
import type { FormOption } from '../../types/components'
|
|
2
3
|
|
|
3
|
-
|
|
4
|
+
interface QueryModel {
|
|
5
|
+
andQuery?: Record<string, any>
|
|
6
|
+
likeQuery?: Record<string, any>
|
|
7
|
+
[key: string]: any
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
interface FilterOption extends FormOption {
|
|
11
|
+
queryType?: string
|
|
12
|
+
value?: any
|
|
13
|
+
type?: string
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
interface UseListReturn {
|
|
17
|
+
loading: Ref<boolean>
|
|
18
|
+
data: Ref<any[]>
|
|
19
|
+
model: Ref<QueryModel>
|
|
20
|
+
initData: () => void
|
|
21
|
+
onSearch: () => void
|
|
22
|
+
onClear: () => void
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function useList(
|
|
26
|
+
source: any[] = [],
|
|
27
|
+
filterOptions: FormOption[] = [],
|
|
28
|
+
): UseListReturn {
|
|
4
29
|
const loading = ref(false)
|
|
5
|
-
const data = ref([])
|
|
30
|
+
const data = ref<any[]>([])
|
|
6
31
|
const sourceList = computed(() => unref(source))
|
|
7
32
|
|
|
8
|
-
const model = ref({
|
|
33
|
+
const model = ref<QueryModel>({
|
|
9
34
|
andQuery: {},
|
|
10
35
|
likeQuery: {},
|
|
11
36
|
})
|
|
@@ -52,17 +77,21 @@ export function useList(source = [], filterOptions = []) {
|
|
|
52
77
|
}
|
|
53
78
|
|
|
54
79
|
export const matchMethod = {
|
|
55
|
-
andQuery: (data, value) =>
|
|
80
|
+
andQuery: (data: any, value: any): boolean =>
|
|
56
81
|
Array.isArray(value) ? value.includes(data) : data === value,
|
|
57
|
-
likeQuery: (data, value
|
|
82
|
+
likeQuery: (data: string | undefined, value: string): boolean =>
|
|
83
|
+
data?.indexOf(value) > -1 || false,
|
|
58
84
|
}
|
|
59
85
|
|
|
60
|
-
export function handleFilterValue(
|
|
86
|
+
export function handleFilterValue(
|
|
87
|
+
runOptions: FormOption[],
|
|
88
|
+
model: QueryModel,
|
|
89
|
+
): FilterOption[] {
|
|
61
90
|
console.log('handleFilterValue', runOptions)
|
|
62
91
|
|
|
63
92
|
return runOptions
|
|
64
93
|
.map((v) => {
|
|
65
|
-
const filedValue = v?.key || v?.value
|
|
94
|
+
const filedValue = (v?.key as string) || (v as any)?.value
|
|
66
95
|
const value = v?.queryType
|
|
67
96
|
? model?.[v?.queryType]?.[filedValue]
|
|
68
97
|
: model?.[filedValue]
|
|
@@ -72,24 +101,30 @@ export function handleFilterValue(runOptions, model) {
|
|
|
72
101
|
key: filedValue,
|
|
73
102
|
type: v?.queryType,
|
|
74
103
|
value,
|
|
75
|
-
}
|
|
104
|
+
} as FilterOption
|
|
76
105
|
: undefined
|
|
77
106
|
})
|
|
78
|
-
.filter(v => v)
|
|
107
|
+
.filter((v): v is FilterOption => v !== undefined)
|
|
79
108
|
}
|
|
80
109
|
|
|
81
|
-
export function handleFilterOption(
|
|
110
|
+
export function handleFilterOption(
|
|
111
|
+
runOption: FilterOption[],
|
|
112
|
+
options: any[],
|
|
113
|
+
): any[] {
|
|
82
114
|
console.log('runOption', runOption)
|
|
83
115
|
|
|
84
116
|
if (runOption.length) {
|
|
85
117
|
return options?.filter(item =>
|
|
86
118
|
runOption.length === 1
|
|
87
|
-
? matchMethod?.[runOption?.[0].type](
|
|
88
|
-
item?.[runOption?.[0]?.key],
|
|
119
|
+
? matchMethod?.[runOption?.[0].type as keyof typeof matchMethod]?.(
|
|
120
|
+
item?.[runOption?.[0]?.key as string],
|
|
89
121
|
runOption?.[0]?.value,
|
|
90
122
|
)
|
|
91
123
|
: runOption?.every(v =>
|
|
92
|
-
matchMethod?.[v.type](
|
|
124
|
+
matchMethod?.[v.type as keyof typeof matchMethod]?.(
|
|
125
|
+
item?.[v.key as string],
|
|
126
|
+
v.value,
|
|
127
|
+
),
|
|
93
128
|
),
|
|
94
129
|
)
|
|
95
130
|
}
|