v-nuxt-ui 0.1.32 → 0.1.34

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 (48) hide show
  1. package/dist/module.json +1 -1
  2. package/dist/runtime/assets/css/main.css +1 -1
  3. package/dist/runtime/components/form/create-modal-template/index.d.vue.ts +3 -1
  4. package/dist/runtime/components/form/create-modal-template/index.vue +1 -0
  5. package/dist/runtime/components/form/create-modal-template/index.vue.d.ts +3 -1
  6. package/dist/runtime/components/sys/role/CreateModal.vue +14 -2
  7. package/dist/runtime/components/sys/table/CreateModal.d.vue.ts +13 -0
  8. package/dist/runtime/components/sys/table/CreateModal.vue +239 -0
  9. package/dist/runtime/components/sys/table/CreateModal.vue.d.ts +13 -0
  10. package/dist/runtime/components/sys/table/Table.d.vue.ts +3 -0
  11. package/dist/runtime/components/sys/table/Table.vue +116 -0
  12. package/dist/runtime/components/sys/table/Table.vue.d.ts +3 -0
  13. package/dist/runtime/components/sys/table/TableColumnModal.d.vue.ts +22 -0
  14. package/dist/runtime/components/sys/table/TableColumnModal.vue +107 -0
  15. package/dist/runtime/components/sys/table/TableColumnModal.vue.d.ts +22 -0
  16. package/dist/runtime/components/sys/user/CreateModal.vue +14 -2
  17. package/dist/runtime/components/table/permission/TablePermissionConfig.d.vue.ts +14 -0
  18. package/dist/runtime/components/table/permission/TablePermissionConfig.vue +230 -0
  19. package/dist/runtime/components/table/permission/TablePermissionConfig.vue.d.ts +14 -0
  20. package/dist/runtime/components/table/permission/TablePermissionTab.d.vue.ts +11 -0
  21. package/dist/runtime/components/table/permission/TablePermissionTab.vue +95 -0
  22. package/dist/runtime/components/table/permission/TablePermissionTab.vue.d.ts +11 -0
  23. package/dist/runtime/components/table/settings/TableSettings.d.vue.ts +3 -0
  24. package/dist/runtime/components/table/settings/TableSettings.vue +118 -0
  25. package/dist/runtime/components/table/settings/TableSettings.vue.d.ts +3 -0
  26. package/dist/runtime/components/table/settings/UserTableColumnModal.d.vue.ts +17 -0
  27. package/dist/runtime/components/table/settings/UserTableColumnModal.vue +106 -0
  28. package/dist/runtime/components/table/settings/UserTableColumnModal.vue.d.ts +17 -0
  29. package/dist/runtime/composables/api/sys/index.d.ts +3 -0
  30. package/dist/runtime/composables/api/sys/index.js +3 -0
  31. package/dist/runtime/composables/api/useTableApi.d.ts +2 -0
  32. package/dist/runtime/composables/api/useTableApi.js +5 -0
  33. package/dist/runtime/composables/api/useTableColumnApi.d.ts +11 -0
  34. package/dist/runtime/composables/api/useTableColumnApi.js +11 -0
  35. package/dist/runtime/composables/api/useTablePermissionApi.d.ts +8 -0
  36. package/dist/runtime/composables/api/useTablePermissionApi.js +8 -0
  37. package/dist/runtime/composables/table/useTableColumnPermission.d.ts +34 -0
  38. package/dist/runtime/composables/table/useTableColumnPermission.js +47 -0
  39. package/dist/runtime/composables/useAuth.d.ts +56 -0
  40. package/dist/runtime/composables/useForm.d.ts +1 -1
  41. package/dist/runtime/composables/useForm.js +7 -3
  42. package/dist/runtime/types/cmds/sys.d.ts +3 -0
  43. package/dist/runtime/types/models/index.d.ts +1 -0
  44. package/dist/runtime/types/models/index.js +1 -0
  45. package/dist/runtime/types/models/sys.d.ts +3 -0
  46. package/dist/runtime/types/models/table.d.ts +59 -0
  47. package/dist/runtime/types/models/table.js +0 -0
  48. package/package.json +1 -1
package/dist/module.json CHANGED
@@ -7,7 +7,7 @@
7
7
  "dependencies": [
8
8
  "@nuxt/ui"
9
9
  ],
10
- "version": "0.1.32",
10
+ "version": "0.1.34",
11
11
  "builder": {
12
12
  "@nuxt/module-builder": "1.0.2",
13
13
  "unbuild": "3.6.1"
@@ -1 +1 @@
1
- :root{--ui-header-height:3.5rem;--ui-table-header-height:3rem;--ui-footer-height:3rem}::-webkit-scrollbar{height:.25rem;width:.25rem}::-webkit-scrollbar-thumb{background-color:#e5e7eb;border-radius:9999px}.dark ::-webkit-scrollbar-thumb{background-color:#404040}.dark,:root{--chart-1:var(--ui-color-primary-300);--chart-2:var(--ui-color-primary-500);--chart-3:var(--ui-color-primary-700);--chart-4:var(--ui-color-primary-900)}input[type=number]{-moz-appearance:textfield;-webkit-appearance:textfield;appearance:textfield}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}:focus-visible{outline:none!important}
1
+ :root{--ui-header-height:3.5rem;--ui-table-header-height:3rem;--ui-footer-height:3rem}::-webkit-scrollbar{height:.25rem;width:.25rem}::-webkit-scrollbar-thumb{background-color:#e5e7eb;border-radius:9999px}.dark ::-webkit-scrollbar-thumb{background-color:#404040}input[type=number]{-moz-appearance:textfield;-webkit-appearance:textfield;appearance:textfield}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}:focus-visible{outline:none!important}
@@ -5,7 +5,9 @@ declare const __VLS_export: <T extends BaseModel>(__VLS_props: NonNullable<Await
5
5
  } ? P : {});
6
6
  expose: (exposed: {}) => void;
7
7
  attrs: any;
8
- slots: {};
8
+ slots: {
9
+ 'after-form'?: (props: {}) => any;
10
+ };
9
11
  emit: {};
10
12
  }>) => import("vue").VNode & {
11
13
  __ctx?: Awaited<typeof __VLS_setup>;
@@ -53,6 +53,7 @@ async function onSubmitWithValidation(e) {
53
53
  @trigger-submit="onSubmitWithValidation"
54
54
  @update-model-value="onUpdateModelValue"
55
55
  />
56
+ <slot name="after-form" />
56
57
  </template>
57
58
  <template #footer>
58
59
  <UButton
@@ -5,7 +5,9 @@ declare const __VLS_export: <T extends BaseModel>(__VLS_props: NonNullable<Await
5
5
  } ? P : {});
6
6
  expose: (exposed: {}) => void;
7
7
  attrs: any;
8
- slots: {};
8
+ slots: {
9
+ 'after-form'?: (props: {}) => any;
10
+ };
9
11
  emit: {};
10
12
  }>) => import("vue").VNode & {
11
13
  __ctx?: Awaited<typeof __VLS_setup>;
@@ -1,6 +1,7 @@
1
1
  <script setup>
2
2
  import * as z from "zod";
3
3
  import FormCreateModalTemplate from "#v/components/form/create-modal-template/index.vue";
4
+ import TablePermissionTab from "#v/components/table/permission/TablePermissionTab.vue";
4
5
  import { useFormSubmission, useFormValues, useMenuApi, useRoleApi } from "#v/composables";
5
6
  import { computed, onMounted, ref, toRef } from "vue";
6
7
  import { treeifyOptions } from "#v/utils";
@@ -15,7 +16,10 @@ const { onSubmit } = useFormSubmission(
15
16
  (close) => emit("close", close),
16
17
  (model) => emit("save", model),
17
18
  useRoleApi,
18
- ["menus"]
19
+ ["menus"],
20
+ "id",
21
+ "version",
22
+ () => ({ tablePermissions: tablePermissions.value })
19
23
  );
20
24
  const menus = ref([]);
21
25
  const onFetchMenus = async () => {
@@ -56,6 +60,7 @@ const targetTreeItems = computed({
56
60
  function updateTargetTreeItems(newVal) {
57
61
  targetTreeItems.value = newVal;
58
62
  }
63
+ const tablePermissions = ref(props.model.tablePermissions || []);
59
64
  const fields = computed(() => [
60
65
  { name: "name", type: "input", label: "\u89D2\u8272\u540D\u79F0", colSpan: "12", zodType: z.string().min(2, "\u540D\u79F0\u5B57\u6570\u4E0D\u8DB3") },
61
66
  { name: "isAdmin", type: "button-switch", label: "\u662F\u5426\u662F\u7CFB\u7EDF\u89D2\u8272", colSpan: "12", zodType: z.boolean() },
@@ -88,5 +93,12 @@ onMounted(async () => {
88
93
  :model-value="newValues"
89
94
  @update-model-value="updateModelValue"
90
95
  @submit="onSubmit"
91
- />
96
+ >
97
+ <template #after-form>
98
+ <div class="border-t pt-4 mt-4">
99
+ <div class="font-semibold mb-2">Table 权限</div>
100
+ <TablePermissionTab v-model="tablePermissions" />
101
+ </div>
102
+ </template>
103
+ </FormCreateModalTemplate>
92
104
  </template>
@@ -0,0 +1,13 @@
1
+ import type { Table } from '#v/types';
2
+ type __VLS_Props = {
3
+ model: Table;
4
+ };
5
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
6
+ close: (args_0: boolean) => any;
7
+ save: (args_0: Table) => any;
8
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
9
+ onClose?: ((args_0: boolean) => any) | undefined;
10
+ onSave?: ((args_0: Table) => any) | undefined;
11
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
12
+ declare const _default: typeof __VLS_export;
13
+ export default _default;
@@ -0,0 +1,239 @@
1
+ <script setup>
2
+ import * as z from "zod";
3
+ import { useOverlay } from "@nuxt/ui/composables";
4
+ import FormCreateModalTemplate from "#v/components/form/create-modal-template/index.vue";
5
+ import ProSimpleTable from "#v/components/simple-table/index.vue";
6
+ import TableColumnModal from "./TableColumnModal.vue";
7
+ import { useFormSubmission, useFormValues, useTableApi, useTableColumnApi } from "#v/composables";
8
+ import { computed, ref, toRef, onMounted } from "vue";
9
+ const props = defineProps({
10
+ model: { type: Object, required: true }
11
+ });
12
+ const emit = defineEmits(["close", "save"]);
13
+ const overlay = useOverlay();
14
+ const columnModal = overlay.create(TableColumnModal);
15
+ const { oldValues, newValues } = useFormValues(toRef(props.model), { id: 0 });
16
+ const tableColumnApi = useTableColumnApi();
17
+ const columns = ref([]);
18
+ const deletedColumnIds = ref([]);
19
+ const loading = ref(false);
20
+ async function fetchColumns() {
21
+ if (props.model.id === 0) return;
22
+ loading.value = true;
23
+ const { data } = await tableColumnApi.list({
24
+ pagination: { pageNum: 0, pageSize: 0 },
25
+ orderQuery: [{ field: "order", order: "asc" }],
26
+ whereQuery: {
27
+ items: [{ field: "tableId", value: props.model.id, opr: "eq" }]
28
+ }
29
+ });
30
+ if (data.value.data) {
31
+ columns.value = data.value.data.list.map((col) => ({
32
+ id: col.id,
33
+ columnKey: col.columnKey,
34
+ label: col.label,
35
+ order: col.order,
36
+ width: col.width,
37
+ fixed: col.fixed,
38
+ visible: col.visible
39
+ }));
40
+ }
41
+ loading.value = false;
42
+ }
43
+ onMounted(fetchColumns);
44
+ function addColumn() {
45
+ const maxOrder = columns.value.reduce((max, col) => Math.max(max, col.order ?? 0), 0);
46
+ columns.value.push({
47
+ id: 0,
48
+ columnKey: "",
49
+ label: "",
50
+ order: maxOrder + 1,
51
+ width: 100,
52
+ fixed: "",
53
+ visible: true,
54
+ _isDirty: true
55
+ });
56
+ }
57
+ function removeColumn(index) {
58
+ const col = columns.value[index];
59
+ if (col.id !== 0) {
60
+ deletedColumnIds.value.push(col.id);
61
+ }
62
+ columns.value.splice(index, 1);
63
+ }
64
+ async function editColumn(index) {
65
+ const col = columns.value[index];
66
+ const isNew = col.id === 0;
67
+ if (isNew) {
68
+ return;
69
+ }
70
+ const result = await columnModal.open({ table: props.model, column: col }).result;
71
+ if (result) {
72
+ const updatedCol = result;
73
+ columns.value[index] = { ...updatedCol, _isDirty: true };
74
+ }
75
+ }
76
+ const tableColumns = [
77
+ {
78
+ accessorKey: "columnKey",
79
+ header: "\u5217\u6807\u8BC6",
80
+ size: 120
81
+ },
82
+ {
83
+ accessorKey: "label",
84
+ header: "\u663E\u793A\u540D",
85
+ size: 120
86
+ },
87
+ {
88
+ accessorKey: "order",
89
+ header: "\u987A\u5E8F",
90
+ size: 80
91
+ },
92
+ {
93
+ accessorKey: "width",
94
+ header: "\u5BBD\u5EA6",
95
+ size: 80
96
+ },
97
+ {
98
+ accessorKey: "fixed",
99
+ header: "\u56FA\u5B9A",
100
+ size: 80,
101
+ cell: ({ row }) => {
102
+ const fixedMap = { "": "\u5426", left: "\u5DE6", right: "\u53F3" };
103
+ return fixedMap[row.fixed] ?? "\u5426";
104
+ }
105
+ },
106
+ {
107
+ accessorKey: "visible",
108
+ header: "\u663E\u793A",
109
+ size: 60,
110
+ cell: ({ row }) => row.visible ? "\u662F" : "\u5426"
111
+ },
112
+ {
113
+ accessorKey: "actions",
114
+ header: "\u64CD\u4F5C",
115
+ size: 100,
116
+ cell: ({ row, index }) => {
117
+ return {
118
+ type: "div",
119
+ class: "flex gap-1",
120
+ children: [
121
+ {
122
+ type: "button",
123
+ label: "\u7F16\u8F91",
124
+ icon: "i-lucide-edit",
125
+ variant: "ghost",
126
+ size: "xs",
127
+ onClick: () => editColumn(index)
128
+ },
129
+ {
130
+ type: "button",
131
+ label: "\u5220\u9664",
132
+ icon: "i-lucide-trash-2",
133
+ color: "error",
134
+ variant: "ghost",
135
+ size: "xs",
136
+ onClick: () => removeColumn(index)
137
+ }
138
+ ]
139
+ };
140
+ }
141
+ }
142
+ ];
143
+ const { onSubmit } = useFormSubmission(
144
+ toRef(oldValues),
145
+ toRef(newValues),
146
+ (close) => emit("close", close),
147
+ async (model) => {
148
+ const tableApi = useTableApi();
149
+ if (model.id === 0) {
150
+ const { data } = await tableApi.create(model);
151
+ const newTable = data.value?.data;
152
+ if (newTable && columns.value.length > 0) {
153
+ for (const col of columns.value) {
154
+ await tableColumnApi.create({
155
+ ...col,
156
+ tableId: newTable.id
157
+ });
158
+ }
159
+ }
160
+ emit("save", newTable);
161
+ } else {
162
+ for (const col of columns.value) {
163
+ if (col._isDirty) {
164
+ const colData = {
165
+ id: col.id,
166
+ tableId: props.model.id,
167
+ columnKey: col.columnKey,
168
+ label: col.label,
169
+ order: col.order,
170
+ width: col.width,
171
+ fixed: col.fixed,
172
+ visible: col.visible
173
+ };
174
+ if (col.id === 0) {
175
+ await tableColumnApi.create(tableColumnApi.prune(colData));
176
+ } else {
177
+ await tableColumnApi.update(tableColumnApi.prune(colData));
178
+ }
179
+ }
180
+ }
181
+ for (const id of deletedColumnIds.value) {
182
+ await tableColumnApi.deleteById(id);
183
+ }
184
+ emit("save", model);
185
+ }
186
+ },
187
+ useTableApi
188
+ );
189
+ const fields = computed(() => [
190
+ { name: "tblName", type: "input", label: "\u8868\u540D", colSpan: "12", zodType: z.string().min(1, "\u8868\u540D\u4E0D\u80FD\u4E3A\u7A7A") },
191
+ { name: "label", type: "input", label: "\u663E\u793A\u540D", colSpan: "12", zodType: z.string().min(1, "\u663E\u793A\u540D\u4E0D\u80FD\u4E3A\u7A7A") },
192
+ { name: "labelI18nKey", type: "input", label: "i18n Key", colSpan: "24", zodType: z.string().optional().nullable() }
193
+ ]);
194
+ function updateModelValue(newVal) {
195
+ newValues.value = { id: 0, ...newVal };
196
+ }
197
+ </script>
198
+
199
+ <template>
200
+ <FormCreateModalTemplate
201
+ title="Table"
202
+ :on-close="(ok) => emit('close', ok)"
203
+ :fields="fields"
204
+ :model-value="newValues"
205
+ @update-model-value="updateModelValue"
206
+ @submit="onSubmit"
207
+ >
208
+ <template #after-form>
209
+ <div class="border-t pt-4 mt-4">
210
+ <div class="flex items-center justify-between mb-2">
211
+ <div>
212
+ <div class="font-semibold">列配置</div>
213
+ <div class="text-sm text-dimmed">配置 Table 的列信息</div>
214
+ </div>
215
+ <UButton
216
+ label="添加列"
217
+ icon="i-lucide-plus"
218
+ variant="soft"
219
+ size="sm"
220
+ @click="addColumn"
221
+ />
222
+ </div>
223
+
224
+ <div v-if="loading" class="py-8 text-center text-dimmed">
225
+ 加载中...
226
+ </div>
227
+ <div v-else-if="columns.length === 0" class="py-8 text-center text-dimmed">
228
+ 暂无列配置,点击"添加列"创建
229
+ </div>
230
+ <ProSimpleTable
231
+ v-else
232
+ :data="columns"
233
+ :biz-columns="tableColumns"
234
+ class="max-h-64 overflow-y-auto"
235
+ />
236
+ </div>
237
+ </template>
238
+ </FormCreateModalTemplate>
239
+ </template>
@@ -0,0 +1,13 @@
1
+ import type { Table } from '#v/types';
2
+ type __VLS_Props = {
3
+ model: Table;
4
+ };
5
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
6
+ close: (args_0: boolean) => any;
7
+ save: (args_0: Table) => any;
8
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
9
+ onClose?: ((args_0: boolean) => any) | undefined;
10
+ onSave?: ((args_0: Table) => any) | undefined;
11
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
12
+ declare const _default: typeof __VLS_export;
13
+ export default _default;
@@ -0,0 +1,3 @@
1
+ declare const __VLS_export: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
2
+ declare const _default: typeof __VLS_export;
3
+ export default _default;
@@ -0,0 +1,116 @@
1
+ <script setup>
2
+ import { useOverlay } from "@nuxt/ui/composables";
3
+ import { useTableApi, useTableColumnApi, useTablePermissionApi } from "#v/composables/api";
4
+ import { getOprColumns } from "#v/constants";
5
+ import TablePage from "#v/components/table/Page.vue";
6
+ import CreateModal from "./CreateModal.vue";
7
+ import { h, ref, watch } from "vue";
8
+ const overlay = useOverlay();
9
+ const createModal = overlay.create(CreateModal);
10
+ const tableMeta = ref({});
11
+ const columns = [
12
+ {
13
+ accessorKey: "tblName",
14
+ header: "\u8868\u540D",
15
+ sortOption: true,
16
+ filterOption: {
17
+ type: "input",
18
+ initHide: false
19
+ }
20
+ },
21
+ {
22
+ accessorKey: "label",
23
+ header: "\u663E\u793A\u540D",
24
+ sortOption: true,
25
+ filterOption: {
26
+ type: "input",
27
+ initHide: false
28
+ }
29
+ },
30
+ {
31
+ accessorKey: "meta",
32
+ header: "\u5217\u6570",
33
+ cell: ({ row }) => tableMeta.value[row.original.id]?.columnCount ?? "-"
34
+ },
35
+ {
36
+ accessorKey: "permissionCount",
37
+ header: "\u6743\u9650\u6570",
38
+ cell: ({ row }) => tableMeta.value[row.original.id]?.permissionCount ?? "-"
39
+ },
40
+ ...getOprColumns()
41
+ ];
42
+ const tablePageRef = ref(null);
43
+ async function fetchTableMeta(tables) {
44
+ const tableColumnApi = useTableColumnApi();
45
+ const tablePermissionApi = useTablePermissionApi();
46
+ const newMeta = {};
47
+ await Promise.all(
48
+ tables.map(async (table) => {
49
+ const [columnResult, permissionResult] = await Promise.all([
50
+ tableColumnApi.count({
51
+ whereQuery: {
52
+ items: [{ field: "tableId", value: table.id, opr: "eq" }]
53
+ }
54
+ }),
55
+ tablePermissionApi.count({
56
+ whereQuery: {
57
+ items: [{ field: "tableId", value: table.id, opr: "eq" }]
58
+ }
59
+ })
60
+ ]);
61
+ newMeta[table.id] = {
62
+ columnCount: columnResult.data.value?.data ?? 0,
63
+ permissionCount: permissionResult.data.value?.data ?? 0
64
+ };
65
+ })
66
+ );
67
+ tableMeta.value = { ...tableMeta.value, ...newMeta };
68
+ }
69
+ function getExpandVNode(row) {
70
+ const meta = tableMeta.value[row.id];
71
+ return h("div", { class: "p-4 text-sm text-dimmed" }, [
72
+ h("div", { class: "font-medium mb-2" }, `Table: ${row.tblName}`),
73
+ h("div", {}, `\u663E\u793A\u540D: ${row.label}`),
74
+ h("div", {}, `\u5217\u6570: ${meta?.columnCount ?? "-"}`),
75
+ h("div", {}, `\u6743\u9650\u914D\u7F6E\u6570: ${meta?.permissionCount ?? "-"}`),
76
+ h("div", {}, `\u521B\u5EFA\u65F6\u95F4: ${row.createdAt ? new Date(row.createdAt).toLocaleString() : "-"}`),
77
+ h("div", {}, `\u66F4\u65B0\u65F6\u95F4: ${row.updatedAt ? new Date(row.updatedAt).toLocaleString() : "-"}`)
78
+ ]);
79
+ }
80
+ const extraRowActions = [
81
+ {
82
+ label: "\u7F16\u8F91",
83
+ icon: "i-lucide-edit",
84
+ fnWithModal: async (row) => {
85
+ const result = await createModal.open({ model: { ...row } }).result;
86
+ return result;
87
+ }
88
+ }
89
+ ];
90
+ watch(
91
+ () => tablePageRef.value?.data,
92
+ async (newData) => {
93
+ if (newData && newData.length > 0) {
94
+ await fetchTableMeta(newData);
95
+ }
96
+ },
97
+ { immediate: true }
98
+ );
99
+ </script>
100
+
101
+ <template>
102
+ <TablePage
103
+ ref="tablePageRef"
104
+ name="sys-table"
105
+ cn-name="Table 配置"
106
+ :use-api-group="useTableApi"
107
+ :biz-columns="columns"
108
+ :expandable="true"
109
+ :expand-v-node="getExpandVNode"
110
+ :extra-row-actions="extraRowActions"
111
+ @edit-row-from-modal="async (row) => {
112
+ const result = await createModal.open({ model: { ...row } }).result;
113
+ return result === true;
114
+ }"
115
+ />
116
+ </template>
@@ -0,0 +1,3 @@
1
+ declare const __VLS_export: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
2
+ declare const _default: typeof __VLS_export;
3
+ export default _default;
@@ -0,0 +1,22 @@
1
+ import type { TableColumn, Table } from '#v/types';
2
+ type __VLS_Props = {
3
+ table: Table;
4
+ column?: {
5
+ id: number;
6
+ columnKey: string;
7
+ label: string;
8
+ order: number;
9
+ width: number;
10
+ fixed: 'left' | 'right' | '';
11
+ visible: boolean;
12
+ };
13
+ };
14
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
15
+ close: (args_0: boolean) => any;
16
+ save: (args_0: Partial<TableColumn>) => any;
17
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
18
+ onClose?: ((args_0: boolean) => any) | undefined;
19
+ onSave?: ((args_0: Partial<TableColumn>) => any) | undefined;
20
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
21
+ declare const _default: typeof __VLS_export;
22
+ export default _default;
@@ -0,0 +1,107 @@
1
+ <script setup>
2
+ import { useTableColumnApi } from "#v/composables/api";
3
+ import { ref } from "vue";
4
+ import { useToast } from "@nuxt/ui/composables";
5
+ const props = defineProps({
6
+ table: { type: Object, required: true },
7
+ column: { type: Object, required: false }
8
+ });
9
+ const emit = defineEmits(["close", "save"]);
10
+ const tableColumnApi = useTableColumnApi();
11
+ const saving = ref(false);
12
+ const formData = ref({
13
+ columnKey: props.column?.columnKey ?? "",
14
+ label: props.column?.label ?? "",
15
+ order: props.column?.order ?? 0,
16
+ width: props.column?.width ?? 100,
17
+ fixed: props.column?.fixed ?? "",
18
+ visible: props.column?.visible ?? true
19
+ });
20
+ async function handleSave() {
21
+ saving.value = true;
22
+ try {
23
+ emit("save", {
24
+ id: props.column?.id,
25
+ columnKey: formData.value.columnKey,
26
+ label: formData.value.label,
27
+ order: formData.value.order,
28
+ width: formData.value.width,
29
+ fixed: formData.value.fixed,
30
+ visible: formData.value.visible
31
+ });
32
+ emit("close", true);
33
+ } catch (error) {
34
+ useToast().add({
35
+ title: "\u4FDD\u5B58\u5931\u8D25",
36
+ description: String(error),
37
+ color: "error",
38
+ icon: "i-lucide-x-circle"
39
+ });
40
+ emit("close", false);
41
+ } finally {
42
+ saving.value = false;
43
+ }
44
+ }
45
+ </script>
46
+
47
+ <template>
48
+ <UModal
49
+ :title="`\u7F16\u8F91\u5217 - ${column?.columnKey ?? ''}`"
50
+ size="md"
51
+ :close="{ onClick: () => emit('close', false) }"
52
+ >
53
+ <div class="p-4 space-y-4">
54
+ <div class="grid grid-cols-2 gap-4">
55
+ <div>
56
+ <label class="text-sm font-medium mb-1 block">列标识</label>
57
+ <UInput v-model="formData.columnKey" placeholder="columnKey" />
58
+ </div>
59
+ <div>
60
+ <label class="text-sm font-medium mb-1 block">显示名</label>
61
+ <UInput v-model="formData.label" placeholder="显示名" />
62
+ </div>
63
+ </div>
64
+ <div class="grid grid-cols-3 gap-4">
65
+ <div>
66
+ <label class="text-sm font-medium mb-1 block">顺序</label>
67
+ <UInputNumber v-model="formData.order" :min="0" class="w-full" />
68
+ </div>
69
+ <div>
70
+ <label class="text-sm font-medium mb-1 block">宽度</label>
71
+ <UInputNumber v-model="formData.width" :min="0" class="w-full" />
72
+ </div>
73
+ <div>
74
+ <label class="text-sm font-medium mb-1 block">固定</label>
75
+ <USelect
76
+ v-model="formData.fixed"
77
+ :items="[
78
+ { label: '\u4E0D\u56FA\u5B9A', value: '' },
79
+ { label: '\u5DE6\u4FA7', value: 'left' },
80
+ { label: '\u53F3\u4FA7', value: 'right' }
81
+ ]"
82
+ class="w-full"
83
+ />
84
+ </div>
85
+ </div>
86
+ <div class="flex items-center gap-2">
87
+ <USwitch v-model="formData.visible" />
88
+ <span class="text-sm">{{ formData.visible ? "\u663E\u793A" : "\u9690\u85CF" }}</span>
89
+ </div>
90
+ </div>
91
+ <template #footer>
92
+ <UButton
93
+ label="取消"
94
+ color="neutral"
95
+ variant="subtle"
96
+ @click="emit('close', false)"
97
+ />
98
+ <UButton
99
+ label="保存"
100
+ color="primary"
101
+ variant="solid"
102
+ :loading="saving"
103
+ @click="handleSave"
104
+ />
105
+ </template>
106
+ </UModal>
107
+ </template>
@@ -0,0 +1,22 @@
1
+ import type { TableColumn, Table } from '#v/types';
2
+ type __VLS_Props = {
3
+ table: Table;
4
+ column?: {
5
+ id: number;
6
+ columnKey: string;
7
+ label: string;
8
+ order: number;
9
+ width: number;
10
+ fixed: 'left' | 'right' | '';
11
+ visible: boolean;
12
+ };
13
+ };
14
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
15
+ close: (args_0: boolean) => any;
16
+ save: (args_0: Partial<TableColumn>) => any;
17
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
18
+ onClose?: ((args_0: boolean) => any) | undefined;
19
+ onSave?: ((args_0: Partial<TableColumn>) => any) | undefined;
20
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
21
+ declare const _default: typeof __VLS_export;
22
+ export default _default;
@@ -3,6 +3,7 @@ import { useFormValues, useFormSubmission, useUserApi, useRoleApi, useMenuApi, u
3
3
  import { treeifyOptions } from "#v/utils";
4
4
  import { toRef, ref, computed, onMounted } from "vue";
5
5
  import FormCreateModalTemplate from "#v/components/form/create-modal-template/index.vue";
6
+ import TablePermissionTab from "#v/components/table/permission/TablePermissionTab.vue";
6
7
  import { loginTypeOptions, genderOptions, Gender } from "#v/constants";
7
8
  import * as z from "zod";
8
9
  const props = defineProps({
@@ -16,7 +17,10 @@ const { onSubmit } = useFormSubmission(
16
17
  (close) => emit("close", close),
17
18
  (model) => emit("save", model),
18
19
  useUserApi,
19
- ["roles", "menus"]
20
+ ["roles", "menus"],
21
+ "id",
22
+ "version",
23
+ () => ({ tablePermissions: tablePermissions.value })
20
24
  );
21
25
  const roles = ref([]);
22
26
  const onFetchRoles = async () => {
@@ -103,6 +107,7 @@ const menuTargetTreeItems = computed({
103
107
  function updateMenuTargetTreeItems(newVal) {
104
108
  menuTargetTreeItems.value = newVal;
105
109
  }
110
+ const tablePermissions = ref(props.model.tablePermissions || []);
106
111
  function updateDepartment(newInitModelValues) {
107
112
  newValues.value.department = newInitModelValues;
108
113
  }
@@ -193,5 +198,12 @@ onMounted(async () => {
193
198
  :model-value="newValues"
194
199
  @update-model-value="updateModelValue"
195
200
  @submit="onSubmit"
196
- />
201
+ >
202
+ <template #after-form>
203
+ <div class="border-t pt-4 mt-4">
204
+ <div class="font-semibold mb-2">Table 权限</div>
205
+ <TablePermissionTab v-model="tablePermissions" />
206
+ </div>
207
+ </template>
208
+ </FormCreateModalTemplate>
197
209
  </template>