@xmszm/core 0.0.1

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.
Files changed (45) hide show
  1. package/dist/index.cjs +2 -0
  2. package/dist/index.mjs +2145 -0
  3. package/dist/style.css +1 -0
  4. package/docs/components/dataform.md +61 -0
  5. package/docs/components/datatable.md +77 -0
  6. package/docs/components/dialog.md +78 -0
  7. package/docs/components/options.md +55 -0
  8. package/docs/components/query.md +49 -0
  9. package/docs/components/utils.md +56 -0
  10. package/docs/guide/demo.md +213 -0
  11. package/docs/guide/quickstart.md +77 -0
  12. package/docs/index.md +25 -0
  13. package/docs/usage.md +61 -0
  14. package/examples/demo.vue +224 -0
  15. package/package.json +64 -0
  16. package/src/dialog/commonDialog.jsx +230 -0
  17. package/src/dialog/style/commonDialog.less +40 -0
  18. package/src/dialog/utils/dialog.js +82 -0
  19. package/src/enum/options.js +3 -0
  20. package/src/enum/sort.jsx +31 -0
  21. package/src/form/DataForm.vue +125 -0
  22. package/src/image/ImagesUpload.vue +268 -0
  23. package/src/image/SvgIcon.vue +30 -0
  24. package/src/index.js +46 -0
  25. package/src/list/useList.jsx +99 -0
  26. package/src/options/Options.jsx +338 -0
  27. package/src/options/defaultOptions.jsx +580 -0
  28. package/src/options/options.md +77 -0
  29. package/src/plugin/vite/initRouteMeta.js +54 -0
  30. package/src/query/CommonQuery.vue +272 -0
  31. package/src/store/utils/index.js +6 -0
  32. package/src/table/DataTable.vue +315 -0
  33. package/src/table/FilterDialog.vue +157 -0
  34. package/src/table/opr/DataColumnCollet.jsx +127 -0
  35. package/src/table/opr/useDataColumn.jsx +196 -0
  36. package/src/table/opr/useDataColumnButton.jsx +56 -0
  37. package/src/table/opr/useDataColumnPop.jsx +57 -0
  38. package/src/table/test.md +248 -0
  39. package/src/table/utils/ellipsis.js +22 -0
  40. package/src/utils/array.js +26 -0
  41. package/src/utils/auth.js +118 -0
  42. package/src/utils/object.js +32 -0
  43. package/src/utils/time.js +7 -0
  44. package/src/utils/upload.js +46 -0
  45. package/types/index.d.ts +67 -0
@@ -0,0 +1,580 @@
1
+ import DataTable from 'core/table/DataTable.vue'
2
+ import dayjs from 'dayjs'
3
+ import {
4
+ NButton,
5
+ NCheckbox,
6
+ NCheckboxGroup,
7
+ NDatePicker,
8
+ NDivider,
9
+ NEllipsis,
10
+ NIcon,
11
+ NInput,
12
+ NInputNumber,
13
+ NProgress,
14
+ NRadio,
15
+ NRadioGroup,
16
+ NSelect,
17
+ NSpace,
18
+ NSwitch,
19
+ NText,
20
+ NTimePicker,
21
+ NUpload,
22
+ NUploadDragger,
23
+ } from 'naive-ui'
24
+ import { unref } from 'vue'
25
+ import {
26
+ labelField as globalLabelField,
27
+ valueField as globalValueField,
28
+ } from '../enum/options'
29
+ import ImagesUpload from '../image/ImagesUpload.vue'
30
+ import { ArrayToObject } from '../utils/array'
31
+
32
+ import { timeFormat } from '../utils/time'
33
+
34
+ const defaultOptions = {
35
+ input: (
36
+ { label, key, props, readProps, format = null, read },
37
+ { _value, _isRead },
38
+ ) => {
39
+ return (read ?? _isRead)
40
+ ? (
41
+ <NEllipsis {...readProps}>
42
+ {format
43
+ ? format?.(unref(_value)[key], unref(_value))
44
+ : unref(_value)[key]}
45
+ </NEllipsis>
46
+ )
47
+ : (
48
+ <NInput
49
+ v-model:value={_value[key]}
50
+ clearable
51
+ placeholder={`请输入${unref(label)}`}
52
+ {...props}
53
+ >
54
+ {{
55
+ ...(props?.slots || {}),
56
+ }}
57
+ </NInput>
58
+ )
59
+ },
60
+ select: (
61
+ { label, key, props, options = [], loading = false, format = null, read },
62
+ { _value, _isRead },
63
+ ) => {
64
+ const fnOptions
65
+ = (Array.isArray(unref(options))
66
+ ? unref(options)
67
+ : options?.(_value[key])) || []
68
+ return (read ?? _isRead)
69
+ ? (
70
+ <div>
71
+ {format
72
+ ? format?.(_value[key], fnOptions)
73
+ : ArrayToObject(
74
+ fnOptions,
75
+ props?.labelField || globalLabelField,
76
+ props?.valueField || globalValueField,
77
+ )?.[_value[key]]?.[props?.labelField || globalLabelField]}
78
+ </div>
79
+ )
80
+ : (
81
+ <NSelect
82
+ v-model:value={_value[key]}
83
+ options={fnOptions}
84
+ loading={unref(loading)}
85
+ clearable
86
+ filterable
87
+ fallback-option={() => {
88
+ if (!props?.asyncFallback)
89
+ _value[key] = null
90
+ return false
91
+ }}
92
+ labelField={props?.labelField || globalLabelField}
93
+ valueField={props?.valueField || globalValueField}
94
+ placeholder={`请选择${unref(label)}`}
95
+ style="width:100%"
96
+ max-tag-count="responsive"
97
+ {...props}
98
+ >
99
+ {{
100
+ ...(props?.slots || {}),
101
+ }}
102
+ </NSelect>
103
+ )
104
+ },
105
+ date: (
106
+ {
107
+ label,
108
+ key,
109
+ props,
110
+ formatTime = 'YYYY-MM-DD',
111
+ type = 'date',
112
+ format,
113
+ read,
114
+ },
115
+ { _value, _isRead },
116
+ ) => {
117
+ return (read ?? _isRead)
118
+ ? (
119
+ <div>
120
+ {format ? format?.(_value[key]) : timeFormat(_value[key], formatTime)}
121
+ </div>
122
+ )
123
+ : (
124
+ <NDatePicker
125
+ formatted-value={_value[key]}
126
+ onUpdate:formatted-value={(v) => {
127
+ _value[key] = v
128
+ }}
129
+ type={type}
130
+ clearable
131
+ placeholder={`请选择${unref(label)}`}
132
+ update-value-on-close={!['year']?.includes(props?.type)}
133
+ style="width:100%"
134
+ {...props}
135
+ >
136
+ {{
137
+ ...(props?.slots || {}),
138
+ }}
139
+ </NDatePicker>
140
+ )
141
+ },
142
+ time: (
143
+ { label, key, props, format, formatTime = 'YYYY-MM-DD', read },
144
+ { _value, _isRead },
145
+ ) => {
146
+ return (read ?? _isRead)
147
+ ? (
148
+ <div>
149
+ {format ? format?.(_value[key]) : timeFormat(_value[key], formatTime)}
150
+ </div>
151
+ )
152
+ : (
153
+ <NTimePicker
154
+ formatted-value={_value[key]}
155
+ onUpdate:value={(_,v) => {
156
+ console.log('v', v)
157
+
158
+ _value[key] = v
159
+ }}
160
+ clearable
161
+ format="HH:mm:ss"
162
+ style="width:100%"
163
+ placeholder={`请选择${unref(label)}`}
164
+ {...props}
165
+ >
166
+ {{
167
+ ...(props?.slots || {}),
168
+ }}
169
+ </NTimePicker>
170
+ )
171
+ },
172
+ dateRange: (
173
+ { key, props, type = 'datetimerange', read },
174
+ { _value, _isRead },
175
+ ) => {
176
+ const timeEnum = {
177
+ date: 'YYYY-MM-DD',
178
+ datetime: 'YYYY-MM-DD HH:mm:ss',
179
+ time: 'HH:mm:ss',
180
+ datetimerange: 'YYYY-MM-DD HH:mm:ss',
181
+ daterange: 'YYYY-MM-DD',
182
+ }
183
+ const formatStr = props?.format
184
+ ? props?.format?.replace('yyyy', 'YYYY')?.replace('dd', 'DD')
185
+ : timeEnum[props?.type || type]
186
+
187
+ console.log('formatStr type', type)
188
+ console.log('formatStr', formatStr)
189
+
190
+ return (read ?? _isRead)
191
+ ? (
192
+ <div>
193
+ {Array.isArray(key)
194
+ ? `${_value?.[key?.[0]]} - ${_value?.[key?.[1]]}`
195
+ : _value?.[key]}
196
+ </div>
197
+ )
198
+ : (
199
+ <NDatePicker
200
+ formatted-value={
201
+ Array.isArray(key)
202
+ ? _value?.[key?.[0]] && _value?.[key?.[1]]
203
+ ? [
204
+ dayjs(_value?.[key?.[0]]).format(formatStr),
205
+ dayjs(_value?.[key?.[1]]).format(formatStr),
206
+ ]
207
+ : null
208
+ : _value?.[key] || null
209
+ }
210
+ onUpdate:formatted-value={(v) => {
211
+ console.log(v)
212
+
213
+ if (v && ![timeEnum.datetime, timeEnum.datetimerange].includes(formatStr)) {
214
+ v = v.map((d, i) =>
215
+ dayjs(d, formatStr)
216
+ [!i ? 'startOf' : 'endOf']('day')
217
+ .format(formatStr),
218
+ )
219
+ }
220
+ if (Array.isArray(key)) {
221
+ _value[key?.[0]] = v?.[0]
222
+ _value[key?.[1]] = v?.[1]
223
+ }
224
+ else {
225
+ _value[key] = v
226
+ }
227
+ }}
228
+ update-value-on-close={!['year', 'month']?.includes(props?.type)}
229
+ type={type}
230
+ clearable
231
+ style="width:100%"
232
+ {...props}
233
+ >
234
+ {{
235
+ ...(props?.slots || {}),
236
+ }}
237
+ </NDatePicker>
238
+ )
239
+ },
240
+ radio: (
241
+ { key, options = [], props, radioLabelProps, read },
242
+ { _value, _isRead, labelField, valueField },
243
+ ) => {
244
+ return (read ?? _isRead)
245
+ ? (
246
+ <div>
247
+ {
248
+ ArrayToObject(
249
+ options,
250
+ props?.labelField || labelField,
251
+ props?.valueField || valueField,
252
+ )?.[_value[key]]?.[props?.labelField || labelField]
253
+ }
254
+ </div>
255
+ )
256
+ : (
257
+ <NRadioGroup
258
+ style={{ width: '100%' }}
259
+ v-model:value={_value[key]}
260
+ {...props}
261
+ >
262
+ {{
263
+ ...(props?.slots || {}),
264
+ default: () => (
265
+ <NSpace item-wrap={false} {...(props?.radioProps || {})}>
266
+ {options?.map(v => (
267
+ <NRadio
268
+ key={v.value}
269
+ value={v?.[props?.valueField || valueField]}
270
+ class="items-center"
271
+ >
272
+ <div {...(radioLabelProps?.(v) || {})}>
273
+ {v?.[props?.labelField || labelField]}
274
+ </div>
275
+ </NRadio>
276
+ ))}
277
+ </NSpace>
278
+ ),
279
+ }}
280
+ </NRadioGroup>
281
+ )
282
+ },
283
+ inputPhone: ({ label, key, props, read }, { _value, _isRead }) => {
284
+ return (read ?? _isRead)
285
+ ? (
286
+ <div>{_value[key]}</div>
287
+ )
288
+ : (
289
+ <NInput
290
+ v-model:value={_value[key]}
291
+ clearable
292
+ style="width:100%"
293
+ allow-input={v => !v || /^\d$/.test(v) || v.length <= 11}
294
+ placeholder={`请输入${unref(label)}`}
295
+ {...props}
296
+ >
297
+ {{
298
+ ...props?.slots,
299
+ }}
300
+ </NInput>
301
+ )
302
+ },
303
+ inputNumber: ({ label, key, props, read }, { _value, _isRead }) => {
304
+ return (read ?? _isRead)
305
+ ? (
306
+ <div>{_value[key]}</div>
307
+ )
308
+ : (
309
+ <NInputNumber
310
+ value={
311
+ typeof _value[key] === 'string' && _value[key]
312
+ ? Number(_value[key])
313
+ : _value[key]
314
+ }
315
+ onUpdate:value={(v) => {
316
+ _value[key] = v
317
+ }}
318
+ showButton={false}
319
+ clearable
320
+ style="width:100%"
321
+ placeholder={`请输入${unref(label)}`}
322
+ min={0}
323
+ {...props}
324
+ >
325
+ {{
326
+ ...(props?.slots || {}),
327
+ }}
328
+ </NInputNumber>
329
+ )
330
+ },
331
+ uploadFile: ({ key, props }, { _value }) => (
332
+ <NUpload
333
+ multiple
334
+ max={1}
335
+ accept=".xls,.xlsx"
336
+ v-model:file-list={_value[key]}
337
+ {...props}
338
+ >
339
+ <NUploadDragger>
340
+ <div style="margin-bottom: 12px">
341
+ <NIcon size="48" depth={3}>
342
+ <ArchiveOutline />
343
+ </NIcon>
344
+ </div>
345
+ <NText style="font-size: 16px">点击或者拖动文件到该区域来上传</NText>
346
+ </NUploadDragger>
347
+ </NUpload>
348
+ ),
349
+ dataTable: (
350
+ { key, loading = false, props, options, opr, pageState },
351
+ { _value, _isRead },
352
+ ) => {
353
+ console.log(loading)
354
+ console.log(pageState)
355
+
356
+ return (
357
+ <DataTable
358
+ data={pageState?.data?.length ? pageState.data : _value[key]}
359
+ columns={unref(options)}
360
+ maxHeight={200}
361
+ minHeight={200}
362
+ is-ellipsis={false}
363
+ opr-columns={opr}
364
+ loading={pageState?.loading}
365
+ {...props}
366
+ />
367
+ )
368
+ },
369
+ progress: ({ key, props }, { _value }) => (
370
+ <NProgress percentage={_value[key]} {...props} />
371
+ ),
372
+ line: () => <NDivider />,
373
+
374
+ image: ({ key, props, read }, { _isRead, _value }) => (
375
+ <ImagesUpload
376
+ v-model:value={_value[key]}
377
+ max={1}
378
+ {...props}
379
+ read={read ?? _isRead}
380
+ />
381
+ ),
382
+ button: ({ onClick, props, text }, { _value }) => {
383
+ return (
384
+ <NButton
385
+ type="info"
386
+ {...props}
387
+ onClick={() =>
388
+ props?.onClick
389
+ ? props?.onClick(unref(_value))
390
+ : onClick(unref(_value))}
391
+ >
392
+ {text}
393
+ </NButton>
394
+ )
395
+ },
396
+ switch: ({ key, props, read }, { _isRead, _value }) =>
397
+ (read ?? _isRead)
398
+ ? (
399
+ <div>{_value[key] ? '是' : '否'}</div>
400
+ )
401
+ : (
402
+ <NSwitch v-model:value={_value[key]} {...props}>
403
+ {{
404
+ ...(props?.slots || {}),
405
+ }}
406
+ </NSwitch>
407
+ ),
408
+ checkbox: (
409
+ { key, options = [], props, read },
410
+ { _value, _isRead, labelField, valueField },
411
+ ) =>
412
+ (read ?? _isRead)
413
+ ? (
414
+ <div>
415
+ {unref(options)
416
+ ?.filter(v =>
417
+ unref(_value)[key]?.includes(
418
+ v[props?.valueField || valueField || globalValueField],
419
+ ),
420
+ )
421
+ ?.map(v => v[[props?.labelField || labelField || globalLabelField]])
422
+ ?.join('、')}
423
+ </div>
424
+ )
425
+ : (
426
+ <NCheckboxGroup
427
+ v-model:value={_value[key]}
428
+ style={{ width: '100%' }}
429
+ {...props}
430
+ >
431
+ {{
432
+ ...(props?.slots || {}),
433
+ default: () => (
434
+ <NSpace {...(props?.checkBoxProps || {})}>
435
+ {unref(options)?.map(v => (
436
+ <NCheckbox
437
+ key={v?.[props?.valueField || valueField || globalValueField]}
438
+ value={
439
+ v?.[props?.valueField || valueField || globalValueField]
440
+ }
441
+ >
442
+ {v?.[props?.labelField || labelField || globalLabelField]}
443
+ </NCheckbox>
444
+ ))}
445
+ </NSpace>
446
+ ),
447
+ }}
448
+ </NCheckboxGroup>
449
+ ),
450
+ filterList: ({ key, props, options }, { _value }) => (
451
+ <FilterSelect
452
+ v-model:value={_value[key]}
453
+ option={options}
454
+ clearable
455
+ filterButtonKey={['all', 'selectDefault']}
456
+ {...props}
457
+ />
458
+ ),
459
+ }
460
+ let extendOptions = {}
461
+
462
+ let extendCallBack = null
463
+ class DefaultOptions {
464
+ defaultMap = null
465
+ extendOptions = null
466
+ constructor() {
467
+ console.log('DefaultOptions init')
468
+
469
+ this.defaultMap = null
470
+ this.init()
471
+ }
472
+
473
+ set(key, fn) {
474
+ this.options.set(key, fn)
475
+ }
476
+
477
+ get(key) {
478
+ return this.options.get(key)
479
+ }
480
+
481
+ clear() {
482
+ this.defaultMap.clear()
483
+ }
484
+
485
+ setupOptions(key, fn) {
486
+ const keys = this.defaultMap.size > 0 ? [...this.defaultMap.keys()] : []
487
+ if (this.defaultMap.has(key))
488
+ return console.error(`${key} 已存在,不能使用${keys?.join('、')}`)
489
+ this.defaultMap.set(key, fn)
490
+ }
491
+
492
+ setupExtendOptions(key, fn) {
493
+ if(!extendOptions) extendOptions = {}
494
+ if (!extendOptions?.[key]) {
495
+ extendOptions[key] = fn
496
+ }
497
+ }
498
+
499
+ getAllOptions() {
500
+ const options = {}
501
+ this.defaultMap.forEach((v, key) => {
502
+ options[key] = v
503
+ })
504
+
505
+ return options
506
+ }
507
+
508
+ getOptions(keys = []) {
509
+ console.log('getOptions',this.defaultMap)
510
+ const options = keys.reduce((o, key) => {
511
+ if (this.defaultMap.has(key))
512
+ o[key] = this.defaultMap.get(key)
513
+ return o
514
+ }, {})
515
+
516
+ return options
517
+ }
518
+
519
+ initOptions(options = []) {
520
+ Object.keys(options).forEach((key) => {
521
+ this.setupOptions(key, options[key])
522
+ })
523
+ }
524
+
525
+ initSetup(callback) {
526
+ if (this.defaultMap)
527
+ this.clear()
528
+ this.defaultMap = new Map()
529
+ this.initOptions(defaultOptions)
530
+ callback && callback()
531
+ if (import.meta.hot) {
532
+ if (Object.keys(extendOptions).length)
533
+ import.meta.hot.data.extendOptions = extendOptions
534
+ else extendOptions = import.meta.hot?.data?.extendOptions
535
+ }
536
+ this.initOptions(extendOptions)
537
+ }
538
+
539
+ init(callback) {
540
+ this.initSetup(callback)
541
+ }
542
+ }
543
+
544
+ const defaultOptionsMap = new DefaultOptions()
545
+
546
+ /**
547
+ * @returns {void}
548
+ * 初始化默认选项
549
+ */
550
+ export const initOptions = (...arg) => defaultOptionsMap.initOptions(...arg)
551
+
552
+ export default (...arg) =>defaultOptionsMap.init(...arg)
553
+
554
+ /**
555
+ *
556
+ * @param {string[]} keys
557
+ * @returns
558
+ * 获取选项
559
+ */
560
+ export const getOptions = (...arg) => defaultOptionsMap.getOptions(...arg)
561
+
562
+ /**
563
+ * @returns {Object[string,any]>}
564
+ * 获取所有选项
565
+ */
566
+ export function getAllOptions(...arg) {
567
+ return defaultOptionsMap.getAllOptions(...arg)
568
+ }
569
+
570
+ /**
571
+ *
572
+ * @param {string} key
573
+ * @param {Function} fn
574
+ * @returns {void}
575
+ * 注册一个选项
576
+ * @example setupOptions('input',({},{_value,_isRead})=>{})
577
+ */
578
+ export function setupOptions(...arg) {
579
+ return defaultOptionsMap.setupExtendOptions(...arg)
580
+ }
@@ -0,0 +1,77 @@
1
+ ```javascript
2
+
3
+
4
+ const opr = createActionColumnJsx([
5
+ {
6
+ label: '编辑',
7
+ type: 'primary',
8
+ onClick: row => onAdd(row, 'edit'),
9
+ },
10
+ {
11
+ label: '删除',
12
+ type: 'error',
13
+ mode: 'pop',
14
+ content: '确定删除该记录?',
15
+ onClick: (row) => {
16
+ $message.success('删除成功')
17
+ pageState.data = pageState.data.filter(item => item.id !== row.id)
18
+ pageState.itemCount--
19
+ },
20
+ },
21
+ ])
22
+
23
+ function onAdd(row = null, str = 'add') {
24
+
25
+ commonDialogMethod({
26
+ title: `示例`,
27
+ mode:str,
28
+ options: [
29
+ {
30
+ label: '名称',
31
+ key: 'name',
32
+ required: true,
33
+ },
34
+ {
35
+ label: '类型',
36
+ key: 'type',
37
+ way: 'select',
38
+ options: [
39
+ { label: '类型1', value: 'type1' },
40
+ { label: '类型2', value: 'type2' },
41
+ ],
42
+ },
43
+ {
44
+ label: '状态',
45
+ key: 'status',
46
+ way: 'switch',
47
+ },
48
+ ],
49
+ valueData: { ...row },
50
+ isRead: dialogState?.[str].isRead,
51
+ interfaceFn: (data, { hideLoading, close }) => {
52
+ // 模拟接口调用
53
+ setTimeout(() => {
54
+ $message.success(`${dialogState?.[str]?.title}成功`)
55
+ if (str === 'add') {
56
+ pageState.data.unshift({
57
+ id: Date.now(),
58
+ ...data,
59
+ createTime: new Date().toLocaleString(),
60
+ })
61
+ pageState.itemCount++
62
+ }
63
+ else {
64
+ const index = pageState.data.findIndex(item => item.id === data.id)
65
+ if (index > -1) {
66
+ pageState.data[index] = { ...pageState.data[index], ...data }
67
+ }
68
+ }
69
+ close()
70
+ hideLoading()
71
+ }, 500)
72
+ },
73
+ })
74
+ }
75
+
76
+
77
+ ```
@@ -0,0 +1,54 @@
1
+ export function initRouteMeta(routes, str = '') {
2
+ if (routes.length) {
3
+ routes.forEach((v) => {
4
+ if (v.children) {
5
+ initRouteMeta(v.children, v?.path)
6
+ }
7
+ if (v.path)
8
+ v.sourceFullPath = `${str ? `${str}/`.replace(/^\/\//, '/') : ''}${v.path}`
9
+
10
+ if (!v.meta)
11
+ v.meta = {}
12
+ const title = v?.title ?? v?.meta?.title ?? '未命名页面'
13
+
14
+ if (v?.api)
15
+ v.meta.api = v.api
16
+
17
+ if (title) {
18
+ v.meta.title = title
19
+ v.title = title
20
+ }
21
+
22
+ if (v?.hidden)
23
+ v.meta.hidden = v.hidden
24
+
25
+ let authPermission = []
26
+ if (v?.auth) {
27
+ v.meta.auth = v.auth
28
+
29
+ authPermission = Object.keys(v.auth).reduce((a, b) => {
30
+ if (typeof v.auth[b] === 'string')
31
+ a.push(v.auth[b])
32
+ else if (typeof v.auth[b] === 'boolean')
33
+ a.push(b)
34
+ return a
35
+ }, [])
36
+ }
37
+
38
+ if (v?.permission)
39
+ v.meta.permission = v.permission
40
+
41
+ if (v.meta.permission && Array.isArray(v.meta.permission)) {
42
+ v.meta.permission = v.meta.permission.concat(authPermission)
43
+ }
44
+ else if (authPermission.length) {
45
+ v.meta.permission = authPermission
46
+ }
47
+ })
48
+
49
+ return routes
50
+ }
51
+ else {
52
+ return []
53
+ }
54
+ }