@befly-addon/admin 1.1.29 → 1.1.31

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 (123) hide show
  1. package/apis/admin/cacheRefresh.ts +29 -24
  2. package/apis/admin/del.ts +12 -12
  3. package/apis/admin/detail.ts +9 -41
  4. package/apis/admin/ins.ts +28 -21
  5. package/apis/admin/list.ts +12 -12
  6. package/apis/admin/upd.ts +49 -14
  7. package/apis/api/all.ts +14 -10
  8. package/apis/api/list.ts +16 -25
  9. package/apis/auth/login.ts +55 -52
  10. package/apis/auth/sendSmsCode.ts +6 -6
  11. package/apis/dashboard/configStatus.ts +18 -18
  12. package/apis/dashboard/environmentInfo.ts +12 -12
  13. package/apis/dashboard/performanceMetrics.ts +5 -5
  14. package/apis/dashboard/permissionStats.ts +7 -7
  15. package/apis/dashboard/serviceStatus.ts +29 -29
  16. package/apis/dashboard/systemInfo.ts +5 -5
  17. package/apis/dashboard/systemOverview.ts +7 -7
  18. package/apis/dashboard/systemResources.ts +8 -8
  19. package/apis/dict/all.ts +24 -7
  20. package/apis/dict/del.ts +9 -17
  21. package/apis/dict/detail.ts +30 -16
  22. package/apis/dict/ins.ts +36 -18
  23. package/apis/dict/items.ts +27 -0
  24. package/apis/dict/list.ts +35 -10
  25. package/apis/dict/upd.ts +54 -20
  26. package/apis/dictType/all.ts +11 -0
  27. package/apis/dictType/del.ts +32 -0
  28. package/apis/dictType/detail.ts +17 -0
  29. package/apis/dictType/ins.ts +30 -0
  30. package/apis/dictType/list.ts +22 -0
  31. package/apis/dictType/upd.ts +42 -0
  32. package/apis/email/config.ts +4 -4
  33. package/apis/email/logList.ts +10 -10
  34. package/apis/email/send.ts +18 -18
  35. package/apis/email/verify.ts +5 -5
  36. package/apis/loginLog/list.ts +10 -10
  37. package/apis/menu/all.ts +17 -20
  38. package/apis/menu/list.ts +12 -13
  39. package/apis/operateLog/list.ts +10 -10
  40. package/apis/role/all.ts +7 -7
  41. package/apis/role/apiSave.ts +14 -16
  42. package/apis/role/apis.ts +24 -0
  43. package/apis/role/del.ts +27 -19
  44. package/apis/role/detail.ts +6 -7
  45. package/apis/role/ins.ts +10 -10
  46. package/apis/role/list.ts +11 -11
  47. package/apis/role/menuSave.ts +12 -14
  48. package/apis/role/menus.ts +24 -0
  49. package/apis/role/save.ts +14 -15
  50. package/apis/role/upd.ts +10 -10
  51. package/apis/sysConfig/all.ts +5 -6
  52. package/apis/sysConfig/del.ts +10 -10
  53. package/apis/sysConfig/get.ts +10 -11
  54. package/apis/sysConfig/ins.ts +11 -11
  55. package/apis/sysConfig/list.ts +9 -9
  56. package/apis/sysConfig/upd.ts +11 -11
  57. package/libs/emailHelper.ts +7 -7
  58. package/package.json +46 -34
  59. package/plugins/email.ts +9 -9
  60. package/tables/admin.json +0 -6
  61. package/tables/dict.json +13 -19
  62. package/tables/dictType.json +28 -0
  63. package/tables/role.json +4 -2
  64. package/views/403_1/index.vue +19 -3
  65. package/views/config/dict/components/edit.vue +76 -124
  66. package/views/config/dict/index.vue +142 -84
  67. package/views/config/dictType/components/edit.vue +105 -0
  68. package/views/config/dictType/index.vue +242 -0
  69. package/views/config/index.vue +12 -0
  70. package/views/config/system/components/edit.vue +36 -36
  71. package/views/config/system/index.vue +79 -50
  72. package/views/index/components/addonList.vue +3 -3
  73. package/views/index/components/environmentInfo.vue +10 -10
  74. package/views/index/components/operationLogs.vue +10 -10
  75. package/views/index/components/performanceMetrics.vue +8 -8
  76. package/views/index/components/quickActions.vue +3 -3
  77. package/views/index/components/serviceStatus.vue +19 -19
  78. package/views/index/components/systemNotifications.vue +12 -12
  79. package/views/index/components/systemOverview.vue +7 -7
  80. package/views/index/components/systemResources.vue +11 -11
  81. package/views/index/components/userInfo.vue +20 -19
  82. package/views/index/index.vue +12 -5
  83. package/views/log/email/index.vue +58 -51
  84. package/views/log/index.vue +12 -0
  85. package/views/log/login/index.vue +45 -38
  86. package/views/log/operate/index.vue +55 -48
  87. package/views/login_1/index.vue +191 -2
  88. package/views/people/admin/components/edit.vue +28 -29
  89. package/views/people/admin/index.vue +76 -40
  90. package/views/people/index.vue +12 -0
  91. package/views/permission/api/index.vue +21 -15
  92. package/views/permission/index.vue +12 -0
  93. package/views/permission/menu/index.vue +31 -16
  94. package/views/permission/role/components/api.vue +23 -23
  95. package/views/permission/role/components/edit.vue +18 -18
  96. package/views/permission/role/components/menu.vue +17 -19
  97. package/views/permission/role/index.vue +84 -49
  98. package/apis/admin/roleDetail.ts +0 -29
  99. package/apis/admin/roleSave.ts +0 -39
  100. package/apis/auth/logout.ts +0 -17
  101. package/apis/auth/register.ts +0 -43
  102. package/apis/dashboard/changelog.ts +0 -31
  103. package/apis/role/apiDetail.ts +0 -24
  104. package/apis/role/menuDetail.ts +0 -24
  105. package/views/403_1/meta.json +0 -4
  106. package/views/config/dict/meta.json +0 -4
  107. package/views/config/meta.json +0 -4
  108. package/views/config/system/meta.json +0 -4
  109. package/views/index/meta.json +0 -4
  110. package/views/log/email/meta.json +0 -4
  111. package/views/log/login/meta.json +0 -4
  112. package/views/log/meta.json +0 -4
  113. package/views/log/operate/meta.json +0 -4
  114. package/views/login_1/components/emailLoginForm.vue +0 -174
  115. package/views/login_1/components/registerForm.vue +0 -175
  116. package/views/login_1/components/welcomePanel.vue +0 -61
  117. package/views/login_1/meta.json +0 -4
  118. package/views/people/admin/meta.json +0 -4
  119. package/views/people/meta.json +0 -4
  120. package/views/permission/api/meta.json +0 -4
  121. package/views/permission/menu/meta.json +0 -4
  122. package/views/permission/meta.json +0 -4
  123. package/views/permission/role/meta.json +0 -4
@@ -1,162 +1,114 @@
1
1
  <template>
2
- <TDialog v-model:visible="$Data.visible" :title="$Prop.actionType === 'upd' ? '编辑字典' : '添加字典'" width="600px" :append-to-body="true" :show-footer="true" :esc-closable="false" top="10vh" @close="$Method.onClose">
3
- <TForm :model="$Data.formData" label-width="120px" label-position="left" :rules="$Data2.formRules" :ref="(el) => ($From.form = el)">
4
- <TFormItem label="字典名称" prop="name">
5
- <TInput v-model="$Data.formData.name" placeholder="请输入字典名称" />
2
+ <TDialog v-model:visible="visible" :header="actionType === 'add' ? '添加字典项' : '编辑字典项'" width="600px" @confirm="$Method.handleSubmit" @close="$Method.handleClose">
3
+ <TForm ref="formRef" :data="$Data.formData" :rules="$Data.rules" label-width="100px">
4
+ <TFormItem label="字典类型" name="typeCode">
5
+ <TSelect v-model="$Data.formData.typeCode" placeholder="请选择字典类型" filterable>
6
+ <TOption v-for="item in typeList" :key="item.code" :value="item.code" :label="item.name" />
7
+ </TSelect>
6
8
  </TFormItem>
7
- <TFormItem label="字典代码" prop="code">
8
- <TInput v-model="$Data.formData.code" placeholder="请输入字典代码,如:gender" />
9
+ <TFormItem label="键值" name="key">
10
+ <TInput v-model="$Data.formData.key" placeholder="请输入键名(英文/数字/下划线)" />
9
11
  </TFormItem>
10
- <TFormItem label="字典值" prop="value">
11
- <TInput v-model="$Data.formData.value" placeholder="请输入字典值" />
12
+ <TFormItem label="标签" name="label">
13
+ <TInput v-model="$Data.formData.label" placeholder="请输入标签(显示名称)" />
12
14
  </TFormItem>
13
- <TFormItem label="父级ID" prop="pid">
14
- <TInputNumber v-model="$Data.formData.pid" :min="0" />
15
+ <TFormItem label="排序" name="sort">
16
+ <TInputNumber v-model="$Data.formData.sort" :min="0" placeholder="请输入排序值" />
15
17
  </TFormItem>
16
- <TFormItem label="排序" prop="sort">
17
- <TInputNumber v-model="$Data.formData.sort" :min="0" :max="9999" />
18
- </TFormItem>
19
- <TFormItem label="描述" prop="description">
20
- <TInput v-model="$Data.formData.description" type="textarea" placeholder="请输入描述" :rows="3" />
21
- </TFormItem>
22
- <TFormItem label="状态" prop="state">
23
- <TRadioGroup v-model="$Data.formData.state">
24
- <TRadio :label="1">正常</TRadio>
25
- <TRadio :label="2">禁用</TRadio>
26
- </TRadioGroup>
18
+ <TFormItem label="备注" name="remark">
19
+ <TTextarea v-model="$Data.formData.remark" placeholder="请输入备注信息" :autosize="{ minRows: 3, maxRows: 6 }" />
27
20
  </TFormItem>
28
21
  </TForm>
29
- <template #footer>
30
- <TButton @click="$Method.onClose">取消</TButton>
31
- <TButton theme="primary" :loading="$Data.submitting" @click="$Method.onSubmit">确定</TButton>
32
- </template>
33
22
  </TDialog>
34
23
  </template>
35
24
 
36
25
  <script setup>
37
- import { watch } from 'vue';
38
- import { Dialog as TDialog, Form as TForm, FormItem as TFormItem, Input as TInput, InputNumber as TInputNumber, RadioGroup as TRadioGroup, Radio as TRadio, Button as TButton, MessagePlugin } from 'tdesign-vue-next';
39
- import { $Http } from '@/plugins/http';
26
+ import { Dialog as TDialog, Form as TForm, FormItem as TFormItem, Input as TInput, Select as TSelect, Option as TOption, Textarea as TTextarea, InputNumber as TInputNumber, MessagePlugin } from "tdesign-vue-next";
27
+ import { $Http } from "@/plugins/http";
40
28
 
41
- const $Prop = defineProps({
42
- modelValue: {
43
- type: Boolean,
44
- default: false
45
- },
46
- actionType: {
47
- type: String,
48
- default: 'add'
49
- },
50
- rowData: {
51
- type: Object,
52
- default: {}
53
- }
29
+ const props = defineProps({
30
+ modelValue: Boolean,
31
+ actionType: String,
32
+ rowData: Object,
33
+ typeList: Array
54
34
  });
55
35
 
56
- const $Emit = defineEmits(['update:modelValue', 'success']);
36
+ const emit = defineEmits(["update:modelValue", "success"]);
57
37
 
58
- // 表单引用
59
- const $From = $shallowRef({
60
- form: null
38
+ const visible = computed({
39
+ get: () => props.modelValue,
40
+ set: (val) => emit("update:modelValue", val)
61
41
  });
62
42
 
43
+ const formRef = $ref(null);
44
+
63
45
  const $Data = $ref({
64
- visible: false,
65
- submitting: false,
66
46
  formData: {
67
- id: 0,
68
- name: '',
69
- code: '',
70
- value: '',
71
- pid: 0,
47
+ typeCode: "",
48
+ key: "",
49
+ label: "",
72
50
  sort: 0,
73
- description: '',
74
- state: 1
75
- }
76
- });
77
-
78
- const $Data2 = $shallowRef({
79
- formRules: {
80
- name: [{ required: true, message: '请输入字典名称', trigger: 'blur' }],
81
- code: [
82
- { required: true, message: '请输入字典代码', trigger: 'blur' },
83
- { pattern: /^[a-zA-Z0-9_]+$/, message: '字典代码只能包含字母、数字和下划线', trigger: 'blur' }
84
- ],
85
- value: [{ required: true, message: '请输入字典值', trigger: 'blur' }]
51
+ remark: ""
52
+ },
53
+ rules: {
54
+ typeCode: [{ required: true, message: "请选择字典类型" }],
55
+ key: [{ required: true, message: "请输入键值" }],
56
+ label: [{ required: true, message: "请输入标签" }]
86
57
  }
87
58
  });
88
59
 
89
- // 方法集合
90
60
  const $Method = {
91
- async initData() {
92
- $Method.onShow();
93
- },
94
-
95
- onShow() {
96
- $Data.visible = true;
97
- if ($Prop.actionType === 'upd' && $Prop.rowData) {
98
- $Data.formData.id = $Prop.rowData.id || 0;
99
- $Data.formData.name = $Prop.rowData.name || '';
100
- $Data.formData.code = $Prop.rowData.code || '';
101
- $Data.formData.value = $Prop.rowData.value || '';
102
- $Data.formData.pid = $Prop.rowData.pid || 0;
103
- $Data.formData.sort = $Prop.rowData.sort || 0;
104
- $Data.formData.description = $Prop.rowData.description || '';
105
- $Data.formData.state = $Prop.rowData.state ?? 1;
106
- } else {
107
- // 重置表单
108
- $Data.formData.id = 0;
109
- $Data.formData.name = '';
110
- $Data.formData.code = '';
111
- $Data.formData.value = '';
112
- $Data.formData.pid = 0;
113
- $Data.formData.sort = 0;
114
- $Data.formData.description = '';
115
- $Data.formData.state = 1;
116
- }
117
- },
118
-
119
- onClose() {
120
- $Data.visible = false;
121
- setTimeout(() => {
122
- $Emit('update:modelValue', false);
123
- }, 300);
124
- },
125
-
126
- async onSubmit() {
61
+ async handleSubmit() {
127
62
  try {
128
- const valid = await $From.form.validate();
129
- if (!valid) return;
130
-
131
- $Data.submitting = true;
132
- const res = await $Http($Prop.actionType === 'add' ? '/addon/admin/dictIns' : '/addon/admin/dictUpd', $Data.formData);
63
+ const valid = await formRef.validate();
64
+ const apiUrl = props.actionType === "add" ? "/addon/admin/dict/ins" : "/addon/admin/dict/upd";
65
+ const params = {
66
+ typeCode: $Data.formData.typeCode,
67
+ key: $Data.formData.key,
68
+ label: $Data.formData.label,
69
+ sort: $Data.formData.sort,
70
+ remark: $Data.formData.remark
71
+ };
72
+ if (props.actionType === "upd") {
73
+ params.id = props.rowData.id;
74
+ }
133
75
 
134
- MessagePlugin.success($Prop.actionType === 'add' ? '添加成功' : '编辑成功');
135
- $Method.onClose();
136
- $Emit('success');
76
+ const res = await $Http(apiUrl, params);
77
+ if (res.code === 0) {
78
+ MessagePlugin.success(props.actionType === "add" ? "添加成功" : "更新成功");
79
+ visible.value = false;
80
+ emit("success");
81
+ } else {
82
+ MessagePlugin.error(res.msg || "操作失败");
83
+ }
137
84
  } catch (error) {
138
- console.error('提交失败:', error);
139
- MessagePlugin.error('提交失败');
140
- } finally {
141
- $Data.submitting = false;
85
+ MessagePlugin.error("操作失败");
142
86
  }
87
+ },
88
+ handleClose() {
89
+ visible.value = false;
143
90
  }
144
91
  };
145
92
 
146
- // 监听 modelValue 变化
147
93
  watch(
148
- () => $Prop.modelValue,
94
+ () => props.modelValue,
149
95
  (val) => {
150
- if (val && !$Data.visible) {
151
- $Method.initData();
152
- } else if (!val && $Data.visible) {
153
- $Data.visible = false;
96
+ if (val) {
97
+ if (props.actionType === "upd" && props.rowData) {
98
+ $Data.formData.typeCode = props.rowData.typeCode || "";
99
+ $Data.formData.key = props.rowData.key || "";
100
+ $Data.formData.label = props.rowData.label || "";
101
+ $Data.formData.sort = props.rowData.sort || 0;
102
+ $Data.formData.remark = props.rowData.remark || "";
103
+ } else {
104
+ $Data.formData.typeCode = "";
105
+ $Data.formData.key = "";
106
+ $Data.formData.label = "";
107
+ $Data.formData.sort = 0;
108
+ $Data.formData.remark = "";
109
+ }
154
110
  }
155
111
  },
156
112
  { immediate: true }
157
113
  );
158
114
  </script>
159
-
160
- <style scoped lang="scss">
161
- // 可根据需要添加样式
162
- </style>
@@ -9,6 +9,14 @@
9
9
  </TButton>
10
10
  </div>
11
11
  <div class="right">
12
+ <TSelect v-model="$Data.searchTypeCode" placeholder="请选择字典类型" clearable filterable @change="$Method.handleSearch">
13
+ <TOption v-for="item in $Data.typeList" :key="item.code" :value="item.code" :label="item.name" />
14
+ </TSelect>
15
+ <TInput v-model="$Data.searchKeyword" placeholder="搜索键/标签" clearable @enter="$Method.handleSearch" @clear="$Method.handleSearch">
16
+ <template #suffix-icon>
17
+ <ILucideSearch />
18
+ </template>
19
+ </TInput>
12
20
  <TButton shape="circle" @click="$Method.handleRefresh">
13
21
  <template #icon>
14
22
  <ILucideRotateCw />
@@ -18,12 +26,16 @@
18
26
  </div>
19
27
  <div class="main-content">
20
28
  <div class="main-table">
21
- <TTable :data="$Data.dictList" :columns="$Data.columns" :loading="$Data.loading" :active-row-keys="$Data.activeRowKeys" row-key="id" height="calc(100vh - var(--search-height) - var(--pagination-height) - var(--layout-gap) * 4)" active-row-type="single" @active-change="$Method.onActiveChange">
22
- <template #state="{ row }">
23
- <TTag v-if="row.state === 1" shape="round" theme="success" variant="light-outline">正常</TTag>
24
- <TTag v-else-if="row.state === 2" shape="round" theme="warning" variant="light-outline">禁用</TTag>
25
- <TTag v-else shape="round" theme="danger" variant="light-outline">已删除</TTag>
26
- </template>
29
+ <TTable
30
+ :data="$Data.tableData"
31
+ :columns="$Data.columns"
32
+ :loading="$Data.loading"
33
+ :active-row-keys="$Data.activeRowKeys"
34
+ row-key="id"
35
+ height="calc(100vh - var(--search-height) - var(--pagination-height) - var(--layout-gap) * 4)"
36
+ active-row-type="single"
37
+ @active-change="$Method.onActiveChange"
38
+ >
27
39
  <template #operation="{ row }">
28
40
  <TDropdown trigger="click" placement="bottom-right" @click="(data) => $Method.onAction(data.value, row)">
29
41
  <TButton theme="primary" size="small">
@@ -54,153 +66,199 @@
54
66
  <TPagination :current-page="$Data.pagerConfig.currentPage" :page-size="$Data.pagerConfig.limit" :total="$Data.pagerConfig.total" @current-change="$Method.onPageChange" @page-size-change="$Method.handleSizeChange" />
55
67
  </div>
56
68
 
57
- <!-- 编辑对话框组件 -->
58
- <EditDialog v-if="$Data.editVisible" v-model="$Data.editVisible" :action-type="$Data.actionType" :row-data="$Data.rowData" @success="$Method.apiDictList" />
69
+ <EditDialog v-if="$Data.editVisible" v-model="$Data.editVisible" :action-type="$Data.actionType" :row-data="$Data.rowData" :type-list="$Data.typeList" @success="$Method.apiDictList" />
59
70
  </div>
60
71
  </template>
61
72
 
62
73
  <script setup>
63
- import { Button as TButton, Table as TTable, Tag as TTag, Dropdown as TDropdown, DropdownMenu as TDropdownMenu, DropdownItem as TDropdownItem, Pagination as TPagination, MessagePlugin, DialogPlugin } from 'tdesign-vue-next';
64
- import ILucidePlus from '~icons/lucide/plus';
65
- import ILucideRotateCw from '~icons/lucide/rotate-cw';
66
- import ILucidePencil from '~icons/lucide/pencil';
67
- import ILucideTrash2 from '~icons/lucide/trash-2';
68
- import ILucideChevronDown from '~icons/lucide/chevron-down';
69
- import EditDialog from './components/edit.vue';
70
- import DetailPanel from '@/components/DetailPanel.vue';
71
- import { $Http } from '@/plugins/http';
72
- import { withDefaultColumns } from 'befly-shared/withDefaultColumns';
74
+ import { Button as TButton, Table as TTable, Input as TInput, Select as TSelect, Option as TOption, Dropdown as TDropdown, DropdownMenu as TDropdownMenu, DropdownItem as TDropdownItem, Pagination as TPagination, MessagePlugin, DialogPlugin } from "tdesign-vue-next";
75
+ import ILucidePlus from "~icons/lucide/plus";
76
+ import ILucideRotateCw from "~icons/lucide/rotate-cw";
77
+ import ILucideSearch from "~icons/lucide/search";
78
+ import ILucidePencil from "~icons/lucide/pencil";
79
+ import ILucideTrash2 from "~icons/lucide/trash-2";
80
+ import ILucideChevronDown from "~icons/lucide/chevron-down";
81
+ import EditDialog from "./components/edit.vue";
82
+ import DetailPanel from "@/components/DetailPanel.vue";
83
+ import { $Http } from "@/plugins/http";
84
+ import { withDefaultColumns } from "befly-vite/utils/withDefaultColumns";
85
+
86
+ definePage({
87
+ meta: {
88
+ title: "字典列表",
89
+ order: 1
90
+ }
91
+ });
73
92
 
74
- // 响应式数据
75
93
  const $Data = $ref({
76
- dictList: [],
94
+ tableData: [],
95
+ typeList: [],
77
96
  loading: false,
78
97
  activeRowKeys: [],
79
98
  currentRow: null,
99
+ searchTypeCode: "",
100
+ searchKeyword: "",
80
101
  columns: withDefaultColumns([
81
- { colKey: 'index', title: '序号' },
82
- { colKey: 'name', title: '字典名称' },
83
- { colKey: 'code', title: '字典代码' },
84
- { colKey: 'value', title: '字典值' },
85
- { colKey: 'pid', title: '父级ID' },
86
- { colKey: 'sort', title: '排序' },
87
- { colKey: 'description', title: '描述' },
88
- { colKey: 'state', title: '状态' },
89
- { colKey: 'operation', title: '操作' }
102
+ { colKey: "id", title: "ID" },
103
+ { colKey: "typeName", title: "类型名称" },
104
+ { colKey: "typeCode", title: "类型代码" },
105
+ { colKey: "label", title: "标签" },
106
+ { colKey: "key", title: "键值" },
107
+ { colKey: "sort", title: "排序", width: 100 },
108
+ { colKey: "remark", title: "备注" },
109
+ { colKey: "operation", title: "操作" }
90
110
  ]),
91
111
  pagerConfig: {
92
112
  currentPage: 1,
93
113
  limit: 30,
94
114
  total: 0,
95
- align: 'right',
96
- layout: 'total, prev, pager, next, jumper'
115
+ align: "right",
116
+ layout: "total, prev, pager, next, jumper"
97
117
  },
98
118
  editVisible: false,
99
- actionType: 'add',
119
+ actionType: "add",
100
120
  rowData: {}
101
121
  });
102
122
 
103
- // 方法
104
123
  const $Method = {
105
124
  async initData() {
125
+ await $Method.apiDictTypeAll();
106
126
  await $Method.apiDictList();
107
127
  },
108
-
109
- // 加载字典列表
128
+ async apiDictTypeAll() {
129
+ try {
130
+ const res = await $Http("/addon/admin/dictType/all");
131
+ $Data.typeList = res.data.lists || [];
132
+ } catch (error) {
133
+ MessagePlugin.error("加载数据失败");
134
+ }
135
+ },
110
136
  async apiDictList() {
111
137
  $Data.loading = true;
112
138
  try {
113
- const res = await $Http('/addon/admin/dict/list', {
139
+ const res = await $Http("/addon/admin/dict/list", {
114
140
  page: $Data.pagerConfig.currentPage,
115
- limit: $Data.pagerConfig.limit
141
+ limit: $Data.pagerConfig.limit,
142
+ typeCode: $Data.searchTypeCode,
143
+ keyword: $Data.searchKeyword
116
144
  });
117
- $Data.dictList = res.data.lists || [];
145
+ $Data.tableData = res.data.lists || [];
118
146
  $Data.pagerConfig.total = res.data.total || 0;
119
147
 
120
- // 自动选中并高亮第一行
121
- if ($Data.dictList.length > 0) {
122
- $Data.currentRow = $Data.dictList[0];
123
- $Data.activeRowKeys = [$Data.dictList[0].id];
148
+ if ($Data.tableData.length > 0) {
149
+ $Data.currentRow = $Data.tableData[0];
150
+ $Data.activeRowKeys = [$Data.tableData[0].id];
124
151
  } else {
125
152
  $Data.currentRow = null;
126
153
  $Data.activeRowKeys = [];
127
154
  }
128
155
  } catch (error) {
129
- console.error('加载字典列表失败:', error);
130
- MessagePlugin.error('加载数据失败');
156
+ MessagePlugin.error("加载数据失败");
131
157
  } finally {
132
158
  $Data.loading = false;
133
159
  }
134
160
  },
135
-
136
- // 删除字典
137
161
  async apiDictDel(row) {
138
- DialogPlugin.confirm({
139
- header: '确认删除',
140
- body: `确定要删除字典“${row.name}” 吗?`,
141
- status: 'warning'
142
- }).then(async () => {
143
- try {
144
- const res = await $Http('/addon/admin/dict/del', { id: row.id });
145
- if (res.code === 0) {
146
- MessagePlugin.success('删除成功');
147
- $Method.apiDictList();
148
- } else {
149
- MessagePlugin.error(res.msg || '删除失败');
162
+ let dialog = null;
163
+ let destroyed = false;
164
+
165
+ const destroy = () => {
166
+ if (destroyed) return;
167
+ destroyed = true;
168
+ if (dialog && typeof dialog.destroy === "function") {
169
+ dialog.destroy();
170
+ }
171
+ };
172
+
173
+ dialog = DialogPlugin.confirm({
174
+ header: "确认删除",
175
+ body: `确认删除字典项“${row.label}”吗?`,
176
+ status: "warning",
177
+ confirmBtn: "删除",
178
+ cancelBtn: "取消",
179
+ onConfirm: async () => {
180
+ if (dialog && typeof dialog.setConfirmLoading === "function") {
181
+ dialog.setConfirmLoading(true);
182
+ }
183
+
184
+ try {
185
+ await $Http("/addon/admin/dict/del", { id: row.id });
186
+ MessagePlugin.success("删除成功");
187
+ destroy();
188
+ await $Method.apiDictList();
189
+ } catch (error) {
190
+ MessagePlugin.error("删除失败");
191
+ } finally {
192
+ if (dialog && typeof dialog.setConfirmLoading === "function") {
193
+ dialog.setConfirmLoading(false);
194
+ }
150
195
  }
151
- } catch (error) {
152
- console.error('删除失败:', error);
153
- MessagePlugin.error('删除失败');
196
+ },
197
+ onClose: () => {
198
+ destroy();
154
199
  }
155
200
  });
156
201
  },
157
-
158
- // 刷新
202
+ handleSearch() {
203
+ $Data.pagerConfig.currentPage = 1;
204
+ $Method.apiDictList();
205
+ },
159
206
  handleRefresh() {
207
+ $Data.searchTypeCode = "";
208
+ $Data.searchKeyword = "";
209
+ $Data.pagerConfig.currentPage = 1;
160
210
  $Method.apiDictList();
161
211
  },
162
-
163
- // 分页改变
164
212
  onPageChange({ currentPage }) {
165
213
  $Data.pagerConfig.currentPage = currentPage;
166
214
  $Method.apiDictList();
167
215
  },
168
-
169
- // 每页条数改变
170
216
  handleSizeChange({ pageSize }) {
171
217
  $Data.pagerConfig.limit = pageSize;
172
218
  $Data.pagerConfig.currentPage = 1;
173
219
  $Method.apiDictList();
174
220
  },
175
-
176
- // 高亮行变化
177
221
  onActiveChange(value, context) {
178
- // 禁止取消高亮:如果新值为空,保持当前选中
179
222
  if (value.length === 0 && $Data.activeRowKeys.length > 0) {
180
223
  return;
181
224
  }
182
225
  $Data.activeRowKeys = value;
183
- // 更新当前高亮的行数据
184
- if (context.activeRowList && context.activeRowList.length > 0) {
185
- $Data.currentRow = context.activeRowList[0].row;
186
- }
226
+ $Data.currentRow = context.currentRowData;
187
227
  },
188
-
189
- // 操作菜单点击
190
- onAction(command, rowData) {
191
- $Data.actionType = command;
192
- $Data.rowData = rowData;
193
- if (command === 'add' || command === 'upd') {
228
+ onAction(type, row) {
229
+ if (type === "add") {
230
+ $Data.actionType = "add";
231
+ $Data.rowData = {};
232
+ $Data.editVisible = true;
233
+ } else if (type === "upd") {
234
+ $Data.actionType = "upd";
235
+ $Data.rowData = { ...row };
194
236
  $Data.editVisible = true;
195
- } else if (command === 'del') {
196
- $Method.apiDictDel(rowData);
237
+ } else if (type === "del") {
238
+ $Method.apiDictDel(row);
197
239
  }
198
240
  }
199
241
  };
200
242
 
201
- $Method.initData();
243
+ onMounted(() => {
244
+ $Method.initData();
245
+ });
202
246
  </script>
203
247
 
204
248
  <style scoped lang="scss">
205
- // 样式继承自全局 page-table
249
+ .page-dict {
250
+ .main-tool .right {
251
+ display: flex;
252
+ gap: 8px;
253
+ align-items: center;
254
+
255
+ .t-select {
256
+ width: 200px;
257
+ }
258
+
259
+ .t-input {
260
+ width: 240px;
261
+ }
262
+ }
263
+ }
206
264
  </style>
@@ -0,0 +1,105 @@
1
+ <template>
2
+ <TDialog v-model:visible="visible" :header="actionType === 'add' ? '添加字典类型' : '编辑字典类型'" width="600px" @confirm="$Method.handleSubmit" @close="$Method.handleClose">
3
+ <TForm ref="formRef" :data="$Data.formData" :rules="$Data.rules" label-width="100px">
4
+ <TFormItem label="类型代码" name="code">
5
+ <TInput v-model="$Data.formData.code" placeholder="请输入类型代码(英文/数字/下划线)" :disabled="actionType === 'upd'" />
6
+ </TFormItem>
7
+ <TFormItem label="类型名称" name="name">
8
+ <TInput v-model="$Data.formData.name" placeholder="请输入类型名称" />
9
+ </TFormItem>
10
+ <TFormItem label="描述" name="description">
11
+ <TTextarea v-model="$Data.formData.description" placeholder="请输入描述信息" :autosize="{ minRows: 3, maxRows: 6 }" />
12
+ </TFormItem>
13
+ <TFormItem label="排序" name="sort">
14
+ <TInputNumber v-model="$Data.formData.sort" :min="0" placeholder="请输入排序值" />
15
+ </TFormItem>
16
+ </TForm>
17
+ </TDialog>
18
+ </template>
19
+
20
+ <script setup>
21
+ import { Dialog as TDialog, Form as TForm, FormItem as TFormItem, Input as TInput, Textarea as TTextarea, InputNumber as TInputNumber, MessagePlugin } from "tdesign-vue-next";
22
+ import { $Http } from "@/plugins/http";
23
+
24
+ const props = defineProps({
25
+ modelValue: Boolean,
26
+ actionType: String,
27
+ rowData: Object
28
+ });
29
+
30
+ const emit = defineEmits(["update:modelValue", "success"]);
31
+
32
+ const visible = computed({
33
+ get: () => props.modelValue,
34
+ set: (val) => emit("update:modelValue", val)
35
+ });
36
+
37
+ const formRef = $ref(null);
38
+
39
+ const $Data = $ref({
40
+ formData: {
41
+ code: "",
42
+ name: "",
43
+ description: "",
44
+ sort: 0
45
+ },
46
+ rules: {
47
+ code: [{ required: true, message: "请输入类型代码" }],
48
+ name: [{ required: true, message: "请输入类型名称" }]
49
+ }
50
+ });
51
+
52
+ const $Method = {
53
+ async handleSubmit() {
54
+ const valid = await formRef.validate();
55
+ if (!valid) return;
56
+
57
+ try {
58
+ const apiUrl = props.actionType === "add" ? "/addon/admin/dictType/ins" : "/addon/admin/dictType/upd";
59
+ const params = {
60
+ code: $Data.formData.code,
61
+ name: $Data.formData.name,
62
+ description: $Data.formData.description,
63
+ sort: $Data.formData.sort
64
+ };
65
+ if (props.actionType === "upd") {
66
+ params.id = props.rowData.id;
67
+ }
68
+
69
+ const res = await $Http(apiUrl, params);
70
+ if (res.code === 0) {
71
+ MessagePlugin.success(props.actionType === "add" ? "添加成功" : "更新成功");
72
+ visible.value = false;
73
+ emit("success");
74
+ } else {
75
+ MessagePlugin.error(res.msg || "操作失败");
76
+ }
77
+ } catch (error) {
78
+ MessagePlugin.error("操作失败");
79
+ }
80
+ },
81
+ handleClose() {
82
+ visible.value = false;
83
+ }
84
+ };
85
+
86
+ watch(
87
+ () => props.modelValue,
88
+ (val) => {
89
+ if (val) {
90
+ if (props.actionType === "upd" && props.rowData) {
91
+ $Data.formData.code = props.rowData.code || "";
92
+ $Data.formData.name = props.rowData.name || "";
93
+ $Data.formData.description = props.rowData.description || "";
94
+ $Data.formData.sort = props.rowData.sort || 0;
95
+ } else {
96
+ $Data.formData.code = "";
97
+ $Data.formData.name = "";
98
+ $Data.formData.description = "";
99
+ $Data.formData.sort = 0;
100
+ }
101
+ }
102
+ },
103
+ { immediate: true }
104
+ );
105
+ </script>