v-nuxt-ui 0.2.25 → 0.2.27

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 (96) hide show
  1. package/README.md +6 -0
  2. package/dist/module.json +1 -1
  3. package/dist/runtime/components/AsyncSelect.vue +16 -1
  4. package/dist/runtime/components/AsyncTreeSelect.vue +15 -9
  5. package/dist/runtime/components/DeleteModal.d.vue.ts +25 -22
  6. package/dist/runtime/components/DeleteModal.vue +39 -4
  7. package/dist/runtime/components/DeleteModal.vue.d.ts +25 -22
  8. package/dist/runtime/components/ScrollArea.vue +20 -9
  9. package/dist/runtime/components/form/save-modal-template/ConfirmUpdateModal.d.vue.ts +19 -0
  10. package/dist/runtime/components/form/save-modal-template/ConfirmUpdateModal.vue +111 -0
  11. package/dist/runtime/components/form/save-modal-template/ConfirmUpdateModal.vue.d.ts +19 -0
  12. package/dist/runtime/components/form/{create-modal-template → save-modal-template}/WithApi.d.vue.ts +2 -2
  13. package/dist/runtime/components/form/{create-modal-template → save-modal-template}/WithApi.vue +4 -3
  14. package/dist/runtime/components/form/{create-modal-template → save-modal-template}/WithApi.vue.d.ts +2 -2
  15. package/dist/runtime/components/form/{create-modal-template → save-modal-template}/index.d.vue.ts +2 -2
  16. package/dist/runtime/components/form/{create-modal-template → save-modal-template}/index.vue +54 -7
  17. package/dist/runtime/components/form/{create-modal-template → save-modal-template}/index.vue.d.ts +2 -2
  18. package/dist/runtime/components/form/save-model-template/ConfirmUpdateModal.d.vue.ts +19 -0
  19. package/dist/runtime/components/form/save-model-template/ConfirmUpdateModal.vue +111 -0
  20. package/dist/runtime/components/form/save-model-template/ConfirmUpdateModal.vue.d.ts +19 -0
  21. package/dist/runtime/components/form/save-model-template/WithApi.d.vue.ts +19 -0
  22. package/dist/runtime/components/form/save-model-template/WithApi.vue +37 -0
  23. package/dist/runtime/components/form/save-model-template/WithApi.vue.d.ts +19 -0
  24. package/dist/runtime/components/form/save-model-template/index.d.vue.ts +21 -0
  25. package/dist/runtime/components/form/save-model-template/index.vue +123 -0
  26. package/dist/runtime/components/form/save-model-template/index.vue.d.ts +21 -0
  27. package/dist/runtime/components/layout/button/UserMenu.vue +1 -2
  28. package/dist/runtime/components/sys/company/{CreateModal.vue → SaveModal.vue} +2 -2
  29. package/dist/runtime/components/sys/company/Table.vue +5 -4
  30. package/dist/runtime/components/sys/department/{CreateModal.vue → SaveModal.vue} +3 -2
  31. package/dist/runtime/components/sys/department/Table.vue +6 -5
  32. package/dist/runtime/components/sys/flow/EditNodeModal.vue +4 -3
  33. package/dist/runtime/components/sys/flow/{CreateModal.vue → SaveModal.vue} +3 -2
  34. package/dist/runtime/components/sys/flow/Table.vue +5 -4
  35. package/dist/runtime/components/sys/issue-record/{CreateModal.vue → SaveModal.vue} +2 -2
  36. package/dist/runtime/components/sys/issue-record/Table.vue +5 -4
  37. package/dist/runtime/components/sys/job-title/{CreateModal.vue → SaveModal.vue} +2 -2
  38. package/dist/runtime/components/sys/job-title/Table.vue +5 -4
  39. package/dist/runtime/components/sys/menu/{CreateModal.vue → SaveModal.vue} +3 -2
  40. package/dist/runtime/components/sys/menu/Table.vue +6 -5
  41. package/dist/runtime/components/sys/role/{CreateModal.vue → SaveModal.vue} +8 -5
  42. package/dist/runtime/components/sys/role/Table.vue +5 -4
  43. package/dist/runtime/components/sys/table/{CreateModal.vue → SaveModal.vue} +4 -3
  44. package/dist/runtime/components/sys/table/Table.vue +4 -4
  45. package/dist/runtime/components/sys/table/TableColumnModal.vue +4 -3
  46. package/dist/runtime/components/sys/user/{CreateModal.vue → SaveModal.vue} +4 -3
  47. package/dist/runtime/components/sys/user/Table.vue +7 -6
  48. package/dist/runtime/components/table/Page.vue +2 -1
  49. package/dist/runtime/components/table/UpdateDiffModal.d.vue.ts +14 -0
  50. package/dist/runtime/components/table/UpdateDiffModal.vue +156 -0
  51. package/dist/runtime/components/table/UpdateDiffModal.vue.d.ts +14 -0
  52. package/dist/runtime/components/table/header/index.vue +181 -183
  53. package/dist/runtime/components/table/index.vue +2 -1
  54. package/dist/runtime/composables/form/index.d.ts +2 -0
  55. package/dist/runtime/composables/form/index.js +2 -0
  56. package/dist/runtime/composables/form/useForm.d.ts +21 -0
  57. package/dist/runtime/composables/{useForm.js → form/useForm.js} +23 -1
  58. package/dist/runtime/composables/form/useFormUpdate.d.ts +6 -0
  59. package/dist/runtime/composables/form/useFormUpdate.js +101 -0
  60. package/dist/runtime/composables/index.d.ts +1 -1
  61. package/dist/runtime/composables/index.js +1 -1
  62. package/dist/runtime/composables/table/useTable.js +10 -1
  63. package/dist/runtime/composables/table/useTableRowActions.d.ts +3 -0
  64. package/dist/runtime/composables/table/useTableRowActions.js +24 -0
  65. package/dist/runtime/composables/useDate.js +2 -0
  66. package/dist/runtime/types/components/form/field.d.ts +2 -0
  67. package/dist/runtime/types/components/form/index.d.ts +4 -3
  68. package/dist/runtime/types/components/table/header.d.ts +2 -0
  69. package/dist/runtime/types/components/table/index.d.ts +1 -0
  70. package/dist/runtime/types/time.d.ts +1 -1
  71. package/dist/runtime/utils/cron.d.ts +1 -0
  72. package/dist/runtime/utils/cron.js +182 -0
  73. package/dist/runtime/utils/index.d.ts +1 -0
  74. package/dist/runtime/utils/index.js +1 -0
  75. package/dist/runtime/utils/vueuse.d.ts +1 -1
  76. package/dist/runtime/utils/vueuse.js +1 -0
  77. package/package.json +16 -15
  78. package/dist/runtime/composables/useForm.d.ts +0 -9
  79. /package/dist/runtime/components/sys/company/{CreateModal.d.vue.ts → SaveModal.d.vue.ts} +0 -0
  80. /package/dist/runtime/components/sys/company/{CreateModal.vue.d.ts → SaveModal.vue.d.ts} +0 -0
  81. /package/dist/runtime/components/sys/department/{CreateModal.d.vue.ts → SaveModal.d.vue.ts} +0 -0
  82. /package/dist/runtime/components/sys/department/{CreateModal.vue.d.ts → SaveModal.vue.d.ts} +0 -0
  83. /package/dist/runtime/components/sys/flow/{CreateModal.d.vue.ts → SaveModal.d.vue.ts} +0 -0
  84. /package/dist/runtime/components/sys/flow/{CreateModal.vue.d.ts → SaveModal.vue.d.ts} +0 -0
  85. /package/dist/runtime/components/sys/issue-record/{CreateModal.d.vue.ts → SaveModal.d.vue.ts} +0 -0
  86. /package/dist/runtime/components/sys/issue-record/{CreateModal.vue.d.ts → SaveModal.vue.d.ts} +0 -0
  87. /package/dist/runtime/components/sys/job-title/{CreateModal.d.vue.ts → SaveModal.d.vue.ts} +0 -0
  88. /package/dist/runtime/components/sys/job-title/{CreateModal.vue.d.ts → SaveModal.vue.d.ts} +0 -0
  89. /package/dist/runtime/components/sys/menu/{CreateModal.d.vue.ts → SaveModal.d.vue.ts} +0 -0
  90. /package/dist/runtime/components/sys/menu/{CreateModal.vue.d.ts → SaveModal.vue.d.ts} +0 -0
  91. /package/dist/runtime/components/sys/role/{CreateModal.d.vue.ts → SaveModal.d.vue.ts} +0 -0
  92. /package/dist/runtime/components/sys/role/{CreateModal.vue.d.ts → SaveModal.vue.d.ts} +0 -0
  93. /package/dist/runtime/components/sys/table/{CreateModal.d.vue.ts → SaveModal.d.vue.ts} +0 -0
  94. /package/dist/runtime/components/sys/table/{CreateModal.vue.d.ts → SaveModal.vue.d.ts} +0 -0
  95. /package/dist/runtime/components/sys/user/{CreateModal.d.vue.ts → SaveModal.d.vue.ts} +0 -0
  96. /package/dist/runtime/components/sys/user/{CreateModal.vue.d.ts → SaveModal.vue.d.ts} +0 -0
@@ -1,5 +1,5 @@
1
1
  <script setup>
2
- import { computed, h } from "vue";
2
+ import { markRaw } from "vue";
3
3
  import { defu } from "defu";
4
4
  import { useOverlay } from "@nuxt/ui/composables";
5
5
  import UButton from "@nuxt/ui/components/Button.vue";
@@ -21,6 +21,8 @@ const props = defineProps({
21
21
  fetchList: { type: Function, required: true },
22
22
  onEditRowFromModal: { type: Function, required: false },
23
23
  selectedIds: { type: Array, required: false },
24
+ selectedModels: { type: Array, required: false },
25
+ displayFnInDeleteModal: { type: Function, required: false },
24
26
  disableCreation: { type: Boolean, required: false },
25
27
  disableWhereQuery: { type: Boolean, required: false },
26
28
  whereQueryProps: { type: Object, required: true },
@@ -36,190 +38,186 @@ const props = defineProps({
36
38
  });
37
39
  const defaultNewRow = { id: 0 };
38
40
  const overlay = useOverlay();
39
- const deleteModal = overlay.create(DeleteModal);
40
- const settingsModal = overlay.create(TableHeaderSettings);
41
- const excelExportModal = overlay.create(TableExcelExportModal);
42
- const oprButtons = computed(() => {
43
- const defaultButtons = props.oprOrder.map((opr) => {
44
- switch (opr) {
45
- case "create":
46
- if (props.disableCreation) return null;
47
- return h(
48
- UButton,
49
- {
50
- icon: "i-lucide-plus",
51
- size: props.size,
52
- onClick: async () => {
53
- const result = await props.onEditRowFromModal?.(props.onNew?.() ?? defaultNewRow);
54
- if (result) {
55
- props.fetchList();
56
- }
57
- }
58
- },
59
- () => "\u65B0\u589E"
60
- );
61
- case "refresh":
62
- return h(
63
- UButton,
64
- {
65
- icon: "i-lucide-refresh-ccw",
66
- size: props.size,
67
- color: "neutral",
68
- loading: props.fetching,
69
- variant: "outline",
70
- onClick: () => props.fetchList()
71
- },
72
- () => "\u5237\u65B0"
73
- );
74
- case "whereQuery":
75
- if (props.disableWhereQuery) return null;
76
- return h(
77
- UChip,
78
- { show: !props.whereQueryProps.isWhereQueryValueEmpty },
79
- () => h(
80
- UButton,
81
- {
82
- icon: "i-lucide-list-filter",
83
- size: props.size,
84
- color: props.whereQueryProps.whereQueryOpen ? "primary" : "neutral",
85
- loading: props.fetching,
86
- variant: "outline",
87
- onClick: () => {
88
- props.whereQueryProps.onUpdateWhereQueryOpen?.(!props.whereQueryProps.whereQueryOpen);
89
- }
90
- },
91
- () => "\u67E5\u8BE2"
92
- )
93
- );
94
- case "orderQuery":
95
- if (props.disableOrderQuery) return null;
96
- return h(
97
- TableQueryOrder,
98
- { ...props.orderQueryProps, size: props.size }
99
- );
100
- case "settings":
101
- if (props.disableSettings) return null;
102
- return props.rawBizColumns && props.rawBizColumns.length > 0 && props.onUpdateBizColumns && h(
103
- UButton,
104
- {
105
- icon: "i-lucide-settings",
106
- size: props.size,
107
- color: "neutral",
108
- variant: "outline",
109
- onClick: async () => {
110
- if (!props.onUpdateBizColumns) return;
111
- const updateFn = props.onUpdateBizColumns;
112
- await settingsModal.open({
113
- tblName: props.name,
114
- rawBizColumns: props.rawBizColumns,
115
- // 列数据由父组件创建(VColumn<T>),模态框仅重排顺序后返回,运行时类型不变
116
- onUpdateBizColumns: ((cols) => updateFn(cols))
117
- });
118
- }
119
- },
120
- () => "\u8BBE\u7F6E"
121
- );
122
- case "exportExcel": {
123
- if (!props.exportExcel) return null;
124
- const exportButton = h(
125
- UButton,
126
- {
127
- icon: "i-lucide-sheet",
128
- size: props.size,
129
- color: "neutral",
130
- variant: "outline",
131
- onClick: async () => {
132
- await excelExportModal.open({
133
- columns: props.rawBizColumns,
134
- filename: props.exportExcel.filename,
135
- filenameWithDateTime: props.exportExcel.filenameWithDateTime,
136
- listFn: props.apiGroup?.().countAndList,
137
- whereQueryOptions: props.whereQueryProps.whereOptions,
138
- extraWhereQueryInitValues: defu(props.extraWhereQueryInitValues, props.exportExcel.extraWhereQueryInitValues)
139
- });
140
- }
141
- },
142
- () => "\u5BFC\u51FA"
143
- );
144
- if (!props.exportExcel.permissionKey) {
145
- return exportButton;
146
- }
147
- return h(PermissionWrapper, { permission: props.exportExcel.permissionKey }, {
148
- default: () => exportButton
149
- });
150
- }
151
- case "batchDelete":
152
- if (props.disableBatchDeletion) return null;
153
- return props.selectedIds && props.selectedIds.length > 0 && h(
154
- UButton,
155
- {
156
- icon: "i-lucide-trash-2",
157
- size: props.size,
158
- color: "error",
159
- variant: "outline",
160
- onClick: async () => {
161
- const result = await deleteModal.open({
162
- ids: props.selectedIds,
163
- onDelete: (ids) => props.apiGroup?.().batchDelete({ ids })
164
- }).result;
165
- if (result) {
166
- await props.fetchList();
167
- }
168
- }
169
- },
170
- {
171
- default: () => "\u6279\u91CF\u5220\u9664",
172
- trailing: () => h(UKbd, { size: "sm" }, () => props.selectedIds?.length ?? 0)
173
- }
174
- );
175
- default:
176
- return null;
177
- }
41
+ const deleteModal = markRaw(overlay.create(DeleteModal));
42
+ const settingsModal = markRaw(overlay.create(TableHeaderSettings));
43
+ const excelExportModal = markRaw(overlay.create(TableExcelExportModal));
44
+ function omitOnClick(button) {
45
+ const { onClick: _, ...rest } = button;
46
+ return rest;
47
+ }
48
+ async function handleCreate() {
49
+ const result = await props.onEditRowFromModal?.(props.onNew?.() ?? defaultNewRow);
50
+ if (result) {
51
+ props.fetchList();
52
+ }
53
+ }
54
+ async function handleSettings() {
55
+ if (!props.onUpdateBizColumns) return;
56
+ const updateFn = props.onUpdateBizColumns;
57
+ await settingsModal.open({
58
+ tblName: props.name,
59
+ rawBizColumns: props.rawBizColumns,
60
+ onUpdateBizColumns: ((cols) => updateFn(cols))
178
61
  });
179
- const buttons = [
180
- ...props.extraButtons?.filter((btn) => btn.appendTo === "left")?.filter((btn) => btn.withBatchData ? props.selectedIds && props.selectedIds.length > 0 : true).map((btn) => h(
181
- UButton,
182
- {
183
- ...btn.button,
184
- onClick: async (e) => {
185
- if (btn.withBatchData && props.selectedIds && btn.batchFn) {
186
- await btn.batchFn(props.selectedIds);
187
- await props.fetchList();
188
- }
189
- if (Array.isArray(btn.button.onClick)) {
190
- btn.button.onClick.forEach((fn) => fn?.(e));
191
- } else {
192
- btn.button.onClick?.(e);
193
- }
194
- }
195
- }
196
- )) ?? [],
197
- ...defaultButtons,
198
- ...props.extraButtons?.filter((btn) => btn.appendTo === "right")?.filter((btn) => btn.withBatchData ? props.selectedIds && props.selectedIds.length > 0 : true).map((btn) => h(
199
- UButton,
200
- {
201
- ...btn.button,
202
- onClick: async (e) => {
203
- if (btn.withBatchData && props.selectedIds && btn.batchFn) {
204
- await btn.batchFn(props.selectedIds);
205
- }
206
- if (Array.isArray(btn.button.onClick)) {
207
- btn.button.onClick.forEach((fn) => fn?.(e));
208
- } else {
209
- btn.button.onClick?.(e);
210
- }
211
- }
212
- }
213
- )) ?? []
214
- ];
215
- return h(
216
- "div",
217
- { class: "flex flex-wrap items-center gap-3" },
218
- buttons
219
- );
220
- });
62
+ }
63
+ async function handleExportExcel() {
64
+ await excelExportModal.open({
65
+ columns: props.rawBizColumns,
66
+ filename: props.exportExcel.filename,
67
+ filenameWithDateTime: props.exportExcel.filenameWithDateTime,
68
+ listFn: props.apiGroup?.().countAndList,
69
+ whereQueryOptions: props.whereQueryProps.whereOptions,
70
+ extraWhereQueryInitValues: defu(props.extraWhereQueryInitValues, props.exportExcel.extraWhereQueryInitValues)
71
+ });
72
+ }
73
+ async function handleBatchDelete() {
74
+ const result = await deleteModal.open({
75
+ ids: props.selectedIds,
76
+ models: props.selectedModels,
77
+ displayFn: props.displayFnInDeleteModal,
78
+ onDelete: (ids) => props.apiGroup?.().batchDelete({ ids })
79
+ }).result;
80
+ if (result) {
81
+ await props.fetchList();
82
+ }
83
+ }
84
+ async function onLeftExtraButtonClick(btn, e) {
85
+ if (btn.withBatchData && props.selectedIds && btn.batchFn) {
86
+ await btn.batchFn(props.selectedIds);
87
+ await props.fetchList();
88
+ }
89
+ const originalOnClick = btn.button.onClick;
90
+ if (Array.isArray(originalOnClick)) {
91
+ originalOnClick.forEach((fn) => fn?.(e));
92
+ } else {
93
+ originalOnClick?.(e);
94
+ }
95
+ }
96
+ async function onRightExtraButtonClick(btn, e) {
97
+ if (btn.withBatchData && props.selectedIds && btn.batchFn) {
98
+ await btn.batchFn(props.selectedIds);
99
+ }
100
+ const originalOnClick = btn.button.onClick;
101
+ if (Array.isArray(originalOnClick)) {
102
+ originalOnClick.forEach((fn) => fn?.(e));
103
+ } else {
104
+ originalOnClick?.(e);
105
+ }
106
+ }
221
107
  </script>
222
108
 
223
109
  <template>
224
- <component :is="oprButtons" />
110
+ <div class="flex flex-wrap items-center gap-3">
111
+ <template v-for="(btn, i) in extraButtons" :key="`extra-left-${i}`">
112
+ <UButton
113
+ v-if="(!btn.withBatchData || selectedIds?.length) && btn.appendTo === 'left'"
114
+ v-bind="omitOnClick(btn.button)"
115
+ @click="(e) => onLeftExtraButtonClick(btn, e)"
116
+ />
117
+ </template>
118
+
119
+ <template v-for="opr in oprOrder" :key="opr">
120
+ <UButton
121
+ v-if="opr === 'create' && !disableCreation"
122
+ icon="i-lucide-plus"
123
+ :size="size"
124
+ @click="handleCreate"
125
+ >
126
+ 新增
127
+ </UButton>
128
+
129
+ <UButton
130
+ v-if="opr === 'refresh'"
131
+ icon="i-lucide-refresh-ccw"
132
+ :size="size"
133
+ color="neutral"
134
+ :loading="fetching"
135
+ variant="outline"
136
+ @click="fetchList"
137
+ >
138
+ 刷新
139
+ </UButton>
140
+
141
+ <UChip
142
+ v-if="opr === 'whereQuery' && !disableWhereQuery"
143
+ :show="!whereQueryProps.isWhereQueryValueEmpty"
144
+ >
145
+ <UButton
146
+ icon="i-lucide-list-filter"
147
+ :size="size"
148
+ :color="whereQueryProps.whereQueryOpen ? 'primary' : 'neutral'"
149
+ :loading="fetching"
150
+ variant="outline"
151
+ @click="whereQueryProps.onUpdateWhereQueryOpen?.(!whereQueryProps.whereQueryOpen)"
152
+ >
153
+ 查询
154
+ </UButton>
155
+ </UChip>
156
+
157
+ <TableQueryOrder
158
+ v-if="opr === 'orderQuery' && !disableOrderQuery"
159
+ v-bind="orderQueryProps"
160
+ :size="size"
161
+ />
162
+
163
+ <UButton
164
+ v-if="opr === 'settings' && !disableSettings && rawBizColumns?.length && onUpdateBizColumns"
165
+ icon="i-lucide-settings"
166
+ :size="size"
167
+ color="neutral"
168
+ variant="outline"
169
+ @click="handleSettings"
170
+ >
171
+ 设置
172
+ </UButton>
173
+
174
+ <template v-if="opr === 'exportExcel' && exportExcel">
175
+ <PermissionWrapper v-if="exportExcel.permissionKey" :permission="exportExcel.permissionKey">
176
+ <UButton
177
+ icon="i-lucide-sheet"
178
+ :size="size"
179
+ color="neutral"
180
+ variant="outline"
181
+ @click="handleExportExcel"
182
+ >
183
+ 导出
184
+ </UButton>
185
+ </PermissionWrapper>
186
+ <UButton
187
+ v-else
188
+ icon="i-lucide-sheet"
189
+ :size="size"
190
+ color="neutral"
191
+ variant="outline"
192
+ @click="handleExportExcel"
193
+ >
194
+ 导出
195
+ </UButton>
196
+ </template>
197
+
198
+ <UButton
199
+ v-if="opr === 'batchDelete' && !disableBatchDeletion && selectedIds?.length"
200
+ icon="i-lucide-trash-2"
201
+ :size="size"
202
+ color="error"
203
+ variant="outline"
204
+ @click="handleBatchDelete"
205
+ >
206
+ 批量删除
207
+ <template #trailing>
208
+ <UKbd size="sm">
209
+ {{ selectedIds?.length ?? 0 }}
210
+ </UKbd>
211
+ </template>
212
+ </UButton>
213
+ </template>
214
+
215
+ <template v-for="(btn, i) in extraButtons" :key="`extra-right-${i}`">
216
+ <UButton
217
+ v-if="(!btn.withBatchData || selectedIds?.length) && btn.appendTo === 'right'"
218
+ v-bind="omitOnClick(btn.button)"
219
+ @click="(e) => onRightExtraButtonClick(btn, e)"
220
+ />
221
+ </template>
222
+ </div>
225
223
  </template>
@@ -43,7 +43,8 @@ const props = defineProps({
43
43
  expandable: { type: Boolean, required: false },
44
44
  expandVNode: { type: Function, required: false },
45
45
  rowSpanColumns: { type: Array, required: false },
46
- customRowCopyFn: { type: Function, required: false }
46
+ customRowCopyFn: { type: Function, required: false },
47
+ displayFnInDeleteModal: { type: Function, required: false }
47
48
  });
48
49
  const {
49
50
  // data
@@ -0,0 +1,2 @@
1
+ export * from './useForm.js';
2
+ export * from './useFormUpdate.js';
@@ -0,0 +1,2 @@
1
+ export * from "./useForm.js";
2
+ export * from "./useFormUpdate.js";
@@ -0,0 +1,21 @@
1
+ import { type Ref, type MaybeRefOrGetter } from 'vue';
2
+ import type { ApiGroup, BaseModel, VFormFieldProps } from '#v/types';
3
+ import type { ConfirmDiffItem } from '#v/components/form/save-modal-template/ConfirmUpdateModal.vue';
4
+ export declare const useFormValues: <T>(raw: Ref<T>, defaultValues?: Partial<T>) => {
5
+ oldValues: Ref<T>;
6
+ newValues: Ref<T>;
7
+ };
8
+ export declare const useFormSubmission: <T extends BaseModel>(oldValues: Ref<T>, newValues: Ref<T>, close: (ok: boolean) => void, save: (model: T) => void, apiGroup: () => ApiGroup<T>, arrayTypeFieldKeys?: (keyof T)[], rowKey?: keyof T, versionKey?: keyof T, getExtraFields?: () => Record<string, any>) => {
9
+ onSubmit: () => Promise<void>;
10
+ };
11
+ export declare const useConfirmDiff: (fields: MaybeRefOrGetter<VFormFieldProps[]>, diffItems: MaybeRefOrGetter<ConfirmDiffItem[]>, oldModelValue: MaybeRefOrGetter<Record<string, unknown>>, newModelValue: MaybeRefOrGetter<Record<string, unknown>>) => {
12
+ diffedItems: import("vue").ComputedRef<{
13
+ oldDisplay: string;
14
+ newDisplay: string;
15
+ parts: import("diff").ChangeObject<string>[];
16
+ field: VFormFieldProps | undefined;
17
+ fieldName: string;
18
+ oldValue: unknown;
19
+ newValue: unknown;
20
+ }[]>;
21
+ };
@@ -1,6 +1,7 @@
1
- import { ref, watch } from "vue";
1
+ import { ref, watch, computed, toValue } from "vue";
2
2
  import { defu } from "defu";
3
3
  import { getObjWithModifiedFields } from "#v/utils";
4
+ import { resolveDisplayValue, smartDiff } from "#v/composables";
4
5
  import { useToast } from "@nuxt/ui/composables";
5
6
  export const useFormValues = (raw, defaultValues) => {
6
7
  const oldValues = ref({});
@@ -62,3 +63,24 @@ export const useFormSubmission = (oldValues, newValues, close, save, apiGroup, a
62
63
  }
63
64
  return { onSubmit };
64
65
  };
66
+ export const useConfirmDiff = (fields, diffItems, oldModelValue, newModelValue) => {
67
+ const resolvedItems = computed(
68
+ () => toValue(diffItems).map((item) => ({
69
+ ...item,
70
+ field: toValue(fields).find((f) => f.name === item.fieldName)
71
+ })).filter((item) => item.field != null)
72
+ );
73
+ const diffedItems = computed(
74
+ () => resolvedItems.value.map((item) => {
75
+ const oldDisplay = resolveDisplayValue(item.field, item.oldValue, toValue(oldModelValue));
76
+ const newDisplay = resolveDisplayValue(item.field, item.newValue, toValue(newModelValue));
77
+ return {
78
+ ...item,
79
+ oldDisplay,
80
+ newDisplay,
81
+ parts: smartDiff(oldDisplay, newDisplay)
82
+ };
83
+ })
84
+ );
85
+ return { diffedItems };
86
+ };
@@ -0,0 +1,6 @@
1
+ import type { VFormFieldProps } from '#v/types';
2
+ export declare function resolveSelectLabel(rawVal: unknown, items: readonly any[]): string;
3
+ export declare function resolveDisplayValue(field: VFormFieldProps, rawVal: unknown, modelSource: Record<string, unknown>): string;
4
+ export declare function smartDiff(oldStr: string, newStr: string): import("diff").ChangeObject<string>[];
5
+ export declare const diffEligibleTypes: Set<string>;
6
+ export declare function formatValue(val: unknown): string;
@@ -0,0 +1,101 @@
1
+ import dayjs from "dayjs";
2
+ import { diffWords, diffChars } from "diff";
3
+ import { dateFormat } from "#v/constants";
4
+ export function resolveSelectLabel(rawVal, items) {
5
+ if (Array.isArray(rawVal)) {
6
+ return rawVal.map((v) => items.find((i) => i?.value === v)?.label ?? String(v)).join(", ") || "";
7
+ }
8
+ return items.find((i) => i?.value === rawVal)?.label ?? String(rawVal);
9
+ }
10
+ export function resolveDisplayValue(field, rawVal, modelSource) {
11
+ if (rawVal === null || rawVal === void 0) return "";
12
+ switch (field.type) {
13
+ case "switch":
14
+ case "button-switch":
15
+ return rawVal ? "\u662F" : "\u5426";
16
+ case "date-picker": {
17
+ if (typeof rawVal === "string") {
18
+ const d = dayjs(rawVal);
19
+ if (d.isValid()) return d.format(dateFormat);
20
+ }
21
+ return String(rawVal);
22
+ }
23
+ case "select": {
24
+ const items = field.enableEmptyOption ? [{ label: "\u65E0", value: 0 }, ...field.items ?? []] : field.items ?? [];
25
+ return resolveSelectLabel(rawVal, items);
26
+ }
27
+ case "multiple-select-string":
28
+ case "radio-select":
29
+ return resolveSelectLabel(rawVal, field.items ?? []);
30
+ case "async-select":
31
+ case "async-tree-select":
32
+ case "async-object-select": {
33
+ if (!field.name) return String(rawVal);
34
+ if (rawVal === 0) return "";
35
+ const labelField = field.labelField;
36
+ if (!labelField) return String(rawVal);
37
+ let model;
38
+ for (const v of Object.values(modelSource)) {
39
+ if (v && typeof v === "object" && v[labelField] !== void 0) {
40
+ if (String(v.id) === String(rawVal)) {
41
+ model = v;
42
+ break;
43
+ }
44
+ }
45
+ }
46
+ if (!model) {
47
+ model = field.initModel;
48
+ }
49
+ if (!model) return String(rawVal);
50
+ if (Array.isArray(model)) {
51
+ return model.map((m) => m && typeof m === "object" ? String(m[labelField] ?? "") : String(m)).filter(Boolean).join(", ") || "";
52
+ }
53
+ if (typeof model === "object") {
54
+ const label = model[labelField];
55
+ if (label != null) return String(label);
56
+ }
57
+ return String(rawVal);
58
+ }
59
+ case "input-string-number": {
60
+ const v = rawVal === 0 ? "0" : String(rawVal);
61
+ const trailing = field.trailingString;
62
+ return trailing ? `${v} ${trailing}` : v;
63
+ }
64
+ case "tree-select-transfer": {
65
+ if (Array.isArray(rawVal)) {
66
+ return rawVal.map((item) => {
67
+ if (item && typeof item === "object") {
68
+ const obj = item;
69
+ return String(obj.label ?? obj.name ?? "");
70
+ }
71
+ return String(item);
72
+ }).filter(Boolean).join(", ") || "";
73
+ }
74
+ return formatValue(rawVal);
75
+ }
76
+ default:
77
+ return formatValue(rawVal);
78
+ }
79
+ }
80
+ export function smartDiff(oldStr, newStr) {
81
+ if (!oldStr.includes(" ") && !newStr.includes(" ")) {
82
+ return diffChars(oldStr, newStr);
83
+ }
84
+ return diffWords(oldStr, newStr);
85
+ }
86
+ export const diffEligibleTypes = /* @__PURE__ */ new Set([
87
+ "input",
88
+ "dynamic-input",
89
+ "input-string-number",
90
+ "input-number",
91
+ "textarea",
92
+ "input-pwd",
93
+ "sql-editor",
94
+ "date-picker"
95
+ ]);
96
+ export function formatValue(val) {
97
+ if (val === null || val === void 0) return "";
98
+ if (typeof val === "boolean") return val ? "\u662F" : "\u5426";
99
+ if (typeof val === "object") return JSON.stringify(val);
100
+ return String(val);
101
+ }
@@ -5,7 +5,7 @@ export * from './useApp.js';
5
5
  export * from './useBoolean.js';
6
6
  export * from './useDate.js';
7
7
  export * from './useEChart.js';
8
- export * from './useForm.js';
8
+ export * from './form/index.js';
9
9
  export * from './useTheme.js';
10
10
  export * from './useSidebarMenu.js';
11
11
  export * from './usePermission.js';
@@ -5,7 +5,7 @@ export * from "./useApp.js";
5
5
  export * from "./useBoolean.js";
6
6
  export * from "./useDate.js";
7
7
  export * from "./useEChart.js";
8
- export * from "./useForm.js";
8
+ export * from "./form/index.js";
9
9
  export * from "./useTheme.js";
10
10
  export * from "./useSidebarMenu.js";
11
11
  export * from "./usePermission.js";
@@ -44,7 +44,8 @@ export function useTable(props) {
44
44
  disableRowSelection,
45
45
  expandable,
46
46
  rowSpanColumns,
47
- customRowCopyFn
47
+ customRowCopyFn,
48
+ displayFnInDeleteModal
48
49
  } = props;
49
50
  const queryComposable = useTableQuery({
50
51
  name,
@@ -96,6 +97,9 @@ export function useTable(props) {
96
97
  } = dataComposable;
97
98
  const rowSelectionComposable = useTableRowSelection(data, rowKey);
98
99
  const { rowSelection, selectedIds, clearRowSelection: _clearRowSelection } = rowSelectionComposable;
100
+ const selectedModels = computed(
101
+ () => data.value.filter((row) => selectedIds.value.includes(row[rowKey]))
102
+ );
99
103
  const whereQueryRef = useTemplateRef("proTableQueryWhere");
100
104
  const onFilterClick = (field) => {
101
105
  whereQueryOpen.value = true;
@@ -149,6 +153,8 @@ export function useTable(props) {
149
153
  } = columnsComposable;
150
154
  const rowActionsComposable = useTableRowActions({
151
155
  rowKey,
156
+ tableName: name,
157
+ bizColumns,
152
158
  disableRowActions,
153
159
  disableRowUpdate,
154
160
  disableRowCopy,
@@ -157,6 +163,7 @@ export function useTable(props) {
157
163
  extraRowActions,
158
164
  useApiGroup,
159
165
  customRowCopyFn,
166
+ displayFnInDeleteModal,
160
167
  fetchList
161
168
  });
162
169
  const { getRowActions, generateActionColumn } = rowActionsComposable;
@@ -287,6 +294,8 @@ export function useTable(props) {
287
294
  fetchList,
288
295
  onEditRowFromModal,
289
296
  selectedIds: selectedIds.value,
297
+ selectedModels: selectedModels.value,
298
+ displayFnInDeleteModal,
290
299
  disableCreation,
291
300
  disableWhereQuery,
292
301
  whereQueryProps: tblWhereQueryProps.value,
@@ -2,6 +2,8 @@ import type { VColumn } from '#v/types';
2
2
  import type { DropdownMenuItem, TableRow } from '@nuxt/ui';
3
3
  export declare function useTableRowActions<T>(props: {
4
4
  rowKey: keyof T;
5
+ tableName?: string;
6
+ bizColumns?: VColumn<T>[];
5
7
  disableRowActions?: boolean;
6
8
  disableRowUpdate?: boolean;
7
9
  disableRowCopy?: boolean;
@@ -10,6 +12,7 @@ export declare function useTableRowActions<T>(props: {
10
12
  extraRowActions?: any[];
11
13
  useApiGroup?: (...args: any[]) => any;
12
14
  customRowCopyFn?: (...args: any[]) => any;
15
+ displayFnInDeleteModal?: (model: T) => string | undefined;
13
16
  fetchList: () => Promise<void>;
14
17
  }): {
15
18
  getRowActions: (row: TableRow<T>) => DropdownMenuItem[];