@liujitcn/kratos-admin-system 0.0.39 → 0.0.40

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 (39) hide show
  1. package/README.md +22 -0
  2. package/dist/package/declarations/src/api/system/admin/v1/base_config.d.ts +1 -5
  3. package/dist/package/declarations/src/components/DynamicI18nCell.vue.d.ts +2 -8
  4. package/dist/package/declarations/src/components/DynamicI18nEditor.vue.d.ts +20 -3
  5. package/dist/package/declarations/src/components/dynamicI18n.d.ts +2 -2
  6. package/dist/package/declarations/src/locales/generated.d.ts +5797 -5813
  7. package/dist/package/declarations/src/rpc/system/admin/v1/base_config.d.ts +4 -40
  8. package/dist/package/declarations/src/utils/code-gen-progress.d.ts +3 -0
  9. package/dist/package/declarations/src/views/tool/code-gen/components/CodeGenGenerateConfirm.vue.d.ts +11 -0
  10. package/dist/package/declarations/src/views/tool/code-gen/components/CodeGenLocaleEditor.vue.d.ts +5 -9
  11. package/dist/package/declarations/src/views/tool/code-gen/config.d.ts +3 -0
  12. package/dist/package/src/api/system/admin/v1/base_config.ts +0 -20
  13. package/dist/package/src/components/DynamicI18nCell.vue +55 -220
  14. package/dist/package/src/components/DynamicI18nEditor.vue +150 -146
  15. package/dist/package/src/components/dynamicI18n.ts +10 -6
  16. package/dist/package/src/config/index.ts +1 -3
  17. package/dist/package/src/locales/en-US.json +1430 -1434
  18. package/dist/package/src/locales/ja-JP.json +1430 -1434
  19. package/dist/package/src/locales/zh-CN.json +1429 -1433
  20. package/dist/package/src/locales/zh-TW.json +1429 -1433
  21. package/dist/package/src/module.ts +0 -1
  22. package/dist/package/src/rpc/system/admin/v1/base_config.ts +3 -43
  23. package/dist/package/src/utils/code-gen-progress.ts +15 -0
  24. package/dist/package/src/views/base/config/index.vue +183 -48
  25. package/dist/package/src/views/base/dict/index.vue +6 -9
  26. package/dist/package/src/views/base/dict/item.vue +6 -15
  27. package/dist/package/src/views/base/job/index.vue +16 -17
  28. package/dist/package/src/views/base/menu/index.vue +78 -15
  29. package/dist/package/src/views/tool/code-gen/columns/index.vue +17 -25
  30. package/dist/package/src/views/tool/code-gen/components/CodeGenGenerateConfirm.vue +115 -0
  31. package/dist/package/src/views/tool/code-gen/components/CodeGenLocaleEditor.vue +27 -186
  32. package/dist/package/src/views/tool/code-gen/components/CodeGenProgressDialog.vue +2 -0
  33. package/dist/package/src/views/tool/code-gen/config.ts +15 -1
  34. package/dist/package/src/views/tool/code-gen/table/index.vue +69 -40
  35. package/package.json +3 -2
  36. package/dist/package/declarations/src/config/database-backup.d.ts +0 -12
  37. package/dist/package/declarations/src/views/base/runtime-config/index.vue.d.ts +0 -3
  38. package/dist/package/src/config/database-backup.ts +0 -57
  39. package/dist/package/src/views/base/runtime-config/index.vue +0 -479
@@ -15,16 +15,9 @@ export declare enum BaseConfigType {
15
15
  /** BASE_CONFIG_TYPE_DICT - 字典。 */
16
16
  BASE_CONFIG_TYPE_DICT = 4,
17
17
  /** BASE_CONFIG_TYPE_BOOLEAN - 布尔。 */
18
- BASE_CONFIG_TYPE_BOOLEAN = 5
19
- }
20
- /** 系统配置隐藏状态。 */
21
- export declare enum BaseConfigHiddenStatus {
22
- /** BASE_CONFIG_HIDDEN_STATUS_UNSPECIFIED - 未指定隐藏状态。 */
23
- BASE_CONFIG_HIDDEN_STATUS_UNSPECIFIED = 0,
24
- /** BASE_CONFIG_HIDDEN_STATUS_VISIBLE - 普通配置,可在通用配置页面展示。 */
25
- BASE_CONFIG_HIDDEN_STATUS_VISIBLE = 1,
26
- /** BASE_CONFIG_HIDDEN_STATUS_HIDDEN - 隐藏配置,仅允许通过专用配置表单访问。 */
27
- BASE_CONFIG_HIDDEN_STATUS_HIDDEN = 2
18
+ BASE_CONFIG_TYPE_BOOLEAN = 5,
19
+ /** BASE_CONFIG_TYPE_FORM - 表单。 */
20
+ BASE_CONFIG_TYPE_FORM = 6
28
21
  }
29
22
  /** 系统配置分页查询条件 */
30
23
  export interface PageBaseConfigRequest {
@@ -63,14 +56,12 @@ export interface BaseConfigForm {
63
56
  site: BaseConfigSite;
64
57
  /** 配置名称 */
65
58
  name: string;
66
- /** 配置类型:1、文本,2、图片,3、富文本,4、字典,5、布尔 */
59
+ /** 配置类型:1、文本,2、图片,3、富文本,4、字典,5、布尔,6、表单 */
67
60
  type: BaseConfigType;
68
61
  /** 配置key */
69
62
  key: string;
70
63
  /** 配置value */
71
64
  value: string;
72
- /** 隐藏状态 */
73
- hidden_status: BaseConfigHiddenStatus;
74
65
  /** 配置名称多语言翻 */
75
66
  name_i18ns: BaseI18n[];
76
67
  /** 配置value文本/富文本配置值的多语言翻译 */
@@ -117,8 +108,6 @@ export interface BaseConfig {
117
108
  key: string;
118
109
  /** 配置value */
119
110
  value: string;
120
- /** 隐藏状态 */
121
- hidden_status: BaseConfigHiddenStatus;
122
111
  /** 状态:枚举【Status】 */
123
112
  status: Status;
124
113
  /** 创建时间 */
@@ -128,27 +117,6 @@ export interface BaseConfig {
128
117
  /** 配置名称及文本/富文本配置值的多语言翻译 */
129
118
  i18ns: BaseI18n[];
130
119
  }
131
- /** 按配置键查询系统配置请求参数。 */
132
- export interface GetBaseConfigByKeyRequest {
133
- /** 配置key */
134
- key: string;
135
- }
136
- /** 按配置键返回系统配置值。 */
137
- export interface BaseConfigValue {
138
- /** 配置key */
139
- key: string;
140
- /** JSON格式配置值 */
141
- value_json: string;
142
- /** 更新时间 */
143
- updated_at: string;
144
- }
145
- /** 按配置键更新系统配置请求参数。 */
146
- export interface UpdateBaseConfigByKeyRequest {
147
- /** 配置key */
148
- key: string;
149
- /** JSON格式配置值 */
150
- value_json: string;
151
- }
152
120
  /** Admin系统配置服务 */
153
121
  export interface BaseConfigService {
154
122
  /** 刷新缓存 */
@@ -157,14 +125,10 @@ export interface BaseConfigService {
157
125
  PageBaseConfig(request: PageBaseConfigRequest): Promise<PageBaseConfigResponse>;
158
126
  /** 查询系统配置 */
159
127
  GetBaseConfig(request: GetBaseConfigRequest): Promise<BaseConfigForm>;
160
- /** 按配置键查询隐藏系统配置。 */
161
- GetBaseConfigByKey(request: GetBaseConfigByKeyRequest): Promise<BaseConfigValue>;
162
128
  /** 创建系统配置 */
163
129
  CreateBaseConfig(request: CreateBaseConfigRequest): Promise<Empty>;
164
130
  /** 更新系统配置 */
165
131
  UpdateBaseConfig(request: UpdateBaseConfigRequest): Promise<Empty>;
166
- /** 按配置键更新隐藏系统配置。 */
167
- UpdateBaseConfigByKey(request: UpdateBaseConfigByKeyRequest): Promise<Empty>;
168
132
  /** 删除系统配置 */
169
133
  DeleteBaseConfig(request: DeleteBaseConfigRequest): Promise<Empty>;
170
134
  /** 设置状态 */
@@ -0,0 +1,3 @@
1
+ import type { CodeGenTask } from "../rpc/system/admin/v1/code_gen";
2
+ /** 补齐 ProtoJSON 省略的零值计数,统一 HTTP 与 SSE 任务快照。 */
3
+ export declare function normalizeCodeGenTask(task: CodeGenTask): CodeGenTask;
@@ -0,0 +1,11 @@
1
+ /** 生成确认内容,按业务表保留缺失翻译明细。 */
2
+ type __VLS_Props = {
3
+ message: string;
4
+ groups: Array<{
5
+ name: string;
6
+ items: string[];
7
+ }>;
8
+ };
9
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
10
+ declare const _default: typeof __VLS_export;
11
+ export default _default;
@@ -1,23 +1,19 @@
1
1
  import type { CodeGenLocaleConfig } from "@liujitcn/kratos-admin-system/rpc/system/admin/v1/base_i18n";
2
- /** 代码生成多语言编辑器属性。 */
2
+ /** 代码生成描述使用统一国际化入口,按字段保存回语言配置。 */
3
3
  interface CodeGenLocaleEditorProps {
4
- /** 按语言区域索引的生成配置。 */
5
4
  modelValue: Map<string, CodeGenLocaleConfig>;
6
- /** 中文业务或字段描述。 */
7
5
  sourceComment?: string;
8
- /** 是否编辑左树标题。 */
9
- showLeftTreeComment?: boolean;
10
- /** 中文左树标题。 */
11
- sourceLeftTreeComment?: string;
6
+ field?: keyof CodeGenLocaleConfig;
7
+ disabled?: boolean;
12
8
  }
13
9
  declare const __VLS_export: import("vue").DefineComponent<CodeGenLocaleEditorProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
14
10
  "update:modelValue": (value: Map<string, CodeGenLocaleConfig>) => any;
15
11
  }, string, import("vue").PublicProps, Readonly<CodeGenLocaleEditorProps> & Readonly<{
16
12
  "onUpdate:modelValue"?: ((value: Map<string, CodeGenLocaleConfig>) => any) | undefined;
17
13
  }>, {
14
+ disabled: boolean;
15
+ field: keyof CodeGenLocaleConfig;
18
16
  sourceComment: string;
19
- showLeftTreeComment: boolean;
20
- sourceLeftTreeComment: string;
21
17
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
22
18
  declare const _default: typeof __VLS_export;
23
19
  export default _default;
@@ -1,3 +1,4 @@
1
+ import type { CodeGenLocaleConfig } from "@liujitcn/kratos-admin-system/rpc/system/admin/v1/base_i18n";
1
2
  import type { FormRules } from "element-plus";
2
3
  import type { ProFormOption } from "@liujitcn/kratos-admin-core/components/ProForm/interface";
3
4
  import type { CodeGenColumnFormConfig, CodeGenColumnListConfig, CodeGenColumnOptionConfig, CodeGenColumnQueryConfig } from "@liujitcn/kratos-admin-system/rpc/system/admin/v1/code_gen_column";
@@ -30,3 +31,5 @@ export declare function createDefaultCodeGenListConfig(): CodeGenColumnListConfi
30
31
  export declare function createDefaultCodeGenFormConfig(): CodeGenColumnFormConfig;
31
32
  /** 创建一份独立的字段选项配置。 */
32
33
  export declare function createDefaultCodeGenOptionConfig(): CodeGenColumnOptionConfig;
34
+ /** 保存代码生成配置时,以原值补齐尚未填写的启用语言描述。 */
35
+ export declare function withCodeGenLocaleDefaults(values: Map<string, CodeGenLocaleConfig>, comment: string, leftTreeComment?: string): Map<string, CodeGenLocaleConfig>;
@@ -4,14 +4,11 @@ import {
4
4
  type BaseConfigService,
5
5
  type CreateBaseConfigRequest,
6
6
  type DeleteBaseConfigRequest,
7
- type GetBaseConfigByKeyRequest,
8
- type BaseConfigValue,
9
7
  type GetBaseConfigRequest,
10
8
  type PageBaseConfigRequest,
11
9
  type PageBaseConfigResponse,
12
10
  type RefreshBaseConfigCacheRequest,
13
11
  type SetBaseConfigStatusRequest,
14
- type UpdateBaseConfigByKeyRequest,
15
12
  type UpdateBaseConfigRequest
16
13
  } from "@liujitcn/kratos-admin-system/rpc/system/admin/v1/base_config";
17
14
  import type { Empty } from "@liujitcn/kratos-admin-system/rpc/google/protobuf/empty";
@@ -46,14 +43,6 @@ export class BaseConfigServiceImpl implements BaseConfigService {
46
43
  });
47
44
  }
48
45
 
49
- /** 按配置键查询隐藏系统配置。 */
50
- GetBaseConfigByKey(request: GetBaseConfigByKeyRequest): Promise<BaseConfigValue> {
51
- return service<GetBaseConfigByKeyRequest, BaseConfigValue>({
52
- url: `${BASE_CONFIG_URL}/key/${request.key}`,
53
- method: "get"
54
- });
55
- }
56
-
57
46
  /** 创建系统配置 */
58
47
  CreateBaseConfig(request: CreateBaseConfigRequest): Promise<Empty> {
59
48
  return service<BaseConfigForm | undefined, Empty>({
@@ -72,15 +61,6 @@ export class BaseConfigServiceImpl implements BaseConfigService {
72
61
  });
73
62
  }
74
63
 
75
- /** 按配置键更新隐藏系统配置。 */
76
- UpdateBaseConfigByKey(request: UpdateBaseConfigByKeyRequest): Promise<Empty> {
77
- return service<Pick<UpdateBaseConfigByKeyRequest, "value_json">, Empty>({
78
- url: `${BASE_CONFIG_URL}/key/${request.key}`,
79
- method: "put",
80
- data: { value_json: request.value_json }
81
- });
82
- }
83
-
84
64
  /** 删除系统配置 */
85
65
  DeleteBaseConfig(request: DeleteBaseConfigRequest): Promise<Empty> {
86
66
  return service<DeleteBaseConfigRequest, Empty>({
@@ -1,269 +1,104 @@
1
1
  <template>
2
- <el-link class="dynamic-i18n-cell" type="primary" underline="never" @click="openDialog">
3
- <span class="dynamic-i18n-cell__source">{{ displaySource || "--" }}</span>
4
- </el-link>
5
-
6
- <ProDialog
7
- v-model="dialogVisible"
8
- :title="displaySource"
9
- width="760px"
10
- append-to-body
11
- :show-footer="false"
12
- :destroy-on-close="true"
13
- @closed="handleDialogClosed"
2
+ <DynamicI18nEditor
3
+ v-if="enabled"
4
+ :key="`${targetType}:${targetId}`"
5
+ :model-value="values"
6
+ :source="source"
7
+ :readonly="!editable || !targetType || !targetId || saving"
8
+ :maxlength="10000"
9
+ @update:model-value="saveValues"
14
10
  >
15
- <el-table v-loading="loading" :data="i18nRows" border>
16
- <el-table-column :label="t('common.field.language')" width="150">
17
- <template #default="{ row }">
18
- {{ getLanguageLabel(row.locale) }}
19
- </template>
20
- </el-table-column>
21
- <el-table-column :label="t('system.base.i18n.field.i18ns')" min-width="360">
22
- <template #default="{ row }">
23
- <el-input
24
- v-if="row.editing"
25
- v-model="row.text"
26
- :placeholder="t('system.base.i18n.placeholder.text', { language: getLanguageLabel(row.locale) })"
27
- />
28
- <span v-else class="dynamic-i18n-dialog__text">
29
- {{ row.text || t("common.value.none") }}
30
- </span>
31
- </template>
32
- </el-table-column>
33
- <el-table-column v-if="editable" :label="t('common.field.operation')" width="200" fixed="right">
34
- <template #default="{ row }">
35
- <el-button
36
- v-if="editable && !row.editing"
37
- link
38
- type="primary"
39
- :icon="EditPen"
40
- @click="startEdit(row as DynamicI18nRow)"
41
- >
42
- {{ t("common.action.edit") }}
43
- </el-button>
44
- <template v-else>
45
- <el-button
46
- link
47
- type="primary"
48
- :icon="Check"
49
- :loading="row.saving"
50
- @click="saveI18n(row as DynamicI18nRow)"
51
- >
52
- {{ t("common.action.save") }}
53
- </el-button>
54
- <el-button link :icon="Close" :disabled="row.saving" @click="cancelEdit(row as DynamicI18nRow)">
55
- {{ t("common.action.cancel") }}
56
- </el-button>
57
- </template>
58
- </template>
59
- </el-table-column>
60
- </el-table>
61
- </ProDialog>
11
+ <template #trigger="{ open }">
12
+ <el-link class="dynamic-i18n-cell" type="primary" underline="never" @click="open">
13
+ <span>{{ displaySource || "--" }}</span>
14
+ </el-link>
15
+ </template>
16
+ </DynamicI18nEditor>
17
+ <span v-else>{{ source || "--" }}</span>
62
18
  </template>
63
19
 
64
20
  <script setup lang="ts">
65
21
  import { computed, ref, watch } from "vue";
66
- import { ElMessage } from "element-plus";
67
- import { Check, Close, EditPen } from "@element-plus/icons-vue";
68
- import ProDialog from "@liujitcn/kratos-admin-core/components/Dialog/ProDialog.vue";
69
22
  import { t, useLocaleStore } from "@liujitcn/kratos-admin-core";
70
- import { loadEnabledBaseLanguages, useEnabledBaseLanguages } from "@liujitcn/kratos-admin-system/api/system/admin/v1/base_language";
71
23
  import { defBaseI18nService } from "@liujitcn/kratos-admin-system/api/system/admin/v1/base_i18n";
72
- import type { BaseI18n } from "@liujitcn/kratos-admin-system/rpc/system/admin/v1/base_i18n";
73
- import { I18nTargetType } from "@liujitcn/kratos-admin-system/rpc/system/admin/v1/base_i18n";
74
- import { getLanguageLabel } from "./dynamicI18n";
24
+ import type { BaseI18n, I18nTargetType } from "@liujitcn/kratos-admin-system/rpc/system/admin/v1/base_i18n";
25
+ import DynamicI18nEditor from "./DynamicI18nEditor.vue";
26
+ import { getEditableLanguageOptions, type DynamicI18nValue } from "./dynamicI18n";
75
27
 
76
- /** DynamicI18nCellProps 动态翻译列表单元格属性。 */
28
+ /** 列表国际化字段入口,未启用非主语言时退回普通文本。 */
77
29
  interface DynamicI18nCellProps {
78
- /** 资源源文。 */
79
30
  source: string;
80
- /** 统一翻译表目标类型。 */
81
31
  targetType?: I18nTargetType;
82
- /** 目标资源编号。 */
83
32
  targetId?: number;
84
- /** 资源列表返回的非主语言翻译。 */
85
33
  i18ns?: BaseI18n[];
86
- /** 是否允许编辑翻译。 */
87
34
  editable?: boolean;
88
35
  }
89
-
90
- const props = withDefaults(defineProps<DynamicI18nCellProps>(), {
91
- editable: true
92
- });
93
-
94
- const editable = computed(() => props.editable);
95
-
96
- const { languages } = useEnabledBaseLanguages();
36
+ const props = withDefaults(defineProps<DynamicI18nCellProps>(), { editable: true });
97
37
  const { locale } = useLocaleStore();
98
- const dialogVisible = ref(false);
99
- const loading = ref(false);
100
- const i18nRows = ref<DynamicI18nRow[]>([]);
101
- const i18nOverrides = ref(new Map<string, string>());
102
-
103
- const displaySource = computed(() => {
104
- const override = i18nOverrides.value.get(locale.value);
105
- if (override) return override;
106
- const i18n = props.i18ns?.find(item => item.locale === locale.value && item.name);
107
- return i18n?.name || props.source;
108
- });
109
-
110
- watch(
111
- () => [props.targetType, props.targetId],
112
- () => {
113
- i18nRows.value = [];
114
- i18nOverrides.value.clear();
115
- dialogVisible.value = false;
116
- }
38
+ const enabled = computed(() => getEditableLanguageOptions().length > 0);
39
+ const overrides = ref(new Map<string, string>());
40
+ const saving = ref(false);
41
+ let resourceVersion = 0;
42
+ const values = computed<DynamicI18nValue[]>(() =>
43
+ getEditableLanguageOptions().map(({ value }) => {
44
+ const record = props.i18ns?.find(item => item.locale === value);
45
+ return { id: record?.id ?? 0, locale: value, text: overrides.value.get(value) ?? record?.name ?? "" };
46
+ })
117
47
  );
48
+ const displaySource = computed(() => values.value.find(item => item.locale === locale.value)?.text || props.source);
118
49
 
119
- /** DynamicI18nRow 描述弹窗内可编辑的单语言翻译行。 */
120
- interface DynamicI18nRow {
121
- /** 翻译记录主键,新增翻译时为空。 */
122
- id: number;
123
- /** 语言区域。 */
124
- locale: string;
125
- /** 翻译文本。 */
126
- text: string;
127
- /** 是否处于编辑状态。 */
128
- editing: boolean;
129
- /** 是否正在保存。 */
130
- saving: boolean;
131
- /** 编辑前的文本,用于取消编辑。 */
132
- originalText: string;
133
- }
134
-
135
- /** openDialog 打开翻译编辑弹窗并加载当前资源译文。 */
136
- async function openDialog() {
137
- dialogVisible.value = true;
138
- await loadI18ns();
139
- }
140
-
141
- /** loadI18ns 查询当前资源的翻译并补齐启用语言行。 */
142
- async function loadI18ns() {
50
+ /** 仅在确认后保存发生变化的译文,打开窗口不会自动翻译或写库。 */
51
+ async function saveValues(next: DynamicI18nValue[]) {
143
52
  const targetType = props.targetType;
144
53
  const targetId = props.targetId;
145
- if (!targetType || !targetId) return;
146
- loading.value = true;
54
+ if (!props.editable || !targetType || !targetId || saving.value) return;
55
+ const changed = next.filter(item => item.text !== values.value.find(value => value.locale === item.locale)?.text);
56
+ if (!changed.length) return;
57
+ const version = resourceVersion;
58
+ saving.value = true;
147
59
  try {
148
- await loadEnabledBaseLanguages();
149
- const rows = await queryI18nRows();
150
- i18nRows.value = rows;
151
- if (!props.editable) return;
152
- const missingRows = rows.filter(row => !row.text);
153
- if (missingRows.length === 0) return;
154
- if (!props.source) return;
155
- const draft = await defBaseI18nService.DraftBaseI18n({ source: props.source });
156
- const i18ns = new Map(draft.i18ns.map(item => [item.locale, item.i18n]));
157
60
  const results = await Promise.allSettled(
158
- missingRows.map(async row => {
159
- const i18n = i18ns.get(row.locale);
160
- if (!i18n) throw new Error("i18n not found");
61
+ changed.map(async item => {
161
62
  await defBaseI18nService.UpdateBaseI18n({
162
- id: row.id,
63
+ id: item.id,
163
64
  target_type: targetType,
164
65
  target_id: targetId,
165
- locale: row.locale,
166
- name: i18n
66
+ locale: item.locale,
67
+ name: item.text
167
68
  });
168
- return { row, text: i18n };
69
+ return item;
169
70
  })
170
71
  );
72
+ if (version !== resourceVersion) return;
171
73
  for (const result of results) {
172
- if (result.status !== "fulfilled") continue;
173
- result.value.row.text = result.value.text;
174
- result.value.row.originalText = result.value.text;
175
- i18nOverrides.value.set(result.value.row.locale, result.value.text);
74
+ if (result.status === "fulfilled") overrides.value.set(result.value.locale, result.value.text);
176
75
  }
177
- } catch {
178
- ElMessage.error(t("common.message.system_error"));
76
+ if (results.some(result => result.status === "rejected")) ElMessage.error(t("common.message.system_error"));
77
+ else ElMessage.success(t("common.message.operation_success"));
179
78
  } finally {
180
- loading.value = false;
79
+ if (version === resourceVersion) saving.value = false;
181
80
  }
182
81
  }
183
82
 
184
- /** queryI18nRows 将列表返回的翻译记录补齐为可编辑语言行。 */
185
- async function queryI18nRows(): Promise<DynamicI18nRow[]> {
186
- const records = new Map((props.i18ns ?? []).map(item => [item.locale, item]));
187
- return languages.value
188
- .filter(item => !item.is_primary)
189
- .map(item => {
190
- const record = records.get(item.language_code);
191
- const text = i18nOverrides.value.get(item.language_code) ?? record?.name ?? "";
192
- return {
193
- id: record?.id ?? 0,
194
- locale: item.language_code,
195
- text,
196
- editing: false,
197
- saving: false,
198
- originalText: text
199
- };
200
- });
201
- }
202
-
203
- /** startEdit 开启指定语言的编辑状态。 */
204
- function startEdit(row: DynamicI18nRow) {
205
- if (!props.editable) return;
206
- row.originalText = row.text;
207
- row.editing = true;
208
- }
209
-
210
- /** cancelEdit 恢复编辑前的内容。 */
211
- function cancelEdit(row: DynamicI18nRow) {
212
- row.text = row.originalText;
213
- row.editing = false;
214
- }
215
-
216
- /** saveI18n 使用统一更新接口保存指定语言译文。 */
217
- async function saveI18n(row: DynamicI18nRow) {
218
- const targetType = props.targetType;
219
- const targetId = props.targetId;
220
- if (!props.editable || row.saving || !targetType || !targetId) return;
221
- if (row.id === 0 && !row.text) {
222
- row.editing = false;
223
- return;
224
- }
225
- row.saving = true;
226
- try {
227
- await defBaseI18nService.UpdateBaseI18n({
228
- id: row.id,
229
- target_type: targetType,
230
- target_id: targetId,
231
- locale: row.locale,
232
- name: row.text
233
- });
234
- ElMessage.success(t("common.message.operation_success"));
235
- row.editing = false;
236
- row.originalText = row.text;
237
- i18nOverrides.value.set(row.locale, row.text);
238
- } catch {
239
- ElMessage.error(t("common.message.system_error"));
240
- } finally {
241
- row.saving = false;
83
+ watch(
84
+ () => [props.targetType, props.targetId],
85
+ () => {
86
+ resourceVersion++;
87
+ overrides.value.clear();
88
+ saving.value = false;
242
89
  }
243
- }
244
-
245
- /** handleDialogClosed 清理弹窗状态,避免复用旧资源译文。 */
246
- function handleDialogClosed() {
247
- i18nRows.value = [];
248
- loading.value = false;
249
- }
90
+ );
250
91
  </script>
251
92
 
252
93
  <style scoped>
253
94
  .dynamic-i18n-cell {
254
95
  display: inline-flex;
255
- align-items: center;
256
96
  min-width: 0;
257
97
  max-width: 100%;
258
98
  }
259
- .dynamic-i18n-cell__source {
260
- min-width: 0;
99
+ .dynamic-i18n-cell span {
261
100
  overflow: hidden;
262
101
  text-overflow: ellipsis;
263
102
  white-space: nowrap;
264
103
  }
265
- .dynamic-i18n-dialog__text {
266
- min-width: 0;
267
- overflow-wrap: anywhere;
268
- }
269
104
  </style>