@liujitcn/kratos-admin-system 0.0.49 → 0.0.51

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 (107) hide show
  1. package/README.md +44 -8
  2. package/dist/package/declarations/src/api/system/admin/v1/base_i18n_custom.d.ts +18 -0
  3. package/dist/package/declarations/src/api/system/admin/v1/base_redact_output_policy.d.ts +4 -1
  4. package/dist/package/declarations/src/api/system/admin/v1/base_redact_storage_policy.d.ts +3 -1
  5. package/dist/package/declarations/src/api/system/admin/v1/base_tenant.d.ts +2 -2
  6. package/dist/package/declarations/src/api/system/admin/v1/base_tenant_project.d.ts +23 -0
  7. package/dist/package/declarations/src/api/system/admin/v1/base_tenant_project_grant.d.ts +16 -0
  8. package/dist/package/declarations/src/components/tenant-project/TenantProjectManager.vue.d.ts +29 -0
  9. package/dist/package/declarations/src/components/tenant-project/TenantProjectSelect.vue.d.ts +31 -0
  10. package/dist/package/declarations/src/components/tenant-project/TenantProjectText.vue.d.ts +19 -0
  11. package/dist/package/declarations/src/components/tenant-project/tenant-project-manager-data.d.ts +14 -0
  12. package/dist/package/declarations/src/components/tenant-project/tenant-project-manager.d.ts +40 -0
  13. package/dist/package/declarations/src/components/tenant-project-grant/ProjectGrantDialog.vue.d.ts +8 -0
  14. package/dist/package/declarations/src/index.d.ts +2 -0
  15. package/dist/package/declarations/src/locales/generated.d.ts +196 -0
  16. package/dist/package/declarations/src/rpc/base/v1/config.d.ts +11 -0
  17. package/dist/package/declarations/src/rpc/system/admin/v1/base_i18n_custom.d.ts +105 -0
  18. package/dist/package/declarations/src/rpc/system/admin/v1/base_redact_output_policy.d.ts +8 -0
  19. package/dist/package/declarations/src/rpc/system/admin/v1/base_redact_storage_policy.d.ts +25 -0
  20. package/dist/package/declarations/src/rpc/system/admin/v1/base_tenant.d.ts +10 -1
  21. package/dist/package/declarations/src/rpc/system/admin/v1/base_tenant_project.d.ts +141 -0
  22. package/dist/package/declarations/src/rpc/system/admin/v1/base_tenant_project_grant.d.ts +105 -0
  23. package/dist/package/declarations/src/views/ai/chat/components/SessionPanel.vue.d.ts +2 -2
  24. package/dist/package/declarations/src/views/ai/chat/components/speech-recognition.d.ts +33 -0
  25. package/dist/package/declarations/src/views/base/i18n-custom/index.vue.d.ts +3 -0
  26. package/dist/package/declarations/src/views/base/tenant-project/index.vue.d.ts +3 -0
  27. package/dist/package/declarations/src/views/base/tenant-project-grant/index.vue.d.ts +3 -0
  28. package/dist/package/src/api/system/admin/v1/base_i18n_custom.ts +72 -0
  29. package/dist/package/src/api/system/admin/v1/base_redact_output_policy.ts +7 -0
  30. package/dist/package/src/api/system/admin/v1/base_redact_storage_policy.ts +7 -0
  31. package/dist/package/src/api/system/admin/v1/base_tenant.ts +3 -2
  32. package/dist/package/src/api/system/admin/v1/base_tenant_project.ts +94 -0
  33. package/dist/package/src/api/system/admin/v1/base_tenant_project_grant.ts +63 -0
  34. package/dist/package/src/components/tenant-project/TenantProjectManager.vue +431 -0
  35. package/dist/package/src/components/tenant-project/TenantProjectSelect.vue +83 -0
  36. package/dist/package/src/components/tenant-project/TenantProjectText.vue +37 -0
  37. package/dist/package/src/components/tenant-project/tenant-project-manager-data.ts +26 -0
  38. package/dist/package/src/components/tenant-project/tenant-project-manager.ts +48 -0
  39. package/dist/package/src/components/tenant-project-grant/ProjectGrantDialog.vue +108 -0
  40. package/dist/package/src/index.ts +12 -0
  41. package/dist/package/src/locales/README.md +1 -1
  42. package/dist/package/src/locales/en-US.json +51 -2
  43. package/dist/package/src/locales/ja-JP.json +51 -2
  44. package/dist/package/src/locales/zh-CN.json +51 -2
  45. package/dist/package/src/locales/zh-TW.json +51 -2
  46. package/dist/package/src/module.ts +3 -3
  47. package/dist/package/src/rpc/base/v1/config.ts +12 -0
  48. package/dist/package/src/rpc/system/admin/v1/base_i18n_custom.ts +126 -0
  49. package/dist/package/src/rpc/system/admin/v1/base_redact_output_policy.ts +9 -0
  50. package/dist/package/src/rpc/system/admin/v1/base_redact_storage_policy.ts +30 -0
  51. package/dist/package/src/rpc/system/admin/v1/base_tenant.ts +11 -1
  52. package/dist/package/src/rpc/system/admin/v1/base_tenant_project.ts +166 -0
  53. package/dist/package/src/rpc/system/admin/v1/base_tenant_project_grant.ts +128 -0
  54. package/dist/package/src/views/ai/chat/components/XSender.vue +21 -28
  55. package/dist/package/src/views/ai/chat/components/speech-recognition.ts +156 -0
  56. package/dist/package/src/views/base/api-log/index.vue +3 -3
  57. package/dist/package/src/views/base/config/index.vue +3 -3
  58. package/dist/package/src/views/base/data-access-log/index.vue +3 -3
  59. package/dist/package/src/views/base/dept/index.vue +10 -45
  60. package/dist/package/src/views/base/dict/index.vue +3 -3
  61. package/dist/package/src/views/base/dict/item.vue +3 -3
  62. package/dist/package/src/views/base/file/index.vue +12 -3
  63. package/dist/package/src/views/base/i18n-custom/index.vue +321 -0
  64. package/dist/package/src/views/base/job/index.vue +85 -161
  65. package/dist/package/src/views/base/login-log/index.vue +13 -4
  66. package/dist/package/src/views/base/login-policy/index.vue +109 -40
  67. package/dist/package/src/views/base/menu/index.vue +3 -3
  68. package/dist/package/src/views/base/message/index.vue +9 -32
  69. package/dist/package/src/views/base/message-category/index.vue +2 -4
  70. package/dist/package/src/views/base/oauth-client/index.vue +8 -42
  71. package/dist/package/src/views/base/online-session/index.vue +8 -27
  72. package/dist/package/src/views/base/operation-log/index.vue +3 -3
  73. package/dist/package/src/views/base/permission-log/index.vue +3 -3
  74. package/dist/package/src/views/base/policy-evaluation-log/index.vue +3 -3
  75. package/dist/package/src/views/base/post/index.vue +9 -42
  76. package/dist/package/src/views/base/redact-output-policy/index.vue +19 -7
  77. package/dist/package/src/views/base/redact-rule/index.vue +70 -53
  78. package/dist/package/src/views/base/redact-storage-policy/index.vue +18 -7
  79. package/dist/package/src/views/base/role/index.vue +14 -48
  80. package/dist/package/src/views/base/tenant/index.vue +163 -19
  81. package/dist/package/src/views/base/tenant-project/index.vue +12 -0
  82. package/dist/package/src/views/base/tenant-project-grant/index.vue +338 -0
  83. package/dist/package/src/views/base/user/index.vue +30 -51
  84. package/dist/package/src/views/profile/components/login-log.vue +15 -2
  85. package/dist/package/src/views/profile/components/password.vue +1 -1
  86. package/dist/package/src/views/profile/components/security.vue +2 -2
  87. package/dist/package/src/views/tool/code-gen/components/CodeGenLocaleEditor.vue +2 -2
  88. package/dist/package/src/views/tool/code-gen/config.ts +2 -1
  89. package/package.json +2 -2
  90. /package/dist/package/declarations/src/components/{ChangePasswordForm.vue.d.ts → account/ChangePasswordForm.vue.d.ts} +0 -0
  91. /package/dist/package/declarations/src/components/{ForcedPasswordDialog.vue.d.ts → account/ForcedPasswordDialog.vue.d.ts} +0 -0
  92. /package/dist/package/declarations/src/components/{Ai.vue.d.ts → ai/Ai.vue.d.ts} +0 -0
  93. /package/dist/package/declarations/src/components/{DynamicI18nCell.vue.d.ts → i18n/DynamicI18nCell.vue.d.ts} +0 -0
  94. /package/dist/package/declarations/src/components/{DynamicI18nEditor.vue.d.ts → i18n/DynamicI18nEditor.vue.d.ts} +0 -0
  95. /package/dist/package/declarations/src/components/{dynamicI18n.d.ts → i18n/dynamicI18n.d.ts} +0 -0
  96. /package/dist/package/declarations/src/components/{LogTable.vue.d.ts → log/LogTable.vue.d.ts} +0 -0
  97. /package/dist/package/declarations/src/components/{log.d.ts → log/log.d.ts} +0 -0
  98. /package/dist/package/declarations/src/components/{Notification.vue.d.ts → notification/Notification.vue.d.ts} +0 -0
  99. /package/dist/package/src/components/{ChangePasswordForm.vue → account/ChangePasswordForm.vue} +0 -0
  100. /package/dist/package/src/components/{ForcedPasswordDialog.vue → account/ForcedPasswordDialog.vue} +0 -0
  101. /package/dist/package/src/components/{Ai.vue → ai/Ai.vue} +0 -0
  102. /package/dist/package/src/components/{DynamicI18nCell.vue → i18n/DynamicI18nCell.vue} +0 -0
  103. /package/dist/package/src/components/{DynamicI18nEditor.vue → i18n/DynamicI18nEditor.vue} +0 -0
  104. /package/dist/package/src/components/{dynamicI18n.ts → i18n/dynamicI18n.ts} +0 -0
  105. /package/dist/package/src/components/{LogTable.vue → log/LogTable.vue} +0 -0
  106. /package/dist/package/src/components/{log.ts → log/log.ts} +0 -0
  107. /package/dist/package/src/components/{Notification.vue → notification/Notification.vue} +0 -0
@@ -0,0 +1,321 @@
1
+ <!-- 国际化自定义翻译 -->
2
+ <template>
3
+ <div class="table-box">
4
+ <ProTable
5
+ ref="proTable"
6
+ row-key="id"
7
+ :columns="columns"
8
+ :header-actions="headerActions"
9
+ :request-api="requestBaseI18nCustomTable"
10
+ />
11
+
12
+ <FormDialog
13
+ v-model="dialog.visible"
14
+ ref="formDialogRef"
15
+ :title="t(dialog.editing ? 'system.base.i18n_custom.action.edit' : 'system.base.i18n_custom.action.create')"
16
+ width="680px"
17
+ :model="formData"
18
+ :fields="formFields"
19
+ :rules="rules"
20
+ @confirm="handleSubmit"
21
+ @close="handleCloseDialog"
22
+ />
23
+ </div>
24
+ </template>
25
+
26
+ <script setup lang="ts">
27
+ import { computed, reactive, ref } from "vue";
28
+ import { ElMessage, ElMessageBox } from "element-plus";
29
+ import { CirclePlus, Delete, EditPen } from "@element-plus/icons-vue";
30
+ import type { ColumnProps, HeaderActionProps, ProTableInstance } from "@liujitcn/kratos-admin-core/components/ProTable/interface";
31
+ import ProTable from "@liujitcn/kratos-admin-core/components/ProTable";
32
+ import FormDialog from "@liujitcn/kratos-admin-core/components/Dialog/FormDialog.vue";
33
+ import type { ProFormField, ProFormOption } from "@liujitcn/kratos-admin-core/components/ProForm/interface";
34
+ import { useAuthButtons } from "@liujitcn/kratos-admin-core/auth";
35
+ import { buildPageRequest, normalizeSelectedIds } from "@liujitcn/kratos-admin-core/table";
36
+ import {
37
+ getCurrentLocale,
38
+ getDefaultLocaleText,
39
+ normalizeLocale,
40
+ refreshAdminRuntimeConfig,
41
+ t
42
+ } from "@liujitcn/kratos-admin-core";
43
+ import { defBaseI18nCustomService } from "@liujitcn/kratos-admin-system/api/system/admin/v1/base_i18n_custom";
44
+ import { loadEnabledBaseLanguages } from "@liujitcn/kratos-admin-system/api/system/admin/v1/base_language";
45
+ import type {
46
+ BaseI18nCustom,
47
+ BaseI18nCustomForm,
48
+ PageBaseI18nCustomRequest
49
+ } from "@liujitcn/kratos-admin-system/rpc/system/admin/v1/base_i18n_custom";
50
+ import { BaseConfigSite } from "@liujitcn/kratos-admin-system/rpc/base/v1/config";
51
+ import { Status } from "@liujitcn/kratos-admin-system/rpc/common/v1/enum";
52
+
53
+ defineOptions({ name: "BaseI18nCustom", inheritAttrs: false });
54
+
55
+ const { BUTTONS } = useAuthButtons();
56
+ const proTable = ref<ProTableInstance>();
57
+ const formDialogRef = ref<InstanceType<typeof FormDialog>>();
58
+ const enabledLanguages = ref<Array<{ language_code: string; native_name?: string; language_name?: string }>>([]);
59
+ const dialog = reactive({ editing: false, visible: false });
60
+ const formData = reactive<BaseI18nCustomForm>({
61
+ id: 0,
62
+ site: BaseConfigSite.BASE_CONFIG_SITE_ADMIN,
63
+ key: "",
64
+ locale: getCurrentLocale(),
65
+ value: "",
66
+ status: Status.STATUS_ENABLE,
67
+ remark: ""
68
+ });
69
+
70
+ const siteOptions = computed<ProFormOption[]>(() => [
71
+ { label: t("system.base.i18n_custom.site.system"), value: BaseConfigSite.BASE_CONFIG_SITE_SYSTEM },
72
+ { label: t("system.base.i18n_custom.site.admin"), value: BaseConfigSite.BASE_CONFIG_SITE_ADMIN },
73
+ { label: t("system.base.i18n_custom.site.app"), value: BaseConfigSite.BASE_CONFIG_SITE_APP }
74
+ ]);
75
+
76
+ const localeOptions = computed<ProFormOption[]>(() =>
77
+ enabledLanguages.value.map(item => ({
78
+ label: item.native_name || item.language_name || item.language_code,
79
+ value: item.language_code
80
+ }))
81
+ );
82
+
83
+ const statusOptions = computed<ProFormOption[]>(() => [
84
+ { label: t("common.status.enabled"), value: Status.STATUS_ENABLE },
85
+ { label: t("common.status.disabled"), value: Status.STATUS_DISABLE }
86
+ ]);
87
+
88
+ const rules = computed(() => ({
89
+ site: [{ required: true, message: t("system.base.i18n_custom.placeholder.site"), trigger: "change" }],
90
+ key: [{ required: true, message: t("system.base.i18n_custom.placeholder.key"), trigger: "blur" }],
91
+ locale: [{ required: true, message: t("system.base.i18n_custom.placeholder.locale"), trigger: "change" }],
92
+ value: [{ required: true, message: t("system.base.i18n_custom.placeholder.value"), trigger: "blur" }]
93
+ }));
94
+
95
+ const formFields = computed<ProFormField[]>(() => [
96
+ {
97
+ prop: "site",
98
+ label: t("system.base.i18n_custom.field.site"),
99
+ component: "select",
100
+ options: siteOptions.value,
101
+ props: { disabled: dialog.editing }
102
+ },
103
+ {
104
+ prop: "key",
105
+ label: t("system.base.i18n_custom.field.key"),
106
+ component: "input",
107
+ props: { maxlength: 255, placeholder: t("system.base.i18n_custom.placeholder.key"), disabled: dialog.editing }
108
+ },
109
+ {
110
+ prop: "locale",
111
+ label: t("system.base.i18n_custom.field.locale"),
112
+ component: "select",
113
+ options: localeOptions.value,
114
+ props: { filterable: true, placeholder: t("system.base.i18n_custom.placeholder.locale"), disabled: dialog.editing }
115
+ },
116
+ {
117
+ prop: "value",
118
+ label: t("system.base.i18n_custom.field.value"),
119
+ component: "input",
120
+ props: { type: "textarea", rows: 4, maxlength: 10000, showWordLimit: true, placeholder: t("system.base.i18n_custom.placeholder.value") }
121
+ },
122
+ { prop: "status", label: t("system.base.i18n_custom.field.status"), component: "radio-group", options: statusOptions.value },
123
+ {
124
+ prop: "remark",
125
+ label: t("system.base.i18n_custom.field.remark"),
126
+ component: "input",
127
+ props: { maxlength: 255, placeholder: t("system.base.i18n_custom.placeholder.remark") }
128
+ }
129
+ ]);
130
+
131
+ const columns = computed<ColumnProps[]>(() => [
132
+ { type: "selection", width: 55 },
133
+ { prop: "key", label: t("system.base.i18n_custom.field.key"), minWidth: 250, search: { el: "input" } },
134
+ {
135
+ prop: "site",
136
+ label: t("system.base.i18n_custom.field.site"),
137
+ width: 110,
138
+ search: { el: "select", enum: siteOptions.value },
139
+ render: scope => siteOptions.value.find(item => item.value === (scope.row as BaseI18nCustom).site)?.label || "-"
140
+ },
141
+ {
142
+ prop: "locale",
143
+ label: t("system.base.i18n_custom.field.locale"),
144
+ width: 120,
145
+ search: { el: "select", enum: localeOptions },
146
+ render: scope => getLanguageLabel((scope.row as BaseI18nCustom).locale)
147
+ },
148
+ {
149
+ prop: "default_value",
150
+ label: t("system.base.i18n_custom.field.default_value"),
151
+ minWidth: 200,
152
+ render: scope => getDefaultLocaleText(normalizeLocale((scope.row as BaseI18nCustom).locale), (scope.row as BaseI18nCustom).key) || "-"
153
+ },
154
+ { prop: "value", label: t("system.base.i18n_custom.field.value"), minWidth: 200 },
155
+ {
156
+ prop: "status",
157
+ label: t("system.base.i18n_custom.field.status"),
158
+ width: 100,
159
+ search: { el: "select", enum: statusOptions.value },
160
+ cellType: "status",
161
+ statusProps: {
162
+ activeValue: Status.STATUS_ENABLE,
163
+ inactiveValue: Status.STATUS_DISABLE,
164
+ activeText: t("common.status.enabled"),
165
+ inactiveText: t("common.status.disabled"),
166
+ disabled: () => !BUTTONS.value["base:i18n-custom:status"],
167
+ beforeChange: scope => handleBeforeSetStatus(scope.row as BaseI18nCustom)
168
+ }
169
+ },
170
+ { prop: "created_at", label: t("common.field.created_at"), minWidth: 180, align: "center" },
171
+ {
172
+ prop: "operation",
173
+ label: t("common.field.operation"),
174
+ cellType: "actions",
175
+ actions: [
176
+ {
177
+ label: t("common.action.edit"),
178
+ type: "primary",
179
+ link: true,
180
+ icon: EditPen,
181
+ hidden: () => !BUTTONS.value["base:i18n-custom:update"],
182
+ onClick: scope => handleOpenDialog((scope.row as BaseI18nCustom).id)
183
+ },
184
+ {
185
+ label: t("common.action.delete"),
186
+ type: "danger",
187
+ link: true,
188
+ icon: Delete,
189
+ hidden: () => !BUTTONS.value["base:i18n-custom:delete"],
190
+ onClick: scope => handleDelete(scope.row as BaseI18nCustom)
191
+ }
192
+ ]
193
+ }
194
+ ]);
195
+
196
+ const headerActions = computed<HeaderActionProps[]>(() => [
197
+ {
198
+ label: t("common.action.create"),
199
+ type: "success",
200
+ icon: CirclePlus,
201
+ hidden: () => !BUTTONS.value["base:i18n-custom:create"],
202
+ onClick: () => handleOpenDialog()
203
+ },
204
+ {
205
+ label: t("common.action.delete"),
206
+ type: "danger",
207
+ icon: Delete,
208
+ hidden: () => !BUTTONS.value["base:i18n-custom:delete"],
209
+ disabled: scope => !scope.selectedList.length,
210
+ onClick: scope => handleDelete(scope.selectedList as BaseI18nCustom[])
211
+ }
212
+ ]);
213
+
214
+ /** 请求国际化自定义翻译分页列表。 */
215
+ async function requestBaseI18nCustomTable(params: PageBaseI18nCustomRequest) {
216
+ await loadLanguages();
217
+ const data = await defBaseI18nCustomService.PageBaseI18nCustom(buildPageRequest(params));
218
+ return { data: { list: data.items ?? [], total: data.total } };
219
+ }
220
+
221
+ /** 加载启用语言选项。 */
222
+ async function loadLanguages() {
223
+ enabledLanguages.value = await loadEnabledBaseLanguages();
224
+ }
225
+
226
+ /** 返回语言显示名称。 */
227
+ function getLanguageLabel(locale: string) {
228
+ const language = enabledLanguages.value.find(item => item.language_code === locale);
229
+ return language?.native_name || language?.language_name || locale;
230
+ }
231
+
232
+ /** 打开国际化自定义翻译编辑弹窗。 */
233
+ async function handleOpenDialog(id?: number) {
234
+ await loadLanguages();
235
+ resetForm();
236
+ dialog.editing = Boolean(id);
237
+ dialog.visible = true;
238
+ if (!id) return;
239
+ Object.assign(formData, await defBaseI18nCustomService.GetBaseI18nCustom({ id }));
240
+ }
241
+
242
+ /** 关闭编辑弹窗并重置表单。 */
243
+ function handleCloseDialog() {
244
+ dialog.visible = false;
245
+ resetForm();
246
+ }
247
+
248
+ /** 重置国际化自定义翻译表单。 */
249
+ function resetForm() {
250
+ formDialogRef.value?.resetFields();
251
+ formDialogRef.value?.clearValidate();
252
+ Object.assign(formData, {
253
+ id: 0,
254
+ site: BaseConfigSite.BASE_CONFIG_SITE_ADMIN,
255
+ key: "",
256
+ locale: getCurrentLocale(),
257
+ value: "",
258
+ status: Status.STATUS_ENABLE,
259
+ remark: ""
260
+ });
261
+ }
262
+
263
+ /** 提交国际化自定义翻译。 */
264
+ async function handleSubmit() {
265
+ const valid = await formDialogRef.value?.validate();
266
+ if (!valid) return;
267
+ const payload = JSON.parse(JSON.stringify(formData)) as BaseI18nCustomForm;
268
+ if (payload.id) {
269
+ await defBaseI18nCustomService.UpdateBaseI18nCustom({ i18n_custom: payload });
270
+ } else {
271
+ await defBaseI18nCustomService.CreateBaseI18nCustom({ i18n_custom: payload });
272
+ }
273
+ await refreshAdminRuntimeConfig();
274
+ ElMessage.success(t(payload.id ? "common.message.update_success" : "common.message.create_success", { resource: t("system.base.i18n_custom.resource") }));
275
+ handleCloseDialog();
276
+ proTable.value?.getTableList();
277
+ }
278
+
279
+ /** 设置国际化自定义翻译状态前确认。 */
280
+ function handleBeforeSetStatus(row: BaseI18nCustom) {
281
+ return ElMessageBox.confirm(
282
+ t("system.base.i18n_custom.message.confirm_status", {
283
+ action: row.status === Status.STATUS_ENABLE ? t("common.status.disabled") : t("common.status.enabled"),
284
+ name: row.key
285
+ }),
286
+ t("common.title.warning"),
287
+ { type: "warning", confirmButtonText: t("common.action.confirm"), cancelButtonText: t("common.action.cancel") }
288
+ ).then(
289
+ async () => {
290
+ await defBaseI18nCustomService.SetBaseI18nCustomStatus({
291
+ id: row.id,
292
+ status: row.status === Status.STATUS_ENABLE ? Status.STATUS_DISABLE : Status.STATUS_ENABLE
293
+ });
294
+ await refreshAdminRuntimeConfig();
295
+ return true;
296
+ },
297
+ () => false
298
+ );
299
+ }
300
+
301
+ /** 删除国际化自定义翻译,兼容单项和批量操作。 */
302
+ function handleDelete(selected?: BaseI18nCustom | BaseI18nCustom[] | number | string | Array<number | string>) {
303
+ const rows = Array.isArray(selected) ? (selected.filter(item => typeof item === "object") as BaseI18nCustom[]) : selected && typeof selected === "object" ? [selected] : [];
304
+ const ids = (rows.length ? rows.map(item => item.id) : normalizeSelectedIds(selected as number | string | Array<number | string>)).join(",");
305
+ if (!ids) {
306
+ ElMessage.warning(t("common.message.select_delete_item"));
307
+ return;
308
+ }
309
+ ElMessageBox.confirm(
310
+ t("system.base.i18n_custom.message.confirm_delete", { name: rows.length === 1 ? rows[0].key : ids }),
311
+ t("common.title.warning"),
312
+ { type: "warning", confirmButtonText: t("common.action.confirm"), cancelButtonText: t("common.action.cancel") }
313
+ ).then(async () => {
314
+ await defBaseI18nCustomService.DeleteBaseI18nCustom({ id: ids });
315
+ await refreshAdminRuntimeConfig();
316
+ ElMessage.success(t("common.message.delete_success"));
317
+ proTable.value?.getTableList();
318
+ });
319
+ }
320
+
321
+ </script>
@@ -22,8 +22,8 @@
22
22
  </template>
23
23
 
24
24
  <script setup lang="ts">
25
- import { computed, h, reactive, ref, type VNode } from "vue";
26
- import { ElButton, ElMessage, ElMessageBox, ElTag } from "element-plus";
25
+ import { computed, h, reactive, ref } from "vue";
26
+ import { ElMessage, ElMessageBox, ElTag } from "element-plus";
27
27
  import { CirclePlus, Delete, EditPen, Promotion, Tickets, VideoPause, VideoPlay } from "@element-plus/icons-vue";
28
28
  import type {
29
29
  ColumnProps,
@@ -48,14 +48,14 @@ import { Status } from "@liujitcn/kratos-admin-system/rpc/common/v1/enum";
48
48
  import { I18nTargetType } from "@liujitcn/kratos-admin-system/rpc/system/admin/v1/base_i18n";
49
49
  import { buildPageRequest, normalizeSelectedIds } from "@liujitcn/kratos-admin-core/table";
50
50
  import { t } from "@liujitcn/kratos-admin-core";
51
- import DynamicI18nCell from "@liujitcn/kratos-admin-system/components/DynamicI18nCell.vue";
52
- import DynamicI18nEditor from "@liujitcn/kratos-admin-system/components/DynamicI18nEditor.vue";
51
+ import DynamicI18nCell from "@liujitcn/kratos-admin-system/components/i18n/DynamicI18nCell.vue";
52
+ import DynamicI18nEditor from "@liujitcn/kratos-admin-system/components/i18n/DynamicI18nEditor.vue";
53
53
  import {
54
54
  normalizeDynamicI18ns,
55
55
  serializeDynamicI18ns,
56
56
  type DynamicI18nRecord,
57
57
  type DynamicI18nValue
58
- } from "@liujitcn/kratos-admin-system/components/dynamicI18n";
58
+ } from "@liujitcn/kratos-admin-system/components/i18n/dynamicI18n";
59
59
 
60
60
  defineOptions({
61
61
  name: "BaseJob",
@@ -172,132 +172,6 @@ function renderJobNameCell(scope: RenderScope<BaseJob>) {
172
172
  });
173
173
  }
174
174
 
175
- /**
176
- * 渲染定时任务操作列。
177
- */
178
- function renderOperationCell(scope: RenderScope<BaseJob>) {
179
- const row = scope.row;
180
- const actionNodes: VNode[] = [];
181
-
182
- if (BUTTONS.value["base:job:update"]) {
183
- actionNodes.push(
184
- h(
185
- ElButton,
186
- {
187
- key: `edit-${row.id}`,
188
- type: "primary",
189
- link: true,
190
- icon: EditPen,
191
- onClick: () => handleOpenDialog(row.id)
192
- },
193
- () => t("common.action.edit")
194
- )
195
- );
196
- }
197
-
198
- if (BUTTONS.value["base:job:delete"]) {
199
- actionNodes.push(
200
- h(
201
- ElButton,
202
- {
203
- key: `delete-${row.id}`,
204
- type: "danger",
205
- link: true,
206
- icon: Delete,
207
- onClick: () => handleDelete(row)
208
- },
209
- () => t("common.action.delete")
210
- )
211
- );
212
- }
213
-
214
- if (
215
- row.status === Status.STATUS_ENABLE &&
216
- (row.entry_id === undefined || row.entry_id === 0) &&
217
- BUTTONS.value["base:job:start"]
218
- ) {
219
- actionNodes.push(
220
- h(
221
- ElButton,
222
- {
223
- key: `start-${row.id}`,
224
- type: "primary",
225
- link: true,
226
- icon: VideoPlay,
227
- class: "job-action job-action--start",
228
- onClick: () => handleStart(row.id, row.name)
229
- },
230
- () => t("system.base.job.action.start")
231
- )
232
- );
233
- }
234
-
235
- if (row.status === Status.STATUS_ENABLE && row.entry_id > 0 && BUTTONS.value["base:job:stop"]) {
236
- actionNodes.push(
237
- h(
238
- ElButton,
239
- {
240
- key: `stop-${row.id}`,
241
- type: "warning",
242
- link: true,
243
- icon: VideoPause,
244
- class: "job-action job-action--stop",
245
- onClick: () => handleStop(row.id, row.name)
246
- },
247
- () => t("system.base.job.action.stop")
248
- )
249
- );
250
- }
251
-
252
- if (
253
- row.status === Status.STATUS_ENABLE &&
254
- (row.entry_id === undefined || row.entry_id === 0) &&
255
- BUTTONS.value["base:job:exec"]
256
- ) {
257
- actionNodes.push(
258
- h(
259
- ElButton,
260
- {
261
- key: `exec-${row.id}`,
262
- type: "success",
263
- link: true,
264
- icon: Promotion,
265
- class: "job-action job-action--exec",
266
- onClick: () => handleExec(row.id, row.name)
267
- },
268
- () => t("system.base.job.action.execute")
269
- )
270
- );
271
- }
272
-
273
- if (BUTTONS.value["base:job:log"]) {
274
- actionNodes.push(
275
- h(
276
- ElButton,
277
- {
278
- key: `log-${row.id}`,
279
- type: "primary",
280
- link: true,
281
- icon: Tickets,
282
- class: "job-action job-action--log",
283
- onClick: () => handleOpenBaseJob(row.id, row.name)
284
- },
285
- () => t("system.base.job.action.log")
286
- )
287
- );
288
- }
289
-
290
- if (!actionNodes.length) return "--";
291
- return h(
292
- "div",
293
- {
294
- class: "job-operation",
295
- key: `job-operation-${row.id}`
296
- },
297
- actionNodes
298
- );
299
- }
300
-
301
175
  /** 定时任务表单字段配置。 */
302
176
  const formFields = computed<ProFormField[]>(() => [
303
177
  {
@@ -372,7 +246,86 @@ const columns = computed<ColumnProps[]>(() => [
372
246
  {
373
247
  prop: "operation",
374
248
  label: t("common.field.action"),
375
- render: scope => renderOperationCell(scope as unknown as RenderScope<BaseJob>)
249
+ cellType: "actions",
250
+ actions: [
251
+ {
252
+ label: t("common.action.edit"),
253
+ type: "primary",
254
+ link: true,
255
+ icon: EditPen,
256
+ hidden: () => !BUTTONS.value["base:job:update"],
257
+ onClick: scope => handleOpenDialog((scope.row as BaseJob).id)
258
+ },
259
+ {
260
+ label: t("common.action.delete"),
261
+ type: "danger",
262
+ link: true,
263
+ icon: Delete,
264
+ hidden: () => !BUTTONS.value["base:job:delete"],
265
+ onClick: scope => handleDelete(scope.row as BaseJob)
266
+ },
267
+ {
268
+ label: t("system.base.job.action.start"),
269
+ type: "primary",
270
+ link: true,
271
+ icon: VideoPlay,
272
+ hidden: scope => {
273
+ const row = scope.row as BaseJob;
274
+ return (
275
+ row.status !== Status.STATUS_ENABLE ||
276
+ (row.entry_id !== undefined && row.entry_id !== 0) ||
277
+ !BUTTONS.value["base:job:start"]
278
+ );
279
+ },
280
+ onClick: scope => {
281
+ const row = scope.row as BaseJob;
282
+ return handleStart(row.id, row.name);
283
+ }
284
+ },
285
+ {
286
+ label: t("system.base.job.action.stop"),
287
+ type: "warning",
288
+ link: true,
289
+ icon: VideoPause,
290
+ hidden: scope => {
291
+ const row = scope.row as BaseJob;
292
+ return row.status !== Status.STATUS_ENABLE || !(row.entry_id > 0) || !BUTTONS.value["base:job:stop"];
293
+ },
294
+ onClick: scope => {
295
+ const row = scope.row as BaseJob;
296
+ return handleStop(row.id, row.name);
297
+ }
298
+ },
299
+ {
300
+ label: t("system.base.job.action.execute"),
301
+ type: "success",
302
+ link: true,
303
+ icon: Promotion,
304
+ hidden: scope => {
305
+ const row = scope.row as BaseJob;
306
+ return (
307
+ row.status !== Status.STATUS_ENABLE ||
308
+ (row.entry_id !== undefined && row.entry_id !== 0) ||
309
+ !BUTTONS.value["base:job:exec"]
310
+ );
311
+ },
312
+ onClick: scope => {
313
+ const row = scope.row as BaseJob;
314
+ return handleExec(row.id, row.name);
315
+ }
316
+ },
317
+ {
318
+ label: t("system.base.job.action.log"),
319
+ type: "info",
320
+ link: true,
321
+ icon: Tickets,
322
+ hidden: () => !BUTTONS.value["base:job:log"],
323
+ onClick: scope => {
324
+ const row = scope.row as BaseJob;
325
+ return handleOpenBaseJob(row.id, row.name);
326
+ }
327
+ }
328
+ ]
376
329
  }
377
330
  ]);
378
331
 
@@ -608,32 +561,3 @@ function handleOpenBaseJob(id: number, name: string) {
608
561
  navigateTo(router, "/base/job/log", { jobId: id, title: t("system.base.job.title.log", { name }) });
609
562
  }
610
563
  </script>
611
-
612
- <style scoped>
613
- .job-operation {
614
- display: flex;
615
- flex-wrap: wrap;
616
- gap: 4px 10px;
617
- align-items: center;
618
- white-space: nowrap;
619
- }
620
- .job-action {
621
- margin-left: 0;
622
- font-weight: 500;
623
- }
624
- .job-action:deep(.el-icon) {
625
- margin-right: 4px;
626
- }
627
- .job-action--start {
628
- --el-button-text-color: var(--el-color-primary);
629
- }
630
- .job-action--stop {
631
- --el-button-text-color: var(--el-color-warning);
632
- }
633
- .job-action--exec {
634
- --el-button-text-color: var(--el-color-success);
635
- }
636
- .job-action--log {
637
- --el-button-text-color: var(--el-color-info);
638
- }
639
- </style>
@@ -5,11 +5,12 @@
5
5
  <script setup lang="ts">
6
6
  import { computed, ref } from "vue";
7
7
  import type { ColumnProps } from "@liujitcn/kratos-admin-core/components/ProTable/interface";
8
+ import { requestTenantCodeOptions, useTenantScope } from "@liujitcn/kratos-admin-core/tenant";
8
9
  import { t } from "@liujitcn/kratos-admin-core";
9
- import { formatLogDateTime } from "@liujitcn/kratos-admin-system/components/log";
10
+ import { formatLogDateTime } from "@liujitcn/kratos-admin-system/components/log/log";
10
11
  import { buildPageRequest } from "@liujitcn/kratos-admin-core/table";
11
- import LogTable, { type LogTableConfig } from "@liujitcn/kratos-admin-system/components/LogTable.vue";
12
- import { logDateSearch, logDetailColumn, logEnumLabel, createLogEnumOptions, requestLogTrace } from "@liujitcn/kratos-admin-system/components/log";
12
+ import LogTable, { type LogTableConfig } from "@liujitcn/kratos-admin-system/components/log/LogTable.vue";
13
+ import { logDateSearch, logDetailColumn, logEnumLabel, createLogEnumOptions, requestLogTrace } from "@liujitcn/kratos-admin-system/components/log/log";
13
14
  import { defBaseLoginLogService } from "@liujitcn/kratos-admin-system/api/system/admin/v1/base_login_log";
14
15
  import { BaseLogResult } from "@liujitcn/kratos-admin-system/rpc/system/admin/v1/base_log";
15
16
  import { BaseLoginLogType } from "@liujitcn/kratos-admin-system/rpc/system/admin/v1/base_login_log";
@@ -18,6 +19,7 @@ import type { BaseLoginLog, PageBaseLoginLogRequest } from "@liujitcn/kratos-adm
18
19
  defineOptions({ name: "BaseLoginLog", inheritAttrs: false });
19
20
 
20
21
  const page = ref<InstanceType<typeof LogTable>>();
22
+ const { tenantColumns } = useTenantScope();
21
23
  const resultOptions = computed(() =>
22
24
  createLogEnumOptions([
23
25
  [BaseLogResult.BASE_LOG_RESULT_UNSPECIFIED, t("system.base.log.result.unspecified")],
@@ -39,7 +41,14 @@ const loginTypeOptions = computed(() =>
39
41
 
40
42
  const columns = computed<ColumnProps[]>(() => [
41
43
  { prop: "user_name", label: t("system.base.log.field.user_name"), minWidth: 130 },
42
- { prop: "tenant_code", label: t("system.base.log.field.tenant_code"), minWidth: 120, align: "left" },
44
+ ...tenantColumns({
45
+ prop: "tenant_code",
46
+ label: t("system.base.log.field.tenant_code"),
47
+ minWidth: 120,
48
+ searchEl: "select",
49
+ enum: requestTenantCodeOptions,
50
+ render: scope => String((scope.row as BaseLoginLog).tenant_code ?? "")
51
+ }),
43
52
  {
44
53
  prop: "login_type",
45
54
  label: t("system.base.log.field.login_type"),