@liujitcn/kratos-admin-system 0.0.51 → 0.0.53

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 (60) hide show
  1. package/README.md +1 -1
  2. package/dist/package/declarations/src/api/base/v1/sse.d.ts +1 -1
  3. package/dist/package/declarations/src/components/tenant-project/TenantProjectManager.vue.d.ts +1 -2
  4. package/dist/package/declarations/src/components/tenant-project/tenant-project-manager-data.d.ts +10 -0
  5. package/dist/package/declarations/src/components/tenant-project/tenant-project-manager.d.ts +8 -3
  6. package/dist/package/declarations/src/index.d.ts +1 -1
  7. package/dist/package/declarations/src/locales/generated.d.ts +32 -0
  8. package/dist/package/declarations/src/rpc/base/v1/ai_search.d.ts +26 -0
  9. package/dist/package/declarations/src/rpc/system/admin/v1/base_redact_output_policy.d.ts +0 -1
  10. package/dist/package/declarations/src/views/ai/chat/components/speech-recognition.d.ts +6 -2
  11. package/dist/package/src/api/base/v1/sse.ts +19 -12
  12. package/dist/package/src/components/log/LogTable.vue +25 -18
  13. package/dist/package/src/components/notification/Notification.vue +14 -7
  14. package/dist/package/src/components/tenant-project/TenantProjectManager.vue +106 -62
  15. package/dist/package/src/components/tenant-project/tenant-project-manager-data.ts +39 -1
  16. package/dist/package/src/components/tenant-project/tenant-project-manager.ts +19 -4
  17. package/dist/package/src/components/tenant-project-grant/ProjectGrantDialog.vue +22 -7
  18. package/dist/package/src/index.ts +2 -0
  19. package/dist/package/src/locales/en-US.json +8 -0
  20. package/dist/package/src/locales/ja-JP.json +8 -0
  21. package/dist/package/src/locales/zh-CN.json +8 -0
  22. package/dist/package/src/locales/zh-TW.json +8 -0
  23. package/dist/package/src/rpc/base/v1/ai_search.ts +37 -0
  24. package/dist/package/src/rpc/system/admin/v1/base_redact_output_policy.ts +0 -1
  25. package/dist/package/src/views/ai/chat/components/XSender.vue +1 -36
  26. package/dist/package/src/views/ai/chat/components/speech-recognition.ts +28 -7
  27. package/dist/package/src/views/ai/chat/index.vue +16 -7
  28. package/dist/package/src/views/base/api-log/index.vue +1 -1
  29. package/dist/package/src/views/base/area/index.vue +15 -9
  30. package/dist/package/src/views/base/backup-management/archive-config/index.vue +22 -10
  31. package/dist/package/src/views/base/backup-management/backup-config/index.vue +13 -6
  32. package/dist/package/src/views/base/config/index.vue +38 -14
  33. package/dist/package/src/views/base/dept/index.vue +31 -25
  34. package/dist/package/src/views/base/dict/index.vue +12 -8
  35. package/dist/package/src/views/base/dict/item.vue +12 -8
  36. package/dist/package/src/views/base/i18n-custom/index.vue +13 -7
  37. package/dist/package/src/views/base/job/index.vue +12 -8
  38. package/dist/package/src/views/base/job/log.vue +14 -9
  39. package/dist/package/src/views/base/language/index.vue +7 -4
  40. package/dist/package/src/views/base/login-policy/index.vue +22 -11
  41. package/dist/package/src/views/base/menu/index.vue +23 -16
  42. package/dist/package/src/views/base/message/index.vue +65 -21
  43. package/dist/package/src/views/base/message-category/index.vue +10 -4
  44. package/dist/package/src/views/base/oauth-client/index.vue +15 -5
  45. package/dist/package/src/views/base/post/index.vue +10 -4
  46. package/dist/package/src/views/base/redact-output-policy/index.vue +12 -5
  47. package/dist/package/src/views/base/redact-rule/index.vue +8 -7
  48. package/dist/package/src/views/base/redact-storage-policy/index.vue +32 -8
  49. package/dist/package/src/views/base/role/index.vue +24 -17
  50. package/dist/package/src/views/base/tenant/index.vue +7 -6
  51. package/dist/package/src/views/base/tenant-project-grant/index.vue +44 -27
  52. package/dist/package/src/views/base/user/components/dept-tree.vue +4 -9
  53. package/dist/package/src/views/base/user/index.vue +39 -28
  54. package/dist/package/src/views/message/inbox/index.vue +8 -3
  55. package/dist/package/src/views/profile/components/base.vue +1 -1
  56. package/dist/package/src/views/profile/index.vue +1 -1
  57. package/dist/package/src/views/tool/cache/index.vue +1 -1
  58. package/dist/package/src/views/tool/code-gen/columns/index.vue +35 -16
  59. package/dist/package/src/views/tool/code-gen/table/index.vue +58 -31
  60. package/package.json +2 -2
@@ -28,20 +28,31 @@
28
28
  </template>
29
29
 
30
30
  <script setup lang="ts">
31
- import { computed, reactive, ref, useSlots } from "vue";
31
+ import { computed, onMounted, reactive, ref, useSlots } from "vue";
32
32
  import { ElMessage, ElMessageBox } from "element-plus";
33
33
  import { CirclePlus, Delete, EditPen } from "@element-plus/icons-vue";
34
- import type { ColumnProps, HeaderActionProps, ProTableInstance, RenderScope, TableActionProps } from "@liujitcn/kratos-admin-core/components/ProTable/interface";
34
+ import type {
35
+ ColumnProps,
36
+ HeaderActionProps,
37
+ ProTableInstance,
38
+ RenderScope,
39
+ TableActionProps
40
+ } from "@liujitcn/kratos-admin-core/components/ProTable/interface";
35
41
  import ProTable from "@liujitcn/kratos-admin-core/components/ProTable";
36
42
  import FormDialog from "@liujitcn/kratos-admin-core/components/Dialog/FormDialog.vue";
37
43
  import type { ProFormField, ProFormOption } from "@liujitcn/kratos-admin-core/components/ProForm/interface";
38
44
  import { useAuthButtons } from "@liujitcn/kratos-admin-core/auth";
39
45
  import { defBaseTenantProjectService } from "@liujitcn/kratos-admin-system/api/system/admin/v1/base_tenant_project";
40
- import type { BaseTenantProject, BaseTenantProjectForm, PageBaseTenantProjectRequest } from "@liujitcn/kratos-admin-system/rpc/system/admin/v1/base_tenant_project";
46
+ import type {
47
+ BaseTenantProject,
48
+ BaseTenantProjectForm,
49
+ PageBaseTenantProjectRequest
50
+ } from "@liujitcn/kratos-admin-system/rpc/system/admin/v1/base_tenant_project";
41
51
  import { Status } from "@liujitcn/kratos-admin-system/rpc/common/v1/enum";
42
52
  import { buildPageRequest, normalizeSelectedIds } from "@liujitcn/kratos-admin-core/table";
43
53
  import { useTenantScope } from "@liujitcn/kratos-admin-core/tenant";
44
54
  import { t } from "@liujitcn/kratos-admin-core";
55
+ import { arrangeTenantProjectColumns } from "./tenant-project-manager-data";
45
56
  import {
46
57
  mergeTenantProjectExtraData,
47
58
  tenantProjectKey,
@@ -66,8 +77,11 @@ const emit = defineEmits<{
66
77
  "extra-data-error": [error: unknown];
67
78
  }>();
68
79
 
69
- /** 项目表单状态,租户由服务端租户上下文自动补全。 */
70
- type BaseTenantProjectFormState = Omit<BaseTenantProjectForm, "tenant_id">;
80
+ /** 项目表单状态,默认租户创建时必须选择目标租户。 */
81
+ type BaseTenantProjectFormState = Omit<BaseTenantProjectForm, "tenant_id"> & {
82
+ /** 项目所属租户。 */
83
+ tenant_id?: number;
84
+ };
71
85
 
72
86
  const { BUTTONS } = useAuthButtons();
73
87
  const slots = useSlots();
@@ -88,6 +102,8 @@ const statusOptions = computed<ProFormOption[]>(() => [
88
102
  const formData = reactive<BaseTenantProjectFormState>({
89
103
  /** 项目ID。 */
90
104
  id: 0,
105
+ /** 项目所属租户。 */
106
+ tenant_id: undefined,
91
107
  /** 项目名称。 */
92
108
  name: "",
93
109
  /** 项目编号。 */
@@ -100,6 +116,13 @@ const formData = reactive<BaseTenantProjectFormState>({
100
116
  remark: ""
101
117
  });
102
118
  const rules = computed(() => ({
119
+ tenant_id: [
120
+ {
121
+ required: true,
122
+ message: t("common.validation.required_select", { field: t("common.field.tenant") }),
123
+ trigger: "change"
124
+ }
125
+ ],
103
126
  name: [
104
127
  {
105
128
  required: true,
@@ -141,10 +164,14 @@ const rules = computed(() => ({
141
164
  ]
142
165
  }));
143
166
 
144
- const { isDefaultTenant } = useTenantScope();
167
+ const { isDefaultTenant, tenantColumns, tenantFormField, toRequestTenantId, loadTenantOptions } = useTenantScope();
168
+ onMounted(() => {
169
+ if (isDefaultTenant.value) void loadTenantOptions();
170
+ });
145
171
 
146
172
  /** 项目表单字段配置。 */
147
173
  const formFields = computed<ProFormField[]>(() => [
174
+ tenantFormField({ label: t("common.field.tenant"), disabledOnEdit: true }),
148
175
  {
149
176
  prop: "name",
150
177
  label: t("system.base.tenant_project.field.name"),
@@ -202,56 +229,60 @@ function resolveProjectBoolean(value: boolean | ((context: TenantProjectContext)
202
229
  }
203
230
 
204
231
  /** 项目表格列配置。 */
205
- const columns = computed<ColumnProps[]>(() => [
206
- { type: "selection", width: 55 },
207
- { prop: "name", label: t("system.base.tenant_project.field.name"), minWidth: 180, search: { el: "input" } },
208
- { prop: "code", label: t("system.base.tenant_project.field.code"), minWidth: 140, search: { el: "input" } },
209
- { prop: "sort", label: t("common.field.sort"), minWidth: 90, align: "right" },
210
- {
211
- prop: "status",
212
- label: t("common.field.status"),
213
- minWidth: 100,
214
- search: { el: "select" },
215
- cellType: "status",
216
- statusProps: {
217
- activeValue: Status.STATUS_ENABLE,
218
- inactiveValue: Status.STATUS_DISABLE,
219
- activeText: t("common.status.enabled"),
220
- inactiveText: t("common.status.disabled"),
221
- disabled: () => !isDefaultTenant.value || !BUTTONS.value["base:tenant:project:status"],
222
- beforeChange: scope => handleBeforeSetStatus(scope.row as BaseTenantProject)
223
- }
224
- },
225
- { prop: "remark", label: t("common.field.remark"), minWidth: 160 },
226
- ...props.extraColumns,
227
- { prop: "created_at", align: "center", label: t("common.field.created_at"), minWidth: 180 },
228
- { prop: "updated_at", label: t("common.field.updated_at"), minWidth: 180, align: "center" },
229
- {
230
- prop: "operation",
231
- label: t("common.field.operation"),
232
- cellType: "actions",
233
- actions: [
234
- ...props.extraActions.map(toTableAction),
235
- {
236
- label: t("common.action.edit"),
237
- type: "primary",
238
- link: true,
239
- icon: EditPen,
240
- hidden: () => !isDefaultTenant.value || !BUTTONS.value["base:tenant:project:update"],
241
- params: scope => ({ projectId: scope.row.id }),
242
- onClick: (scope, params) => handleOpenDialog((params?.projectId as number | undefined) ?? (scope.row as BaseTenantProject).id)
243
- },
244
- {
245
- label: t("common.action.delete"),
246
- type: "danger",
247
- link: true,
248
- icon: Delete,
249
- hidden: () => !isDefaultTenant.value || !BUTTONS.value["base:tenant:project:delete"],
250
- onClick: scope => handleDelete(scope.row as BaseTenantProject)
232
+ const columns = computed<ColumnProps[]>(() => {
233
+ const baseColumns: ColumnProps[] = [
234
+ { type: "selection", width: 55 },
235
+ ...tenantColumns({ label: t("common.field.tenant"), order: 1 }),
236
+ { prop: "name", label: t("system.base.tenant_project.field.name"), minWidth: 180, search: { el: "input" } },
237
+ { prop: "code", label: t("system.base.tenant_project.field.code"), minWidth: 140, search: { el: "input" } },
238
+ { prop: "sort", label: t("common.field.sort"), minWidth: 90, align: "right" },
239
+ {
240
+ prop: "status",
241
+ label: t("common.field.status"),
242
+ minWidth: 100,
243
+ search: { el: "select" },
244
+ cellType: "status",
245
+ statusProps: {
246
+ activeValue: Status.STATUS_ENABLE,
247
+ inactiveValue: Status.STATUS_DISABLE,
248
+ activeText: t("common.status.enabled"),
249
+ inactiveText: t("common.status.disabled"),
250
+ disabled: () => !isDefaultTenant.value || !BUTTONS.value["base:tenant:project:status"],
251
+ beforeChange: scope => handleBeforeSetStatus(scope.row as BaseTenantProject)
251
252
  }
252
- ]
253
- }
254
- ]);
253
+ },
254
+ { prop: "remark", label: t("common.field.remark"), minWidth: 160 },
255
+ { prop: "created_at", align: "center", label: t("common.field.created_at"), minWidth: 180 },
256
+ { prop: "updated_at", label: t("common.field.updated_at"), minWidth: 180, align: "center" },
257
+ {
258
+ prop: "operation",
259
+ label: t("common.field.operation"),
260
+ cellType: "actions",
261
+ actions: [
262
+ ...props.extraActions.map(toTableAction),
263
+ {
264
+ label: t("common.action.edit"),
265
+ type: "primary",
266
+ link: true,
267
+ icon: EditPen,
268
+ hidden: () => !isDefaultTenant.value || !BUTTONS.value["base:tenant:project:update"],
269
+ params: scope => ({ projectId: scope.row.id }),
270
+ onClick: (scope, params) =>
271
+ handleOpenDialog((params?.projectId as number | undefined) ?? (scope.row as BaseTenantProject).id)
272
+ },
273
+ {
274
+ label: t("common.action.delete"),
275
+ type: "danger",
276
+ link: true,
277
+ icon: Delete,
278
+ hidden: () => !isDefaultTenant.value || !BUTTONS.value["base:tenant:project:delete"],
279
+ onClick: scope => handleDelete(scope.row as BaseTenantProject)
280
+ }
281
+ ]
282
+ }
283
+ ];
284
+ return arrangeTenantProjectColumns(baseColumns, props.extraColumns);
285
+ });
255
286
 
256
287
  /** 项目顶部按钮配置。 */
257
288
  const headerActions = computed<HeaderActionProps[]>(() => [
@@ -275,7 +306,10 @@ const headerActions = computed<HeaderActionProps[]>(() => [
275
306
  /** 请求项目分页列表并加载当前页外部业务字段。 */
276
307
  async function requestBaseTenantProjectTable(params: PageBaseTenantProjectRequest) {
277
308
  const revision = ++extraDataRequestRevision;
278
- const request = buildPageRequest(params) as PageBaseTenantProjectRequest;
309
+ const request = {
310
+ ...buildPageRequest(params),
311
+ tenant_id: toRequestTenantId(params.tenant_id)
312
+ } as PageBaseTenantProjectRequest;
279
313
  const data = await defBaseTenantProjectService.PageBaseTenantProject(request);
280
314
  const projects = data.base_tenant_projects ?? [];
281
315
  if (!props.loadExtraData || !projects.length) {
@@ -315,15 +349,22 @@ function resolveTenantProjectSlotContext(scope: Record<string, any>) {
315
349
 
316
350
  /** 打开项目编辑弹窗。 */
317
351
  async function handleOpenDialog(id?: number) {
318
- resetForm();
319
- dialog.titleKey = id ? "common.action.edit_resource" : "common.action.create_resource";
320
- dialog.visible = true;
321
- if (id) Object.assign(formData, await defBaseTenantProjectService.GetBaseTenantProject({ id }));
352
+ await formDialogRef.value?.open({
353
+ load: async () => {
354
+ await loadTenantOptions();
355
+ return id ? defBaseTenantProjectService.GetBaseTenantProject({ id }) : undefined;
356
+ },
357
+ commit: data => {
358
+ resetForm();
359
+ dialog.titleKey = id ? "common.action.edit_resource" : "common.action.create_resource";
360
+ if (data) Object.assign(formData, data);
361
+ }
362
+ });
322
363
  }
323
364
 
324
365
  /** 关闭项目弹窗并清理表单。 */
325
366
  function handleCloseDialog() {
326
- dialog.visible = false;
367
+ formDialogRef.value?.close();
327
368
  resetForm();
328
369
  }
329
370
 
@@ -332,6 +373,7 @@ function resetForm() {
332
373
  formDialogRef.value?.resetFields();
333
374
  formDialogRef.value?.clearValidate();
334
375
  formData.id = 0;
376
+ formData.tenant_id = undefined;
335
377
  formData.name = "";
336
378
  formData.code = "";
337
379
  formData.sort = 1;
@@ -344,7 +386,9 @@ function handleSubmit() {
344
386
  formDialogRef.value?.validate()?.then(valid => {
345
387
  if (!valid) return;
346
388
  const submitData = JSON.parse(JSON.stringify(formData)) as Partial<BaseTenantProjectForm>;
347
- delete submitData.tenant_id;
389
+ const tenantId = toRequestTenantId(formData.tenant_id);
390
+ if (tenantId === undefined) delete submitData.tenant_id;
391
+ else submitData.tenant_id = tenantId;
348
392
  const request = submitData.id
349
393
  ? defBaseTenantProjectService.UpdateBaseTenantProject({ base_tenant_project: submitData as BaseTenantProjectForm })
350
394
  : defBaseTenantProjectService.CreateBaseTenantProject({ base_tenant_project: submitData as BaseTenantProjectForm });
@@ -1,5 +1,11 @@
1
1
  import type { BaseTenantProject } from "@liujitcn/kratos-admin-system/rpc/system/admin/v1/base_tenant_project";
2
2
 
3
+ /** 租户项目表格列的最小结构,用于在不依赖表格组件的情况下排列扩展列。 */
4
+ type TenantProjectColumnLike = {
5
+ prop?: string;
6
+ type?: string;
7
+ };
8
+
3
9
  /** 租户项目业务数据查询键。 */
4
10
  export interface TenantProjectKey {
5
11
  /** 租户 ID。 */
@@ -11,13 +17,45 @@ export interface TenantProjectKey {
11
17
  /** 租户项目扩展数据,外层键由租户 ID 和项目 ID 组成。 */
12
18
  export type TenantProjectExtraData = Record<string, Record<string, unknown>>;
13
19
 
20
+ /** 按基础字段位置排列租户项目管理的扩展列。 */
21
+ export function arrangeTenantProjectColumns<T extends TenantProjectColumnLike>(
22
+ baseColumns: T[],
23
+ extraColumns: Array<T & { after?: string }>
24
+ ): T[] {
25
+ const baseKeys = new Set(baseColumns.map(column => column.prop ?? column.type));
26
+ const extrasByAnchor = new Map<string | undefined, T[]>();
27
+ for (const extraColumn of extraColumns) {
28
+ const { after, ...column } = extraColumn;
29
+ const anchor = after && baseKeys.has(after) ? after : "remark";
30
+ const columns = extrasByAnchor.get(anchor) ?? [];
31
+ columns.push(column as T);
32
+ extrasByAnchor.set(anchor, columns);
33
+ }
34
+
35
+ const result: T[] = [];
36
+ for (const baseColumn of baseColumns) {
37
+ result.push(baseColumn);
38
+ const anchor = baseColumn.prop ?? baseColumn.type;
39
+ const columns = extrasByAnchor.get(anchor);
40
+ if (!columns) continue;
41
+ result.push(...columns);
42
+ extrasByAnchor.delete(anchor);
43
+ }
44
+ const remaining: T[] = [];
45
+ for (const columns of extrasByAnchor.values()) remaining.push(...columns);
46
+ return [...result, ...remaining];
47
+ }
48
+
14
49
  /** 创建租户项目扩展数据的稳定键。 */
15
50
  export function tenantProjectKey(tenantId: number, projectId: number): string {
16
51
  return `${tenantId}:${projectId}`;
17
52
  }
18
53
 
19
54
  /** 将外部业务字段合并到项目行,同时保护公共项目字段。 */
20
- export function mergeTenantProjectExtraData(project: BaseTenantProject, extra?: Record<string, unknown>): BaseTenantProject & Record<string, unknown> {
55
+ export function mergeTenantProjectExtraData(
56
+ project: BaseTenantProject,
57
+ extra?: Record<string, unknown>
58
+ ): BaseTenantProject & Record<string, unknown> {
21
59
  if (!extra) return { ...project } as BaseTenantProject & Record<string, unknown>;
22
60
 
23
61
  const protectedFields = new Set(["id", "tenant_id", "code", "name", "status", "sort", "remark", "created_at", "updated_at"]);
@@ -1,8 +1,17 @@
1
- import type { BaseTenantProject, PageBaseTenantProjectRequest } from "@liujitcn/kratos-admin-system/rpc/system/admin/v1/base_tenant_project";
1
+ import type {
2
+ BaseTenantProject,
3
+ PageBaseTenantProjectRequest
4
+ } from "@liujitcn/kratos-admin-system/rpc/system/admin/v1/base_tenant_project";
2
5
  import type { ColumnProps, TableActionProps } from "@liujitcn/kratos-admin-core/components/ProTable/interface";
3
6
  import type { TenantProjectExtraData, TenantProjectKey } from "./tenant-project-manager-data";
4
7
 
5
- export { mergeTenantProjectExtraData, tenantProjectKey, type TenantProjectExtraData, type TenantProjectKey } from "./tenant-project-manager-data";
8
+ export {
9
+ arrangeTenantProjectColumns,
10
+ mergeTenantProjectExtraData,
11
+ tenantProjectKey,
12
+ type TenantProjectExtraData,
13
+ type TenantProjectKey
14
+ } from "./tenant-project-manager-data";
6
15
 
7
16
  /** 租户项目单条业务上下文。 */
8
17
  export interface TenantProjectContext<TData extends Record<string, unknown> = Record<string, unknown>> extends TenantProjectKey {
@@ -37,10 +46,16 @@ export type TenantProjectAction = Omit<TableActionProps, "disabled" | "hidden" |
37
46
  onClick: (context: TenantProjectContext, params?: Record<string, any>) => void | Promise<void>;
38
47
  };
39
48
 
49
+ /** 租户项目管理的扩展列配置。 */
50
+ export type TenantProjectExtraColumn = ColumnProps & {
51
+ /** 插入到指定基础字段后面,未配置时默认插入备注字段后面。 */
52
+ after?: string;
53
+ };
54
+
40
55
  /** 租户项目管理组件属性。 */
41
56
  export interface TenantProjectManagerProps {
42
- /** 追加到基础列表的表格列。 */
43
- extraColumns?: ColumnProps[];
57
+ /** 追加到基础列表的表格列,可通过 after 指定插入位置。 */
58
+ extraColumns?: TenantProjectExtraColumn[];
44
59
  /** 追加到基础操作列的业务操作。 */
45
60
  extraActions?: TenantProjectAction[];
46
61
  /** 加载当前页外部业务字段。 */
@@ -1,5 +1,6 @@
1
1
  <template>
2
2
  <FormDialog
3
+ ref="formDialogRef"
3
4
  v-model="visible"
4
5
  :title="t('system.base.tenant_project.grant')"
5
6
  :model="form"
@@ -26,6 +27,7 @@ import type {
26
27
  import type { SelectOptionResponse_Option } from "@liujitcn/kratos-admin-system/rpc/common/v1/common";
27
28
 
28
29
  const visible = ref(false);
30
+ const formDialogRef = ref<InstanceType<typeof FormDialog>>();
29
31
  const loading = ref(false);
30
32
  const projectOptions = ref<SelectOptionResponse_Option[]>([]);
31
33
  const form = reactive({ tenant_id: 0, all: false, project_id: [] as number[] });
@@ -42,13 +44,26 @@ const fields = computed<ProFormField[]>(() => [
42
44
 
43
45
  /** 打开指定主体的授权表单,目标租户切换后重新加载直接授权。 */
44
46
  async function open(type: BaseTenantProjectGrantSubjectType, id: number, tenantId: number) {
45
- reset();
46
- subjectType = type;
47
- subjectId = id;
48
- await loadTenantOptions(true);
49
- form.tenant_id = tenantId;
50
- visible.value = true;
51
- await load();
47
+ await formDialogRef.value?.open({
48
+ load: async () => {
49
+ await loadTenantOptions(true);
50
+ const request = { tenant_id: tenantId, subject_type: type, subject_id: id };
51
+ const [options, grant] = await Promise.all([
52
+ defBaseTenantProjectService.OptionBaseTenantProject({ tenant_id: request.tenant_id }),
53
+ defBaseTenantProjectGrantService.GetBaseTenantProjectGrant(request)
54
+ ]);
55
+ return { request, projects: options.list ?? [], grant };
56
+ },
57
+ commit: ({ request, projects, grant }) => {
58
+ reset();
59
+ subjectType = request.subject_type;
60
+ subjectId = request.subject_id;
61
+ form.tenant_id = request.tenant_id;
62
+ projectOptions.value = projects;
63
+ form.all = grant.project_id.length === 1 && grant.project_id[0] === 0;
64
+ form.project_id = form.all ? [] : grant.project_id;
65
+ }
66
+ });
52
67
  }
53
68
 
54
69
  /** 加载目标租户项目和当前主体的直接授权,避免快速切换时旧响应覆盖新结果。 */
@@ -3,9 +3,11 @@ export type { AdminAiExtension } from "./ai";
3
3
  export { default as TenantProjectManager } from "./components/tenant-project/TenantProjectManager.vue";
4
4
  export {
5
5
  mergeTenantProjectExtraData,
6
+ arrangeTenantProjectColumns,
6
7
  tenantProjectKey,
7
8
  type TenantProjectAction,
8
9
  type TenantProjectContext,
10
+ type TenantProjectExtraColumn,
9
11
  type TenantProjectExtraData,
10
12
  type TenantProjectExtraDataLoadContext,
11
13
  type TenantProjectExtraDataLoader,
@@ -398,6 +398,8 @@
398
398
  "system.base.log.field.os": "Operating system",
399
399
  "system.base.log.field.path": "Path",
400
400
  "system.base.log.field.project": "Project",
401
+ "system.base.log.field.role_code": "Role code",
402
+ "system.base.log.field.role_id": "Role ID",
401
403
  "system.base.log.field.reason": "Reason",
402
404
  "system.base.log.field.reason_code": "Reason code",
403
405
  "system.base.log.field.referer": "Referrer",
@@ -648,6 +650,11 @@
648
650
  "system.base.message.content_format.plain": "Plain text",
649
651
  "system.base.message.detail.action": "Details",
650
652
  "system.base.message.detail.title": "Message details",
653
+ "system.base.message.dispatch_status.pending": "Pending",
654
+ "system.base.message.dispatch_status.running": "Delivering",
655
+ "system.base.message.dispatch_status.succeeded": "Completed",
656
+ "system.base.message.dispatch_status.failed": "Failed",
657
+ "system.base.message.dispatch_status.cancelled": "Cancelled",
651
658
  "system.base.message.field.action_target": "Action view key",
652
659
  "system.base.message.field.action_type": "Click action",
653
660
  "system.base.message.field.attempt_count": "Attempts",
@@ -760,6 +767,7 @@
760
767
  "system.base.migration.title.list": "Migration records",
761
768
  "system.base.migration.value.default_module": "Database migration",
762
769
  "system.base.oauth_client.action.copy_credentials": "Copy credentials",
770
+ "system.base.oauth_client.confirm.rotate_credentials": "Rotating the client credentials immediately invalidates the old secret. Continue?",
763
771
  "system.base.oauth_client.field.api": "Authorized APIs",
764
772
  "system.base.oauth_client.field.client_id": "Client ID",
765
773
  "system.base.oauth_client.field.client_name": "Client name",
@@ -398,6 +398,8 @@
398
398
  "system.base.log.field.os": "オペレーティング システム",
399
399
  "system.base.log.field.path": "パス",
400
400
  "system.base.log.field.project": "プロジェクト",
401
+ "system.base.log.field.role_code": "ロールコード",
402
+ "system.base.log.field.role_id": "ロール ID",
401
403
  "system.base.log.field.reason": "理由",
402
404
  "system.base.log.field.reason_code": "理由コード",
403
405
  "system.base.log.field.referer": "ソース ページ",
@@ -648,6 +650,11 @@
648
650
  "system.base.message.content_format.plain": "プレーンテキスト",
649
651
  "system.base.message.detail.action": "詳細",
650
652
  "system.base.message.detail.title": "メッセージ詳細",
653
+ "system.base.message.dispatch_status.pending": "配信待ち",
654
+ "system.base.message.dispatch_status.running": "配信中",
655
+ "system.base.message.dispatch_status.succeeded": "完了",
656
+ "system.base.message.dispatch_status.failed": "失敗",
657
+ "system.base.message.dispatch_status.cancelled": "キャンセル済み",
651
658
  "system.base.message.field.action_target": "遷移先ビューキー",
652
659
  "system.base.message.field.action_type": "クリック操作",
653
660
  "system.base.message.field.attempt_count": "試行回数",
@@ -760,6 +767,7 @@
760
767
  "system.base.migration.title.list": "マイグレーション履歴一覧",
761
768
  "system.base.migration.value.default_module": "データベースの移行",
762
769
  "system.base.oauth_client.action.copy_credentials": "資格情報をコピー",
770
+ "system.base.oauth_client.confirm.rotate_credentials": "クライアント資格情報をローテーションすると旧シークレットは直ちに無効になります。続行しますか?",
763
771
  "system.base.oauth_client.field.api": "許可された API",
764
772
  "system.base.oauth_client.field.client_id": "クライアント ID",
765
773
  "system.base.oauth_client.field.client_name": "クライアント名",
@@ -398,6 +398,8 @@
398
398
  "system.base.log.field.os": "操作系统",
399
399
  "system.base.log.field.path": "请求路径",
400
400
  "system.base.log.field.project": "项目范围",
401
+ "system.base.log.field.role_code": "角色编码",
402
+ "system.base.log.field.role_id": "角色 ID",
401
403
  "system.base.log.field.reason": "原因说明",
402
404
  "system.base.log.field.reason_code": "原因编码",
403
405
  "system.base.log.field.referer": "来源页",
@@ -648,6 +650,11 @@
648
650
  "system.base.message.content_format.plain": "纯文本",
649
651
  "system.base.message.detail.action": "详情",
650
652
  "system.base.message.detail.title": "消息详情",
653
+ "system.base.message.dispatch_status.pending": "待投递",
654
+ "system.base.message.dispatch_status.running": "投递中",
655
+ "system.base.message.dispatch_status.succeeded": "已完成",
656
+ "system.base.message.dispatch_status.failed": "失败",
657
+ "system.base.message.dispatch_status.cancelled": "已取消",
651
658
  "system.base.message.field.action_target": "动作视图键",
652
659
  "system.base.message.field.action_type": "点击动作",
653
660
  "system.base.message.field.attempt_count": "尝试次数",
@@ -760,6 +767,7 @@
760
767
  "system.base.migration.title.list": "迁移记录列表",
761
768
  "system.base.migration.value.default_module": "数据库迁移",
762
769
  "system.base.oauth_client.action.copy_credentials": "复制客户端凭据",
770
+ "system.base.oauth_client.confirm.rotate_credentials": "轮换客户端凭据会立即使旧密钥失效,确认继续吗?",
763
771
  "system.base.oauth_client.field.api": "授权接口",
764
772
  "system.base.oauth_client.field.client_id": "客户端标识",
765
773
  "system.base.oauth_client.field.client_name": "客户端名称",
@@ -398,6 +398,8 @@
398
398
  "system.base.log.field.os": "作業系統",
399
399
  "system.base.log.field.path": "請求路徑",
400
400
  "system.base.log.field.project": "專案範圍",
401
+ "system.base.log.field.role_code": "角色編碼",
402
+ "system.base.log.field.role_id": "角色 ID",
401
403
  "system.base.log.field.reason": "原因說明",
402
404
  "system.base.log.field.reason_code": "原因編碼",
403
405
  "system.base.log.field.referer": "來源頁",
@@ -648,6 +650,11 @@
648
650
  "system.base.message.content_format.plain": "純文字",
649
651
  "system.base.message.detail.action": "詳情",
650
652
  "system.base.message.detail.title": "訊息詳情",
653
+ "system.base.message.dispatch_status.pending": "待投遞",
654
+ "system.base.message.dispatch_status.running": "投遞中",
655
+ "system.base.message.dispatch_status.succeeded": "已完成",
656
+ "system.base.message.dispatch_status.failed": "失敗",
657
+ "system.base.message.dispatch_status.cancelled": "已取消",
651
658
  "system.base.message.field.action_target": "動作視圖鍵",
652
659
  "system.base.message.field.action_type": "點擊動作",
653
660
  "system.base.message.field.attempt_count": "嘗試次數",
@@ -760,6 +767,7 @@
760
767
  "system.base.migration.title.list": "遷移記錄列表",
761
768
  "system.base.migration.value.default_module": "資料庫遷移",
762
769
  "system.base.oauth_client.action.copy_credentials": "複製客戶端憑據",
770
+ "system.base.oauth_client.confirm.rotate_credentials": "輪換客戶端憑據會立即使舊密鑰失效,確定要繼續嗎?",
763
771
  "system.base.oauth_client.field.api": "授權介面",
764
772
  "system.base.oauth_client.field.client_id": "客戶端識別碼",
765
773
  "system.base.oauth_client.field.client_name": "客戶端名稱",
@@ -0,0 +1,37 @@
1
+ // Code generated by protoc-gen-ts_proto. DO NOT EDIT.
2
+ // versions:
3
+ // protoc-gen-ts_proto v2.11.8
4
+ // protoc unknown
5
+ // source: base/v1/ai_search.proto
6
+
7
+ /* eslint-disable */
8
+
9
+ /** AI 助手联网搜索请求 */
10
+ export interface SearchAiWebRequest {
11
+ /** 搜索关键词 */
12
+ query: string;
13
+ /** 返回结果数量:0 表示默认5条,最大10条 */
14
+ limit: number;
15
+ }
16
+
17
+ /** AI 助手联网搜索响应 */
18
+ export interface SearchAiWebResponse {
19
+ /** 搜索结果列表 */
20
+ items: SearchAiWebItem[];
21
+ }
22
+
23
+ /** AI 助手联网搜索结果 */
24
+ export interface SearchAiWebItem {
25
+ /** 结果标题 */
26
+ title: string;
27
+ /** 结果链接 */
28
+ url: string;
29
+ /** 结果摘要 */
30
+ snippet: string;
31
+ }
32
+
33
+ /** Base AI 助手联网搜索服务 */
34
+ export interface AiSearchService {
35
+ /** 联网搜索公开信息并返回结果摘要 */
36
+ SearchAiWeb(request: SearchAiWebRequest): Promise<SearchAiWebResponse>;
37
+ }
@@ -143,7 +143,6 @@ export interface BaseRedactOutputPolicy {
143
143
 
144
144
  /** 查询可出库脱敏字段请求。 */
145
145
  export interface GetBaseRedactOutputFieldDocRequest {
146
- /** 接口ID */
147
146
  api_id: number;
148
147
  }
149
148
 
@@ -236,42 +236,7 @@ function setRecordText(recordText: string) {
236
236
 
237
237
  /** 标准化语音识别文本,压掉多余空白。 */
238
238
  function normalizeRecordText(recordText: string) {
239
- return collapseCumulativeRecordText(recordText.replace(/\s+/g, " ").trim());
240
- }
241
-
242
- /** 压缩 useRecord 在中文连续识别时返回的前缀累计文本。 */
243
- function collapseCumulativeRecordText(text: string) {
244
- if (text.length < 4) return text;
245
- for (let candidateLength = 2; candidateLength <= Math.floor(text.length / 2); candidateLength++) {
246
- const candidate = text.slice(-candidateLength);
247
- const matchResult = matchCumulativeRecordCandidate(text, candidate);
248
- if (matchResult.matched && (matchResult.hasPartial || matchResult.segmentCount >= 3)) {
249
- return candidate;
250
- }
251
- }
252
- return text;
253
- }
254
-
255
- /** 判断文本是否由同一识别结果的前缀片段累计组成。 */
256
- function matchCumulativeRecordCandidate(text: string, candidate: string) {
257
- let index = 0;
258
- let segmentCount = 0;
259
- let hasPartial = false;
260
- while (index < text.length) {
261
- let matchedLength = 0;
262
- const maxLength = Math.min(candidate.length, text.length - index);
263
- for (let length = maxLength; length >= 1; length--) {
264
- if (candidate.startsWith(text.slice(index, index + length))) {
265
- matchedLength = length;
266
- break;
267
- }
268
- }
269
- if (!matchedLength) return { matched: false, segmentCount, hasPartial };
270
- if (matchedLength < candidate.length) hasPartial = true;
271
- segmentCount++;
272
- index += matchedLength;
273
- }
274
- return { matched: true, segmentCount, hasPartial };
239
+ return recordText.replace(/\s+/g, " ").trim();
275
240
  }
276
241
 
277
242
  /** 根据浏览器语音识别错误类型生成用户可理解的提示。 */