@liujitcn/kratos-admin-core 0.0.20 → 0.0.21
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 +2 -2
- package/dist/package/declarations/src/api/base/language.d.ts +8 -0
- package/dist/package/declarations/src/components/Dialog/ProDialog.vue.d.ts +1 -0
- package/dist/package/declarations/src/components/LocaleSwitch/index.vue.d.ts +3 -0
- package/dist/package/declarations/src/index.d.ts +2 -0
- package/dist/package/declarations/src/locales/index.d.ts +63 -0
- package/dist/package/declarations/src/modules/index.d.ts +7 -2
- package/dist/package/declarations/src/request.d.ts +1 -0
- package/dist/package/declarations/src/routers/modules/staticRouter.d.ts +1 -0
- package/dist/package/declarations/src/rpc/base/v1/config.d.ts +2 -0
- package/dist/package/declarations/src/rpc/base/v1/language.d.ts +26 -0
- package/dist/package/declarations/src/rpc/system/admin/v1/base_dict.d.ts +79 -0
- package/dist/package/declarations/src/rpc/system/admin/v1/base_translation.d.ts +102 -0
- package/dist/package/declarations/src/stores/interface/index.d.ts +2 -0
- package/dist/package/declarations/src/stores/runtime.d.ts +1 -0
- package/dist/package/declarations/src/utils/dict.d.ts +2 -2
- package/dist/package/declarations/src/utils/index.d.ts +1 -1
- package/dist/package/declarations/src/utils/oauthProvider.d.ts +2 -0
- package/dist/package/declarations/src/utils/passwordStrength.d.ts +0 -7
- package/dist/package/src/App.vue +10 -1
- package/dist/package/src/api/base/language.ts +20 -0
- package/dist/package/src/api/base/oauth.ts +0 -1
- package/dist/package/src/api/system/auth.ts +0 -1
- package/dist/package/src/bootstrap.ts +57 -2
- package/dist/package/src/components/CronExpression/index.vue +80 -82
- package/dist/package/src/components/Dialog/FormDialog.vue +9 -4
- package/dist/package/src/components/Dialog/ProDialog.vue +10 -4
- package/dist/package/src/components/Dict/index.vue +5 -2
- package/dist/package/src/components/ECharts/config/index.ts +6 -1
- package/dist/package/src/components/ErrorMessage/index.vue +3 -1
- package/dist/package/src/components/ImportExcel/index.vue +29 -18
- package/dist/package/src/components/LocaleSwitch/index.vue +28 -0
- package/dist/package/src/components/PasswordStrength/index.vue +8 -5
- package/dist/package/src/components/ProForm/components/DynamicList.vue +8 -3
- package/dist/package/src/components/ProForm/components/KvList.vue +14 -6
- package/dist/package/src/components/ProTable/components/ColSetting.vue +7 -5
- package/dist/package/src/components/ProTable/components/TableColumn.vue +2 -1
- package/dist/package/src/components/ProTable/index.vue +36 -11
- package/dist/package/src/components/SearchForm/components/SearchFormItem.vue +9 -4
- package/dist/package/src/components/SearchForm/index.vue +6 -3
- package/dist/package/src/components/SelectFilter/index.vue +4 -1
- package/dist/package/src/components/SelectIcon/index.vue +8 -4
- package/dist/package/src/components/TreeFilter/index.vue +14 -6
- package/dist/package/src/components/Upload/File.vue +18 -13
- package/dist/package/src/components/Upload/Files.vue +22 -15
- package/dist/package/src/components/Upload/Img.vue +14 -11
- package/dist/package/src/components/Upload/Imgs.vue +15 -12
- package/dist/package/src/components/WangEditor/index.vue +12 -4
- package/dist/package/src/directives/modules/copy.ts +2 -1
- package/dist/package/src/hooks/useDownload.ts +3 -2
- package/dist/package/src/hooks/useHandleData.ts +5 -4
- package/dist/package/src/hooks/useTheme.ts +2 -1
- package/dist/package/src/hooks/useTime.ts +11 -2
- package/dist/package/src/index.ts +2 -0
- package/dist/package/src/layouts/components/Header/ToolBarRight.vue +2 -0
- package/dist/package/src/layouts/components/Header/components/AssemblySize.vue +8 -6
- package/dist/package/src/layouts/components/Header/components/Avatar.vue +11 -9
- package/dist/package/src/layouts/components/Header/components/Breadcrumb.vue +10 -2
- package/dist/package/src/layouts/components/Header/components/Fullscreen.vue +4 -2
- package/dist/package/src/layouts/components/Header/components/InfoDialog.vue +6 -3
- package/dist/package/src/layouts/components/Header/components/PasswordDialog.vue +6 -3
- package/dist/package/src/layouts/components/Header/components/SearchMenu.vue +5 -3
- package/dist/package/src/layouts/components/Header/components/ThemeSetting.vue +3 -1
- package/dist/package/src/layouts/components/Tabs/components/MoreButton.vue +9 -7
- package/dist/package/src/layouts/components/ThemeDrawer/index.vue +27 -24
- package/dist/package/src/locales/README.md +15 -0
- package/dist/package/src/locales/en-US.json +258 -0
- package/dist/package/src/locales/es-ES.json +258 -0
- package/dist/package/src/locales/fr-FR.json +258 -0
- package/dist/package/src/locales/index.ts +223 -0
- package/dist/package/src/locales/ja-JP.json +258 -0
- package/dist/package/src/locales/ko-KR.json +258 -0
- package/dist/package/src/locales/zh-CN.json +258 -0
- package/dist/package/src/locales/zh-TW.json +258 -0
- package/dist/package/src/modules/index.ts +7 -2
- package/dist/package/src/modules/kratosAdmin.ts +19 -1
- package/dist/package/src/request.ts +8 -1
- package/dist/package/src/routers/index.ts +4 -1
- package/dist/package/src/routers/modules/dynamicRouter.ts +3 -2
- package/dist/package/src/routers/modules/staticRouter.ts +8 -4
- package/dist/package/src/rpc/base/v1/config.ts +2 -0
- package/dist/package/src/rpc/base/v1/language.ts +37 -0
- package/dist/package/src/rpc/system/admin/v1/base_dict.ts +81 -0
- package/dist/package/src/rpc/system/admin/v1/base_translation.ts +117 -0
- package/dist/package/src/stores/interface/index.ts +2 -0
- package/dist/package/src/stores/modules/config.ts +5 -1
- package/dist/package/src/stores/modules/user.ts +2 -1
- package/dist/package/src/stores/runtime.ts +1 -0
- package/dist/package/src/utils/color.ts +5 -4
- package/dist/package/src/utils/dict.ts +27 -4
- package/dist/package/src/utils/eleValidate.ts +3 -2
- package/dist/package/src/utils/errorHandler.ts +9 -8
- package/dist/package/src/utils/index.ts +7 -6
- package/dist/package/src/utils/oauthProvider.ts +15 -10
- package/dist/package/src/utils/passwordCrypto.ts +3 -2
- package/dist/package/src/utils/passwordStrength.ts +1 -16
- package/dist/package/src/utils/request.ts +13 -8
- package/dist/package/src/views/error/403.vue +3 -1
- package/dist/package/src/views/error/404.vue +3 -1
- package/dist/package/src/views/error/500.vue +3 -1
- package/dist/package/src/views/error/pending.vue +5 -2
- package/dist/package/src/views/login/components/LoginForm.vue +53 -27
- package/dist/package/src/views/login/index.scss +6 -0
- package/dist/package/src/views/login/index.vue +2 -0
- package/dist/package/types/generated/auto-imports.d.ts +129 -111
- package/dist/package/types/generated/components.d.ts +67 -67
- package/package.json +3 -1
- package/types/generated/auto-imports.d.ts +129 -111
- package/types/generated/components.d.ts +67 -67
- package/vite.config.ts +8 -0
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<el-input v-model="currentValue" :placeholder="placeholder" clearable>
|
|
4
4
|
<template #suffix>
|
|
5
5
|
<div class="cron-expression__actions">
|
|
6
|
-
<el-tooltip content="
|
|
6
|
+
<el-tooltip :content="t('core.cron.edit')" placement="top">
|
|
7
7
|
<el-icon class="cron-expression__icon" @click="handleOpenEditor()">
|
|
8
8
|
<Operation />
|
|
9
9
|
</el-icon>
|
|
@@ -12,10 +12,10 @@
|
|
|
12
12
|
</template>
|
|
13
13
|
</el-input>
|
|
14
14
|
|
|
15
|
-
<el-dialog v-model="dialogVisible" title="
|
|
15
|
+
<el-dialog v-model="dialogVisible" :title="t('core.cron.title')" width="980px" top="2vh" destroy-on-close>
|
|
16
16
|
<div class="cron-editor">
|
|
17
17
|
<div class="cron-editor__preset">
|
|
18
|
-
<div class="cron-editor__section-title"
|
|
18
|
+
<div class="cron-editor__section-title">{{ t("core.cron.presets") }}</div>
|
|
19
19
|
<div class="cron-editor__preset-list">
|
|
20
20
|
<el-tag
|
|
21
21
|
v-for="option in presetOptions"
|
|
@@ -30,36 +30,36 @@
|
|
|
30
30
|
</div>
|
|
31
31
|
|
|
32
32
|
<el-tabs v-model="activeTab">
|
|
33
|
-
<el-tab-pane label="
|
|
33
|
+
<el-tab-pane :label="t('core.cron.segment.second')" name="second">
|
|
34
34
|
<CronSegmentEditor
|
|
35
|
-
unit="
|
|
35
|
+
unit-key="second"
|
|
36
36
|
:max="59"
|
|
37
37
|
:state="editorState.second"
|
|
38
38
|
:supports-unspecified="false"
|
|
39
39
|
@change="value => handleUpdateSegment('second', value)"
|
|
40
40
|
/>
|
|
41
41
|
</el-tab-pane>
|
|
42
|
-
<el-tab-pane label="
|
|
42
|
+
<el-tab-pane :label="t('core.cron.segment.minute')" name="minute">
|
|
43
43
|
<CronSegmentEditor
|
|
44
|
-
unit="
|
|
44
|
+
unit-key="minute"
|
|
45
45
|
:max="59"
|
|
46
46
|
:state="editorState.minute"
|
|
47
47
|
:supports-unspecified="false"
|
|
48
48
|
@change="value => handleUpdateSegment('minute', value)"
|
|
49
49
|
/>
|
|
50
50
|
</el-tab-pane>
|
|
51
|
-
<el-tab-pane label="
|
|
51
|
+
<el-tab-pane :label="t('core.cron.segment.hour')" name="hour">
|
|
52
52
|
<CronSegmentEditor
|
|
53
|
-
unit="
|
|
53
|
+
unit-key="hour"
|
|
54
54
|
:max="23"
|
|
55
55
|
:state="editorState.hour"
|
|
56
56
|
:supports-unspecified="false"
|
|
57
57
|
@change="value => handleUpdateSegment('hour', value)"
|
|
58
58
|
/>
|
|
59
59
|
</el-tab-pane>
|
|
60
|
-
<el-tab-pane label="
|
|
60
|
+
<el-tab-pane :label="t('core.cron.segment.day')" name="day">
|
|
61
61
|
<CronSegmentEditor
|
|
62
|
-
unit="
|
|
62
|
+
unit-key="day"
|
|
63
63
|
:min="1"
|
|
64
64
|
:max="31"
|
|
65
65
|
:state="editorState.day"
|
|
@@ -69,9 +69,9 @@
|
|
|
69
69
|
@change="value => handleUpdateSegment('day', value)"
|
|
70
70
|
/>
|
|
71
71
|
</el-tab-pane>
|
|
72
|
-
<el-tab-pane label="
|
|
72
|
+
<el-tab-pane :label="t('core.cron.segment.month')" name="month">
|
|
73
73
|
<CronSegmentEditor
|
|
74
|
-
unit="
|
|
74
|
+
unit-key="month"
|
|
75
75
|
:min="1"
|
|
76
76
|
:max="12"
|
|
77
77
|
:state="editorState.month"
|
|
@@ -79,9 +79,9 @@
|
|
|
79
79
|
@change="value => handleUpdateSegment('month', value)"
|
|
80
80
|
/>
|
|
81
81
|
</el-tab-pane>
|
|
82
|
-
<el-tab-pane label="
|
|
82
|
+
<el-tab-pane :label="t('core.cron.segment.year')" name="year">
|
|
83
83
|
<CronSegmentEditor
|
|
84
|
-
unit="
|
|
84
|
+
unit-key="year"
|
|
85
85
|
:min="currentYear"
|
|
86
86
|
:max="currentYear + 20"
|
|
87
87
|
:state="editorState.year"
|
|
@@ -95,7 +95,7 @@
|
|
|
95
95
|
</el-tabs>
|
|
96
96
|
|
|
97
97
|
<div class="cron-editor__preview">
|
|
98
|
-
<div class="cron-editor__section-title">
|
|
98
|
+
<div class="cron-editor__section-title">{{ t("core.cron.expression") }}</div>
|
|
99
99
|
<el-input :model-value="previewExpression" readonly />
|
|
100
100
|
<div class="cron-editor__preview-desc">{{ expressionDescription }}</div>
|
|
101
101
|
</div>
|
|
@@ -103,8 +103,8 @@
|
|
|
103
103
|
|
|
104
104
|
<template #footer>
|
|
105
105
|
<div class="dialog-footer">
|
|
106
|
-
<el-button type="primary" @click="handleConfirmEditor"
|
|
107
|
-
<el-button @click="dialogVisible = false"
|
|
106
|
+
<el-button type="primary" @click="handleConfirmEditor">{{ t("common.action.confirm") }}</el-button>
|
|
107
|
+
<el-button @click="dialogVisible = false">{{ t("common.action.cancel") }}</el-button>
|
|
108
108
|
</div>
|
|
109
109
|
</template>
|
|
110
110
|
</el-dialog>
|
|
@@ -116,6 +116,9 @@ import { computed, defineComponent, h, reactive, ref, watch } from "vue";
|
|
|
116
116
|
import type { PropType } from "vue";
|
|
117
117
|
import { ElCheckbox, ElCheckboxGroup, ElInputNumber, ElRadio } from "element-plus";
|
|
118
118
|
import { Operation } from "@element-plus/icons-vue";
|
|
119
|
+
import { useLocaleStore } from "../../locales";
|
|
120
|
+
|
|
121
|
+
const { t } = useLocaleStore();
|
|
119
122
|
|
|
120
123
|
/** Cron 单个字段支持的编辑模式。 */
|
|
121
124
|
type CronSegmentMode = "every" | "unspecified" | "range" | "step" | "specific" | "last" | "weekday";
|
|
@@ -144,8 +147,9 @@ type CronEditorState = Record<CronSegmentKey, CronSegmentState>;
|
|
|
144
147
|
|
|
145
148
|
const props = withDefaults(defineProps<CronExpressionProps>(), {
|
|
146
149
|
modelValue: "",
|
|
147
|
-
placeholder: "
|
|
150
|
+
placeholder: ""
|
|
148
151
|
});
|
|
152
|
+
const placeholder = computed(() => props.placeholder || t("core.cron.placeholder"));
|
|
149
153
|
|
|
150
154
|
const emit = defineEmits<{
|
|
151
155
|
"update:modelValue": [value: string];
|
|
@@ -155,15 +159,15 @@ const currentYear = new Date().getFullYear();
|
|
|
155
159
|
const dialogVisible = ref(false);
|
|
156
160
|
const activeTab = ref<CronSegmentKey>("second");
|
|
157
161
|
|
|
158
|
-
const presetOptions = [
|
|
159
|
-
{ label: "
|
|
160
|
-
{ label: "
|
|
161
|
-
{ label: "
|
|
162
|
-
{ label: "
|
|
163
|
-
{ label: "
|
|
164
|
-
{ label: "
|
|
165
|
-
{ label: "
|
|
166
|
-
];
|
|
162
|
+
const presetOptions = computed(() => [
|
|
163
|
+
{ label: t("core.cron.preset.everyMinute"), value: "0 * * * * *" },
|
|
164
|
+
{ label: t("core.cron.preset.everyFiveMinutes"), value: "0 */5 * * * *" },
|
|
165
|
+
{ label: t("core.cron.preset.everyHour"), value: "0 0 * * * *" },
|
|
166
|
+
{ label: t("core.cron.preset.dailyMidnight"), value: "0 0 0 * * *" },
|
|
167
|
+
{ label: t("core.cron.preset.dailyEight"), value: "0 0 8 * * *" },
|
|
168
|
+
{ label: t("core.cron.preset.monthlyFirst"), value: "0 0 0 1 * *" },
|
|
169
|
+
{ label: t("core.cron.preset.nextYearDaily"), value: `0 0 0 * * ${currentYear + 1}` }
|
|
170
|
+
]);
|
|
167
171
|
|
|
168
172
|
/** 创建单个 Cron 字段的默认编辑状态。 */
|
|
169
173
|
function createSegmentState(min = 0): CronSegmentState {
|
|
@@ -210,14 +214,14 @@ const previewExpression = computed(() => {
|
|
|
210
214
|
|
|
211
215
|
const expressionDescription = computed(() => {
|
|
212
216
|
const descriptionList = [
|
|
213
|
-
formatSegmentDescription("
|
|
214
|
-
formatSegmentDescription("
|
|
215
|
-
formatSegmentDescription("
|
|
216
|
-
formatSegmentDescription("
|
|
217
|
-
formatSegmentDescription("
|
|
218
|
-
formatSegmentDescription("
|
|
217
|
+
formatSegmentDescription("second", editorState.second),
|
|
218
|
+
formatSegmentDescription("minute", editorState.minute),
|
|
219
|
+
formatSegmentDescription("hour", editorState.hour),
|
|
220
|
+
formatSegmentDescription("day", editorState.day),
|
|
221
|
+
formatSegmentDescription("month", editorState.month),
|
|
222
|
+
formatSegmentDescription("year", editorState.year)
|
|
219
223
|
].filter(Boolean);
|
|
220
|
-
return descriptionList.length ? descriptionList.join("
|
|
224
|
+
return descriptionList.length ? descriptionList.join(t("core.cron.descriptionSeparator")) : t("core.cron.notConfigured");
|
|
221
225
|
});
|
|
222
226
|
|
|
223
227
|
/** 打开 Cron 编辑弹窗,并按当前表达式回填编辑状态。 */
|
|
@@ -280,50 +284,43 @@ function buildSegmentValue(segment: CronSegmentState) {
|
|
|
280
284
|
}
|
|
281
285
|
}
|
|
282
286
|
|
|
283
|
-
/**
|
|
284
|
-
function formatSegmentDescription(
|
|
287
|
+
/** 将单个字段编辑状态转换为当前语言的预览描述。 */
|
|
288
|
+
function formatSegmentDescription(segmentKey: CronSegmentKey, segment: CronSegmentState) {
|
|
289
|
+
const segmentName = t(`core.cron.segment.${segmentKey}`);
|
|
290
|
+
const unit = t(`core.cron.unit.${segmentKey}`);
|
|
285
291
|
switch (segment.mode) {
|
|
286
292
|
case "every":
|
|
287
|
-
return
|
|
293
|
+
return t("core.cron.description.every", { unit });
|
|
288
294
|
case "unspecified":
|
|
289
|
-
return
|
|
295
|
+
return t("core.cron.description.unspecified", { segment: segmentName });
|
|
290
296
|
case "range":
|
|
291
|
-
return
|
|
297
|
+
return t("core.cron.description.range", { segment: segmentName, start: segment.rangeStart, end: segment.rangeEnd });
|
|
292
298
|
case "step":
|
|
293
|
-
return
|
|
299
|
+
return t("core.cron.description.step", {
|
|
300
|
+
start: segment.stepStart,
|
|
301
|
+
unit,
|
|
302
|
+
step: segment.stepValue,
|
|
303
|
+
cycleUnit: t(`core.cron.cycleUnit.${segmentKey}`)
|
|
304
|
+
});
|
|
294
305
|
case "specific":
|
|
295
306
|
return segment.specific.length
|
|
296
|
-
?
|
|
297
|
-
|
|
307
|
+
? t("core.cron.description.specific", {
|
|
308
|
+
segment: segmentName,
|
|
309
|
+
values: segment.specific.map(item => formatSpecificLabel(segmentKey, item)).join(t("core.cron.valueSeparator"))
|
|
310
|
+
})
|
|
311
|
+
: t("core.cron.description.unspecified", { segment: segmentName });
|
|
298
312
|
case "last":
|
|
299
|
-
return "
|
|
313
|
+
return t("core.cron.lastDay");
|
|
300
314
|
case "weekday":
|
|
301
|
-
return
|
|
315
|
+
return t("core.cron.description.weekday", { day: segment.weekday });
|
|
302
316
|
default:
|
|
303
317
|
return "";
|
|
304
318
|
}
|
|
305
319
|
}
|
|
306
320
|
|
|
307
|
-
/** 获取 Cron 字段在范围描述中的单位后缀。 */
|
|
308
|
-
function formatUnitSuffix(label: string) {
|
|
309
|
-
if (label === "日期") return "日";
|
|
310
|
-
if (label === "月份") return "月";
|
|
311
|
-
if (label === "年份") return "年";
|
|
312
|
-
return label;
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
/** 获取 Cron 字段在周期描述中的单位后缀。 */
|
|
316
|
-
function formatCycleSuffix(label: string) {
|
|
317
|
-
if (label === "日期") return "天";
|
|
318
|
-
if (label === "月份") return "个月";
|
|
319
|
-
if (label === "年份") return "年";
|
|
320
|
-
return label;
|
|
321
|
-
}
|
|
322
|
-
|
|
323
321
|
/** 格式化指定值模式下的单个展示值。 */
|
|
324
|
-
function formatSpecificLabel(
|
|
325
|
-
|
|
326
|
-
return String(value);
|
|
322
|
+
function formatSpecificLabel(segmentKey: CronSegmentKey, value: number) {
|
|
323
|
+
return t("core.cron.valueWithUnit", { value, unit: t(`core.cron.unit.${segmentKey}`) });
|
|
327
324
|
}
|
|
328
325
|
|
|
329
326
|
/**
|
|
@@ -404,8 +401,8 @@ watch(
|
|
|
404
401
|
const CronSegmentEditor = defineComponent({
|
|
405
402
|
name: "CronSegmentEditor",
|
|
406
403
|
props: {
|
|
407
|
-
|
|
408
|
-
type: String
|
|
404
|
+
unitKey: {
|
|
405
|
+
type: String as PropType<CronSegmentKey>,
|
|
409
406
|
required: true
|
|
410
407
|
},
|
|
411
408
|
min: {
|
|
@@ -468,9 +465,10 @@ const CronSegmentEditor = defineComponent({
|
|
|
468
465
|
});
|
|
469
466
|
|
|
470
467
|
const specificOptions = computed(() => {
|
|
468
|
+
const unit = t(`core.cron.unit.${segmentProps.unitKey}`);
|
|
471
469
|
return numberOptions.value.map(item => ({
|
|
472
470
|
value: item,
|
|
473
|
-
label:
|
|
471
|
+
label: t("core.cron.valueWithUnit", { value: item, unit })
|
|
474
472
|
}));
|
|
475
473
|
});
|
|
476
474
|
|
|
@@ -501,21 +499,21 @@ const CronSegmentEditor = defineComponent({
|
|
|
501
499
|
{segmentProps.supportsEvery && (
|
|
502
500
|
<label class="segment-editor__row">
|
|
503
501
|
{h(ElRadio, { modelValue: localState.mode, value: "every", onChange: () => handleModeChange("every") })}
|
|
504
|
-
<span
|
|
502
|
+
<span>{t("core.cron.everyUnit", { unit: t(`core.cron.unit.${segmentProps.unitKey}`) })}</span>
|
|
505
503
|
</label>
|
|
506
504
|
)}
|
|
507
505
|
|
|
508
506
|
{segmentProps.supportsUnspecified && (
|
|
509
507
|
<label class="segment-editor__row">
|
|
510
508
|
{h(ElRadio, { modelValue: localState.mode, value: "unspecified", onChange: () => handleModeChange("unspecified") })}
|
|
511
|
-
<span
|
|
509
|
+
<span>{t("core.cron.unspecified")}</span>
|
|
512
510
|
</label>
|
|
513
511
|
)}
|
|
514
512
|
|
|
515
513
|
<label class="segment-editor__row">
|
|
516
514
|
{h(ElRadio, { modelValue: localState.mode, value: "range", onChange: () => handleModeChange("range") })}
|
|
517
|
-
<span
|
|
518
|
-
<span
|
|
515
|
+
<span>{t("core.cron.range")}</span>
|
|
516
|
+
<span>{t("core.cron.from")}</span>
|
|
519
517
|
{h(ElInputNumber, {
|
|
520
518
|
modelValue: localState.rangeStart,
|
|
521
519
|
min: segmentProps.min,
|
|
@@ -523,7 +521,7 @@ const CronSegmentEditor = defineComponent({
|
|
|
523
521
|
controlsPosition: "right",
|
|
524
522
|
"onUpdate:modelValue": value => handleNumberChange("rangeStart", Number(value))
|
|
525
523
|
})}
|
|
526
|
-
<span
|
|
524
|
+
<span>{t("core.cron.to")}</span>
|
|
527
525
|
{h(ElInputNumber, {
|
|
528
526
|
modelValue: localState.rangeEnd,
|
|
529
527
|
min: segmentProps.min,
|
|
@@ -531,14 +529,14 @@ const CronSegmentEditor = defineComponent({
|
|
|
531
529
|
controlsPosition: "right",
|
|
532
530
|
"onUpdate:modelValue": value => handleNumberChange("rangeEnd", Number(value))
|
|
533
531
|
})}
|
|
534
|
-
<span>{segmentProps.
|
|
532
|
+
<span>{t(`core.cron.unit.${segmentProps.unitKey}`)}</span>
|
|
535
533
|
</label>
|
|
536
534
|
|
|
537
535
|
{segmentProps.supportsStep && (
|
|
538
536
|
<label class="segment-editor__row">
|
|
539
537
|
{h(ElRadio, { modelValue: localState.mode, value: "step", onChange: () => handleModeChange("step") })}
|
|
540
|
-
<span
|
|
541
|
-
<span
|
|
538
|
+
<span>{t("core.cron.repeat")}</span>
|
|
539
|
+
<span>{t("core.cron.from")}</span>
|
|
542
540
|
{h(ElInputNumber, {
|
|
543
541
|
modelValue: localState.stepStart,
|
|
544
542
|
min: segmentProps.min,
|
|
@@ -546,7 +544,7 @@ const CronSegmentEditor = defineComponent({
|
|
|
546
544
|
controlsPosition: "right",
|
|
547
545
|
"onUpdate:modelValue": value => handleNumberChange("stepStart", Number(value))
|
|
548
546
|
})}
|
|
549
|
-
<span>{segmentProps.
|
|
547
|
+
<span>{t("core.cron.startEvery", { unit: t(`core.cron.unit.${segmentProps.unitKey}`) })}</span>
|
|
550
548
|
{h(ElInputNumber, {
|
|
551
549
|
modelValue: localState.stepValue,
|
|
552
550
|
min: 1,
|
|
@@ -554,14 +552,14 @@ const CronSegmentEditor = defineComponent({
|
|
|
554
552
|
controlsPosition: "right",
|
|
555
553
|
"onUpdate:modelValue": value => handleNumberChange("stepValue", Number(value))
|
|
556
554
|
})}
|
|
557
|
-
<span>{segmentProps.
|
|
555
|
+
<span>{t("core.cron.runOnce", { unit: t(`core.cron.cycleUnit.${segmentProps.unitKey}`) })}</span>
|
|
558
556
|
</label>
|
|
559
557
|
)}
|
|
560
558
|
|
|
561
559
|
{segmentProps.supportsSpecific && (
|
|
562
560
|
<div class="segment-editor__row segment-editor__row--top">
|
|
563
561
|
{h(ElRadio, { modelValue: localState.mode, value: "specific", onChange: () => handleModeChange("specific") })}
|
|
564
|
-
<span
|
|
562
|
+
<span>{t("core.cron.specific")}</span>
|
|
565
563
|
{h(
|
|
566
564
|
ElCheckboxGroup,
|
|
567
565
|
{
|
|
@@ -582,15 +580,15 @@ const CronSegmentEditor = defineComponent({
|
|
|
582
580
|
{segmentProps.supportsLast && (
|
|
583
581
|
<label class="segment-editor__row">
|
|
584
582
|
{h(ElRadio, { modelValue: localState.mode, value: "last", onChange: () => handleModeChange("last") })}
|
|
585
|
-
<span
|
|
583
|
+
<span>{t("core.cron.lastDay")}</span>
|
|
586
584
|
</label>
|
|
587
585
|
)}
|
|
588
586
|
|
|
589
587
|
{segmentProps.supportsWeekday && (
|
|
590
588
|
<label class="segment-editor__row">
|
|
591
589
|
{h(ElRadio, { modelValue: localState.mode, value: "weekday", onChange: () => handleModeChange("weekday") })}
|
|
592
|
-
<span
|
|
593
|
-
<span
|
|
590
|
+
<span>{t("core.cron.workday")}</span>
|
|
591
|
+
<span>{t("core.cron.thisMonth")}</span>
|
|
594
592
|
{h(ElInputNumber, {
|
|
595
593
|
modelValue: localState.weekday,
|
|
596
594
|
min: segmentProps.min,
|
|
@@ -598,7 +596,7 @@ const CronSegmentEditor = defineComponent({
|
|
|
598
596
|
controlsPosition: "right",
|
|
599
597
|
"onUpdate:modelValue": value => handleNumberChange("weekday", Number(value))
|
|
600
598
|
})}
|
|
601
|
-
<span
|
|
599
|
+
<span>{t("core.cron.nearestWorkday")}</span>
|
|
602
600
|
</label>
|
|
603
601
|
)}
|
|
604
602
|
</div>
|
|
@@ -35,8 +35,10 @@
|
|
|
35
35
|
<template #footer>
|
|
36
36
|
<slot name="footer">
|
|
37
37
|
<div class="dialog-footer">
|
|
38
|
-
<el-button @click="handleCancel">{{ cancelText }}</el-button>
|
|
39
|
-
<el-button type="primary" :loading="confirmLoading" @click="handleConfirm">
|
|
38
|
+
<el-button @click="handleCancel">{{ cancelText || t("common.action.cancel") }}</el-button>
|
|
39
|
+
<el-button type="primary" :loading="confirmLoading" @click="handleConfirm">
|
|
40
|
+
{{ confirmText || t("common.action.confirm") }}
|
|
41
|
+
</el-button>
|
|
40
42
|
</div>
|
|
41
43
|
</slot>
|
|
42
44
|
</template>
|
|
@@ -49,6 +51,9 @@ import type { FormRules } from "element-plus";
|
|
|
49
51
|
import ProDialog from "../../components/Dialog/ProDialog.vue";
|
|
50
52
|
import ProForm from "../../components/ProForm/index.vue";
|
|
51
53
|
import type { ProFormField, ProFormInstance } from "../../components/ProForm/interface";
|
|
54
|
+
import { useLocaleStore } from "../../locales";
|
|
55
|
+
|
|
56
|
+
const { t } = useLocaleStore();
|
|
52
57
|
|
|
53
58
|
/** 表单弹窗组件属性。 */
|
|
54
59
|
interface FormDialogProps {
|
|
@@ -79,8 +84,8 @@ const props = withDefaults(defineProps<FormDialogProps>(), {
|
|
|
79
84
|
labelWidth: "110px",
|
|
80
85
|
gutter: 20,
|
|
81
86
|
colSpan: 24,
|
|
82
|
-
confirmText: "
|
|
83
|
-
cancelText: "
|
|
87
|
+
confirmText: "",
|
|
88
|
+
cancelText: "",
|
|
84
89
|
confirmLoading: false,
|
|
85
90
|
destroyOnClose: false,
|
|
86
91
|
closeOnClickModal: true,
|
|
@@ -23,14 +23,20 @@
|
|
|
23
23
|
</template>
|
|
24
24
|
<template v-else-if="showFooter" #footer>
|
|
25
25
|
<div class="dialog-footer">
|
|
26
|
-
<el-button @click="handleCancel">
|
|
27
|
-
<el-button type="primary" :loading="confirmLoading" @click="handleConfirm">
|
|
26
|
+
<el-button @click="handleCancel">{{ cancelText || t("common.action.cancel") }}</el-button>
|
|
27
|
+
<el-button type="primary" :loading="confirmLoading" @click="handleConfirm">
|
|
28
|
+
{{ confirmText || t("common.action.confirm") }}
|
|
29
|
+
</el-button>
|
|
28
30
|
</div>
|
|
29
31
|
</template>
|
|
30
32
|
</el-dialog>
|
|
31
33
|
</template>
|
|
32
34
|
|
|
33
35
|
<script setup lang="ts" name="ProDialog">
|
|
36
|
+
import { useLocaleStore } from "../../locales";
|
|
37
|
+
|
|
38
|
+
const { t } = useLocaleStore();
|
|
39
|
+
|
|
34
40
|
/** 通用弹窗组件属性。 */
|
|
35
41
|
interface ProDialogProps {
|
|
36
42
|
modelValue: boolean;
|
|
@@ -51,8 +57,8 @@ withDefaults(defineProps<ProDialogProps>(), {
|
|
|
51
57
|
title: "",
|
|
52
58
|
width: "500px",
|
|
53
59
|
top: "8vh",
|
|
54
|
-
confirmText: "
|
|
55
|
-
cancelText: "
|
|
60
|
+
confirmText: "",
|
|
61
|
+
cancelText: "",
|
|
56
62
|
confirmLoading: false,
|
|
57
63
|
destroyOnClose: false,
|
|
58
64
|
closeOnClickModal: true,
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
<el-select
|
|
3
3
|
v-if="type === 'select'"
|
|
4
4
|
v-model="selectedSingleValue"
|
|
5
|
-
:placeholder="placeholder"
|
|
5
|
+
:placeholder="placeholder || t('common.placeholder.select')"
|
|
6
6
|
:disabled="disabled"
|
|
7
7
|
clearable
|
|
8
8
|
:style="style"
|
|
@@ -41,6 +41,9 @@ import type { CSSProperties } from "vue";
|
|
|
41
41
|
import { ref, watch } from "vue";
|
|
42
42
|
import { useDictStore } from "../../stores/modules/dict";
|
|
43
43
|
import type { OptionBaseDictResponse_BaseDictItem } from "../../rpc/system/admin/v1/base_dict";
|
|
44
|
+
import { useLocaleStore } from "../../locales";
|
|
45
|
+
|
|
46
|
+
const { t } = useLocaleStore();
|
|
44
47
|
|
|
45
48
|
/** 字典组件支持的控件类型。 */
|
|
46
49
|
type DictType = "select" | "radio" | "checkbox";
|
|
@@ -63,7 +66,7 @@ interface DictProps {
|
|
|
63
66
|
const props = withDefaults(defineProps<DictProps>(), {
|
|
64
67
|
codeType: "number",
|
|
65
68
|
type: "select",
|
|
66
|
-
placeholder: "
|
|
69
|
+
placeholder: "",
|
|
67
70
|
disabled: false,
|
|
68
71
|
style: () =>
|
|
69
72
|
({
|
|
@@ -12,7 +12,12 @@ import {
|
|
|
12
12
|
import { LabelLayout, UniversalTransition } from "echarts/features";
|
|
13
13
|
import { CanvasRenderer } from "echarts/renderers";
|
|
14
14
|
import type { BarSeriesOption, LineSeriesOption, PieSeriesOption } from "echarts/charts";
|
|
15
|
-
import type {
|
|
15
|
+
import type {
|
|
16
|
+
TitleComponentOption,
|
|
17
|
+
TooltipComponentOption,
|
|
18
|
+
GridComponentOption,
|
|
19
|
+
DatasetComponentOption
|
|
20
|
+
} from "echarts/components";
|
|
16
21
|
import type { ComposeOption } from "echarts/core";
|
|
17
22
|
|
|
18
23
|
/** 管理后台 ECharts 组件统一支持的图表配置类型。 */
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<script setup lang="ts" name="ErrorMessage">
|
|
2
2
|
import { useRouter } from "vue-router";
|
|
3
|
+
import { useLocaleStore } from "../../locales";
|
|
3
4
|
|
|
4
5
|
/** 错误状态展示属性。 */
|
|
5
6
|
interface ErrorMessageProps {
|
|
@@ -14,6 +15,7 @@ interface ErrorMessageProps {
|
|
|
14
15
|
defineProps<ErrorMessageProps>();
|
|
15
16
|
|
|
16
17
|
const router = useRouter();
|
|
18
|
+
const { t } = useLocaleStore();
|
|
17
19
|
</script>
|
|
18
20
|
|
|
19
21
|
<template>
|
|
@@ -22,7 +24,7 @@ const router = useRouter();
|
|
|
22
24
|
<div class="not-detail">
|
|
23
25
|
<h2>{{ code }}</h2>
|
|
24
26
|
<h4>{{ message }}</h4>
|
|
25
|
-
<el-button type="primary" @click="router.back()">
|
|
27
|
+
<el-button type="primary" @click="router.back()">{{ t("common.action.back") }}</el-button>
|
|
26
28
|
</div>
|
|
27
29
|
</div>
|
|
28
30
|
</template>
|
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<el-dialog
|
|
2
|
+
<el-dialog
|
|
3
|
+
v-model="dialogVisible"
|
|
4
|
+
:title="t('core.upload.batchAdd', { resource: parameter.title })"
|
|
5
|
+
:destroy-on-close="true"
|
|
6
|
+
width="580px"
|
|
7
|
+
draggable
|
|
8
|
+
>
|
|
3
9
|
<el-form class="drawer-multiColumn-form" label-width="100px">
|
|
4
|
-
<el-form-item label="
|
|
5
|
-
<el-button type="primary" :icon="Download" @click="downloadTemp">
|
|
10
|
+
<el-form-item :label="t('core.upload.templateDownload')">
|
|
11
|
+
<el-button type="primary" :icon="Download" @click="downloadTemp">{{ t("common.action.download") }}</el-button>
|
|
6
12
|
</el-form-item>
|
|
7
|
-
<el-form-item label="
|
|
13
|
+
<el-form-item :label="t('core.upload.file')">
|
|
8
14
|
<el-upload
|
|
9
15
|
action="#"
|
|
10
16
|
class="upload"
|
|
@@ -23,16 +29,18 @@
|
|
|
23
29
|
<el-icon class="el-icon--upload">
|
|
24
30
|
<upload-filled />
|
|
25
31
|
</el-icon>
|
|
26
|
-
<div class="el-upload__text"
|
|
32
|
+
<div class="el-upload__text">
|
|
33
|
+
{{ t("core.upload.dragOrClick") }}<em>{{ t("core.upload.click") }}</em>
|
|
34
|
+
</div>
|
|
27
35
|
</slot>
|
|
28
36
|
<template #tip>
|
|
29
37
|
<slot name="tip">
|
|
30
|
-
<div class="el-upload__tip"
|
|
38
|
+
<div class="el-upload__tip">{{ t("core.upload.excelFormat", { size: parameter.fileSize ?? 5 }) }}</div>
|
|
31
39
|
</slot>
|
|
32
40
|
</template>
|
|
33
41
|
</el-upload>
|
|
34
42
|
</el-form-item>
|
|
35
|
-
<el-form-item label="
|
|
43
|
+
<el-form-item :label="t('core.upload.dataCover')">
|
|
36
44
|
<el-switch v-model="isCover" />
|
|
37
45
|
</el-form-item>
|
|
38
46
|
</el-form>
|
|
@@ -44,6 +52,9 @@ import { ref } from "vue";
|
|
|
44
52
|
import { useDownload } from "../../hooks/useDownload";
|
|
45
53
|
import { Download } from "@element-plus/icons-vue";
|
|
46
54
|
import { ElNotification, UploadRequestOptions, UploadRawFile } from "element-plus";
|
|
55
|
+
import { useLocaleStore } from "../../locales";
|
|
56
|
+
|
|
57
|
+
const { t } = useLocaleStore();
|
|
47
58
|
|
|
48
59
|
/** Excel 导入弹窗参数。 */
|
|
49
60
|
export interface ExcelParameterProps {
|
|
@@ -77,7 +88,7 @@ const acceptParams = (params: ExcelParameterProps) => {
|
|
|
77
88
|
// Excel 导入模板下载
|
|
78
89
|
const downloadTemp = () => {
|
|
79
90
|
if (!parameter.value.tempApi) return;
|
|
80
|
-
useDownload(parameter.value.tempApi,
|
|
91
|
+
useDownload(parameter.value.tempApi, t("core.upload.template", { resource: parameter.value.title }));
|
|
81
92
|
};
|
|
82
93
|
|
|
83
94
|
// 文件上传
|
|
@@ -99,15 +110,15 @@ const beforeExcelUpload = (file: UploadRawFile) => {
|
|
|
99
110
|
const fileSize = file.size / 1024 / 1024 < parameter.value.fileSize!;
|
|
100
111
|
if (!isExcel)
|
|
101
112
|
ElNotification({
|
|
102
|
-
title: "
|
|
103
|
-
message: "
|
|
113
|
+
title: t("common.title.warning"),
|
|
114
|
+
message: t("core.upload.fileFormatInvalid"),
|
|
104
115
|
type: "warning"
|
|
105
116
|
});
|
|
106
117
|
if (!fileSize)
|
|
107
118
|
setTimeout(() => {
|
|
108
119
|
ElNotification({
|
|
109
|
-
title: "
|
|
110
|
-
message:
|
|
120
|
+
title: t("common.title.warning"),
|
|
121
|
+
message: t("core.upload.fileSizeExceeded", { size: parameter.value.fileSize ?? 5 }),
|
|
111
122
|
type: "warning"
|
|
112
123
|
});
|
|
113
124
|
}, 0);
|
|
@@ -117,8 +128,8 @@ const beforeExcelUpload = (file: UploadRawFile) => {
|
|
|
117
128
|
// 文件数超出提示
|
|
118
129
|
const handleExceed = () => {
|
|
119
130
|
ElNotification({
|
|
120
|
-
title: "
|
|
121
|
-
message: "
|
|
131
|
+
title: t("common.title.warning"),
|
|
132
|
+
message: t("core.upload.singleFileOnly"),
|
|
122
133
|
type: "warning"
|
|
123
134
|
});
|
|
124
135
|
};
|
|
@@ -126,8 +137,8 @@ const handleExceed = () => {
|
|
|
126
137
|
// 上传错误提示
|
|
127
138
|
const excelUploadError = () => {
|
|
128
139
|
ElNotification({
|
|
129
|
-
title: "
|
|
130
|
-
message:
|
|
140
|
+
title: t("common.title.warning"),
|
|
141
|
+
message: t("core.upload.batchFailed", { resource: parameter.value.title }),
|
|
131
142
|
type: "error"
|
|
132
143
|
});
|
|
133
144
|
};
|
|
@@ -135,8 +146,8 @@ const excelUploadError = () => {
|
|
|
135
146
|
// 上传成功提示
|
|
136
147
|
const excelUploadSuccess = () => {
|
|
137
148
|
ElNotification({
|
|
138
|
-
title: "
|
|
139
|
-
message:
|
|
149
|
+
title: t("common.title.notice"),
|
|
150
|
+
message: t("core.upload.batchSuccess", { resource: parameter.value.title }),
|
|
140
151
|
type: "success"
|
|
141
152
|
});
|
|
142
153
|
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<el-dropdown trigger="click" placement="bottom-end" @command="handleLocaleChange">
|
|
3
|
+
<Languages class="toolBar-icon" :size="20" :title="t('core.header.language')" />
|
|
4
|
+
<template #dropdown>
|
|
5
|
+
<el-dropdown-menu>
|
|
6
|
+
<el-dropdown-item v-for="item in localeOptions" :key="item.value" :command="item.value" :disabled="item.value === locale">
|
|
7
|
+
{{ item.label }}
|
|
8
|
+
</el-dropdown-item>
|
|
9
|
+
</el-dropdown-menu>
|
|
10
|
+
</template>
|
|
11
|
+
</el-dropdown>
|
|
12
|
+
</template>
|
|
13
|
+
|
|
14
|
+
<script setup lang="ts">
|
|
15
|
+
import { computed } from "vue";
|
|
16
|
+
import { Languages } from "@lucide/vue";
|
|
17
|
+
import { type SupportedLocale, useLocaleStore } from "../../locales";
|
|
18
|
+
|
|
19
|
+
const { locale, setLocale, languageOptions, t } = useLocaleStore();
|
|
20
|
+
const localeOptions = computed(() => {
|
|
21
|
+
return languageOptions.value.map(item => ({ value: item.language_code, label: item.language_name }));
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
/** 切换管理端语言并刷新动态本地化数据。 */
|
|
25
|
+
function handleLocaleChange(value: SupportedLocale) {
|
|
26
|
+
void setLocale(value);
|
|
27
|
+
}
|
|
28
|
+
</script>
|