@liujitcn/kratos-admin-system 0.0.27 → 0.0.29

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 (52) hide show
  1. package/README.md +1 -1
  2. package/dist/package/declarations/src/api/system/base_i18n.d.ts +5 -5
  3. package/dist/package/declarations/src/api/system/runtime_log.d.ts +13 -0
  4. package/dist/package/declarations/src/api/system/runtime_log_sse.d.ts +8 -0
  5. package/dist/package/declarations/src/components/DynamicI18nCell.vue.d.ts +16 -0
  6. package/dist/package/declarations/src/components/DynamicI18nEditor.vue.d.ts +20 -0
  7. package/dist/package/declarations/src/components/dynamicI18n.d.ts +38 -0
  8. package/dist/package/declarations/src/locales/generated.d.ts +168 -52
  9. package/dist/package/declarations/src/rpc/system/admin/v1/base_config.d.ts +3 -3
  10. package/dist/package/declarations/src/rpc/system/admin/v1/base_dict.d.ts +4 -4
  11. package/dist/package/declarations/src/rpc/system/admin/v1/base_i18n.d.ts +23 -23
  12. package/dist/package/declarations/src/rpc/system/admin/v1/base_menu.d.ts +2 -2
  13. package/dist/package/declarations/src/rpc/system/admin/v1/code_gen.d.ts +1 -1
  14. package/dist/package/declarations/src/rpc/system/admin/v1/ops_monitoring.d.ts +4 -0
  15. package/dist/package/declarations/src/rpc/system/admin/v1/project_document.d.ts +4 -6
  16. package/dist/package/declarations/src/rpc/system/admin/v1/runtime_log.d.ts +96 -0
  17. package/dist/package/declarations/src/views/tool/runtime-log/index.vue.d.ts +3 -0
  18. package/dist/package/src/api/system/base_i18n.ts +12 -12
  19. package/dist/package/src/api/system/runtime_log.ts +80 -0
  20. package/dist/package/src/api/system/runtime_log_sse.ts +40 -0
  21. package/dist/package/src/components/{DynamicTranslationCell.vue → DynamicI18nCell.vue} +50 -50
  22. package/dist/package/src/components/{DynamicTranslationEditor.vue → DynamicI18nEditor.vue} +45 -45
  23. package/dist/package/src/components/{dynamicTranslation.ts → dynamicI18n.ts} +15 -15
  24. package/dist/package/src/locales/README.md +1 -1
  25. package/dist/package/src/locales/en-US.json +46 -17
  26. package/dist/package/src/locales/ja-JP.json +44 -15
  27. package/dist/package/src/locales/zh-CN.json +44 -15
  28. package/dist/package/src/locales/zh-TW.json +44 -15
  29. package/dist/package/src/rpc/system/admin/v1/base_config.ts +3 -3
  30. package/dist/package/src/rpc/system/admin/v1/base_dict.ts +4 -4
  31. package/dist/package/src/rpc/system/admin/v1/base_i18n.ts +23 -23
  32. package/dist/package/src/rpc/system/admin/v1/base_menu.ts +2 -2
  33. package/dist/package/src/rpc/system/admin/v1/code_gen.ts +1 -1
  34. package/dist/package/src/rpc/system/admin/v1/ops_monitoring.ts +4 -0
  35. package/dist/package/src/rpc/system/admin/v1/project_document.ts +4 -7
  36. package/dist/package/src/rpc/system/admin/v1/runtime_log.ts +113 -0
  37. package/dist/package/src/views/base/config/index.vue +38 -38
  38. package/dist/package/src/views/base/dict/index.vue +23 -23
  39. package/dist/package/src/views/base/dict/item.vue +25 -25
  40. package/dist/package/src/views/base/menu/index.vue +23 -23
  41. package/dist/package/src/views/tool/api-doc/index.vue +14 -6
  42. package/dist/package/src/views/tool/code-gen/code-preview/index.vue +23 -6
  43. package/dist/package/src/views/tool/code-gen/columns/index.vue +1 -1
  44. package/dist/package/src/views/tool/code-gen/components/CodeGenLocaleEditor.vue +96 -14
  45. package/dist/package/src/views/tool/code-gen/table/index.vue +33 -1
  46. package/dist/package/src/views/tool/ops-monitoring/index.vue +130 -24
  47. package/dist/package/src/views/tool/project-doc/index.vue +9 -4
  48. package/dist/package/src/views/tool/runtime-log/index.vue +883 -0
  49. package/package.json +2 -2
  50. package/dist/package/declarations/src/components/DynamicTranslationCell.vue.d.ts +0 -16
  51. package/dist/package/declarations/src/components/DynamicTranslationEditor.vue.d.ts +0 -20
  52. package/dist/package/declarations/src/components/dynamicTranslation.d.ts +0 -38
@@ -50,7 +50,7 @@ export interface BaseMenuForm {
50
50
  /** 分配的API列表 */
51
51
  api: string[];
52
52
  /** 非主语言翻译 */
53
- translations: BaseI18n[];
53
+ i18ns: BaseI18n[];
54
54
  /** 排序 */
55
55
  sort: number;
56
56
  /** 状态 */
@@ -109,7 +109,7 @@ export interface BaseMenu {
109
109
  /** 是否存在子节点 */
110
110
  has_children: boolean;
111
111
  /** 非主语言翻译 */
112
- translations: BaseI18n[];
112
+ i18ns: BaseI18n[];
113
113
  }
114
114
  /** 菜单元信息 */
115
115
  export interface BaseMenuMeta {
@@ -67,7 +67,7 @@ export interface PreviewCodeGenResponse {
67
67
  /** 本次生效输出路径 */
68
68
  output_paths: CodeGenOutputPaths | undefined;
69
69
  /** 正式生成前必须补齐的翻译配置 */
70
- missing_translations: string[];
70
+ missing_i18ns: string[];
71
71
  }
72
72
  /** 启动代码生成任务条件 */
73
73
  export interface StartCodeGenTaskRequest {
@@ -191,6 +191,10 @@ export interface OpsNodeMetric {
191
191
  label: string;
192
192
  /** 指标使用百分比 */
193
193
  value: number;
194
+ /** 当前已用容量,单位字节 */
195
+ used_bytes: number;
196
+ /** 总容量,单位字节 */
197
+ total_bytes: number;
194
198
  }
195
199
  /** 告警事件。 */
196
200
  export interface OpsAlert {
@@ -17,6 +17,8 @@ export interface ProjectDocumentListItem {
17
17
  id: string;
18
18
  /** 项目内相对路径 */
19
19
  path: string;
20
+ /** 当前语言下的文档显示文件名 */
21
+ name: string;
20
22
  /** Markdown文件更新时间,RFC3339格式 */
21
23
  updated_at: string;
22
24
  }
@@ -52,17 +54,13 @@ export interface ProjectDocument {
52
54
  project_name: string;
53
55
  /** 项目内相对路径 */
54
56
  path: string;
57
+ /** 当前语言下的文档显示文件名 */
58
+ name: string;
55
59
  /** Markdown文档内容 */
56
60
  content: string;
57
- /** 按语言标识索引的Markdown翻译内容 */
58
- locale: Map<string, string>;
59
61
  /** Markdown文件更新时间,RFC3339格式 */
60
62
  updated_at: string;
61
63
  }
62
- export interface ProjectDocument_LocaleEntry {
63
- key: string;
64
- value: string;
65
- }
66
64
  /** 项目文档服务 */
67
65
  export interface ProjectDocumentService {
68
66
  /** 查询项目文档树 */
@@ -0,0 +1,96 @@
1
+ /** 历史日志文件列表查询条件。 */
2
+ export interface ListRuntimeLogFilesRequest {
3
+ }
4
+ /** 历史日志文件列表响应。 */
5
+ export interface ListRuntimeLogFilesResponse {
6
+ /** 历史日志文件列表 */
7
+ files: RuntimeLogFile[];
8
+ }
9
+ /** 历史日志文件信息。 */
10
+ export interface RuntimeLogFile {
11
+ /** 服务端签发的日志文件标识 */
12
+ file_id: string;
13
+ /** 日志文件名称 */
14
+ name: string;
15
+ /** 日志文件大小,单位字节 */
16
+ size_bytes: number;
17
+ /** 最后修改时间,RFC3339格式 */
18
+ modified_at: string;
19
+ /** 是否为Gzip压缩文件 */
20
+ is_compressed: boolean;
21
+ /** 是否为当前活动日志文件 */
22
+ is_active: boolean;
23
+ }
24
+ /** 历史日志文件读取条件。 */
25
+ export interface ReadRuntimeLogFileRequest {
26
+ /** 服务端签发的日志文件标识 */
27
+ file_id: string;
28
+ /** 向更早日志翻页的不透明游标,留空时从文件尾部读取 */
29
+ cursor: string;
30
+ /** 单次读取条数,0使用默认值,最大500 */
31
+ limit: number;
32
+ /** 日志内容搜索关键字 */
33
+ keyword: string;
34
+ /** 日志级别筛选列表 */
35
+ levels: string[];
36
+ }
37
+ /** 历史日志文件读取响应。 */
38
+ export interface ReadRuntimeLogFileResponse {
39
+ /** 按时间正序排列的日志条目 */
40
+ entries: RuntimeLogEntry[];
41
+ /** 继续读取更早日志的不透明游标 */
42
+ next_cursor: string;
43
+ /** 是否还有更早日志 */
44
+ has_more: boolean;
45
+ /** 读取期间日志文件是否已滚动或截断 */
46
+ file_changed: boolean;
47
+ }
48
+ /** 实时或历史日志条目。 */
49
+ export interface RuntimeLogEntry {
50
+ /** 当前进程内的日志序号,历史文件日志为空 */
51
+ sequence: string;
52
+ /** 日志时间 */
53
+ timestamp: string;
54
+ /** 日志级别 */
55
+ level: string;
56
+ /** 日志来源 */
57
+ source: string;
58
+ /** 日志消息 */
59
+ message: string;
60
+ /** 可直接展示的纯文本日志行 */
61
+ line: string;
62
+ /** 日志行是否因长度限制被截断 */
63
+ is_truncated: boolean;
64
+ }
65
+ /** 实时控制台开启条件。 */
66
+ export interface OpenRuntimeConsoleRequest {
67
+ /** 首次返回的最近日志条数,0使用默认值,最大500 */
68
+ backlog_limit: number;
69
+ }
70
+ /** 实时控制台开启响应。 */
71
+ export interface OpenRuntimeConsoleResponse {
72
+ /** SSE业务流标识 */
73
+ stream: string;
74
+ /** 当前用户专属SSE频道标识 */
75
+ channel_id: string;
76
+ /** 频道过期时间,RFC3339格式 */
77
+ expires_at: string;
78
+ /** 当前服务实例标识 */
79
+ instance_id: string;
80
+ /** 当前进程最新日志序号 */
81
+ latest_sequence: string;
82
+ /** 当前进程最近日志 */
83
+ entries: RuntimeLogEntry[];
84
+ }
85
+ /** 实时控制台丢失消息提示。 */
86
+ export interface RuntimeLogGap {
87
+ /** 本次丢弃的日志条数 */
88
+ dropped_count: number;
89
+ /** 发生丢弃时的最新日志序号 */
90
+ latest_sequence: string;
91
+ }
92
+ /** 历史日志文件下载条件。 */
93
+ export interface DownloadRuntimeLogFileRequest {
94
+ /** 服务端签发的日志文件标识 */
95
+ file_id: string;
96
+ }
@@ -0,0 +1,3 @@
1
+ declare const __VLS_export: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
2
+ declare const _default: typeof __VLS_export;
3
+ export default _default;
@@ -2,28 +2,28 @@ import service from "@liujitcn/kratos-admin-core/request";
2
2
  import type { Empty } from "@liujitcn/kratos-admin-system/rpc/google/protobuf/empty";
3
3
  import type {
4
4
  BaseI18nService,
5
- DraftBaseTranslationRequest,
6
- DraftBaseTranslationResponse,
7
- UpdateBaseTranslationRequest
5
+ DraftBaseI18nRequest,
6
+ DraftBaseI18nResponse,
7
+ UpdateBaseI18nRequest
8
8
  } from "@liujitcn/kratos-admin-system/rpc/system/admin/v1/base_i18n";
9
9
 
10
- const BASE_TRANSLATION_URL = "/v1/admin/base/translation";
10
+ const BASE_I18N_URL = "/v1/admin/base/i18n";
11
11
 
12
12
  /** BaseI18nServiceImpl Admin 单条动态翻译服务。 */
13
13
  export class BaseI18nServiceImpl implements BaseI18nService {
14
- /** DraftBaseTranslation 翻译请求中的单个文本。 */
15
- DraftBaseTranslation(request: DraftBaseTranslationRequest): Promise<DraftBaseTranslationResponse> {
16
- return service<DraftBaseTranslationRequest, DraftBaseTranslationResponse>({
17
- url: `${BASE_TRANSLATION_URL}/draft`,
14
+ /** DraftBaseI18n 翻译请求中的单个文本。 */
15
+ DraftBaseI18n(request: DraftBaseI18nRequest): Promise<DraftBaseI18nResponse> {
16
+ return service<DraftBaseI18nRequest, DraftBaseI18nResponse>({
17
+ url: `${BASE_I18N_URL}/draft`,
18
18
  method: "post",
19
19
  data: request
20
20
  });
21
21
  }
22
22
 
23
- /** UpdateBaseTranslation 修改或新增单条翻译信息。 */
24
- UpdateBaseTranslation(request: UpdateBaseTranslationRequest): Promise<Empty> {
25
- return service<UpdateBaseTranslationRequest, Empty>({
26
- url: BASE_TRANSLATION_URL,
23
+ /** UpdateBaseI18n 修改或新增单条翻译信息。 */
24
+ UpdateBaseI18n(request: UpdateBaseI18nRequest): Promise<Empty> {
25
+ return service<UpdateBaseI18nRequest, Empty>({
26
+ url: BASE_I18N_URL,
27
27
  method: "put",
28
28
  data: request
29
29
  });
@@ -0,0 +1,80 @@
1
+ import service from "@liujitcn/kratos-admin-core/request";
2
+ import type {
3
+ DownloadRuntimeLogFileRequest,
4
+ ListRuntimeLogFilesRequest,
5
+ ListRuntimeLogFilesResponse,
6
+ OpenRuntimeConsoleRequest,
7
+ OpenRuntimeConsoleResponse,
8
+ ReadRuntimeLogFileRequest,
9
+ ReadRuntimeLogFileResponse
10
+ } from "@liujitcn/kratos-admin-system/rpc/system/admin/v1/runtime_log";
11
+
12
+ const RUNTIME_LOG_URL = "/v1/admin/runtime-log";
13
+
14
+ /** Admin运行日志服务。 */
15
+ export class RuntimeLogServiceImpl {
16
+ /** 查询历史日志文件列表。 */
17
+ ListRuntimeLogFiles(request: ListRuntimeLogFilesRequest): Promise<ListRuntimeLogFilesResponse> {
18
+ return service<ListRuntimeLogFilesRequest, ListRuntimeLogFilesResponse>({
19
+ url: `${RUNTIME_LOG_URL}/files`,
20
+ method: "get",
21
+ params: request
22
+ });
23
+ }
24
+
25
+ /** 分页读取历史日志文件内容。 */
26
+ ReadRuntimeLogFile(request: ReadRuntimeLogFileRequest): Promise<ReadRuntimeLogFileResponse> {
27
+ return service<ReadRuntimeLogFileRequest, ReadRuntimeLogFileResponse>({
28
+ url: `${RUNTIME_LOG_URL}/files/${encodeURIComponent(request.file_id)}`,
29
+ method: "get",
30
+ params: {
31
+ cursor: request.cursor,
32
+ limit: request.limit,
33
+ keyword: request.keyword,
34
+ levels: request.levels
35
+ }
36
+ });
37
+ }
38
+
39
+ /** 创建当前用户的实时控制台频道。 */
40
+ OpenRuntimeConsole(request: OpenRuntimeConsoleRequest): Promise<OpenRuntimeConsoleResponse> {
41
+ return service<OpenRuntimeConsoleRequest, OpenRuntimeConsoleResponse>({
42
+ url: `${RUNTIME_LOG_URL}/console`,
43
+ method: "post",
44
+ data: request
45
+ });
46
+ }
47
+
48
+ /** 下载历史日志原文件。 */
49
+ async DownloadRuntimeLogFile(request: DownloadRuntimeLogFileRequest, fallbackName: string): Promise<void> {
50
+ const response = await service<DownloadRuntimeLogFileRequest, any>({
51
+ url: `${RUNTIME_LOG_URL}/files/${encodeURIComponent(request.file_id)}/download`,
52
+ method: "get",
53
+ responseType: "blob"
54
+ });
55
+ const contentDisposition = String(response.headers?.["content-disposition"] ?? "");
56
+ const encodedName = contentDisposition.match(/filename\*=UTF-8''([^;]+)/i)?.[1];
57
+ const plainName = contentDisposition.match(/filename="?([^";]+)"?/i)?.[1];
58
+ let filename = fallbackName;
59
+ if (encodedName) {
60
+ try {
61
+ filename = decodeURIComponent(encodedName);
62
+ } catch {
63
+ filename = fallbackName;
64
+ }
65
+ } else if (plainName) {
66
+ filename = plainName;
67
+ }
68
+ const blob = response.data instanceof Blob ? response.data : new Blob([response.data]);
69
+ const objectURL = window.URL.createObjectURL(blob);
70
+ const anchor = document.createElement("a");
71
+ anchor.href = objectURL;
72
+ anchor.download = filename;
73
+ document.body.appendChild(anchor);
74
+ anchor.click();
75
+ anchor.remove();
76
+ window.URL.revokeObjectURL(objectURL);
77
+ }
78
+ }
79
+
80
+ export const defRuntimeLogService = new RuntimeLogServiceImpl();
@@ -0,0 +1,40 @@
1
+ import { subscribeSseEvent, type SseStop } from "../base/sse";
2
+ import type {
3
+ RuntimeLogEntry,
4
+ RuntimeLogGap
5
+ } from "@liujitcn/kratos-admin-system/rpc/system/admin/v1/runtime_log";
6
+
7
+ const RUNTIME_LOG_SSE_STREAM = "system.admin.runtime-console";
8
+ const RUNTIME_LOG_SSE_ENTRY = "runtime.log";
9
+ const RUNTIME_LOG_SSE_GAP = "runtime.gap";
10
+
11
+ /** 实时日志事件处理函数。 */
12
+ export type RuntimeLogEntryHandler = (entry: RuntimeLogEntry) => void;
13
+
14
+ /** 实时日志丢失事件处理函数。 */
15
+ export type RuntimeLogGapHandler = (gap: RuntimeLogGap) => void;
16
+
17
+ /** 订阅指定用户频道的实时日志和丢失提示事件。 */
18
+ export function subscribeRuntimeLog(
19
+ channelId: string,
20
+ entryHandler: RuntimeLogEntryHandler,
21
+ gapHandler: RuntimeLogGapHandler
22
+ ): SseStop {
23
+ const request = { stream: RUNTIME_LOG_SSE_STREAM, channel_id: channelId };
24
+ const stopEntry = subscribeSseEvent(request, RUNTIME_LOG_SSE_ENTRY, parsePayload<RuntimeLogEntry>, entryHandler);
25
+ const stopGap = subscribeSseEvent(request, RUNTIME_LOG_SSE_GAP, parsePayload<RuntimeLogGap>, gapHandler);
26
+ return () => {
27
+ stopGap();
28
+ stopEntry();
29
+ };
30
+ }
31
+
32
+ /** 解析实时日志 SSE JSON 负载。 */
33
+ function parsePayload<T>(raw: string): T | null {
34
+ if (!raw) return null;
35
+ try {
36
+ return JSON.parse(raw) as T;
37
+ } catch {
38
+ return null;
39
+ }
40
+ }
@@ -1,6 +1,6 @@
1
1
  <template>
2
- <el-link class="dynamic-translation-cell" type="primary" underline="never" @click="openDialog">
3
- <span class="dynamic-translation-cell__source">{{ displaySource || "--" }}</span>
2
+ <el-link class="dynamic-i18n-cell" type="primary" underline="never" @click="openDialog">
3
+ <span class="dynamic-i18n-cell__source">{{ displaySource || "--" }}</span>
4
4
  </el-link>
5
5
 
6
6
  <ProDialog
@@ -12,20 +12,20 @@
12
12
  :destroy-on-close="true"
13
13
  @closed="handleDialogClosed"
14
14
  >
15
- <el-table v-loading="loading" :data="translationRows" border>
15
+ <el-table v-loading="loading" :data="i18nRows" border>
16
16
  <el-table-column :label="t('common.field.language')" width="150">
17
17
  <template #default="{ row }">
18
18
  {{ getLanguageLabel(row.locale) }}
19
19
  </template>
20
20
  </el-table-column>
21
- <el-table-column :label="t('system.base.translation.field.translations')" min-width="360">
21
+ <el-table-column :label="t('system.base.i18n.field.i18ns')" min-width="360">
22
22
  <template #default="{ row }">
23
23
  <el-input
24
24
  v-if="row.editing"
25
25
  v-model="row.text"
26
- :placeholder="t('system.base.translation.placeholder.text', { language: getLanguageLabel(row.locale) })"
26
+ :placeholder="t('system.base.i18n.placeholder.text', { language: getLanguageLabel(row.locale) })"
27
27
  />
28
- <span v-else class="dynamic-translation-dialog__text">
28
+ <span v-else class="dynamic-i18n-dialog__text">
29
29
  {{ row.text || t("common.value.none") }}
30
30
  </span>
31
31
  </template>
@@ -36,7 +36,7 @@
36
36
  {{ t("common.action.edit") }}
37
37
  </el-button>
38
38
  <template v-else>
39
- <el-button link type="primary" :icon="Check" :loading="row.saving" @click="saveTranslation(row)">
39
+ <el-button link type="primary" :icon="Check" :loading="row.saving" @click="saveI18n(row)">
40
40
  {{ t("common.action.save") }}
41
41
  </el-button>
42
42
  <el-button link :icon="Close" :disabled="row.saving" @click="cancelEdit(row)">
@@ -58,48 +58,48 @@ import { t, useLocaleStore } from "@liujitcn/kratos-admin-core";
58
58
  import { loadEnabledBaseLanguages, useEnabledBaseLanguages } from "@liujitcn/kratos-admin-system/api/system/base_language";
59
59
  import { defBaseI18nService } from "@liujitcn/kratos-admin-system/api/system/base_i18n";
60
60
  import type { BaseI18n } from "@liujitcn/kratos-admin-system/rpc/system/admin/v1/base_i18n";
61
- import { TranslationTargetType } from "@liujitcn/kratos-admin-system/rpc/system/admin/v1/base_i18n";
62
- import { getLanguageLabel } from "./dynamicTranslation";
61
+ import { I18nTargetType } from "@liujitcn/kratos-admin-system/rpc/system/admin/v1/base_i18n";
62
+ import { getLanguageLabel } from "./dynamicI18n";
63
63
 
64
- /** DynamicTranslationCellProps 动态翻译列表单元格属性。 */
65
- interface DynamicTranslationCellProps {
64
+ /** DynamicI18nCellProps 动态翻译列表单元格属性。 */
65
+ interface DynamicI18nCellProps {
66
66
  /** 资源源文。 */
67
67
  source: string;
68
68
  /** 统一翻译表目标类型。 */
69
- targetType?: TranslationTargetType;
69
+ targetType?: I18nTargetType;
70
70
  /** 目标资源编号。 */
71
71
  targetId?: number;
72
72
  /** 资源列表返回的非主语言翻译。 */
73
- translations?: BaseI18n[];
73
+ i18ns?: BaseI18n[];
74
74
  }
75
75
 
76
- const props = defineProps<DynamicTranslationCellProps>();
76
+ const props = defineProps<DynamicI18nCellProps>();
77
77
 
78
78
  const { languages } = useEnabledBaseLanguages();
79
79
  const { locale } = useLocaleStore();
80
80
  const dialogVisible = ref(false);
81
81
  const loading = ref(false);
82
- const translationRows = ref<DynamicTranslationRow[]>([]);
83
- const translationOverrides = ref(new Map<string, string>());
82
+ const i18nRows = ref<DynamicI18nRow[]>([]);
83
+ const i18nOverrides = ref(new Map<string, string>());
84
84
 
85
85
  const displaySource = computed(() => {
86
- const override = translationOverrides.value.get(locale.value);
86
+ const override = i18nOverrides.value.get(locale.value);
87
87
  if (override) return override;
88
- const translation = props.translations?.find(item => item.locale === locale.value && item.name);
89
- return translation?.name || props.source;
88
+ const i18n = props.i18ns?.find(item => item.locale === locale.value && item.name);
89
+ return i18n?.name || props.source;
90
90
  });
91
91
 
92
92
  watch(
93
93
  () => [props.targetType, props.targetId],
94
94
  () => {
95
- translationRows.value = [];
96
- translationOverrides.value.clear();
95
+ i18nRows.value = [];
96
+ i18nOverrides.value.clear();
97
97
  dialogVisible.value = false;
98
98
  }
99
99
  );
100
100
 
101
- /** DynamicTranslationRow 描述弹窗内可编辑的单语言翻译行。 */
102
- interface DynamicTranslationRow {
101
+ /** DynamicI18nRow 描述弹窗内可编辑的单语言翻译行。 */
102
+ interface DynamicI18nRow {
103
103
  /** 翻译记录主键,新增翻译时为空。 */
104
104
  id: number;
105
105
  /** 语言区域。 */
@@ -117,43 +117,43 @@ interface DynamicTranslationRow {
117
117
  /** openDialog 打开翻译编辑弹窗并加载当前资源译文。 */
118
118
  async function openDialog() {
119
119
  dialogVisible.value = true;
120
- await loadTranslations();
120
+ await loadI18ns();
121
121
  }
122
122
 
123
- /** loadTranslations 查询当前资源的翻译并补齐启用语言行。 */
124
- async function loadTranslations() {
123
+ /** loadI18ns 查询当前资源的翻译并补齐启用语言行。 */
124
+ async function loadI18ns() {
125
125
  const targetType = props.targetType;
126
126
  const targetId = props.targetId;
127
127
  if (!targetType || !targetId) return;
128
128
  loading.value = true;
129
129
  try {
130
130
  await loadEnabledBaseLanguages();
131
- const rows = await queryTranslationRows();
132
- translationRows.value = rows;
131
+ const rows = await queryI18nRows();
132
+ i18nRows.value = rows;
133
133
  const missingRows = rows.filter(row => !row.text);
134
134
  if (missingRows.length === 0) return;
135
135
  if (!props.source) return;
136
- const draft = await defBaseI18nService.DraftBaseTranslation({ source: props.source });
137
- const translations = new Map(draft.translations.map(item => [item.locale, item.translation]));
136
+ const draft = await defBaseI18nService.DraftBaseI18n({ source: props.source });
137
+ const i18ns = new Map(draft.i18ns.map(item => [item.locale, item.i18n]));
138
138
  const results = await Promise.allSettled(
139
139
  missingRows.map(async row => {
140
- const translation = translations.get(row.locale);
141
- if (!translation) throw new Error("translation not found");
142
- await defBaseI18nService.UpdateBaseTranslation({
140
+ const i18n = i18ns.get(row.locale);
141
+ if (!i18n) throw new Error("i18n not found");
142
+ await defBaseI18nService.UpdateBaseI18n({
143
143
  id: row.id,
144
144
  target_type: targetType,
145
145
  target_id: targetId,
146
146
  locale: row.locale,
147
- name: translation
147
+ name: i18n
148
148
  });
149
- return { row, text: translation };
149
+ return { row, text: i18n };
150
150
  })
151
151
  );
152
152
  for (const result of results) {
153
153
  if (result.status !== "fulfilled") continue;
154
154
  result.value.row.text = result.value.text;
155
155
  result.value.row.originalText = result.value.text;
156
- translationOverrides.value.set(result.value.row.locale, result.value.text);
156
+ i18nOverrides.value.set(result.value.row.locale, result.value.text);
157
157
  }
158
158
  } catch {
159
159
  ElMessage.error(t("common.message.system_error"));
@@ -162,14 +162,14 @@ async function loadTranslations() {
162
162
  }
163
163
  }
164
164
 
165
- /** queryTranslationRows 将列表返回的翻译记录补齐为可编辑语言行。 */
166
- async function queryTranslationRows(): Promise<DynamicTranslationRow[]> {
167
- const records = new Map((props.translations ?? []).map(item => [item.locale, item]));
165
+ /** queryI18nRows 将列表返回的翻译记录补齐为可编辑语言行。 */
166
+ async function queryI18nRows(): Promise<DynamicI18nRow[]> {
167
+ const records = new Map((props.i18ns ?? []).map(item => [item.locale, item]));
168
168
  return languages.value
169
169
  .filter(item => !item.is_primary)
170
170
  .map(item => {
171
171
  const record = records.get(item.language_code);
172
- const text = translationOverrides.value.get(item.language_code) ?? record?.name ?? "";
172
+ const text = i18nOverrides.value.get(item.language_code) ?? record?.name ?? "";
173
173
  return {
174
174
  id: record?.id ?? 0,
175
175
  locale: item.language_code,
@@ -182,19 +182,19 @@ async function queryTranslationRows(): Promise<DynamicTranslationRow[]> {
182
182
  }
183
183
 
184
184
  /** startEdit 开启指定语言的编辑状态。 */
185
- function startEdit(row: DynamicTranslationRow) {
185
+ function startEdit(row: DynamicI18nRow) {
186
186
  row.originalText = row.text;
187
187
  row.editing = true;
188
188
  }
189
189
 
190
190
  /** cancelEdit 恢复编辑前的内容。 */
191
- function cancelEdit(row: DynamicTranslationRow) {
191
+ function cancelEdit(row: DynamicI18nRow) {
192
192
  row.text = row.originalText;
193
193
  row.editing = false;
194
194
  }
195
195
 
196
- /** saveTranslation 使用统一更新接口保存指定语言译文。 */
197
- async function saveTranslation(row: DynamicTranslationRow) {
196
+ /** saveI18n 使用统一更新接口保存指定语言译文。 */
197
+ async function saveI18n(row: DynamicI18nRow) {
198
198
  const targetType = props.targetType;
199
199
  const targetId = props.targetId;
200
200
  if (row.saving || !targetType || !targetId) return;
@@ -204,7 +204,7 @@ async function saveTranslation(row: DynamicTranslationRow) {
204
204
  }
205
205
  row.saving = true;
206
206
  try {
207
- await defBaseI18nService.UpdateBaseTranslation({
207
+ await defBaseI18nService.UpdateBaseI18n({
208
208
  id: row.id,
209
209
  target_type: targetType,
210
210
  target_id: targetId,
@@ -214,7 +214,7 @@ async function saveTranslation(row: DynamicTranslationRow) {
214
214
  ElMessage.success(t("common.message.operation_success"));
215
215
  row.editing = false;
216
216
  row.originalText = row.text;
217
- translationOverrides.value.set(row.locale, row.text);
217
+ i18nOverrides.value.set(row.locale, row.text);
218
218
  } catch {
219
219
  ElMessage.error(t("common.message.system_error"));
220
220
  } finally {
@@ -224,25 +224,25 @@ async function saveTranslation(row: DynamicTranslationRow) {
224
224
 
225
225
  /** handleDialogClosed 清理弹窗状态,避免复用旧资源译文。 */
226
226
  function handleDialogClosed() {
227
- translationRows.value = [];
227
+ i18nRows.value = [];
228
228
  loading.value = false;
229
229
  }
230
230
  </script>
231
231
 
232
232
  <style scoped>
233
- .dynamic-translation-cell {
233
+ .dynamic-i18n-cell {
234
234
  display: inline-flex;
235
235
  align-items: center;
236
236
  min-width: 0;
237
237
  max-width: 100%;
238
238
  }
239
- .dynamic-translation-cell__source {
239
+ .dynamic-i18n-cell__source {
240
240
  min-width: 0;
241
241
  overflow: hidden;
242
242
  text-overflow: ellipsis;
243
243
  white-space: nowrap;
244
244
  }
245
- .dynamic-translation-dialog__text {
245
+ .dynamic-i18n-dialog__text {
246
246
  min-width: 0;
247
247
  overflow-wrap: anywhere;
248
248
  }