@liujitcn/kratos-admin-system 0.0.55 → 0.0.57

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 (62) hide show
  1. package/dist/package/declarations/src/api/system/admin/v1/base_redact_storage_policy.d.ts +3 -1
  2. package/dist/package/declarations/src/api/system/admin/v1/base_table_source.d.ts +3 -3
  3. package/dist/package/declarations/src/locales/generated.d.ts +0 -4
  4. package/dist/package/declarations/src/rpc/base/v1/ai_session.d.ts +4 -0
  5. package/dist/package/declarations/src/rpc/base/v1/config.d.ts +11 -1
  6. package/dist/package/declarations/src/rpc/base/v1/notification.d.ts +2 -0
  7. package/dist/package/declarations/src/rpc/system/admin/v1/auth.d.ts +16 -0
  8. package/dist/package/declarations/src/rpc/system/admin/v1/base_api.d.ts +4 -0
  9. package/dist/package/declarations/src/rpc/system/admin/v1/base_i18n_custom.d.ts +6 -0
  10. package/dist/package/declarations/src/rpc/system/admin/v1/base_message.d.ts +2 -0
  11. package/dist/package/declarations/src/rpc/system/admin/v1/base_redact_output_policy.d.ts +6 -0
  12. package/dist/package/declarations/src/rpc/system/admin/v1/base_redact_storage_policy.d.ts +27 -2
  13. package/dist/package/declarations/src/rpc/system/admin/v1/base_table_source.d.ts +14 -2
  14. package/dist/package/declarations/src/rpc/system/admin/v1/base_tenant_project_grant.d.ts +1 -1
  15. package/dist/package/declarations/src/rpc/system/admin/v1/base_third_account.d.ts +2 -0
  16. package/dist/package/declarations/src/rpc/system/admin/v1/oauth_client.d.ts +2 -0
  17. package/dist/package/src/api/system/admin/v1/base_redact_storage_policy.ts +7 -0
  18. package/dist/package/src/api/system/admin/v1/base_table_source.ts +4 -3
  19. package/dist/package/src/components/account/ChangePasswordForm.vue +1 -1
  20. package/dist/package/src/components/tenant-project/TenantProjectManager.vue +0 -1
  21. package/dist/package/src/locales/en-US.json +0 -1
  22. package/dist/package/src/locales/ja-JP.json +0 -1
  23. package/dist/package/src/locales/zh-CN.json +0 -1
  24. package/dist/package/src/locales/zh-TW.json +0 -1
  25. package/dist/package/src/rpc/base/v1/ai_session.ts +4 -0
  26. package/dist/package/src/rpc/base/v1/config.ts +13 -1
  27. package/dist/package/src/rpc/base/v1/notification.ts +2 -0
  28. package/dist/package/src/rpc/system/admin/v1/auth.ts +18 -0
  29. package/dist/package/src/rpc/system/admin/v1/base_api.ts +7 -1
  30. package/dist/package/src/rpc/system/admin/v1/base_i18n_custom.ts +8 -0
  31. package/dist/package/src/rpc/system/admin/v1/base_message.ts +2 -0
  32. package/dist/package/src/rpc/system/admin/v1/base_redact_output_policy.ts +8 -0
  33. package/dist/package/src/rpc/system/admin/v1/base_redact_storage_policy.ts +34 -4
  34. package/dist/package/src/rpc/system/admin/v1/base_table_source.ts +16 -2
  35. package/dist/package/src/rpc/system/admin/v1/base_tenant_project_grant.ts +1 -1
  36. package/dist/package/src/rpc/system/admin/v1/base_third_account.ts +2 -0
  37. package/dist/package/src/rpc/system/admin/v1/oauth_client.ts +2 -0
  38. package/dist/package/src/views/ai/chat/message.ts +3 -0
  39. package/dist/package/src/views/base/api/index.vue +2 -1
  40. package/dist/package/src/views/base/api-log/index.vue +7 -2
  41. package/dist/package/src/views/base/area/index.vue +33 -9
  42. package/dist/package/src/views/base/backup-management/archive-config/index.vue +7 -2
  43. package/dist/package/src/views/base/data-access-log/index.vue +8 -3
  44. package/dist/package/src/views/base/file/index.vue +1 -1
  45. package/dist/package/src/views/base/i18n-custom/index.vue +32 -4
  46. package/dist/package/src/views/base/job/index.vue +2 -1
  47. package/dist/package/src/views/base/job/log.vue +0 -1
  48. package/dist/package/src/views/base/login-log/index.vue +7 -12
  49. package/dist/package/src/views/base/login-policy/index.vue +63 -4
  50. package/dist/package/src/views/base/menu/index.vue +19 -4
  51. package/dist/package/src/views/base/message-category/index.vue +0 -1
  52. package/dist/package/src/views/base/oauth-client/index.vue +2 -1
  53. package/dist/package/src/views/base/operation-log/index.vue +9 -4
  54. package/dist/package/src/views/base/permission-log/index.vue +7 -2
  55. package/dist/package/src/views/base/policy-evaluation-log/index.vue +7 -2
  56. package/dist/package/src/views/base/redact-output-policy/index.vue +30 -9
  57. package/dist/package/src/views/base/redact-storage-policy/index.vue +19 -11
  58. package/dist/package/src/views/base/tenant/index.vue +5 -0
  59. package/dist/package/src/views/profile/components/login-log.vue +0 -1
  60. package/dist/package/src/views/profile/components/session.vue +18 -12
  61. package/dist/package/src/views/tool/code-gen/table/index.vue +4 -6
  62. package/package.json +2 -2
@@ -20,6 +20,10 @@ export interface PageBaseRedactStoragePolicyRequest {
20
20
  | undefined;
21
21
  /** 数据源名称 */
22
22
  source_name: string;
23
+ /** 租户ID */
24
+ tenant_id?:
25
+ | number
26
+ | undefined;
23
27
  /** 状态 */
24
28
  status?:
25
29
  | Status
@@ -57,6 +61,8 @@ export interface BaseRedactStoragePolicyForm {
57
61
  rule_params: string;
58
62
  /** 数据源名称 */
59
63
  source_name: string;
64
+ /** 租户ID */
65
+ tenant_id: number;
60
66
  /** 状态 */
61
67
  status: Status;
62
68
  /** 备注 */
@@ -108,6 +114,8 @@ export interface BaseRedactStoragePolicy {
108
114
  rule_params: string;
109
115
  /** 数据源名称 */
110
116
  source_name: string;
117
+ /** 租户ID */
118
+ tenant_id: number;
111
119
  /** 状态 */
112
120
  status: Status;
113
121
  /** 备注 */
@@ -118,6 +126,26 @@ export interface BaseRedactStoragePolicy {
118
126
  updated_at: string;
119
127
  }
120
128
 
129
+ /** 可入库脱敏数据表查询条件。 */
130
+ export interface ListBaseRedactStorageTableRequest {
131
+ /** 数据源名称 */
132
+ source_name: string;
133
+ }
134
+
135
+ /** 可入库脱敏数据表。 */
136
+ export interface BaseRedactStorageTable {
137
+ /** 数据库表名 */
138
+ name: string;
139
+ /** 数据表注释 */
140
+ comment: string;
141
+ }
142
+
143
+ /** 可入库脱敏数据表列表响应。 */
144
+ export interface ListBaseRedactStorageTableResponse {
145
+ /** 包含租户ID字段的数据表列表 */
146
+ tables: BaseRedactStorageTable[];
147
+ }
148
+
121
149
  /** 查询可入库脱敏字段请求。 */
122
150
  export interface ListBaseRedactStorageColumnRequest {
123
151
  /** 数据源名称 */
@@ -150,6 +178,12 @@ export interface BaseRedactStoragePolicyService {
150
178
  PageBaseRedactStoragePolicy(
151
179
  request: PageBaseRedactStoragePolicyRequest,
152
180
  ): Promise<PageBaseRedactStoragePolicyResponse>;
181
+ /** 查询包含租户ID字段的数据表列表。 */
182
+ ListBaseRedactStorageTable(request: ListBaseRedactStorageTableRequest): Promise<ListBaseRedactStorageTableResponse>;
183
+ /** 查询可入库脱敏的字符串字段列表。 */
184
+ ListBaseRedactStorageColumn(
185
+ request: ListBaseRedactStorageColumnRequest,
186
+ ): Promise<ListBaseRedactStorageColumnResponse>;
153
187
  /** 查询入库脱敏策略详情。 */
154
188
  GetBaseRedactStoragePolicy(request: GetBaseRedactStoragePolicyRequest): Promise<BaseRedactStoragePolicyForm>;
155
189
  /** 批量创建入库脱敏策略。 */
@@ -160,8 +194,4 @@ export interface BaseRedactStoragePolicyService {
160
194
  DeleteBaseRedactStoragePolicy(request: DeleteBaseRedactStoragePolicyRequest): Promise<Empty>;
161
195
  /** 设置入库脱敏策略状态。 */
162
196
  SetBaseRedactStoragePolicyStatus(request: SetBaseRedactStoragePolicyStatusRequest): Promise<Empty>;
163
- /** 查询可入库脱敏的字符串字段列表。 */
164
- ListBaseRedactStorageColumn(
165
- request: ListBaseRedactStorageColumnRequest,
166
- ): Promise<ListBaseRedactStorageColumnResponse>;
167
197
  }
@@ -17,10 +17,24 @@ export interface OptionBaseTableRequest {
17
17
  source_name: string;
18
18
  }
19
19
 
20
+ /** 数据库表选项。 */
21
+ export interface BaseTableOption {
22
+ /** 数据库表名 */
23
+ name: string;
24
+ /** 数据表注释 */
25
+ comment: string;
26
+ }
27
+
28
+ /** 数据库表选项响应。 */
29
+ export interface OptionBaseTableResponse {
30
+ /** 数据库表选项列表 */
31
+ tables: BaseTableOption[];
32
+ }
33
+
20
34
  /** Admin数据源元数据服务,提供数据备份、数据归档和代码生成共用的数据源信息。 */
21
35
  export interface BaseTableSourceService {
22
36
  /** 查询已初始化的数据源名称。 */
23
37
  OptionBaseTableSource(request: OptionBaseTableSourceRequest): Promise<StringValues>;
24
- /** 查询指定数据源中的数据库表名称。 */
25
- OptionBaseTable(request: OptionBaseTableRequest): Promise<StringValues>;
38
+ /** 查询指定数据源中的数据库表选项。 */
39
+ OptionBaseTable(request: OptionBaseTableRequest): Promise<OptionBaseTableResponse>;
26
40
  }
@@ -113,7 +113,7 @@ export interface DeleteBaseTenantProjectGrantRequest {
113
113
  subject_id: number;
114
114
  }
115
115
 
116
- /** BaseTenantProjectGrantService 管理岗位、角色、部门和用户在目标租户下的项目授权。 */
116
+ /** Admin项目授权服务 */
117
117
  export interface BaseTenantProjectGrantService {
118
118
  /** 查询项目授权分页列表。 */
119
119
  PageBaseTenantProjectGrant(request: PageBaseTenantProjectGrantRequest): Promise<PageBaseTenantProjectGrantResponse>;
@@ -18,6 +18,8 @@ export interface GetBaseThirdAccountIdentifierRequest {
18
18
  export interface GetBaseThirdAccountIdentifierResponse {
19
19
  /** 三方账号唯一标识 */
20
20
  identifier: string;
21
+ /** 租户ID */
22
+ tenant_id: number;
21
23
  }
22
24
 
23
25
  /** Admin用户三方账号服务 */
@@ -143,6 +143,8 @@ export interface OauthClient {
143
143
  export interface OauthClientCredentials {
144
144
  /** 客户端标识 */
145
145
  client_id: string;
146
+ /** 绑定租户ID */
147
+ tenant_id: number;
146
148
  /** 客户端密钥 */
147
149
  client_secret: string;
148
150
  /** 协议加密类型 */
@@ -44,6 +44,7 @@ export function resolveTimestamp(timestamp?: { seconds?: number; nanos?: number
44
44
  export function normalizeSession(session?: Partial<AiSession> | null): AiSession {
45
45
  return {
46
46
  id: String(session?.id ?? ""),
47
+ tenant_id: Number(session?.tenant_id ?? 0),
47
48
  title: resolveSessionText(session?.title, true),
48
49
  summary: resolveSessionText(session?.summary, false),
49
50
  updated_at: session?.updated_at,
@@ -210,6 +211,7 @@ export function createLocalUserMessage(payload: { text: string; attachments: AiA
210
211
  const message = mapMessageItem(
211
212
  {
212
213
  id: `${LOCAL_USER_MESSAGE_ID_PREFIX}-${now.getTime()}`,
214
+ tenant_id: 0,
213
215
  input_content: {
214
216
  kind: "text",
215
217
  content: payload.text
@@ -244,6 +246,7 @@ export function createThinkingMessage(options?: { sessionID?: string; messageID?
244
246
  const message = mapMessageItem(
245
247
  {
246
248
  id: streamKey || `${THINKING_MESSAGE_ID_PREFIX}-${now.getTime()}`,
249
+ tenant_id: 0,
247
250
  input_content: undefined,
248
251
  output_content: {
249
252
  kind: "text",
@@ -119,7 +119,8 @@
119
119
  v-model="editDialog.visible"
120
120
  ref="editDialogRef"
121
121
  :title="t('system.base.api.title.edit')"
122
- width="760px"
122
+ width="min(960px, calc(100vw - 32px))"
123
+ label-width="150px"
123
124
  :model="editForm"
124
125
  :fields="editFields"
125
126
  @confirm="handleSubmitEdit"
@@ -3,11 +3,12 @@
3
3
  </template>
4
4
 
5
5
  <script setup lang="ts">
6
- import { computed, ref } from "vue";
6
+ import { computed, onMounted, ref } from "vue";
7
7
  import type { ColumnProps } from "@liujitcn/kratos-admin-core/components/ProTable/interface";
8
8
  import { t } from "@liujitcn/kratos-admin-core";
9
9
  import { formatLogDateTime } from "@liujitcn/kratos-admin-system/components/log/log";
10
10
  import { buildPageRequest } from "@liujitcn/kratos-admin-core/table";
11
+ import { useTenantScope } from "@liujitcn/kratos-admin-core/tenant";
11
12
  import LogTable, { type LogTableConfig } from "@liujitcn/kratos-admin-system/components/log/LogTable.vue";
12
13
  import {
13
14
  createLogEnumOptions,
@@ -26,6 +27,9 @@ import type { BaseApiLog, PageBaseApiLogRequest } from "@liujitcn/kratos-admin-s
26
27
  defineOptions({ name: "BaseApiLog", inheritAttrs: false });
27
28
 
28
29
  const page = ref<InstanceType<typeof LogTable>>();
30
+ const { tenantColumns, loadTenantOptions, resolveTenantLabel } = useTenantScope();
31
+
32
+ onMounted(() => void loadTenantOptions(true));
29
33
  const resultOptions = computed(() =>
30
34
  createLogEnumOptions([
31
35
  [BaseLogResult.BASE_LOG_RESULT_UNSPECIFIED, t("system.base.log.result.unspecified")],
@@ -35,6 +39,7 @@ const resultOptions = computed(() =>
35
39
  ])
36
40
  );
37
41
  const columns = computed<ColumnProps[]>(() => [
42
+ ...tenantColumns({ label: t("common.field.tenant") }),
38
43
  { prop: "operation", label: t("system.base.log.field.operation"), minWidth: 320, search: { el: "input", key: "keyword" } },
39
44
  { prop: "method", label: t("system.base.log.field.method"), minWidth: 90 },
40
45
  { prop: "status_code", label: t("system.base.log.field.status_code"), minWidth: 100, align: "right" },
@@ -58,7 +63,7 @@ const config = computed<LogTableConfig>(() => ({
58
63
  trace: requestLogTrace,
59
64
  detailFields: [
60
65
  { key: "id", label: t("system.base.log.field.id") },
61
- { key: "tenant_id", label: t("system.base.log.field.tenant_id") },
66
+ { key: "tenant_id", label: t("common.field.tenant"), format: value => resolveTenantLabel({ tenant_id: value }) },
62
67
  { key: "tenant_code", label: t("system.base.log.field.tenant_code") },
63
68
  { key: "user_id", label: t("system.base.log.field.user_id") },
64
69
  { key: "user_name", label: t("system.base.log.field.user_name") },
@@ -143,12 +143,20 @@ const formFields = computed<ProFormField[]>(() => [
143
143
  /** 行政区域表格列配置。 */
144
144
  const columns = computed<ColumnProps[]>(() => [
145
145
  { type: "selection", width: 55 },
146
- { prop: "name", label: t("system.base.area.field.name"), align: "left", search: { el: "input" } },
146
+ { prop: "name", label: t("system.base.area.field.name"), search: { el: "input" } },
147
147
  {
148
148
  prop: "operation",
149
149
  label: t("common.field.operation"),
150
150
  cellType: "actions",
151
151
  actions: [
152
+ {
153
+ label: t("common.action.create"),
154
+ type: "primary",
155
+ link: true,
156
+ icon: CirclePlus,
157
+ hidden: () => !BUTTONS.value["base:area:create"],
158
+ onClick: scope => handleOpenDialog(undefined, scope.row as BaseArea)
159
+ },
152
160
  {
153
161
  label: t("common.action.edit"),
154
162
  type: "primary",
@@ -192,7 +200,11 @@ const headerActions = computed<HeaderActionProps[]>(() => [
192
200
  * 请求行政区域列表,并适配 ProTable 固定列表字段。
193
201
  */
194
202
  async function requestBaseAreaTable(params: TreeBaseAreaRequest) {
195
- const data = await defBaseAreaService.TreeBaseArea({ ...params, parent_id: params.parent_id ?? 0 });
203
+ const data = await defBaseAreaService.TreeBaseArea({
204
+ ...params,
205
+ parent_id: params.parent_id ?? 0,
206
+ lazy: true
207
+ });
196
208
  return { data: data.base_areas ?? [] };
197
209
  }
198
210
 
@@ -216,32 +228,44 @@ function refreshTable() {
216
228
  proTable.value?.getTableList();
217
229
  }
218
230
  /** 加载表单选择项。 */
219
- async function loadFormOptions() {
231
+ async function loadFormOptions(selectedParent?: BaseArea) {
220
232
  const parentIdFormResponse = await defBaseAreaService.OptionBaseArea({ parent_id: 0, lazy: true } as Parameters<
221
233
  typeof defBaseAreaService.OptionBaseArea
222
234
  >[0]);
235
+ const options = normalizeLazyTreeOptions((parentIdFormResponse.list ?? []) as GeneratedTreeOption[]).filter(
236
+ option => Number(option.value) !== 0
237
+ );
238
+ if (selectedParent && !options.some(option => Number(option.value) === selectedParent.id)) {
239
+ options.push({
240
+ label: selectedParent.name,
241
+ value: selectedParent.id,
242
+ isLeaf: !selectedParent.has_children
243
+ });
244
+ }
223
245
  return [
224
246
  { label: t("system.base.area.value.root"), value: 0 },
225
- ...normalizeLazyTreeOptions((parentIdFormResponse.list ?? []) as GeneratedTreeOption[]).filter(
226
- option => Number(option.value) !== 0
227
- )
247
+ ...options
228
248
  ];
229
249
  }
230
250
 
231
251
  /**
232
252
  * 打开行政区域弹窗。
233
253
  */
234
- async function handleOpenDialog(id?: number) {
254
+ async function handleOpenDialog(id?: number, selectedParent?: BaseArea) {
235
255
  resetForm();
236
256
  dialog.titleKey = id ? "system.base.area.action.edit" : "system.base.area.action.create";
237
257
  await formDialogRef.value?.open({
238
258
  load: async () => ({
239
- options: await loadFormOptions(),
259
+ options: await loadFormOptions(selectedParent),
240
260
  data: id ? await defBaseAreaService.GetBaseArea({ id }) : undefined
241
261
  }),
242
262
  commit: ({ options, data }) => {
243
263
  parentIdFormOptions.value = options;
244
- if (data) Object.assign(formData, data);
264
+ if (data) {
265
+ Object.assign(formData, data);
266
+ } else {
267
+ formData.parent_id = selectedParent?.id ?? 0;
268
+ }
245
269
  }
246
270
  });
247
271
  }
@@ -4,6 +4,9 @@
4
4
  <FormDialog
5
5
  ref="formDialogRef"
6
6
  v-model="dialog.visible"
7
+ width="min(900px, calc(100vw - 32px))"
8
+ label-width="140px"
9
+ :col-span="12"
7
10
  :title="t(dialog.editing ? 'common.action.edit_resource' : 'common.action.create_resource', { resource: t('system.backup.archive.config') })"
8
11
  :model="formData"
9
12
  :fields="formFields"
@@ -124,7 +127,7 @@ async function requestTableOptions(sourceName: string) {
124
127
  loadingTables.value = true;
125
128
  try {
126
129
  const data = await defBaseTableSourceService.OptionBaseTable({ source_name: sourceName });
127
- return (data.value ?? []).map(value => ({ label: value, value }));
130
+ return (data.tables ?? []).map(item => ({ label: tableOptionLabel(item.name, item.comment), value: item.name }));
128
131
  } finally {
129
132
  loadingTables.value = false;
130
133
  }
@@ -151,8 +154,8 @@ async function setStatus(row: BaseTableArchiveForm) {
151
154
  }
152
155
  );
153
156
  await defBaseTableArchiveService.SetBaseTableArchiveStatus({ id: row.id, status });
157
+ row.status = status;
154
158
  ElMessage.success(t("common.message.status_success", { action }));
155
- await proTable.value?.getTableList();
156
159
  return true;
157
160
  } catch {
158
161
  return false;
@@ -160,4 +163,6 @@ async function setStatus(row: BaseTableArchiveForm) {
160
163
  }
161
164
  async function remove(selected: number | number[] | BaseTableArchiveForm) { let ids: number[]; if (Array.isArray(selected)) ids = selected.map(Number); else if (typeof selected === "object") ids = [selected.id]; else ids = normalizeSelectedIds(selected).map(Number); if (!ids.length) return; await ElMessageBox.confirm(t("common.dialog.delete_selected", { resource: t("system.backup.archive.config") }), t("common.title.warning"), { type: "warning" }); await defBaseTableArchiveService.DeleteBaseTableArchive({ id: ids.join(",") }); ElMessage.success(t("common.message.delete_success", { resource: t("system.backup.archive.config") })); refresh(); }
162
165
  function modeLabel(value: BaseTableArchiveMode) { return modeOptions.value.find(item => item.value === value)?.label ?? String(value); }
166
+ /** 格式化数据表选项,优先显示中文注释并保留物理表名。 */
167
+ function tableOptionLabel(name: string, comment: string) { return comment && comment !== name ? `${comment}(${name})` : name; }
163
168
  </script>
@@ -3,11 +3,12 @@
3
3
  </template>
4
4
 
5
5
  <script setup lang="ts">
6
- import { computed, ref } from "vue";
6
+ import { computed, onMounted, ref } from "vue";
7
7
  import type { ColumnProps } from "@liujitcn/kratos-admin-core/components/ProTable/interface";
8
8
  import { t } from "@liujitcn/kratos-admin-core";
9
9
  import { formatLogDateTime } from "@liujitcn/kratos-admin-system/components/log/log";
10
10
  import { buildPageRequest } from "@liujitcn/kratos-admin-core/table";
11
+ import { useTenantScope } from "@liujitcn/kratos-admin-core/tenant";
11
12
  import LogTable, { type LogTableConfig } from "@liujitcn/kratos-admin-system/components/log/LogTable.vue";
12
13
  import {
13
14
  createLogEnumOptions,
@@ -26,6 +27,9 @@ import type { BaseDataAccessLog, PageBaseDataAccessLogRequest } from "@liujitcn/
26
27
  defineOptions({ name: "BaseDataAccessLog", inheritAttrs: false });
27
28
 
28
29
  const page = ref<InstanceType<typeof LogTable>>();
30
+ const { tenantColumns, loadTenantOptions, resolveTenantLabel } = useTenantScope();
31
+
32
+ onMounted(() => void loadTenantOptions(true));
29
33
  const resultOptions = computed(() => createLogEnumOptions([
30
34
  [BaseLogResult.BASE_LOG_RESULT_UNSPECIFIED, t("system.base.log.result.unspecified")],
31
35
  [BaseLogResult.BASE_LOG_RESULT_SUCCESS, t("system.base.log.result.success")],
@@ -42,6 +46,7 @@ const accessTypeOptions = computed(() => createLogEnumOptions([
42
46
  [BaseDataAccessType.BASE_DATA_ACCESS_TYPE_IMPORT, t("system.base.log.access_type.import")]
43
47
  ]));
44
48
  const columns = computed<ColumnProps[]>(() => [
49
+ ...tenantColumns({ label: t("common.field.tenant") }),
45
50
  { prop: "resource_type", label: t("system.base.log.field.resource_type"), minWidth: 150, search: { el: "input" } },
46
51
  { prop: "table_name", label: t("system.base.log.field.table_name"), minWidth: 150 },
47
52
  { prop: "access_type", label: t("system.base.log.field.access_type"), minWidth: 120, search: { el: "select", enum: accessTypeOptions.value }, render: scope => logEnumLabel(accessTypeOptions.value, (scope.row as BaseDataAccessLog).access_type) },
@@ -59,12 +64,12 @@ const config = computed<LogTableConfig>(() => ({
59
64
  trace: requestLogTrace,
60
65
  detailFields: [
61
66
  { key: "id", label: t("system.base.log.field.id") },
62
- { key: "tenant_id", label: t("system.base.log.field.tenant_id") },
67
+ { key: "tenant_id", label: t("common.field.tenant"), format: value => resolveTenantLabel({ tenant_id: value }) },
63
68
  { key: "tenant_code", label: t("system.base.log.field.tenant_code") },
64
69
  { key: "user_id", label: t("system.base.log.field.user_id") },
65
70
  { key: "user_name", label: t("system.base.log.field.user_name") },
66
71
  { key: "resource_type", label: t("system.base.log.field.resource_type") },
67
- { key: "resource_id", label: t("system.base.log.field.resource_id"), align: "left" },
72
+ { key: "resource_id", label: t("system.base.log.field.resource_id") },
68
73
  { key: "access_type", label: t("system.base.log.field.access_type"), enum: accessTypeOptions.value },
69
74
  { key: "data_source", label: t("system.base.log.field.data_source") },
70
75
  { key: "table_name", label: t("system.base.log.field.table_name") },
@@ -113,12 +113,12 @@ onMounted(() => {
113
113
  });
114
114
 
115
115
  const columns = computed<ColumnProps[]>(() => [
116
+ ...tenantColumns({ label: t("common.field.tenant"), minWidth: 100 }),
116
117
  { prop: "file_name", label: t("system.base.file.field.name"), minWidth: 220, search: { el: "input" } },
117
118
  { prop: "extension", label: t("system.base.file.field.extension"), width: 100, search: { el: "input" } },
118
119
  { prop: "mime_type", label: t("system.base.file.field.mime"), minWidth: 180 },
119
120
  { prop: "size", label: t("system.base.file.field.size"), width: 120, align: "right", render: scope => formatFileSize((scope.row as BaseFile).size) },
120
121
  { prop: "content_hash", label: t("system.base.file.field.hash"), minWidth: 220 },
121
- ...tenantColumns({ label: t("system.base.file.field.tenant"), minWidth: 100 }),
122
122
  { prop: "created_at", align: "center", label: t("common.field.created_at"), minWidth: 180 },
123
123
  {
124
124
  prop: "operation",
@@ -3,6 +3,7 @@
3
3
  <div class="table-box">
4
4
  <ProTable
5
5
  ref="proTable"
6
+ :key="isDefaultTenant ? 'default-tenant' : 'normal-tenant'"
6
7
  row-key="id"
7
8
  :columns="columns"
8
9
  :header-actions="headerActions"
@@ -24,7 +25,7 @@
24
25
  </template>
25
26
 
26
27
  <script setup lang="ts">
27
- import { computed, reactive, ref } from "vue";
28
+ import { computed, onMounted, reactive, ref } from "vue";
28
29
  import { ElMessage, ElMessageBox } from "element-plus";
29
30
  import { CirclePlus, Delete, EditPen } from "@element-plus/icons-vue";
30
31
  import type { ColumnProps, HeaderActionProps, ProTableInstance } from "@liujitcn/kratos-admin-core/components/ProTable/interface";
@@ -33,6 +34,7 @@ import FormDialog from "@liujitcn/kratos-admin-core/components/Dialog/FormDialog
33
34
  import type { ProFormField, ProFormOption } from "@liujitcn/kratos-admin-core/components/ProForm/interface";
34
35
  import { useAuthButtons } from "@liujitcn/kratos-admin-core/auth";
35
36
  import { buildPageRequest, normalizeSelectedIds } from "@liujitcn/kratos-admin-core/table";
37
+ import { useTenantScope } from "@liujitcn/kratos-admin-core/tenant";
36
38
  import {
37
39
  getCurrentLocale,
38
40
  getDefaultLocaleText,
@@ -52,13 +54,20 @@ import { Status } from "@liujitcn/kratos-admin-system/rpc/common/v1/enum";
52
54
 
53
55
  defineOptions({ name: "BaseI18nCustom", inheritAttrs: false });
54
56
 
57
+ /** 自定义翻译表单状态,平台管理员新增时选择目标租户。 */
58
+ type BaseI18nCustomFormState = Omit<BaseI18nCustomForm, "tenant_id"> & {
59
+ /** 租户ID。 */
60
+ tenant_id?: number;
61
+ };
62
+
55
63
  const { BUTTONS } = useAuthButtons();
56
64
  const proTable = ref<ProTableInstance>();
57
65
  const formDialogRef = ref<InstanceType<typeof FormDialog>>();
58
66
  const enabledLanguages = ref<Array<{ language_code: string; native_name?: string; language_name?: string }>>([]);
59
67
  const dialog = reactive({ editing: false, visible: false });
60
- const formData = reactive<BaseI18nCustomForm>({
68
+ const formData = reactive<BaseI18nCustomFormState>({
61
69
  id: 0,
70
+ tenant_id: undefined,
62
71
  site: BaseConfigSite.BASE_CONFIG_SITE_ADMIN,
63
72
  key: "",
64
73
  locale: getCurrentLocale(),
@@ -86,13 +95,26 @@ const statusOptions = computed<ProFormOption[]>(() => [
86
95
  ]);
87
96
 
88
97
  const rules = computed(() => ({
98
+ tenant_id: [
99
+ {
100
+ required: true,
101
+ message: t("common.validation.required_select", { field: t("common.field.tenant") }),
102
+ trigger: "change"
103
+ }
104
+ ],
89
105
  site: [{ required: true, message: t("system.base.i18n_custom.placeholder.site"), trigger: "change" }],
90
106
  key: [{ required: true, message: t("system.base.i18n_custom.placeholder.key"), trigger: "blur" }],
91
107
  locale: [{ required: true, message: t("system.base.i18n_custom.placeholder.locale"), trigger: "change" }],
92
108
  value: [{ required: true, message: t("system.base.i18n_custom.placeholder.value"), trigger: "blur" }]
93
109
  }));
94
110
 
111
+ const { isDefaultTenant, tenantColumns, tenantFormField, toRequestTenantId, loadTenantOptions } = useTenantScope();
112
+ onMounted(() => {
113
+ if (isDefaultTenant.value) void loadTenantOptions();
114
+ });
115
+
95
116
  const formFields = computed<ProFormField[]>(() => [
117
+ tenantFormField({ label: t("common.field.tenant"), disabledOnEdit: true }),
96
118
  {
97
119
  prop: "site",
98
120
  label: t("system.base.i18n_custom.field.site"),
@@ -130,6 +152,7 @@ const formFields = computed<ProFormField[]>(() => [
130
152
 
131
153
  const columns = computed<ColumnProps[]>(() => [
132
154
  { type: "selection", width: 55 },
155
+ ...tenantColumns({ label: t("common.field.tenant"), order: 1 }),
133
156
  { prop: "key", label: t("system.base.i18n_custom.field.key"), minWidth: 250, search: { el: "input" } },
134
157
  {
135
158
  prop: "site",
@@ -214,7 +237,10 @@ const headerActions = computed<HeaderActionProps[]>(() => [
214
237
  /** 请求国际化自定义翻译分页列表。 */
215
238
  async function requestBaseI18nCustomTable(params: PageBaseI18nCustomRequest) {
216
239
  enabledLanguages.value = await loadLanguages();
217
- const data = await defBaseI18nCustomService.PageBaseI18nCustom(buildPageRequest(params));
240
+ const data = await defBaseI18nCustomService.PageBaseI18nCustom({
241
+ ...buildPageRequest(params),
242
+ tenant_id: toRequestTenantId(params.tenant_id)
243
+ });
218
244
  return { data: { list: data.items ?? [], total: data.total } };
219
245
  }
220
246
 
@@ -236,7 +262,8 @@ async function handleOpenDialog(id?: number) {
236
262
  await formDialogRef.value?.open({
237
263
  load: async () => ({
238
264
  languages: await loadLanguages(),
239
- data: id ? await defBaseI18nCustomService.GetBaseI18nCustom({ id }) : undefined
265
+ data: id ? await defBaseI18nCustomService.GetBaseI18nCustom({ id }) : undefined,
266
+ tenants: await loadTenantOptions()
240
267
  }),
241
268
  commit: ({ languages, data }) => {
242
269
  enabledLanguages.value = languages;
@@ -257,6 +284,7 @@ function resetForm() {
257
284
  formDialogRef.value?.clearValidate();
258
285
  Object.assign(formData, {
259
286
  id: 0,
287
+ tenant_id: undefined,
260
288
  site: BaseConfigSite.BASE_CONFIG_SITE_ADMIN,
261
289
  key: "",
262
290
  locale: getCurrentLocale(),
@@ -7,7 +7,8 @@
7
7
  v-model="dialog.visible"
8
8
  ref="formDialogRef"
9
9
  :title="t(dialog.editing ? 'system.base.job.action.edit' : 'system.base.job.action.create')"
10
- width="1000px"
10
+ width="min(1200px, calc(100vw - 32px))"
11
+ top="4vh"
11
12
  :model="formData"
12
13
  :fields="formFields"
13
14
  :rules="rules"
@@ -97,7 +97,6 @@ const columns = computed<ColumnProps[]>(() => [
97
97
  prop: "job_id",
98
98
  label: t("system.base.job.field.name"),
99
99
  minWidth: 180,
100
- align: "left",
101
100
  search: {
102
101
  el: "select",
103
102
  defaultValue: initialJobID > 0 ? initialJobID : undefined,
@@ -3,9 +3,9 @@
3
3
  </template>
4
4
 
5
5
  <script setup lang="ts">
6
- import { computed, ref } from "vue";
6
+ import { computed, onMounted, 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
+ import { useTenantScope } from "@liujitcn/kratos-admin-core/tenant";
9
9
  import { t } from "@liujitcn/kratos-admin-core";
10
10
  import { formatLogDateTime } from "@liujitcn/kratos-admin-system/components/log/log";
11
11
  import { buildPageRequest } from "@liujitcn/kratos-admin-core/table";
@@ -19,7 +19,9 @@ import type { BaseLoginLog, PageBaseLoginLogRequest } from "@liujitcn/kratos-adm
19
19
  defineOptions({ name: "BaseLoginLog", inheritAttrs: false });
20
20
 
21
21
  const page = ref<InstanceType<typeof LogTable>>();
22
- const { tenantColumns } = useTenantScope();
22
+ const { tenantColumns, loadTenantOptions, resolveTenantLabel } = useTenantScope();
23
+
24
+ onMounted(() => void loadTenantOptions(true));
23
25
  const resultOptions = computed(() =>
24
26
  createLogEnumOptions([
25
27
  [BaseLogResult.BASE_LOG_RESULT_UNSPECIFIED, t("system.base.log.result.unspecified")],
@@ -40,15 +42,8 @@ const loginTypeOptions = computed(() =>
40
42
  );
41
43
 
42
44
  const columns = computed<ColumnProps[]>(() => [
45
+ ...tenantColumns({ label: t("common.field.tenant"), minWidth: 140 }),
43
46
  { prop: "user_name", label: t("system.base.log.field.user_name"), minWidth: 130 },
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
- }),
52
47
  {
53
48
  prop: "login_type",
54
49
  label: t("system.base.log.field.login_type"),
@@ -75,7 +70,7 @@ const config = computed<LogTableConfig>(() => ({
75
70
  trace: requestLogTrace,
76
71
  detailFields: [
77
72
  { key: "id", label: t("system.base.log.field.id") },
78
- { key: "tenant_id", label: t("system.base.log.field.tenant_id") },
73
+ { key: "tenant_id", label: t("common.field.tenant"), format: value => resolveTenantLabel({ tenant_id: value }) },
79
74
  { key: "tenant_code", label: t("system.base.log.field.tenant_code") },
80
75
  { key: "user_id", label: t("system.base.log.field.user_id") },
81
76
  { key: "user_name", label: t("system.base.log.field.user_name") },