@ithinkdt/ui 4.0.0-22 → 4.0.0-30
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/locale.d.ts +3 -0
- package/package.json +6 -6
- package/src/components/Checkboxes.jsx +1 -1
- package/src/components/DataTable.jsx +9 -4
- package/src/components.d.ts +3 -2
- package/src/page.d.ts +18 -2
- package/src/page.jsx +160 -63
package/locale.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ithinkdt/ui",
|
|
3
|
-
"version": "4.0.0-
|
|
3
|
+
"version": "4.0.0-30",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"description": "iThinkDT UI",
|
|
@@ -63,7 +63,7 @@
|
|
|
63
63
|
"sortablejs": "^1.15.6",
|
|
64
64
|
"@types/sortablejs": "^1.15.8",
|
|
65
65
|
"nanoid": "^5.1.6",
|
|
66
|
-
"@ithinkdt/common": "^4.0.0-
|
|
66
|
+
"@ithinkdt/common": "^4.0.0-30"
|
|
67
67
|
},
|
|
68
68
|
"peerDependencies": {
|
|
69
69
|
"@ithinkdt/page": ">=4.0",
|
|
@@ -82,13 +82,13 @@
|
|
|
82
82
|
},
|
|
83
83
|
"devDependencies": {
|
|
84
84
|
"@vitejs/plugin-vue-jsx": "^5.1.1",
|
|
85
|
-
"ithinkdt-ui": "^1.
|
|
85
|
+
"ithinkdt-ui": "^1.8.0",
|
|
86
86
|
"typescript": "~5.9.3",
|
|
87
87
|
"unocss": ">=66.5.4",
|
|
88
|
-
"vite": "npm:rolldown-vite@^7.1.
|
|
88
|
+
"vite": "npm:rolldown-vite@^7.1.19",
|
|
89
89
|
"vue": "^3.5.22",
|
|
90
|
-
"vue-router": "^4.6.
|
|
91
|
-
"@ithinkdt/page": "^4.0.0-
|
|
90
|
+
"vue-router": "^4.6.3",
|
|
91
|
+
"@ithinkdt/page": "^4.0.0-30"
|
|
92
92
|
},
|
|
93
93
|
"scripts": {
|
|
94
94
|
"release": "pnpm publish --no-git-checks"
|
|
@@ -3,7 +3,7 @@ import { computed, defineComponent, ref, watch } from 'vue'
|
|
|
3
3
|
|
|
4
4
|
import { useI18n } from '../use-i18n.js'
|
|
5
5
|
|
|
6
|
-
export const NCheckboxes = defineComponent({
|
|
6
|
+
export const NCheckboxes = /* @__PURE__ */ defineComponent({
|
|
7
7
|
name: 'Checkboxes',
|
|
8
8
|
inheritAttrs: false,
|
|
9
9
|
props: {
|
|
@@ -125,10 +125,7 @@ export const DataTable = /* @__PURE__ */ defineComponent({
|
|
|
125
125
|
type: Array,
|
|
126
126
|
},
|
|
127
127
|
},
|
|
128
|
-
emits:
|
|
129
|
-
sort: () => true,
|
|
130
|
-
select: () => true,
|
|
131
|
-
},
|
|
128
|
+
emits: ['sort', 'select', 'custom'],
|
|
132
129
|
setup(props, { slots, emit, expose }) {
|
|
133
130
|
const { keyField } = inject(PAGE_INJECTION)
|
|
134
131
|
|
|
@@ -207,6 +204,13 @@ export const DataTable = /* @__PURE__ */ defineComponent({
|
|
|
207
204
|
emit('select', keys)
|
|
208
205
|
}
|
|
209
206
|
|
|
207
|
+
const onColumnResize = (resizedWidth, limitedWidth, column) => {
|
|
208
|
+
emit('custom', {
|
|
209
|
+
key: column.key,
|
|
210
|
+
width: resizedWidth,
|
|
211
|
+
})
|
|
212
|
+
}
|
|
213
|
+
|
|
210
214
|
return () => (
|
|
211
215
|
<NDataTable
|
|
212
216
|
class={cls}
|
|
@@ -220,6 +224,7 @@ export const DataTable = /* @__PURE__ */ defineComponent({
|
|
|
220
224
|
checkedRowKeys={props.selectedKeys}
|
|
221
225
|
onUpdateSorter={onUpdateSorter}
|
|
222
226
|
onUpdateCheckedRowKeys={onUpdateCheckedRowKeys}
|
|
227
|
+
onUnstableColumnResize={onColumnResize}
|
|
223
228
|
>
|
|
224
229
|
{slots}
|
|
225
230
|
</NDataTable>
|
package/src/components.d.ts
CHANGED
|
@@ -157,6 +157,7 @@ export type DataTableProps<Data extends {}, KeyField extends keyof Data>
|
|
|
157
157
|
export type DataTableEmits<Data extends {}, KeyField extends keyof Data> = {
|
|
158
158
|
(e: 'sort', param: SortParams<Data>): void
|
|
159
159
|
(e: 'select', param: Data[KeyField][]): void
|
|
160
|
+
(e: 'custom', params: { key: string, width: number }): void
|
|
160
161
|
}
|
|
161
162
|
|
|
162
163
|
export type DataTableInst<Data extends {}, KeyField extends keyof Data> = NDataTableInst & {
|
|
@@ -182,7 +183,7 @@ export declare function useDataTableDrag<T>(
|
|
|
182
183
|
{ data, onSort, ...options }: {
|
|
183
184
|
data: MaybeRef<T[]>
|
|
184
185
|
onSort: (info: { from: number, to: number }) => void
|
|
185
|
-
} & Omit<Sortable.Options, 'onSort'
|
|
186
|
+
} & Omit<Sortable.Options, 'onSort'>,
|
|
186
187
|
): void
|
|
187
188
|
|
|
188
189
|
export type DataPaginationProps = (PageParams | { page: PageParams }) & {
|
|
@@ -302,7 +303,7 @@ export declare function DataLocaleInput(
|
|
|
302
303
|
export declare function useLocaleEdit(
|
|
303
304
|
title: VNodeChild | (() => VNodeChild),
|
|
304
305
|
onSubmit: (data: Record<string, string | undefined>) => void,
|
|
305
|
-
defaultRows?: MaybeRef<number | undefined
|
|
306
|
+
defaultRows?: MaybeRef<number | undefined>,
|
|
306
307
|
): {
|
|
307
308
|
open(this: void, data: MaybePromise<Record<string, string | undefined>>, readonly?: boolean): PromiseLike<Record<string, string | undefined>>
|
|
308
309
|
setSupports(this: void, supports: { label: string, value: string, required?: boolean }[]): void
|
package/src/page.d.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
|
-
CheckboxProps,
|
|
2
|
+
CheckboxProps,
|
|
3
|
+
DatePickerProps, DatePickerSlots,
|
|
3
4
|
DrawerContentProps, DrawerProps,
|
|
4
5
|
InputNumberProps, InputNumberSlots, InputProps, InputSlots,
|
|
5
6
|
ModalOptions,
|
|
6
7
|
SelectGroupOption, SelectOption, SelectProps, SelectSlots,
|
|
7
|
-
UploadFileInfo,
|
|
8
|
+
UploadFileInfo, UploadProps,
|
|
8
9
|
} from 'ithinkdt-ui'
|
|
9
10
|
import { MaybeRef, VNode, VNodeProps } from 'vue'
|
|
10
11
|
|
|
@@ -75,6 +76,20 @@ declare module '@ithinkdt/page' {
|
|
|
75
76
|
max?: number | undefined
|
|
76
77
|
accept?: string | undefined
|
|
77
78
|
maxSize?: number | undefined
|
|
79
|
+
onBeforeUpload?: UploadProps['onBeforeUpload']
|
|
80
|
+
} & VNodeProps>
|
|
81
|
+
slots?: {
|
|
82
|
+
default?: (() => VNode[]) | undefined
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
upload: {
|
|
86
|
+
props?: DeepMaybeRef<{
|
|
87
|
+
type?: 'file' | 'image' | undefined
|
|
88
|
+
multiple?: boolean | undefined
|
|
89
|
+
max?: number | undefined
|
|
90
|
+
accept?: string | undefined
|
|
91
|
+
maxSize?: number | undefined
|
|
92
|
+
onBeforeUpload?: UploadProps['onBeforeUpload']
|
|
78
93
|
} & VNodeProps>
|
|
79
94
|
slots?: {
|
|
80
95
|
default?: (() => VNode[]) | undefined
|
|
@@ -142,6 +157,7 @@ export declare function createPageFormHelper(options?: {
|
|
|
142
157
|
uploadFile?: (file: File, options?: {
|
|
143
158
|
onProgress?: ((percent: number) => void) | undefined
|
|
144
159
|
}) => Promise<string>
|
|
160
|
+
getFileInfos?: (files: string[]) => Promise<UploadFileInfo[]>
|
|
145
161
|
}): PageOptions['getFormItemRenderer']
|
|
146
162
|
export declare function createPageTableHelper(options?: {
|
|
147
163
|
getUsersByUsername?: (usernames: string[]) => Promise<{ username: string, nickname: string }[]>
|
package/src/page.jsx
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
+
import { until } from '@vueuse/core'
|
|
1
2
|
import { format } from 'date-fns'
|
|
2
3
|
import {
|
|
3
4
|
NButton, NCheckbox, NColorPicker, NDatePicker, NDrawer, NDrawerContent, NFlex, NInput,
|
|
4
|
-
NInputNumber, NModal, NScrollbar, NSelect, NText, NUpload,
|
|
5
|
-
useMessage,
|
|
5
|
+
NInputNumber, NModal, NScrollbar, NSelect, NText, NUpload, useMessage,
|
|
6
6
|
} from 'ithinkdt-ui'
|
|
7
|
-
import { defineComponent, h, mergeProps, unref } from 'vue'
|
|
7
|
+
import { computed, defineComponent, h, mergeProps, shallowRef, unref } from 'vue'
|
|
8
8
|
|
|
9
9
|
import { useDict, useDictMap } from '@ithinkdt/common/dict'
|
|
10
10
|
|
|
@@ -14,64 +14,68 @@ import { useI18n } from './use-i18n.js'
|
|
|
14
14
|
const mapProps = (props) => {
|
|
15
15
|
return Object.fromEntries(Object.entries(props || {}).map(([prop, value]) => [prop, unref(value)]))
|
|
16
16
|
}
|
|
17
|
-
export function createPageFormHelper({
|
|
18
|
-
getUserGroups, getUsersByGroup, getUsersByDept, getUsersByUsername, uploadFile,
|
|
19
|
-
}) {
|
|
20
|
-
const SimpleUpload = defineComponent({
|
|
21
|
-
name: 'SimpleUpload',
|
|
22
|
-
props: {
|
|
23
|
-
type: { type: String, default: 'file' }, // file | image
|
|
24
|
-
multiple: { type: Boolean, default: false },
|
|
25
|
-
max: { type: Number, default: undefined },
|
|
26
|
-
accept: { type: String, default: undefined },
|
|
27
|
-
maxSize: { type: Number, default: undefined }, // MB
|
|
28
|
-
disabled: { type: Boolean, default: undefined },
|
|
29
|
-
fileList: { type: Array, default: () => [] },
|
|
30
|
-
onUpdateFileList: { type: [Array, Function] },
|
|
31
|
-
},
|
|
32
|
-
setup(props, { slots }) {
|
|
33
|
-
const { t } = useI18n()
|
|
34
17
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
onUpdate:fileList={onUpdateFileList}
|
|
64
|
-
>
|
|
65
|
-
{{
|
|
66
|
-
default: () => <NButton disabled={props.disabled}>{t('common.page.form.selectFileText')}</NButton>,
|
|
67
|
-
...slots,
|
|
68
|
-
}}
|
|
69
|
-
</NUpload>
|
|
70
|
-
)
|
|
18
|
+
const SimpleUpload = /* @__PURE__ */ defineComponent({
|
|
19
|
+
name: 'SimpleUpload',
|
|
20
|
+
props: {
|
|
21
|
+
type: { type: String, default: 'file' }, // file | image
|
|
22
|
+
multiple: { type: Boolean, default: false },
|
|
23
|
+
max: { type: Number, default: undefined },
|
|
24
|
+
accept: { type: String, default: undefined },
|
|
25
|
+
maxSize: { type: Number, default: undefined }, // MB
|
|
26
|
+
disabled: { type: Boolean, default: undefined },
|
|
27
|
+
fileList: { type: Array, default: () => [] },
|
|
28
|
+
onUpdateFileList: { type: [Array, Function] },
|
|
29
|
+
uploadFile: { type: Function },
|
|
30
|
+
},
|
|
31
|
+
setup(props, { slots, expose }) {
|
|
32
|
+
const { t } = useI18n()
|
|
33
|
+
SimpleUpload.t = t
|
|
34
|
+
|
|
35
|
+
const message = useMessage()
|
|
36
|
+
const customRequest = computed(() => props.customRequest || (
|
|
37
|
+
({ file, onProgress, onFinish, onError }) => {
|
|
38
|
+
props.uploadFile(file.file, percent => onProgress({ percent }))
|
|
39
|
+
.then((id) => {
|
|
40
|
+
file.file.fileId = id
|
|
41
|
+
onFinish()
|
|
42
|
+
}).catch((error) => {
|
|
43
|
+
message.error(error.message)
|
|
44
|
+
onError(error)
|
|
45
|
+
})
|
|
71
46
|
}
|
|
72
|
-
|
|
73
|
-
})
|
|
47
|
+
))
|
|
74
48
|
|
|
49
|
+
const inst = ref()
|
|
50
|
+
expose({
|
|
51
|
+
submit() {
|
|
52
|
+
return until(inst).toBeTruthy().then(inst => inst.submit())
|
|
53
|
+
},
|
|
54
|
+
})
|
|
55
|
+
return () => {
|
|
56
|
+
const { type, onUpdateFileList, ...props0 } = props
|
|
57
|
+
return (
|
|
58
|
+
<NUpload
|
|
59
|
+
{...props0}
|
|
60
|
+
ref={inst}
|
|
61
|
+
customRequest={customRequest.value}
|
|
62
|
+
listType={type === 'image' ? 'image-card' : 'text'}
|
|
63
|
+
accept={props0.accept ?? type === 'image' ? 'image/*' : undefined}
|
|
64
|
+
onUpdate:fileList={onUpdateFileList}
|
|
65
|
+
>
|
|
66
|
+
{{
|
|
67
|
+
default: () => <NButton disabled={props.disabled}>{t('common.page.form.selectFileText')}</NButton>,
|
|
68
|
+
...slots,
|
|
69
|
+
}}
|
|
70
|
+
</NUpload>
|
|
71
|
+
)
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
export function createPageFormHelper({
|
|
77
|
+
getUserGroups, getUsersByGroup, getUsersByDept, getUsersByUsername, uploadFile, getFileInfos,
|
|
78
|
+
}) {
|
|
75
79
|
return {
|
|
76
80
|
input: () => (
|
|
77
81
|
{ slots, props },
|
|
@@ -298,9 +302,10 @@ export function createPageFormHelper({
|
|
|
298
302
|
) => {
|
|
299
303
|
props = mapProps(props)
|
|
300
304
|
if (readonly) {
|
|
301
|
-
|
|
305
|
+
console.warn(`[file] 原则上此组建不应该显示在详情中`)
|
|
306
|
+
if (fileList.value.length === 0) return
|
|
302
307
|
return (
|
|
303
|
-
<NFlex gap="8"
|
|
308
|
+
<NFlex gap="8" vertical>
|
|
304
309
|
{modelValue.map(it => (
|
|
305
310
|
<a
|
|
306
311
|
key={it.id}
|
|
@@ -318,11 +323,97 @@ export function createPageFormHelper({
|
|
|
318
323
|
return h(SimpleUpload, {
|
|
319
324
|
...props,
|
|
320
325
|
...params,
|
|
326
|
+
defaultUpload: false,
|
|
327
|
+
uploadFile,
|
|
321
328
|
fileList: modelValue,
|
|
322
329
|
onUpdateFileList: onUpdateValue,
|
|
323
330
|
}, slots)
|
|
324
331
|
}
|
|
325
332
|
},
|
|
333
|
+
upload: () => {
|
|
334
|
+
let lastModelValue = null
|
|
335
|
+
const idMap = new Map()
|
|
336
|
+
const fileMap = new Map()
|
|
337
|
+
const fileList = shallowRef([])
|
|
338
|
+
let key = 0
|
|
339
|
+
|
|
340
|
+
const update = (ids) => {
|
|
341
|
+
const key0 = ++key
|
|
342
|
+
fileList.value = ids.map(id => fileMap.get(id)).filter(Boolean)
|
|
343
|
+
const ids0 = ids.filter(id => !fileMap.has(id))
|
|
344
|
+
Promise.resolve(ids0.length > 0 ? getFileInfos(ids0) : [])
|
|
345
|
+
.then((res) => {
|
|
346
|
+
if (key0 !== key) return
|
|
347
|
+
fileList.value = ids.map(id => fileMap.get(id) || res.find(it => it.id === id))
|
|
348
|
+
fileMap.clear()
|
|
349
|
+
for (const it of fileList.value) {
|
|
350
|
+
fileMap.set(it.id, it)
|
|
351
|
+
}
|
|
352
|
+
})
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
let inst
|
|
356
|
+
const renderer = (
|
|
357
|
+
{ slots, props },
|
|
358
|
+
{ modelValue, 'onUpdate:modelValue': onUpdateValue, required, readonly, ...params },
|
|
359
|
+
) => {
|
|
360
|
+
const props0 = mapProps(props)
|
|
361
|
+
inst = (props0.ref ??= shallowRef())
|
|
362
|
+
if (lastModelValue !== modelValue) {
|
|
363
|
+
lastModelValue = modelValue
|
|
364
|
+
update(modelValue?.split(',') ?? [])
|
|
365
|
+
}
|
|
366
|
+
if (readonly) {
|
|
367
|
+
if (fileList.value.length === 0) return
|
|
368
|
+
return (
|
|
369
|
+
<NFlex gap="8" vertical>
|
|
370
|
+
{fileList.value.map(it => (
|
|
371
|
+
<a
|
|
372
|
+
key={it.id}
|
|
373
|
+
href={it.url}
|
|
374
|
+
target="_blank"
|
|
375
|
+
rel="noreferrer"
|
|
376
|
+
title={it.name}
|
|
377
|
+
style="max-width: 100px; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; display: inline-block"
|
|
378
|
+
>
|
|
379
|
+
{it.name}
|
|
380
|
+
</a>
|
|
381
|
+
))}
|
|
382
|
+
</NFlex>
|
|
383
|
+
)
|
|
384
|
+
}
|
|
385
|
+
return h(SimpleUpload, {
|
|
386
|
+
...props0,
|
|
387
|
+
...params,
|
|
388
|
+
uploadFile,
|
|
389
|
+
fileList: fileList.value,
|
|
390
|
+
onUpdateFileList: (fileList0 = []) => {
|
|
391
|
+
fileMap.clear()
|
|
392
|
+
for (const f of fileList0) {
|
|
393
|
+
if (f.file.fileId) {
|
|
394
|
+
idMap.set(f.id, f.file.fileId)
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
if (f.file.fileId) fileMap.set(f.file.fileId, f)
|
|
398
|
+
else fileMap.set(f.id, f)
|
|
399
|
+
}
|
|
400
|
+
fileList.value = fileList0
|
|
401
|
+
const ids = fileList.value.map(f => idMap.get(f.id) || f.id).join(',') || null
|
|
402
|
+
onUpdateValue(ids)
|
|
403
|
+
},
|
|
404
|
+
}, slots)
|
|
405
|
+
}
|
|
406
|
+
return {
|
|
407
|
+
renderer,
|
|
408
|
+
beforeSubmit: async () => {
|
|
409
|
+
await inst?.submit()
|
|
410
|
+
await until(fileList).toMatch(list => list.every(file => !['pending', 'uploading'].includes(file.status)))
|
|
411
|
+
if (fileList.value.some(file => file.status === 'error')) {
|
|
412
|
+
return SimpleUpload.t('common.page.form.validate.fileErrorMessage')
|
|
413
|
+
}
|
|
414
|
+
},
|
|
415
|
+
}
|
|
416
|
+
},
|
|
326
417
|
user: () => {
|
|
327
418
|
let users, groups, depts
|
|
328
419
|
return (
|
|
@@ -555,7 +646,7 @@ export function createModalHelper() {
|
|
|
555
646
|
const footer0 = footer
|
|
556
647
|
? () => footer
|
|
557
648
|
: footer === null
|
|
558
|
-
?
|
|
649
|
+
? null
|
|
559
650
|
: () => (
|
|
560
651
|
<NFlex justify="end" gap="16">
|
|
561
652
|
{cancelText === null ? undefined : <NButton onClick={onCancel} disabled={cancelDisabled} loading={cancelLoading} style="min-width: 60px">{cancelText}</NButton>}
|
|
@@ -598,6 +689,7 @@ export function createModalHelper() {
|
|
|
598
689
|
)
|
|
599
690
|
}
|
|
600
691
|
|
|
692
|
+
const { bodyContentClass, bodyContentStyle, ...options2 } = options
|
|
601
693
|
return (
|
|
602
694
|
<NDrawer
|
|
603
695
|
show={visible}
|
|
@@ -613,9 +705,14 @@ export function createModalHelper() {
|
|
|
613
705
|
onAfterEnter={onAfterOpen}
|
|
614
706
|
onAfterLeave={onAfterClose}
|
|
615
707
|
style={style}
|
|
616
|
-
{...
|
|
708
|
+
{...options2}
|
|
617
709
|
>
|
|
618
|
-
<NDrawerContent
|
|
710
|
+
<NDrawerContent
|
|
711
|
+
closable={closable}
|
|
712
|
+
nativeScrollbar={nativeScrollbar ?? false}
|
|
713
|
+
bodyContentClass={bodyContentClass}
|
|
714
|
+
bodyContentStyle={bodyContentStyle}
|
|
715
|
+
>
|
|
619
716
|
{{
|
|
620
717
|
default: () => content,
|
|
621
718
|
header: () => title,
|