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.
- package/README.md +6 -0
- package/dist/module.json +1 -1
- package/dist/runtime/components/AsyncSelect.vue +16 -1
- package/dist/runtime/components/AsyncTreeSelect.vue +15 -9
- package/dist/runtime/components/DeleteModal.d.vue.ts +25 -22
- package/dist/runtime/components/DeleteModal.vue +39 -4
- package/dist/runtime/components/DeleteModal.vue.d.ts +25 -22
- package/dist/runtime/components/ScrollArea.vue +20 -9
- package/dist/runtime/components/form/save-modal-template/ConfirmUpdateModal.d.vue.ts +19 -0
- package/dist/runtime/components/form/save-modal-template/ConfirmUpdateModal.vue +111 -0
- package/dist/runtime/components/form/save-modal-template/ConfirmUpdateModal.vue.d.ts +19 -0
- package/dist/runtime/components/form/{create-modal-template → save-modal-template}/WithApi.d.vue.ts +2 -2
- package/dist/runtime/components/form/{create-modal-template → save-modal-template}/WithApi.vue +4 -3
- package/dist/runtime/components/form/{create-modal-template → save-modal-template}/WithApi.vue.d.ts +2 -2
- package/dist/runtime/components/form/{create-modal-template → save-modal-template}/index.d.vue.ts +2 -2
- package/dist/runtime/components/form/{create-modal-template → save-modal-template}/index.vue +54 -7
- package/dist/runtime/components/form/{create-modal-template → save-modal-template}/index.vue.d.ts +2 -2
- package/dist/runtime/components/form/save-model-template/ConfirmUpdateModal.d.vue.ts +19 -0
- package/dist/runtime/components/form/save-model-template/ConfirmUpdateModal.vue +111 -0
- package/dist/runtime/components/form/save-model-template/ConfirmUpdateModal.vue.d.ts +19 -0
- package/dist/runtime/components/form/save-model-template/WithApi.d.vue.ts +19 -0
- package/dist/runtime/components/form/save-model-template/WithApi.vue +37 -0
- package/dist/runtime/components/form/save-model-template/WithApi.vue.d.ts +19 -0
- package/dist/runtime/components/form/save-model-template/index.d.vue.ts +21 -0
- package/dist/runtime/components/form/save-model-template/index.vue +123 -0
- package/dist/runtime/components/form/save-model-template/index.vue.d.ts +21 -0
- package/dist/runtime/components/layout/button/UserMenu.vue +1 -2
- package/dist/runtime/components/sys/company/{CreateModal.vue → SaveModal.vue} +2 -2
- package/dist/runtime/components/sys/company/Table.vue +5 -4
- package/dist/runtime/components/sys/department/{CreateModal.vue → SaveModal.vue} +3 -2
- package/dist/runtime/components/sys/department/Table.vue +6 -5
- package/dist/runtime/components/sys/flow/EditNodeModal.vue +4 -3
- package/dist/runtime/components/sys/flow/{CreateModal.vue → SaveModal.vue} +3 -2
- package/dist/runtime/components/sys/flow/Table.vue +5 -4
- package/dist/runtime/components/sys/issue-record/{CreateModal.vue → SaveModal.vue} +2 -2
- package/dist/runtime/components/sys/issue-record/Table.vue +5 -4
- package/dist/runtime/components/sys/job-title/{CreateModal.vue → SaveModal.vue} +2 -2
- package/dist/runtime/components/sys/job-title/Table.vue +5 -4
- package/dist/runtime/components/sys/menu/{CreateModal.vue → SaveModal.vue} +3 -2
- package/dist/runtime/components/sys/menu/Table.vue +6 -5
- package/dist/runtime/components/sys/role/{CreateModal.vue → SaveModal.vue} +8 -5
- package/dist/runtime/components/sys/role/Table.vue +5 -4
- package/dist/runtime/components/sys/table/{CreateModal.vue → SaveModal.vue} +4 -3
- package/dist/runtime/components/sys/table/Table.vue +4 -4
- package/dist/runtime/components/sys/table/TableColumnModal.vue +4 -3
- package/dist/runtime/components/sys/user/{CreateModal.vue → SaveModal.vue} +4 -3
- package/dist/runtime/components/sys/user/Table.vue +7 -6
- package/dist/runtime/components/table/Page.vue +2 -1
- package/dist/runtime/components/table/UpdateDiffModal.d.vue.ts +14 -0
- package/dist/runtime/components/table/UpdateDiffModal.vue +156 -0
- package/dist/runtime/components/table/UpdateDiffModal.vue.d.ts +14 -0
- package/dist/runtime/components/table/header/index.vue +181 -183
- package/dist/runtime/components/table/index.vue +2 -1
- package/dist/runtime/composables/form/index.d.ts +2 -0
- package/dist/runtime/composables/form/index.js +2 -0
- package/dist/runtime/composables/form/useForm.d.ts +21 -0
- package/dist/runtime/composables/{useForm.js → form/useForm.js} +23 -1
- package/dist/runtime/composables/form/useFormUpdate.d.ts +6 -0
- package/dist/runtime/composables/form/useFormUpdate.js +101 -0
- package/dist/runtime/composables/index.d.ts +1 -1
- package/dist/runtime/composables/index.js +1 -1
- package/dist/runtime/composables/table/useTable.js +10 -1
- package/dist/runtime/composables/table/useTableRowActions.d.ts +3 -0
- package/dist/runtime/composables/table/useTableRowActions.js +24 -0
- package/dist/runtime/composables/useDate.js +2 -0
- package/dist/runtime/types/components/form/field.d.ts +2 -0
- package/dist/runtime/types/components/form/index.d.ts +4 -3
- package/dist/runtime/types/components/table/header.d.ts +2 -0
- package/dist/runtime/types/components/table/index.d.ts +1 -0
- package/dist/runtime/types/time.d.ts +1 -1
- package/dist/runtime/utils/cron.d.ts +1 -0
- package/dist/runtime/utils/cron.js +182 -0
- package/dist/runtime/utils/index.d.ts +1 -0
- package/dist/runtime/utils/index.js +1 -0
- package/dist/runtime/utils/vueuse.d.ts +1 -1
- package/dist/runtime/utils/vueuse.js +1 -0
- package/package.json +16 -15
- package/dist/runtime/composables/useForm.d.ts +0 -9
- /package/dist/runtime/components/sys/company/{CreateModal.d.vue.ts → SaveModal.d.vue.ts} +0 -0
- /package/dist/runtime/components/sys/company/{CreateModal.vue.d.ts → SaveModal.vue.d.ts} +0 -0
- /package/dist/runtime/components/sys/department/{CreateModal.d.vue.ts → SaveModal.d.vue.ts} +0 -0
- /package/dist/runtime/components/sys/department/{CreateModal.vue.d.ts → SaveModal.vue.d.ts} +0 -0
- /package/dist/runtime/components/sys/flow/{CreateModal.d.vue.ts → SaveModal.d.vue.ts} +0 -0
- /package/dist/runtime/components/sys/flow/{CreateModal.vue.d.ts → SaveModal.vue.d.ts} +0 -0
- /package/dist/runtime/components/sys/issue-record/{CreateModal.d.vue.ts → SaveModal.d.vue.ts} +0 -0
- /package/dist/runtime/components/sys/issue-record/{CreateModal.vue.d.ts → SaveModal.vue.d.ts} +0 -0
- /package/dist/runtime/components/sys/job-title/{CreateModal.d.vue.ts → SaveModal.d.vue.ts} +0 -0
- /package/dist/runtime/components/sys/job-title/{CreateModal.vue.d.ts → SaveModal.vue.d.ts} +0 -0
- /package/dist/runtime/components/sys/menu/{CreateModal.d.vue.ts → SaveModal.d.vue.ts} +0 -0
- /package/dist/runtime/components/sys/menu/{CreateModal.vue.d.ts → SaveModal.vue.d.ts} +0 -0
- /package/dist/runtime/components/sys/role/{CreateModal.d.vue.ts → SaveModal.d.vue.ts} +0 -0
- /package/dist/runtime/components/sys/role/{CreateModal.vue.d.ts → SaveModal.vue.d.ts} +0 -0
- /package/dist/runtime/components/sys/table/{CreateModal.d.vue.ts → SaveModal.d.vue.ts} +0 -0
- /package/dist/runtime/components/sys/table/{CreateModal.vue.d.ts → SaveModal.vue.d.ts} +0 -0
- /package/dist/runtime/components/sys/user/{CreateModal.d.vue.ts → SaveModal.d.vue.ts} +0 -0
- /package/dist/runtime/components/sys/user/{CreateModal.vue.d.ts → SaveModal.vue.d.ts} +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script setup>
|
|
2
2
|
import * as z from "zod";
|
|
3
|
-
import
|
|
3
|
+
import FormSaveModalTemplateWithApi from "#v/components/form/save-modal-template/WithApi.vue";
|
|
4
4
|
import { useJobTitleApi } from "#v/composables";
|
|
5
5
|
defineProps({
|
|
6
6
|
model: { type: Object, required: true }
|
|
@@ -9,7 +9,7 @@ const emit = defineEmits(["close", "save"]);
|
|
|
9
9
|
</script>
|
|
10
10
|
|
|
11
11
|
<template>
|
|
12
|
-
<
|
|
12
|
+
<FormSaveModalTemplateWithApi
|
|
13
13
|
title="职位信息"
|
|
14
14
|
:on-close="(ok) => emit('close', ok)"
|
|
15
15
|
:on-save="(model) => emit('save', model)"
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
<script setup>
|
|
2
2
|
import { useOverlay } from "@nuxt/ui/composables";
|
|
3
3
|
import { useJobTitleApi } from "#v/composables";
|
|
4
|
-
import
|
|
4
|
+
import SysJobTitlesSaveModal from "./SaveModal.vue";
|
|
5
5
|
import { getOprColumns, booleanOptions } from "#v/constants";
|
|
6
6
|
import UBadge from "@nuxt/ui/components/Badge.vue";
|
|
7
7
|
import { h } from "vue";
|
|
8
8
|
import TablePage from "#v/components/table/Page.vue";
|
|
9
9
|
const overlay = useOverlay();
|
|
10
|
-
const
|
|
10
|
+
const saveModal = overlay.create(SysJobTitlesSaveModal);
|
|
11
11
|
const columns = [
|
|
12
12
|
{
|
|
13
13
|
accessorKey: "name",
|
|
@@ -55,13 +55,14 @@ const columns = [
|
|
|
55
55
|
|
|
56
56
|
<template>
|
|
57
57
|
<TablePage
|
|
58
|
-
name="
|
|
58
|
+
name="job_titles"
|
|
59
59
|
cn-name="职位信息"
|
|
60
60
|
:use-api-group="useJobTitleApi"
|
|
61
61
|
:biz-columns="columns"
|
|
62
62
|
:extra-order-query-options="[
|
|
63
63
|
{ field: 'createdAt', label: '\u521B\u5EFA\u65F6\u95F4', defaultOpr: 'desc' }
|
|
64
64
|
]"
|
|
65
|
-
|
|
65
|
+
:display-fn-in-delete-modal="(model) => model.name"
|
|
66
|
+
@edit-row-from-modal="async (row) => await saveModal.open({ model: row }).result"
|
|
66
67
|
/>
|
|
67
68
|
</template>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script setup>
|
|
2
2
|
import * as z from "zod";
|
|
3
|
-
import
|
|
3
|
+
import FormSaveModalTemplate from "#v/components/form/save-modal-template/index.vue";
|
|
4
4
|
import { useMenuApi, useFormSubmission, useFormValues } from "#v/composables";
|
|
5
5
|
import { toRef } from "vue";
|
|
6
6
|
import { menuTypeOptions } from "#v/constants";
|
|
@@ -20,7 +20,7 @@ const { onSubmit } = useFormSubmission(
|
|
|
20
20
|
</script>
|
|
21
21
|
|
|
22
22
|
<template>
|
|
23
|
-
<
|
|
23
|
+
<FormSaveModalTemplate
|
|
24
24
|
title="菜单信息"
|
|
25
25
|
:on-close="(ok) => emit('close', ok)"
|
|
26
26
|
:fields="[
|
|
@@ -53,6 +53,7 @@ const { onSubmit } = useFormSubmission(
|
|
|
53
53
|
{ name: 'isAdmin', type: 'button-switch', label: '\u662F\u5426\u662F\u7CFB\u7EDF\u83DC\u5355', colSpan: '12', zodType: z.boolean() }
|
|
54
54
|
]"
|
|
55
55
|
:model-value="newValues"
|
|
56
|
+
:old-model-value="oldValues"
|
|
56
57
|
@update-model-value="(newVal) => newValues = { id: 0, ...newVal }"
|
|
57
58
|
@submit="onSubmit"
|
|
58
59
|
/>
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
<script setup>
|
|
2
2
|
import { useOverlay } from "@nuxt/ui/composables";
|
|
3
3
|
import { useMenuApi } from "#v/composables";
|
|
4
|
-
import
|
|
4
|
+
import SysMenusSaveModal from "./SaveModal.vue";
|
|
5
5
|
import { getOprColumns } from "#v/constants";
|
|
6
6
|
import UBadge from "@nuxt/ui/components/Badge.vue";
|
|
7
7
|
import TablePage from "#v/components/table/Page.vue";
|
|
8
8
|
import { h } from "vue";
|
|
9
9
|
const overlay = useOverlay();
|
|
10
|
-
const
|
|
10
|
+
const saveModal = overlay.create(SysMenusSaveModal);
|
|
11
11
|
const columns = [
|
|
12
12
|
{
|
|
13
13
|
accessorKey: "type",
|
|
@@ -82,7 +82,7 @@ const columns = [
|
|
|
82
82
|
|
|
83
83
|
<template>
|
|
84
84
|
<TablePage
|
|
85
|
-
name="
|
|
85
|
+
name="menus"
|
|
86
86
|
cn-name="菜单信息"
|
|
87
87
|
:use-api-group="useMenuApi"
|
|
88
88
|
:biz-columns="columns"
|
|
@@ -94,8 +94,9 @@ const columns = [
|
|
|
94
94
|
:extra-row-actions="[{
|
|
95
95
|
icon: 'i-lucide-clipboard-plus',
|
|
96
96
|
label: '\u4EE5\u6B64\u4F5C\u4E3A\u7236\u83DC\u5355\u590D\u5236',
|
|
97
|
-
fnWithModal: async (raw) => await
|
|
97
|
+
fnWithModal: async (raw) => await saveModal.open({ model: useMenuApi().copyAsParent?.(raw) ?? { id: 0 } }).result
|
|
98
98
|
}]"
|
|
99
|
-
|
|
99
|
+
:display-fn-in-delete-modal="(model) => `${model.name} ${model.staticRouteKeys?.join(',')}`"
|
|
100
|
+
@edit-row-from-modal="async (row) => await saveModal.open({ model: row }).result"
|
|
100
101
|
/>
|
|
101
102
|
</template>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script setup>
|
|
2
2
|
import * as z from "zod";
|
|
3
|
-
import
|
|
3
|
+
import FormSaveModalTemplate from "#v/components/form/save-modal-template/index.vue";
|
|
4
4
|
import TablePermissionTab from "#v/components/table/permission/TablePermissionTab.vue";
|
|
5
5
|
import { useFormSubmission, useFormValues, useMenuApi, useRoleApi } from "#v/composables";
|
|
6
6
|
import { computed, onMounted, ref, toRef } from "vue";
|
|
@@ -9,7 +9,7 @@ const props = defineProps({
|
|
|
9
9
|
model: { type: Object, required: true }
|
|
10
10
|
});
|
|
11
11
|
const emit = defineEmits(["close", "save"]);
|
|
12
|
-
const { oldValues, newValues } = useFormValues(toRef(props.model), { id: 0, disabled: false, isAdmin: false });
|
|
12
|
+
const { oldValues, newValues } = useFormValues(toRef(props.model), { id: 0, disabled: false, isAdmin: false, menus: [] });
|
|
13
13
|
const { onSubmit } = useFormSubmission(
|
|
14
14
|
toRef(oldValues),
|
|
15
15
|
toRef(newValues),
|
|
@@ -86,19 +86,22 @@ onMounted(async () => {
|
|
|
86
86
|
</script>
|
|
87
87
|
|
|
88
88
|
<template>
|
|
89
|
-
<
|
|
89
|
+
<FormSaveModalTemplate
|
|
90
90
|
title="角色信息"
|
|
91
91
|
:on-close="(ok) => emit('close', ok)"
|
|
92
92
|
:fields="fields"
|
|
93
93
|
:model-value="newValues"
|
|
94
|
+
:old-model-value="oldValues"
|
|
94
95
|
@update-model-value="updateModelValue"
|
|
95
96
|
@submit="onSubmit"
|
|
96
97
|
>
|
|
97
98
|
<template #after-form>
|
|
98
99
|
<div class="border-t pt-4 mt-4">
|
|
99
|
-
<div class="font-semibold mb-2">
|
|
100
|
+
<div class="font-semibold mb-2">
|
|
101
|
+
Table 权限
|
|
102
|
+
</div>
|
|
100
103
|
<TablePermissionTab v-model="tablePermissions" />
|
|
101
104
|
</div>
|
|
102
105
|
</template>
|
|
103
|
-
</
|
|
106
|
+
</FormSaveModalTemplate>
|
|
104
107
|
</template>
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
<script setup>
|
|
2
2
|
import { useOverlay } from "@nuxt/ui/composables";
|
|
3
3
|
import { useRoleApi } from "#v/composables";
|
|
4
|
-
import
|
|
4
|
+
import SysRolesSaveModal from "./SaveModal.vue";
|
|
5
5
|
import { booleanOptions, getOprColumns } from "#v/constants";
|
|
6
6
|
import UBadge from "@nuxt/ui/components/Badge.vue";
|
|
7
7
|
import TablePage from "#v/components/table/Page.vue";
|
|
8
8
|
import { h } from "vue";
|
|
9
9
|
const overlay = useOverlay();
|
|
10
|
-
const
|
|
10
|
+
const saveModal = overlay.create(SysRolesSaveModal);
|
|
11
11
|
const columns = [
|
|
12
12
|
{
|
|
13
13
|
accessorKey: "name",
|
|
@@ -60,10 +60,11 @@ const columns = [
|
|
|
60
60
|
|
|
61
61
|
<template>
|
|
62
62
|
<TablePage
|
|
63
|
-
name="
|
|
63
|
+
name="roles"
|
|
64
64
|
cn-name="角色信息"
|
|
65
65
|
:use-api-group="useRoleApi"
|
|
66
66
|
:biz-columns="columns"
|
|
67
|
-
|
|
67
|
+
:display-fn-in-delete-modal="(model) => model.name"
|
|
68
|
+
@edit-row-from-modal="async (row) => await saveModal.open({ model: row }).result"
|
|
68
69
|
/>
|
|
69
70
|
</template>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script setup>
|
|
2
2
|
import * as z from "zod";
|
|
3
|
-
import
|
|
3
|
+
import FormSaveModalTemplate from "#v/components/form/save-modal-template/index.vue";
|
|
4
4
|
import TableColumnList from "./TableColumnList.vue";
|
|
5
5
|
import { useFormSubmission, useFormValues, useTableApi } from "#v/composables";
|
|
6
6
|
import { computed, ref, toRef } from "vue";
|
|
@@ -40,16 +40,17 @@ function updateModelValue(newVal) {
|
|
|
40
40
|
</script>
|
|
41
41
|
|
|
42
42
|
<template>
|
|
43
|
-
<
|
|
43
|
+
<FormSaveModalTemplate
|
|
44
44
|
title="Table"
|
|
45
45
|
:on-close="(ok) => emit('close', ok)"
|
|
46
46
|
:fields="fields"
|
|
47
47
|
:model-value="newValues"
|
|
48
|
+
:old-model-value="oldValues"
|
|
48
49
|
@update-model-value="updateModelValue"
|
|
49
50
|
@submit="onSubmit"
|
|
50
51
|
>
|
|
51
52
|
<template #after-form>
|
|
52
53
|
<TableColumnList ref="columnListRef" :initial-columns="model.columns" />
|
|
53
54
|
</template>
|
|
54
|
-
</
|
|
55
|
+
</FormSaveModalTemplate>
|
|
55
56
|
</template>
|
|
@@ -3,10 +3,10 @@ import { useOverlay } from "@nuxt/ui/composables";
|
|
|
3
3
|
import { useTableApi, useTableColumnApi, useTablePermissionApi } from "#v/composables/api";
|
|
4
4
|
import { getOprColumns } from "#v/constants";
|
|
5
5
|
import TablePage from "#v/components/table/Page.vue";
|
|
6
|
-
import
|
|
6
|
+
import SaveModal from "./SaveModal.vue";
|
|
7
7
|
import { h, ref, watch } from "vue";
|
|
8
8
|
const overlay = useOverlay();
|
|
9
|
-
const
|
|
9
|
+
const saveModal = overlay.create(SaveModal);
|
|
10
10
|
const tableMeta = ref({});
|
|
11
11
|
const columns = [
|
|
12
12
|
{
|
|
@@ -93,14 +93,14 @@ watch(
|
|
|
93
93
|
<template>
|
|
94
94
|
<TablePage
|
|
95
95
|
ref="tablePageRef"
|
|
96
|
-
name="
|
|
96
|
+
name="tables"
|
|
97
97
|
cn-name="Table 配置"
|
|
98
98
|
:use-api-group="useTableApi"
|
|
99
99
|
:biz-columns="columns"
|
|
100
100
|
:expandable="true"
|
|
101
101
|
:expand-v-node="getExpandVNode"
|
|
102
102
|
@edit-row-from-modal="async (row) => {
|
|
103
|
-
const result = await
|
|
103
|
+
const result = await saveModal.open({ model: { ...row } }).result;
|
|
104
104
|
return result === true;
|
|
105
105
|
}"
|
|
106
106
|
/>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script setup>
|
|
2
2
|
import * as z from "zod";
|
|
3
|
-
import
|
|
3
|
+
import FormSaveModalTemplate from "#v/components/form/save-modal-template/index.vue";
|
|
4
4
|
import { useFormValues } from "#v/composables";
|
|
5
5
|
import { computed, toRef } from "vue";
|
|
6
6
|
const props = defineProps({
|
|
@@ -8,7 +8,7 @@ const props = defineProps({
|
|
|
8
8
|
onSaveColumn: { type: Function, required: true }
|
|
9
9
|
});
|
|
10
10
|
const emit = defineEmits(["close"]);
|
|
11
|
-
const { newValues } = useFormValues(toRef(props.column), { id: 0 });
|
|
11
|
+
const { oldValues, newValues } = useFormValues(toRef(props.column), { id: 0 });
|
|
12
12
|
const fixedItems = [
|
|
13
13
|
{ label: "\u4E0D\u56FA\u5B9A", value: "" },
|
|
14
14
|
{ label: "\u5DE6\u4FA7\u56FA\u5B9A", value: "left" },
|
|
@@ -25,11 +25,12 @@ const fields = computed(() => [
|
|
|
25
25
|
</script>
|
|
26
26
|
|
|
27
27
|
<template>
|
|
28
|
-
<
|
|
28
|
+
<FormSaveModalTemplate
|
|
29
29
|
title="列配置"
|
|
30
30
|
:on-close="(ok) => emit('close', ok)"
|
|
31
31
|
:fields="fields"
|
|
32
32
|
:model-value="newValues"
|
|
33
|
+
:old-model-value="oldValues"
|
|
33
34
|
@update-model-value="(newVal) => newValues = { id: 0, ...newVal }"
|
|
34
35
|
@submit="async () => {
|
|
35
36
|
props.onSaveColumn(newValues);
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { useFormValues, useFormSubmission, useUserApi, useRoleApi, useMenuApi, useDepartmentApi } from "#v/composables";
|
|
3
3
|
import { treeifyOptions } from "#v/utils";
|
|
4
4
|
import { toRef, ref, computed, onMounted } from "vue";
|
|
5
|
-
import
|
|
5
|
+
import FormSaveModalTemplate from "#v/components/form/save-modal-template/index.vue";
|
|
6
6
|
import TablePermissionTab from "#v/components/table/permission/TablePermissionTab.vue";
|
|
7
7
|
import { loginTypeOptions, genderOptions, Gender } from "#v/constants";
|
|
8
8
|
import * as z from "zod";
|
|
@@ -191,11 +191,12 @@ onMounted(async () => {
|
|
|
191
191
|
</script>
|
|
192
192
|
|
|
193
193
|
<template>
|
|
194
|
-
<
|
|
194
|
+
<FormSaveModalTemplate
|
|
195
195
|
title="用户信息"
|
|
196
196
|
:on-close="(ok) => emit('close', ok)"
|
|
197
197
|
:fields="fields"
|
|
198
198
|
:model-value="newValues"
|
|
199
|
+
:old-model-value="oldValues"
|
|
199
200
|
@update-model-value="updateModelValue"
|
|
200
201
|
@submit="onSubmit"
|
|
201
202
|
>
|
|
@@ -207,5 +208,5 @@ onMounted(async () => {
|
|
|
207
208
|
<TablePermissionTab v-model="tablePermissions" />
|
|
208
209
|
</div>
|
|
209
210
|
</template>
|
|
210
|
-
</
|
|
211
|
+
</FormSaveModalTemplate>
|
|
211
212
|
</template>
|
|
@@ -4,12 +4,12 @@ import { useOverlay } from "@nuxt/ui/composables";
|
|
|
4
4
|
import { isEmptyString } from "#v/utils";
|
|
5
5
|
import { useDepartmentApi, useRoleApi, useUserApi } from "#v/composables";
|
|
6
6
|
import { booleanOptions, dateFormat, genderOptions, loginTypeOptions } from "#v/constants";
|
|
7
|
-
import
|
|
7
|
+
import SysUsersSaveModal from "./SaveModal.vue";
|
|
8
8
|
import UBadge from "@nuxt/ui/components/Badge.vue";
|
|
9
9
|
import TablePage from "#v/components/table/Page.vue";
|
|
10
10
|
import { h } from "vue";
|
|
11
11
|
const overlay = useOverlay();
|
|
12
|
-
const
|
|
12
|
+
const saveModal = overlay.create(SysUsersSaveModal);
|
|
13
13
|
const columns = [
|
|
14
14
|
{
|
|
15
15
|
accessorKey: "isResigned",
|
|
@@ -57,8 +57,8 @@ const columns = [
|
|
|
57
57
|
filterOption: {
|
|
58
58
|
type: "async-select",
|
|
59
59
|
listApi: useUserApi().list,
|
|
60
|
-
likeSearchFields: ["
|
|
61
|
-
labelField: "
|
|
60
|
+
likeSearchFields: ["nickname"],
|
|
61
|
+
labelField: "nickname",
|
|
62
62
|
valueField: "id",
|
|
63
63
|
multiple: true,
|
|
64
64
|
defaultOpr: "in"
|
|
@@ -186,13 +186,14 @@ const columns = [
|
|
|
186
186
|
|
|
187
187
|
<template>
|
|
188
188
|
<TablePage
|
|
189
|
-
name="
|
|
189
|
+
name="users"
|
|
190
190
|
cn-name="用户信息"
|
|
191
191
|
:use-api-group="useUserApi"
|
|
192
192
|
:biz-columns="columns"
|
|
193
193
|
:extra-order-query-options="[
|
|
194
194
|
{ field: 'createdAt', label: '\u521B\u5EFA\u65F6\u95F4', defaultOpr: 'desc' }
|
|
195
195
|
]"
|
|
196
|
-
|
|
196
|
+
:display-fn-in-delete-modal="(model) => model.nickname"
|
|
197
|
+
@edit-row-from-modal="async (row) => await saveModal.open({ model: row }).result"
|
|
197
198
|
/>
|
|
198
199
|
</template>
|
|
@@ -44,7 +44,8 @@ const props = defineProps({
|
|
|
44
44
|
expandable: { type: Boolean, required: false },
|
|
45
45
|
expandVNode: { type: Function, required: false },
|
|
46
46
|
rowSpanColumns: { type: Array, required: false },
|
|
47
|
-
customRowCopyFn: { type: Function, required: false }
|
|
47
|
+
customRowCopyFn: { type: Function, required: false },
|
|
48
|
+
displayFnInDeleteModal: { type: Function, required: false }
|
|
48
49
|
});
|
|
49
50
|
const {
|
|
50
51
|
// data
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { VColumn } from '#v/types';
|
|
2
|
+
type __VLS_Props = {
|
|
3
|
+
tableName: string;
|
|
4
|
+
rowId: number;
|
|
5
|
+
columns: VColumn<any>[];
|
|
6
|
+
title?: string;
|
|
7
|
+
};
|
|
8
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
9
|
+
close: (args_0: boolean) => any;
|
|
10
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
11
|
+
onClose?: ((args_0: boolean) => any) | undefined;
|
|
12
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
13
|
+
declare const _default: typeof __VLS_export;
|
|
14
|
+
export default _default;
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
import { ref, computed } from "vue";
|
|
3
|
+
import { isEmptyString } from "#v/utils";
|
|
4
|
+
import { diffWords } from "diff";
|
|
5
|
+
import { useRowRecordApi } from "#v/composables/api";
|
|
6
|
+
import { useDate } from "#v/composables";
|
|
7
|
+
const props = defineProps({
|
|
8
|
+
tableName: { type: String, required: true },
|
|
9
|
+
rowId: { type: Number, required: true },
|
|
10
|
+
columns: { type: Array, required: true },
|
|
11
|
+
title: { type: String, required: false }
|
|
12
|
+
});
|
|
13
|
+
const emit = defineEmits(["close"]);
|
|
14
|
+
const date = useDate();
|
|
15
|
+
const rowRecordApi = useRowRecordApi();
|
|
16
|
+
const loading = ref(false);
|
|
17
|
+
const rowRecords = ref([]);
|
|
18
|
+
async function fetchRowRecords() {
|
|
19
|
+
loading.value = true;
|
|
20
|
+
try {
|
|
21
|
+
const { data } = await rowRecordApi.getByTableNameAndRowId({
|
|
22
|
+
tableName: props.tableName,
|
|
23
|
+
rowId: props.rowId
|
|
24
|
+
});
|
|
25
|
+
rowRecords.value = data.value.data?.list ?? [];
|
|
26
|
+
} finally {
|
|
27
|
+
loading.value = false;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
fetchRowRecords();
|
|
31
|
+
function resolveHeader(key) {
|
|
32
|
+
if (!key) return "";
|
|
33
|
+
const col = props.columns.find((c) => c.accessorKey === key || c.id === key);
|
|
34
|
+
return col?.header || key;
|
|
35
|
+
}
|
|
36
|
+
const aggregatedRecords = computed(() => {
|
|
37
|
+
if (!rowRecords.value.length) return [];
|
|
38
|
+
const groupMap = /* @__PURE__ */ new Map();
|
|
39
|
+
for (const record of rowRecords.value) {
|
|
40
|
+
const ver = record.rowVersion;
|
|
41
|
+
if (!groupMap.has(ver)) {
|
|
42
|
+
groupMap.set(ver, {
|
|
43
|
+
rowVersion: ver,
|
|
44
|
+
createdAt: record.createdAt,
|
|
45
|
+
creator: record.creator,
|
|
46
|
+
changes: []
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
const oldVal = record.oldValue || "";
|
|
50
|
+
const newVal = record.newValue || "";
|
|
51
|
+
groupMap.get(ver).changes.push({
|
|
52
|
+
header: resolveHeader(record.key || ""),
|
|
53
|
+
oldValue: oldVal,
|
|
54
|
+
newValue: newVal,
|
|
55
|
+
parts: diffWords(oldVal, newVal)
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
return Array.from(groupMap.values()).sort((a, b) => b.rowVersion - a.rowVersion);
|
|
59
|
+
});
|
|
60
|
+
const timelineItems = computed(
|
|
61
|
+
() => aggregatedRecords.value.map((record) => ({
|
|
62
|
+
record,
|
|
63
|
+
icon: "i-lucide-git-commit"
|
|
64
|
+
}))
|
|
65
|
+
);
|
|
66
|
+
</script>
|
|
67
|
+
|
|
68
|
+
<template>
|
|
69
|
+
<UModal
|
|
70
|
+
:title="title || '\u53D8\u66F4\u8BB0\u5F55'"
|
|
71
|
+
:close="{ onClick: () => emit('close', false) }"
|
|
72
|
+
:dismissible="false"
|
|
73
|
+
:ui="{ body: 'p-0!' }"
|
|
74
|
+
>
|
|
75
|
+
<template #body>
|
|
76
|
+
<!-- Loading -->
|
|
77
|
+
<div v-if="loading" class="flex items-center justify-center py-8">
|
|
78
|
+
<UIcon name="i-lucide-loader-circle" class="size-6 animate-spin text-dimmed" />
|
|
79
|
+
</div>
|
|
80
|
+
|
|
81
|
+
<!-- Timeline -->
|
|
82
|
+
<div v-else-if="timelineItems.length > 0" class="overflow-y-auto max-h-96 p-6">
|
|
83
|
+
<UTimeline
|
|
84
|
+
:items="timelineItems"
|
|
85
|
+
size="xs"
|
|
86
|
+
:ui="{ date: 'float-end' }"
|
|
87
|
+
>
|
|
88
|
+
<template #title="{ item }">
|
|
89
|
+
<div class="flex items-center gap-1">
|
|
90
|
+
<span class="font-semibold">{{ item.record.creator?.nickname || "\u672A\u77E5\u7528\u6237" }}</span>
|
|
91
|
+
<UBadge
|
|
92
|
+
:label="`v${item.record.rowVersion}`"
|
|
93
|
+
variant="subtle"
|
|
94
|
+
color="neutral"
|
|
95
|
+
size="xs"
|
|
96
|
+
/>
|
|
97
|
+
<div class="ml-auto text-xs text-dimmed font-normal">
|
|
98
|
+
更新于 {{ date.formatTimeUnit(date.isoUtcStringToDateValue(item.record.createdAt), "time") }}
|
|
99
|
+
</div>
|
|
100
|
+
</div>
|
|
101
|
+
</template>
|
|
102
|
+
|
|
103
|
+
<template #description="{ item }">
|
|
104
|
+
<div class="rounded-md ring ring-default mt-2 p-3 space-y-3">
|
|
105
|
+
<div v-for="(change, idx) in item.record.changes" :key="idx">
|
|
106
|
+
<div class="text-xs font-semibold text-dimmed mb-1">
|
|
107
|
+
{{ change.header }}
|
|
108
|
+
</div>
|
|
109
|
+
<div class="flex items-center flex-wrap gap-2">
|
|
110
|
+
<!-- Old -->
|
|
111
|
+
<span class="rounded-md bg-muted px-2 py-1 text-sm text-dimmed">
|
|
112
|
+
<span v-if="change.parts.filter((part2) => !part2.added).length === 0">{{ "\xA0" }}</span>
|
|
113
|
+
<template v-for="(part, pIdx) in change.parts" :key="pIdx">
|
|
114
|
+
<span
|
|
115
|
+
v-if="!part.added"
|
|
116
|
+
:class="{ 'bg-red-200 text-red-800 dark:bg-red-800 dark:text-red-200 rounded-sm line-through px-0.5': part.removed }"
|
|
117
|
+
>
|
|
118
|
+
{{ isEmptyString(part.value) ? "\xA0" : part.value }}
|
|
119
|
+
</span>
|
|
120
|
+
</template>
|
|
121
|
+
</span>
|
|
122
|
+
<UIcon name="i-lucide-arrow-right" class="text-dimmed shrink-0 size-4" />
|
|
123
|
+
<!-- New -->
|
|
124
|
+
<span class="rounded-md bg-elevated px-2 py-1 text-sm text-highlighted font-medium">
|
|
125
|
+
<span v-if="change.parts.filter((part2) => !part2.removed).length === 0">{{ "\xA0" }}</span>
|
|
126
|
+
<template v-for="(part, pIdx) in change.parts" :key="pIdx">
|
|
127
|
+
<span
|
|
128
|
+
v-if="!part.removed"
|
|
129
|
+
:class="{ 'bg-green-200 text-green-800 dark:bg-green-800 dark:text-green-200 rounded-sm px-0.5': part.added }"
|
|
130
|
+
>
|
|
131
|
+
{{ isEmptyString(part.value) ? "\xA0" : part.value }}
|
|
132
|
+
</span>
|
|
133
|
+
</template>
|
|
134
|
+
</span>
|
|
135
|
+
</div>
|
|
136
|
+
</div>
|
|
137
|
+
</div>
|
|
138
|
+
</template>
|
|
139
|
+
</UTimeline>
|
|
140
|
+
</div>
|
|
141
|
+
|
|
142
|
+
<!-- Empty -->
|
|
143
|
+
<div v-else class="text-center text-dimmed py-8">
|
|
144
|
+
暂无变更记录
|
|
145
|
+
</div>
|
|
146
|
+
</template>
|
|
147
|
+
<template #footer>
|
|
148
|
+
<UButton
|
|
149
|
+
label="关闭"
|
|
150
|
+
color="neutral"
|
|
151
|
+
variant="subtle"
|
|
152
|
+
@click="emit('close', false)"
|
|
153
|
+
/>
|
|
154
|
+
</template>
|
|
155
|
+
</UModal>
|
|
156
|
+
</template>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { VColumn } from '#v/types';
|
|
2
|
+
type __VLS_Props = {
|
|
3
|
+
tableName: string;
|
|
4
|
+
rowId: number;
|
|
5
|
+
columns: VColumn<any>[];
|
|
6
|
+
title?: string;
|
|
7
|
+
};
|
|
8
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
9
|
+
close: (args_0: boolean) => any;
|
|
10
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
11
|
+
onClose?: ((args_0: boolean) => any) | undefined;
|
|
12
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
13
|
+
declare const _default: typeof __VLS_export;
|
|
14
|
+
export default _default;
|