@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.
- package/README.md +1 -1
- package/dist/package/declarations/src/api/system/base_i18n.d.ts +5 -5
- package/dist/package/declarations/src/api/system/runtime_log.d.ts +13 -0
- package/dist/package/declarations/src/api/system/runtime_log_sse.d.ts +8 -0
- package/dist/package/declarations/src/components/DynamicI18nCell.vue.d.ts +16 -0
- package/dist/package/declarations/src/components/DynamicI18nEditor.vue.d.ts +20 -0
- package/dist/package/declarations/src/components/dynamicI18n.d.ts +38 -0
- package/dist/package/declarations/src/locales/generated.d.ts +168 -52
- package/dist/package/declarations/src/rpc/system/admin/v1/base_config.d.ts +3 -3
- package/dist/package/declarations/src/rpc/system/admin/v1/base_dict.d.ts +4 -4
- package/dist/package/declarations/src/rpc/system/admin/v1/base_i18n.d.ts +23 -23
- package/dist/package/declarations/src/rpc/system/admin/v1/base_menu.d.ts +2 -2
- package/dist/package/declarations/src/rpc/system/admin/v1/code_gen.d.ts +1 -1
- package/dist/package/declarations/src/rpc/system/admin/v1/ops_monitoring.d.ts +4 -0
- package/dist/package/declarations/src/rpc/system/admin/v1/project_document.d.ts +4 -6
- package/dist/package/declarations/src/rpc/system/admin/v1/runtime_log.d.ts +96 -0
- package/dist/package/declarations/src/views/tool/runtime-log/index.vue.d.ts +3 -0
- package/dist/package/src/api/system/base_i18n.ts +12 -12
- package/dist/package/src/api/system/runtime_log.ts +80 -0
- package/dist/package/src/api/system/runtime_log_sse.ts +40 -0
- package/dist/package/src/components/{DynamicTranslationCell.vue → DynamicI18nCell.vue} +50 -50
- package/dist/package/src/components/{DynamicTranslationEditor.vue → DynamicI18nEditor.vue} +45 -45
- package/dist/package/src/components/{dynamicTranslation.ts → dynamicI18n.ts} +15 -15
- package/dist/package/src/locales/README.md +1 -1
- package/dist/package/src/locales/en-US.json +46 -17
- package/dist/package/src/locales/ja-JP.json +44 -15
- package/dist/package/src/locales/zh-CN.json +44 -15
- package/dist/package/src/locales/zh-TW.json +44 -15
- package/dist/package/src/rpc/system/admin/v1/base_config.ts +3 -3
- package/dist/package/src/rpc/system/admin/v1/base_dict.ts +4 -4
- package/dist/package/src/rpc/system/admin/v1/base_i18n.ts +23 -23
- package/dist/package/src/rpc/system/admin/v1/base_menu.ts +2 -2
- package/dist/package/src/rpc/system/admin/v1/code_gen.ts +1 -1
- package/dist/package/src/rpc/system/admin/v1/ops_monitoring.ts +4 -0
- package/dist/package/src/rpc/system/admin/v1/project_document.ts +4 -7
- package/dist/package/src/rpc/system/admin/v1/runtime_log.ts +113 -0
- package/dist/package/src/views/base/config/index.vue +38 -38
- package/dist/package/src/views/base/dict/index.vue +23 -23
- package/dist/package/src/views/base/dict/item.vue +25 -25
- package/dist/package/src/views/base/menu/index.vue +23 -23
- package/dist/package/src/views/tool/api-doc/index.vue +14 -6
- package/dist/package/src/views/tool/code-gen/code-preview/index.vue +23 -6
- package/dist/package/src/views/tool/code-gen/columns/index.vue +1 -1
- package/dist/package/src/views/tool/code-gen/components/CodeGenLocaleEditor.vue +96 -14
- package/dist/package/src/views/tool/code-gen/table/index.vue +33 -1
- package/dist/package/src/views/tool/ops-monitoring/index.vue +130 -24
- package/dist/package/src/views/tool/project-doc/index.vue +9 -4
- package/dist/package/src/views/tool/runtime-log/index.vue +883 -0
- package/package.json +2 -2
- package/dist/package/declarations/src/components/DynamicTranslationCell.vue.d.ts +0 -16
- package/dist/package/declarations/src/components/DynamicTranslationEditor.vue.d.ts +0 -20
- package/dist/package/declarations/src/components/dynamicTranslation.d.ts +0 -38
|
@@ -20,9 +20,9 @@
|
|
|
20
20
|
@confirm="handleSubmit"
|
|
21
21
|
@close="handleCloseDialog"
|
|
22
22
|
>
|
|
23
|
-
<template #
|
|
24
|
-
<
|
|
25
|
-
v-model="
|
|
23
|
+
<template #i18ns>
|
|
24
|
+
<DynamicI18nEditor
|
|
25
|
+
v-model="i18nValues"
|
|
26
26
|
:source="formData.name"
|
|
27
27
|
:maxlength="50"
|
|
28
28
|
/>
|
|
@@ -50,17 +50,17 @@ import { loadEnabledBaseLanguages } from "@liujitcn/kratos-admin-system/api/syst
|
|
|
50
50
|
import type { BaseDict, BaseDictForm, PageBaseDictRequest } from "@liujitcn/kratos-admin-system/rpc/system/admin/v1/base_dict";
|
|
51
51
|
import router, { navigateTo } from "@liujitcn/kratos-admin-core/navigation";
|
|
52
52
|
import { Status } from "@liujitcn/kratos-admin-system/rpc/common/v1/enum";
|
|
53
|
-
import {
|
|
53
|
+
import { I18nTargetType } from "@liujitcn/kratos-admin-system/rpc/system/admin/v1/base_i18n";
|
|
54
54
|
import { buildPageRequest, normalizeSelectedIds } from "@liujitcn/kratos-admin-core/table";
|
|
55
55
|
import { t } from "@liujitcn/kratos-admin-core";
|
|
56
|
-
import
|
|
57
|
-
import
|
|
56
|
+
import DynamicI18nEditor from "@liujitcn/kratos-admin-system/components/DynamicI18nEditor.vue";
|
|
57
|
+
import DynamicI18nCell from "@liujitcn/kratos-admin-system/components/DynamicI18nCell.vue";
|
|
58
58
|
import {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
type
|
|
62
|
-
type
|
|
63
|
-
} from "@liujitcn/kratos-admin-system/components/
|
|
59
|
+
normalizeDynamicI18ns,
|
|
60
|
+
serializeDynamicI18ns,
|
|
61
|
+
type DynamicI18nRecord,
|
|
62
|
+
type DynamicI18nValue
|
|
63
|
+
} from "@liujitcn/kratos-admin-system/components/dynamicI18n";
|
|
64
64
|
|
|
65
65
|
defineOptions({
|
|
66
66
|
name: "BaseDict",
|
|
@@ -70,7 +70,7 @@ defineOptions({
|
|
|
70
70
|
const { BUTTONS } = useAuthButtons();
|
|
71
71
|
const proTable = ref<ProTableInstance>();
|
|
72
72
|
const formDialogRef = ref<InstanceType<typeof FormDialog>>();
|
|
73
|
-
const
|
|
73
|
+
const i18nValues = ref<DynamicI18nValue[]>(normalizeDynamicI18ns(undefined, "name"));
|
|
74
74
|
const dialog = reactive({
|
|
75
75
|
editing: false,
|
|
76
76
|
visible: false
|
|
@@ -84,7 +84,7 @@ const formData = reactive<BaseDictForm>({
|
|
|
84
84
|
/** 字典名称 */
|
|
85
85
|
name: "",
|
|
86
86
|
/** 非主语言翻译 */
|
|
87
|
-
|
|
87
|
+
i18ns: [],
|
|
88
88
|
/** 状态 */
|
|
89
89
|
status: Status.STATUS_ENABLE
|
|
90
90
|
});
|
|
@@ -134,18 +134,18 @@ const formFields = computed<ProFormField[]>(() => [
|
|
|
134
134
|
component: "input",
|
|
135
135
|
props: { placeholder: t("system.base.dict.placeholder.code") }
|
|
136
136
|
},
|
|
137
|
-
{ prop: "
|
|
137
|
+
{ prop: "i18ns", label: t("system.base.i18n.field.i18ns"), component: "slot", slotName: "i18ns" },
|
|
138
138
|
{ prop: "status", label: t("common.field.status"), component: "radio-group", options: statusOptions.value }
|
|
139
139
|
]);
|
|
140
140
|
|
|
141
141
|
/** 渲染字典名称翻译预览,并复用当前页面的编辑弹窗。 */
|
|
142
142
|
function renderDictNameCell(scope: RenderScope<BaseDict>) {
|
|
143
143
|
const row = scope.row;
|
|
144
|
-
return h(
|
|
144
|
+
return h(DynamicI18nCell, {
|
|
145
145
|
source: row.name,
|
|
146
|
-
targetType:
|
|
146
|
+
targetType: I18nTargetType.I18N_TARGET_TYPE_BASE_DICT,
|
|
147
147
|
targetId: row.id,
|
|
148
|
-
|
|
148
|
+
i18ns: row.i18ns
|
|
149
149
|
});
|
|
150
150
|
}
|
|
151
151
|
|
|
@@ -261,7 +261,7 @@ async function handleOpenDialog(dictId?: number) {
|
|
|
261
261
|
|
|
262
262
|
const data = await defBaseDictService.GetBaseDict({ id: dictId });
|
|
263
263
|
Object.assign(formData, data);
|
|
264
|
-
|
|
264
|
+
i18nValues.value = normalizeDynamicI18ns(data.i18ns as DynamicI18nRecord[], "name");
|
|
265
265
|
}
|
|
266
266
|
|
|
267
267
|
/**
|
|
@@ -281,9 +281,9 @@ function resetForm() {
|
|
|
281
281
|
formData.id = 0;
|
|
282
282
|
formData.code = "";
|
|
283
283
|
formData.name = "";
|
|
284
|
-
formData.
|
|
284
|
+
formData.i18ns = [];
|
|
285
285
|
formData.status = Status.STATUS_ENABLE;
|
|
286
|
-
|
|
286
|
+
i18nValues.value = normalizeDynamicI18ns(undefined, "name");
|
|
287
287
|
}
|
|
288
288
|
|
|
289
289
|
/**
|
|
@@ -294,9 +294,9 @@ function handleSubmit() {
|
|
|
294
294
|
if (!isValid) return;
|
|
295
295
|
|
|
296
296
|
const submitData = JSON.parse(JSON.stringify(formData)) as BaseDictForm;
|
|
297
|
-
submitData.
|
|
298
|
-
|
|
299
|
-
|
|
297
|
+
submitData.i18ns = serializeDynamicI18ns(
|
|
298
|
+
i18nValues.value,
|
|
299
|
+
I18nTargetType.I18N_TARGET_TYPE_BASE_DICT,
|
|
300
300
|
submitData.id
|
|
301
301
|
);
|
|
302
302
|
const request = submitData.id
|
|
@@ -35,9 +35,9 @@
|
|
|
35
35
|
</el-radio-group>
|
|
36
36
|
</div>
|
|
37
37
|
</template>
|
|
38
|
-
<template #
|
|
39
|
-
<
|
|
40
|
-
v-model="
|
|
38
|
+
<template #i18ns>
|
|
39
|
+
<DynamicI18nEditor
|
|
40
|
+
v-model="i18nValues"
|
|
41
41
|
:source="formData.label"
|
|
42
42
|
:maxlength="100"
|
|
43
43
|
/>
|
|
@@ -69,17 +69,17 @@ import type {
|
|
|
69
69
|
PageBaseDictItemRequest
|
|
70
70
|
} from "@liujitcn/kratos-admin-system/rpc/system/admin/v1/base_dict";
|
|
71
71
|
import { Status } from "@liujitcn/kratos-admin-system/rpc/common/v1/enum";
|
|
72
|
-
import {
|
|
72
|
+
import { I18nTargetType } from "@liujitcn/kratos-admin-system/rpc/system/admin/v1/base_i18n";
|
|
73
73
|
import { buildPageRequest, normalizeSelectedIds } from "@liujitcn/kratos-admin-core/table";
|
|
74
74
|
import { t } from "@liujitcn/kratos-admin-core";
|
|
75
|
-
import
|
|
76
|
-
import
|
|
75
|
+
import DynamicI18nEditor from "@liujitcn/kratos-admin-system/components/DynamicI18nEditor.vue";
|
|
76
|
+
import DynamicI18nCell from "@liujitcn/kratos-admin-system/components/DynamicI18nCell.vue";
|
|
77
77
|
import {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
type
|
|
81
|
-
type
|
|
82
|
-
} from "@liujitcn/kratos-admin-system/components/
|
|
78
|
+
normalizeDynamicI18ns,
|
|
79
|
+
serializeDynamicI18ns,
|
|
80
|
+
type DynamicI18nRecord,
|
|
81
|
+
type DynamicI18nValue
|
|
82
|
+
} from "@liujitcn/kratos-admin-system/components/dynamicI18n";
|
|
83
83
|
|
|
84
84
|
defineOptions({
|
|
85
85
|
name: "BaseDictItem",
|
|
@@ -90,7 +90,7 @@ const route = useRoute();
|
|
|
90
90
|
const { BUTTONS } = useAuthButtons();
|
|
91
91
|
const proTable = ref<ProTableInstance>();
|
|
92
92
|
const formDialogRef = ref<InstanceType<typeof FormDialog>>();
|
|
93
|
-
const
|
|
93
|
+
const i18nValues = ref<DynamicI18nValue[]>(normalizeDynamicI18ns(undefined, "label"));
|
|
94
94
|
|
|
95
95
|
const dictId = ref(Number(route.query.dictId ?? 0));
|
|
96
96
|
|
|
@@ -109,7 +109,7 @@ const formData = reactive<BaseDictItemForm>({
|
|
|
109
109
|
/** 字典项标签 */
|
|
110
110
|
label: "",
|
|
111
111
|
/** 非主语言翻译 */
|
|
112
|
-
|
|
112
|
+
i18ns: [],
|
|
113
113
|
/** 标签类型 */
|
|
114
114
|
tag_type: "",
|
|
115
115
|
/** 排序 */
|
|
@@ -158,10 +158,10 @@ const formFields = computed<ProFormField[]>(() => [
|
|
|
158
158
|
props: { placeholder: t("system.base.dict.item.placeholder.value") }
|
|
159
159
|
},
|
|
160
160
|
{
|
|
161
|
-
prop: "
|
|
162
|
-
label: t("system.base.
|
|
161
|
+
prop: "i18ns",
|
|
162
|
+
label: t("system.base.i18n.field.i18ns"),
|
|
163
163
|
component: "slot",
|
|
164
|
-
slotName: "
|
|
164
|
+
slotName: "i18ns",
|
|
165
165
|
colSpan: 24
|
|
166
166
|
},
|
|
167
167
|
{
|
|
@@ -202,11 +202,11 @@ function renderTagTypeCell(scope: RenderScope<BaseDictItem>) {
|
|
|
202
202
|
/** 渲染字典项标签翻译预览,并复用当前页面的编辑弹窗。 */
|
|
203
203
|
function renderDictItemLabelCell(scope: RenderScope<BaseDictItem>) {
|
|
204
204
|
const row = scope.row;
|
|
205
|
-
return h(
|
|
205
|
+
return h(DynamicI18nCell, {
|
|
206
206
|
source: row.label,
|
|
207
|
-
targetType:
|
|
207
|
+
targetType: I18nTargetType.I18N_TARGET_TYPE_BASE_DICT_ITEM,
|
|
208
208
|
targetId: row.id,
|
|
209
|
-
|
|
209
|
+
i18ns: row.i18ns
|
|
210
210
|
});
|
|
211
211
|
}
|
|
212
212
|
|
|
@@ -330,7 +330,7 @@ async function handleOpenDialog(dictItemId?: number) {
|
|
|
330
330
|
|
|
331
331
|
const data = await defBaseDictService.GetBaseDictItem({ id: dictItemId });
|
|
332
332
|
Object.assign(formData, data);
|
|
333
|
-
|
|
333
|
+
i18nValues.value = normalizeDynamicI18ns(data.i18ns as DynamicI18nRecord[], "label");
|
|
334
334
|
}
|
|
335
335
|
|
|
336
336
|
/**
|
|
@@ -351,11 +351,11 @@ function resetForm() {
|
|
|
351
351
|
formData.dict_id = dictId.value;
|
|
352
352
|
formData.value = "";
|
|
353
353
|
formData.label = "";
|
|
354
|
-
formData.
|
|
354
|
+
formData.i18ns = [];
|
|
355
355
|
formData.tag_type = "";
|
|
356
356
|
formData.sort = 1;
|
|
357
357
|
formData.status = Status.STATUS_ENABLE;
|
|
358
|
-
|
|
358
|
+
i18nValues.value = normalizeDynamicI18ns(undefined, "label");
|
|
359
359
|
}
|
|
360
360
|
|
|
361
361
|
/**
|
|
@@ -367,9 +367,9 @@ function handleSubmit() {
|
|
|
367
367
|
|
|
368
368
|
formData.dict_id = dictId.value;
|
|
369
369
|
const submitData = JSON.parse(JSON.stringify(formData)) as BaseDictItemForm;
|
|
370
|
-
submitData.
|
|
371
|
-
|
|
372
|
-
|
|
370
|
+
submitData.i18ns = serializeDynamicI18ns(
|
|
371
|
+
i18nValues.value,
|
|
372
|
+
I18nTargetType.I18N_TARGET_TYPE_BASE_DICT_ITEM,
|
|
373
373
|
submitData.id
|
|
374
374
|
);
|
|
375
375
|
const request = submitData.id
|
|
@@ -31,9 +31,9 @@
|
|
|
31
31
|
<SelectIcon v-model:icon-value="menuIconValue" :placeholder="t('system.base.menu.placeholder.icon')" />
|
|
32
32
|
</template>
|
|
33
33
|
|
|
34
|
-
<template #
|
|
35
|
-
<
|
|
36
|
-
v-model="
|
|
34
|
+
<template #i18ns>
|
|
35
|
+
<DynamicI18nEditor
|
|
36
|
+
v-model="i18nValues"
|
|
37
37
|
:source="formData.meta.title"
|
|
38
38
|
:maxlength="100"
|
|
39
39
|
/>
|
|
@@ -79,17 +79,17 @@ import type {
|
|
|
79
79
|
} from "@liujitcn/kratos-admin-system/rpc/system/admin/v1/base_menu";
|
|
80
80
|
import { Status } from "@liujitcn/kratos-admin-system/rpc/common/v1/enum";
|
|
81
81
|
import { BaseMenuType } from "@liujitcn/kratos-admin-system/rpc/system/admin/v1/common";
|
|
82
|
-
import {
|
|
82
|
+
import { I18nTargetType } from "@liujitcn/kratos-admin-system/rpc/system/admin/v1/base_i18n";
|
|
83
83
|
import { normalizeSelectedIds } from "@liujitcn/kratos-admin-core/table";
|
|
84
84
|
import { t } from "@liujitcn/kratos-admin-core";
|
|
85
|
-
import
|
|
86
|
-
import
|
|
85
|
+
import DynamicI18nEditor from "@liujitcn/kratos-admin-system/components/DynamicI18nEditor.vue";
|
|
86
|
+
import DynamicI18nCell from "@liujitcn/kratos-admin-system/components/DynamicI18nCell.vue";
|
|
87
87
|
import {
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
type
|
|
91
|
-
type
|
|
92
|
-
} from "@liujitcn/kratos-admin-system/components/
|
|
88
|
+
normalizeDynamicI18ns,
|
|
89
|
+
serializeDynamicI18ns,
|
|
90
|
+
type DynamicI18nRecord,
|
|
91
|
+
type DynamicI18nValue
|
|
92
|
+
} from "@liujitcn/kratos-admin-system/components/dynamicI18n";
|
|
93
93
|
|
|
94
94
|
defineOptions({
|
|
95
95
|
name: "BaseMenu",
|
|
@@ -113,7 +113,7 @@ const menuOptions = ref<ProFormOption[]>([]);
|
|
|
113
113
|
const parentMenuTypeMap = ref(new Map<number, BaseMenuType>());
|
|
114
114
|
const appMenuIds = ref(new Set<number>([APP_MENU_ROOT_ID]));
|
|
115
115
|
const apiList = ref<BaseApi[]>([]);
|
|
116
|
-
const
|
|
116
|
+
const i18nValues = ref<DynamicI18nValue[]>(normalizeDynamicI18ns(undefined, "title"));
|
|
117
117
|
|
|
118
118
|
const dialog = reactive({
|
|
119
119
|
editing: false,
|
|
@@ -159,7 +159,7 @@ function createDefaultMenuForm(): MenuFormState {
|
|
|
159
159
|
redirect: "",
|
|
160
160
|
meta: createDefaultMenuMeta(),
|
|
161
161
|
api: [],
|
|
162
|
-
|
|
162
|
+
i18ns: [],
|
|
163
163
|
sort: 1,
|
|
164
164
|
status: Status.STATUS_ENABLE
|
|
165
165
|
};
|
|
@@ -294,11 +294,11 @@ function renderHiddenCell(scope: RenderScope<BaseMenu>) {
|
|
|
294
294
|
/** 渲染菜单标题翻译预览,并复用当前页面的编辑弹窗。 */
|
|
295
295
|
function renderMenuTitleCell(scope: RenderScope<BaseMenu>) {
|
|
296
296
|
const row = scope.row;
|
|
297
|
-
return h(
|
|
297
|
+
return h(DynamicI18nCell, {
|
|
298
298
|
source: row.meta?.title ?? "",
|
|
299
|
-
targetType:
|
|
299
|
+
targetType: I18nTargetType.I18N_TARGET_TYPE_BASE_MENU,
|
|
300
300
|
targetId: row.id,
|
|
301
|
-
|
|
301
|
+
i18ns: row.i18ns
|
|
302
302
|
});
|
|
303
303
|
}
|
|
304
304
|
|
|
@@ -468,10 +468,10 @@ const formFields = computed<ProFormField[]>(() => [
|
|
|
468
468
|
})
|
|
469
469
|
},
|
|
470
470
|
{
|
|
471
|
-
prop: "
|
|
472
|
-
label: t("system.base.
|
|
471
|
+
prop: "i18ns",
|
|
472
|
+
label: t("system.base.i18n.field.i18ns"),
|
|
473
473
|
component: "slot",
|
|
474
|
-
slotName: "
|
|
474
|
+
slotName: "i18ns",
|
|
475
475
|
colSpan: 24
|
|
476
476
|
},
|
|
477
477
|
{
|
|
@@ -999,9 +999,9 @@ function buildMenuOptions(menuList: BaseMenu[] = []) {
|
|
|
999
999
|
/** 根据菜单类型清理无效字段,避免提交脏数据。 */
|
|
1000
1000
|
function buildSubmitPayload(): BaseMenuForm {
|
|
1001
1001
|
const payload = normalizeMenuForm(formData);
|
|
1002
|
-
payload.
|
|
1003
|
-
|
|
1004
|
-
|
|
1002
|
+
payload.i18ns = serializeDynamicI18ns(
|
|
1003
|
+
i18nValues.value,
|
|
1004
|
+
I18nTargetType.I18N_TARGET_TYPE_BASE_MENU,
|
|
1005
1005
|
payload.id
|
|
1006
1006
|
);
|
|
1007
1007
|
// 一级菜单在表单中保持空白,提交时仍按接口约定传回根节点标识。
|
|
@@ -1145,7 +1145,7 @@ function resetForm(data?: Partial<BaseMenuForm>) {
|
|
|
1145
1145
|
formDialogRef.value?.resetFields();
|
|
1146
1146
|
formDialogRef.value?.clearValidate();
|
|
1147
1147
|
Object.assign(formData, normalizeMenuForm(data));
|
|
1148
|
-
|
|
1148
|
+
i18nValues.value = normalizeDynamicI18ns(data?.i18ns as DynamicI18nRecord[] | undefined, "title");
|
|
1149
1149
|
}
|
|
1150
1150
|
|
|
1151
1151
|
/** 提交菜单表单,并在成功后关闭弹窗、刷新表格。 */
|
|
@@ -27,15 +27,16 @@
|
|
|
27
27
|
<script setup lang="ts">
|
|
28
28
|
import SwaggerUIBundle from "swagger-ui-dist/swagger-ui-bundle.js";
|
|
29
29
|
import "swagger-ui-dist/swagger-ui.css";
|
|
30
|
+
import { DEFAULT_LOCALE, t, useLocaleStore } from "@liujitcn/kratos-admin-core";
|
|
30
31
|
import { getLocaleRequestHeaders, getRequestAccessToken } from "@liujitcn/kratos-admin-core/request";
|
|
31
32
|
import { defBaseApiService } from "@liujitcn/kratos-admin-system/api/system/base_api";
|
|
32
33
|
import type { OpenApiServiceOption } from "@liujitcn/kratos-admin-system/rpc/system/admin/v1/base_api";
|
|
33
|
-
import { t } from "@liujitcn/kratos-admin-core";
|
|
34
34
|
|
|
35
35
|
const swaggerRootRef = ref<HTMLElement>();
|
|
36
36
|
const loading = ref(true);
|
|
37
37
|
const documents = ref<OpenApiServiceOption[]>([]);
|
|
38
38
|
const selectedDocumentKey = ref("");
|
|
39
|
+
const { locale } = useLocaleStore();
|
|
39
40
|
|
|
40
41
|
/** 初始化携带当前登录令牌的 Swagger UI。 */
|
|
41
42
|
function initializeSwaggerUI(documentKey: string) {
|
|
@@ -44,9 +45,10 @@ function initializeSwaggerUI(documentKey: string) {
|
|
|
44
45
|
|
|
45
46
|
loading.value = true;
|
|
46
47
|
swaggerRoot.replaceChildren();
|
|
48
|
+
const localePath = locale.value === DEFAULT_LOCALE ? "" : `/${encodeURIComponent(locale.value)}`;
|
|
47
49
|
SwaggerUIBundle({
|
|
48
50
|
domNode: swaggerRoot,
|
|
49
|
-
url: `/api/docs/openapi/${encodeURIComponent(documentKey)}`,
|
|
51
|
+
url: `/api/docs/openapi/${encodeURIComponent(documentKey)}${localePath}`,
|
|
50
52
|
deepLinking: true,
|
|
51
53
|
displayOperationId: true,
|
|
52
54
|
displayRequestDuration: true,
|
|
@@ -84,16 +86,18 @@ function handleDocumentChange(documentKey: string) {
|
|
|
84
86
|
|
|
85
87
|
/** 加载可访问的 OpenAPI 文档并初始化默认文档。 */
|
|
86
88
|
async function loadOpenAPIDocuments() {
|
|
89
|
+
loading.value = true;
|
|
87
90
|
try {
|
|
88
91
|
const response = await defBaseApiService.OptionOpenApiService({});
|
|
89
92
|
documents.value = response.list;
|
|
90
|
-
const
|
|
91
|
-
if (!
|
|
93
|
+
const selectedDocument = response.list.find(document => document.key === selectedDocumentKey.value) ?? response.list[0];
|
|
94
|
+
if (!selectedDocument) {
|
|
95
|
+
selectedDocumentKey.value = "";
|
|
92
96
|
loading.value = false;
|
|
93
97
|
return;
|
|
94
98
|
}
|
|
95
|
-
selectedDocumentKey.value =
|
|
96
|
-
initializeSwaggerUI(
|
|
99
|
+
selectedDocumentKey.value = selectedDocument.key;
|
|
100
|
+
initializeSwaggerUI(selectedDocument.key);
|
|
97
101
|
} catch {
|
|
98
102
|
loading.value = false;
|
|
99
103
|
}
|
|
@@ -103,6 +107,10 @@ onMounted(() => {
|
|
|
103
107
|
loadOpenAPIDocuments();
|
|
104
108
|
});
|
|
105
109
|
|
|
110
|
+
watch(locale, () => {
|
|
111
|
+
loadOpenAPIDocuments();
|
|
112
|
+
});
|
|
113
|
+
|
|
106
114
|
onBeforeUnmount(() => {
|
|
107
115
|
swaggerRootRef.value?.replaceChildren();
|
|
108
116
|
});
|
|
@@ -60,7 +60,7 @@ const table = ref<CodeGenTableForm>();
|
|
|
60
60
|
const files = ref<CodeGenPreviewFile[]>([]);
|
|
61
61
|
const loading = ref(false);
|
|
62
62
|
const previewError = ref("");
|
|
63
|
-
const
|
|
63
|
+
const missingI18ns = ref<string[]>([]);
|
|
64
64
|
const progressTaskId = ref(typeof window === "undefined" ? "" : (window.sessionStorage.getItem(codeGenTaskStorageKey) ?? ""));
|
|
65
65
|
const progressDialogVisible = ref(
|
|
66
66
|
!!progressTaskId.value &&
|
|
@@ -94,7 +94,7 @@ async function loadCodePreview() {
|
|
|
94
94
|
table.value = undefined;
|
|
95
95
|
files.value = [];
|
|
96
96
|
previewError.value = "";
|
|
97
|
-
|
|
97
|
+
missingI18ns.value = [];
|
|
98
98
|
if (!tableId.value) return;
|
|
99
99
|
loading.value = true;
|
|
100
100
|
try {
|
|
@@ -103,10 +103,10 @@ async function loadCodePreview() {
|
|
|
103
103
|
try {
|
|
104
104
|
const preview = await defCodeGenService.PreviewCodeGen({ table_id: tableId.value, output_paths: undefined });
|
|
105
105
|
files.value = preview.files ?? [];
|
|
106
|
-
|
|
107
|
-
if (
|
|
108
|
-
previewError.value = t("system.code.gen.preview.message.
|
|
109
|
-
items:
|
|
106
|
+
missingI18ns.value = preview.missing_i18ns ?? [];
|
|
107
|
+
if (missingI18ns.value.length) {
|
|
108
|
+
previewError.value = t("system.code.gen.preview.message.missing_i18ns", {
|
|
109
|
+
items: missingI18ns.value.join(t("system.code.gen.preview.value.list_separator"))
|
|
110
110
|
});
|
|
111
111
|
}
|
|
112
112
|
if (!files.value.length && !previewError.value) previewError.value = t("system.code.gen.preview.message.no_preview_files");
|
|
@@ -134,6 +134,23 @@ async function handleGenerate() {
|
|
|
134
134
|
ElMessage.warning(t("system.code.gen.table.message.disabled", { name: table.value.name }));
|
|
135
135
|
return;
|
|
136
136
|
}
|
|
137
|
+
if (missingI18ns.value.length) {
|
|
138
|
+
try {
|
|
139
|
+
await ElMessageBox.alert(
|
|
140
|
+
t("system.code.gen.preview.message.missing_i18ns", {
|
|
141
|
+
items: missingI18ns.value.join(t("system.code.gen.preview.value.list_separator"))
|
|
142
|
+
}),
|
|
143
|
+
t("common.title.warning"),
|
|
144
|
+
{
|
|
145
|
+
confirmButtonText: t("common.action.close"),
|
|
146
|
+
type: "warning"
|
|
147
|
+
}
|
|
148
|
+
);
|
|
149
|
+
} catch {
|
|
150
|
+
// 关闭提示框与点击关闭按钮语义一致。
|
|
151
|
+
}
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
137
154
|
try {
|
|
138
155
|
await ElMessageBox.confirm(
|
|
139
156
|
t("system.code.gen.table.dialog.generate_one", { name: table.value.name }),
|
|
@@ -557,7 +557,7 @@ import type {
|
|
|
557
557
|
} from "@liujitcn/kratos-admin-system/rpc/system/admin/v1/code_gen_column";
|
|
558
558
|
import type { CodeGenDatabaseTable, CodeGenTableForm } from "@liujitcn/kratos-admin-system/rpc/system/admin/v1/code_gen_table";
|
|
559
559
|
import CodeGenLocaleEditor from "../components/CodeGenLocaleEditor.vue";
|
|
560
|
-
import { getEditableLanguageOptions } from "@liujitcn/kratos-admin-system/components/
|
|
560
|
+
import { getEditableLanguageOptions } from "@liujitcn/kratos-admin-system/components/dynamicI18n";
|
|
561
561
|
import {
|
|
562
562
|
copyCodeGenOptionToEmptyMatches,
|
|
563
563
|
copyFirstMatchingCodeGenOption,
|
|
@@ -17,26 +17,57 @@
|
|
|
17
17
|
{{ t("system.code.gen.i18n.status.missing") }}
|
|
18
18
|
</el-tag>
|
|
19
19
|
</div>
|
|
20
|
-
<
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
20
|
+
<div class="code-gen-locale-editor__control">
|
|
21
|
+
<el-input
|
|
22
|
+
:model-value="localeValue(locale.value).comment"
|
|
23
|
+
:placeholder="t('system.code.gen.i18n.placeholder.comment', { source: sourceComment || '-' })"
|
|
24
|
+
:disabled="isTranslating(locale.value, 'comment')"
|
|
25
|
+
maxlength="255"
|
|
26
|
+
@update:model-value="value => updateLocale(locale.value, 'comment', value)"
|
|
27
|
+
/>
|
|
28
|
+
<el-button
|
|
29
|
+
class="code-gen-locale-editor__translate"
|
|
30
|
+
link
|
|
31
|
+
type="primary"
|
|
32
|
+
size="small"
|
|
33
|
+
:icon="Promotion"
|
|
34
|
+
:loading="isTranslating(locale.value, 'comment')"
|
|
35
|
+
:disabled="!canTranslate(locale.value, 'comment', sourceComment)"
|
|
36
|
+
@click="handleTranslate(locale.value, 'comment', sourceComment, locale.label)"
|
|
37
|
+
>
|
|
38
|
+
{{ t("system.base.i18n.action.translate") }}
|
|
39
|
+
</el-button>
|
|
40
|
+
</div>
|
|
41
|
+
<div v-if="showLeftTreeComment" class="code-gen-locale-editor__control">
|
|
42
|
+
<el-input
|
|
43
|
+
:model-value="localeValue(locale.value).left_tree_comment"
|
|
44
|
+
:placeholder="t('system.code.gen.i18n.placeholder.left_tree_comment', { source: sourceLeftTreeComment || '-' })"
|
|
45
|
+
:disabled="isTranslating(locale.value, 'left_tree_comment')"
|
|
46
|
+
maxlength="255"
|
|
47
|
+
@update:model-value="value => updateLocale(locale.value, 'left_tree_comment', value)"
|
|
48
|
+
/>
|
|
49
|
+
<el-button
|
|
50
|
+
class="code-gen-locale-editor__translate"
|
|
51
|
+
link
|
|
52
|
+
type="primary"
|
|
53
|
+
size="small"
|
|
54
|
+
:icon="Promotion"
|
|
55
|
+
:loading="isTranslating(locale.value, 'left_tree_comment')"
|
|
56
|
+
:disabled="!canTranslate(locale.value, 'left_tree_comment', sourceLeftTreeComment)"
|
|
57
|
+
@click="handleTranslate(locale.value, 'left_tree_comment', sourceLeftTreeComment, locale.label)"
|
|
58
|
+
>
|
|
59
|
+
{{ t("system.base.i18n.action.translate") }}
|
|
60
|
+
</el-button>
|
|
61
|
+
</div>
|
|
33
62
|
</div>
|
|
34
63
|
</div>
|
|
35
64
|
</template>
|
|
36
65
|
|
|
37
66
|
<script setup lang="ts">
|
|
38
|
-
import { computed } from "vue";
|
|
67
|
+
import { computed, ref } from "vue";
|
|
68
|
+
import { Promotion } from "@element-plus/icons-vue";
|
|
39
69
|
import { t } from "@liujitcn/kratos-admin-core";
|
|
70
|
+
import { defBaseI18nService } from "@liujitcn/kratos-admin-system/api/system/base_i18n";
|
|
40
71
|
import { loadEnabledBaseLanguages, useEnabledBaseLanguages } from "@liujitcn/kratos-admin-system/api/system/base_language";
|
|
41
72
|
import type { CodeGenLocaleConfig } from "@liujitcn/kratos-admin-system/rpc/system/admin/v1/base_i18n";
|
|
42
73
|
|
|
@@ -63,6 +94,7 @@ const emit = defineEmits<{
|
|
|
63
94
|
}>();
|
|
64
95
|
|
|
65
96
|
const { languages } = useEnabledBaseLanguages();
|
|
97
|
+
const translatingField = ref("");
|
|
66
98
|
void loadEnabledBaseLanguages();
|
|
67
99
|
|
|
68
100
|
const editableLocales = computed(() =>
|
|
@@ -92,6 +124,33 @@ function updateLocale(locale: string, field: keyof CodeGenLocaleConfig, value: s
|
|
|
92
124
|
next.set(locale, { ...localeValue(locale), [field]: value });
|
|
93
125
|
emit("update:modelValue", next);
|
|
94
126
|
}
|
|
127
|
+
|
|
128
|
+
/** 判断指定语言字段是否正在翻译。 */
|
|
129
|
+
function isTranslating(locale: string, field: keyof CodeGenLocaleConfig) {
|
|
130
|
+
return translatingField.value === `${locale}:${field}`;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/** 判断指定语言字段当前是否允许自动翻译。 */
|
|
134
|
+
function canTranslate(locale: string, field: keyof CodeGenLocaleConfig, source: string) {
|
|
135
|
+
return Boolean(source) && !localeValue(locale)[field] && !translatingField.value;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/** 翻译指定语言的单个代码生成描述。 */
|
|
139
|
+
async function handleTranslate(locale: string, field: keyof CodeGenLocaleConfig, source: string, language: string) {
|
|
140
|
+
if (!canTranslate(locale, field, source)) return;
|
|
141
|
+
translatingField.value = `${locale}:${field}`;
|
|
142
|
+
try {
|
|
143
|
+
const response = await defBaseI18nService.DraftBaseI18n({ source, locale });
|
|
144
|
+
const i18n = response.i18ns.find(item => item.locale === locale)?.i18n;
|
|
145
|
+
if (!i18n) throw new Error("i18n not found");
|
|
146
|
+
updateLocale(locale, field, i18n);
|
|
147
|
+
ElMessage.success(t("system.base.i18n.message.translate_success", { language }));
|
|
148
|
+
} catch {
|
|
149
|
+
ElMessage.error(t("system.base.i18n.message.translate_failed", { language }));
|
|
150
|
+
} finally {
|
|
151
|
+
translatingField.value = "";
|
|
152
|
+
}
|
|
153
|
+
}
|
|
95
154
|
</script>
|
|
96
155
|
|
|
97
156
|
<style scoped lang="scss">
|
|
@@ -115,4 +174,27 @@ function updateLocale(locale: string, field: keyof CodeGenLocaleConfig, value: s
|
|
|
115
174
|
font-weight: 600;
|
|
116
175
|
color: var(--el-text-color-primary);
|
|
117
176
|
}
|
|
177
|
+
|
|
178
|
+
.code-gen-locale-editor__control {
|
|
179
|
+
position: relative;
|
|
180
|
+
display: flex;
|
|
181
|
+
align-items: center;
|
|
182
|
+
width: 100%;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
.code-gen-locale-editor__control :deep(.el-input) {
|
|
186
|
+
flex: 1;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
.code-gen-locale-editor__control :deep(.el-input__suffix) {
|
|
190
|
+
padding-right: 78px;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
.code-gen-locale-editor__translate {
|
|
194
|
+
position: absolute;
|
|
195
|
+
z-index: 1;
|
|
196
|
+
top: 50%;
|
|
197
|
+
right: 8px;
|
|
198
|
+
transform: translateY(-50%);
|
|
199
|
+
}
|
|
118
200
|
</style>
|
|
@@ -212,7 +212,7 @@ const formFields = computed<ProFormField[]>(() => [
|
|
|
212
212
|
},
|
|
213
213
|
{
|
|
214
214
|
prop: "i18n_config",
|
|
215
|
-
label: t("system.code.gen.i18n.field.
|
|
215
|
+
label: t("system.code.gen.i18n.field.i18ns"),
|
|
216
216
|
component: "slot",
|
|
217
217
|
slotName: "tableI18nConfig",
|
|
218
218
|
colSpan: 24,
|
|
@@ -588,6 +588,38 @@ async function handleGenerate(selected: CodeGenGenerateTarget) {
|
|
|
588
588
|
ElMessage.warning(t("system.code.gen.table.message.disabled", { name: disabledTable.name }));
|
|
589
589
|
return;
|
|
590
590
|
}
|
|
591
|
+
generating.value = true;
|
|
592
|
+
let missingI18ns: string[] = [];
|
|
593
|
+
try {
|
|
594
|
+
const previewEntries = await Promise.all(
|
|
595
|
+
tables.map(async table => ({
|
|
596
|
+
table,
|
|
597
|
+
preview: await defCodeGenService.PreviewCodeGen({ table_id: table.id, output_paths: undefined })
|
|
598
|
+
}))
|
|
599
|
+
);
|
|
600
|
+
missingI18ns = previewEntries.flatMap(({ table, preview }) =>
|
|
601
|
+
(preview.missing_i18ns ?? []).map(item => (tables.length === 1 ? item : `${table.name}: ${item}`))
|
|
602
|
+
);
|
|
603
|
+
} finally {
|
|
604
|
+
generating.value = false;
|
|
605
|
+
}
|
|
606
|
+
if (missingI18ns.length) {
|
|
607
|
+
try {
|
|
608
|
+
await ElMessageBox.alert(
|
|
609
|
+
t("system.code.gen.preview.message.missing_i18ns", {
|
|
610
|
+
items: missingI18ns.join(t("system.code.gen.preview.value.list_separator"))
|
|
611
|
+
}),
|
|
612
|
+
t("common.title.warning"),
|
|
613
|
+
{
|
|
614
|
+
confirmButtonText: t("common.action.close"),
|
|
615
|
+
type: "warning"
|
|
616
|
+
}
|
|
617
|
+
);
|
|
618
|
+
} catch {
|
|
619
|
+
// 关闭提示框与点击关闭按钮语义一致。
|
|
620
|
+
}
|
|
621
|
+
return;
|
|
622
|
+
}
|
|
591
623
|
const message =
|
|
592
624
|
tables.length === 1
|
|
593
625
|
? t("system.code.gen.table.dialog.generate_one", { name: tables[0].name })
|