@liujitcn/kratos-admin-core 0.0.19 → 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.
Files changed (110) hide show
  1. package/README.md +2 -2
  2. package/dist/package/declarations/src/api/base/language.d.ts +8 -0
  3. package/dist/package/declarations/src/components/Dialog/ProDialog.vue.d.ts +1 -0
  4. package/dist/package/declarations/src/components/LocaleSwitch/index.vue.d.ts +3 -0
  5. package/dist/package/declarations/src/index.d.ts +2 -0
  6. package/dist/package/declarations/src/locales/index.d.ts +63 -0
  7. package/dist/package/declarations/src/modules/index.d.ts +7 -2
  8. package/dist/package/declarations/src/request.d.ts +1 -0
  9. package/dist/package/declarations/src/routers/modules/staticRouter.d.ts +1 -0
  10. package/dist/package/declarations/src/rpc/base/v1/config.d.ts +2 -0
  11. package/dist/package/declarations/src/rpc/base/v1/language.d.ts +26 -0
  12. package/dist/package/declarations/src/rpc/system/admin/v1/base_dict.d.ts +79 -0
  13. package/dist/package/declarations/src/rpc/system/admin/v1/base_translation.d.ts +102 -0
  14. package/dist/package/declarations/src/stores/interface/index.d.ts +2 -0
  15. package/dist/package/declarations/src/stores/runtime.d.ts +1 -0
  16. package/dist/package/declarations/src/utils/dict.d.ts +2 -2
  17. package/dist/package/declarations/src/utils/index.d.ts +1 -1
  18. package/dist/package/declarations/src/utils/oauthProvider.d.ts +2 -0
  19. package/dist/package/declarations/src/utils/passwordStrength.d.ts +0 -7
  20. package/dist/package/src/App.vue +10 -1
  21. package/dist/package/src/api/base/language.ts +20 -0
  22. package/dist/package/src/api/base/oauth.ts +0 -1
  23. package/dist/package/src/api/system/auth.ts +0 -1
  24. package/dist/package/src/bootstrap.ts +57 -2
  25. package/dist/package/src/components/CronExpression/index.vue +80 -82
  26. package/dist/package/src/components/Dialog/FormDialog.vue +9 -4
  27. package/dist/package/src/components/Dialog/ProDialog.vue +10 -4
  28. package/dist/package/src/components/Dict/index.vue +5 -2
  29. package/dist/package/src/components/ECharts/config/index.ts +6 -1
  30. package/dist/package/src/components/ErrorMessage/index.vue +3 -1
  31. package/dist/package/src/components/ImportExcel/index.vue +29 -18
  32. package/dist/package/src/components/LocaleSwitch/index.vue +28 -0
  33. package/dist/package/src/components/PasswordStrength/index.vue +8 -5
  34. package/dist/package/src/components/ProForm/components/DynamicList.vue +8 -3
  35. package/dist/package/src/components/ProForm/components/KvList.vue +14 -6
  36. package/dist/package/src/components/ProTable/components/ColSetting.vue +7 -5
  37. package/dist/package/src/components/ProTable/components/TableColumn.vue +2 -1
  38. package/dist/package/src/components/ProTable/index.vue +36 -11
  39. package/dist/package/src/components/SearchForm/components/SearchFormItem.vue +9 -4
  40. package/dist/package/src/components/SearchForm/index.vue +6 -3
  41. package/dist/package/src/components/SelectFilter/index.vue +4 -1
  42. package/dist/package/src/components/SelectIcon/index.vue +8 -4
  43. package/dist/package/src/components/TreeFilter/index.vue +14 -6
  44. package/dist/package/src/components/Upload/File.vue +18 -13
  45. package/dist/package/src/components/Upload/Files.vue +22 -15
  46. package/dist/package/src/components/Upload/Img.vue +14 -11
  47. package/dist/package/src/components/Upload/Imgs.vue +15 -12
  48. package/dist/package/src/components/WangEditor/index.vue +12 -4
  49. package/dist/package/src/directives/modules/copy.ts +2 -1
  50. package/dist/package/src/hooks/useDownload.ts +3 -2
  51. package/dist/package/src/hooks/useHandleData.ts +5 -4
  52. package/dist/package/src/hooks/useTheme.ts +2 -1
  53. package/dist/package/src/hooks/useTime.ts +11 -2
  54. package/dist/package/src/index.ts +2 -0
  55. package/dist/package/src/layouts/components/Header/ToolBarRight.vue +2 -0
  56. package/dist/package/src/layouts/components/Header/components/AssemblySize.vue +8 -6
  57. package/dist/package/src/layouts/components/Header/components/Avatar.vue +11 -9
  58. package/dist/package/src/layouts/components/Header/components/Breadcrumb.vue +10 -2
  59. package/dist/package/src/layouts/components/Header/components/Fullscreen.vue +4 -2
  60. package/dist/package/src/layouts/components/Header/components/InfoDialog.vue +6 -3
  61. package/dist/package/src/layouts/components/Header/components/PasswordDialog.vue +6 -3
  62. package/dist/package/src/layouts/components/Header/components/SearchMenu.vue +5 -3
  63. package/dist/package/src/layouts/components/Header/components/ThemeSetting.vue +3 -1
  64. package/dist/package/src/layouts/components/Tabs/components/MoreButton.vue +9 -7
  65. package/dist/package/src/layouts/components/ThemeDrawer/index.vue +27 -24
  66. package/dist/package/src/locales/README.md +15 -0
  67. package/dist/package/src/locales/en-US.json +258 -0
  68. package/dist/package/src/locales/es-ES.json +258 -0
  69. package/dist/package/src/locales/fr-FR.json +258 -0
  70. package/dist/package/src/locales/index.ts +223 -0
  71. package/dist/package/src/locales/ja-JP.json +258 -0
  72. package/dist/package/src/locales/ko-KR.json +258 -0
  73. package/dist/package/src/locales/zh-CN.json +258 -0
  74. package/dist/package/src/locales/zh-TW.json +258 -0
  75. package/dist/package/src/modules/index.ts +7 -2
  76. package/dist/package/src/modules/kratosAdmin.ts +19 -1
  77. package/dist/package/src/request.ts +8 -1
  78. package/dist/package/src/routers/index.ts +4 -1
  79. package/dist/package/src/routers/modules/dynamicRouter.ts +3 -2
  80. package/dist/package/src/routers/modules/staticRouter.ts +8 -4
  81. package/dist/package/src/rpc/base/v1/config.ts +2 -0
  82. package/dist/package/src/rpc/base/v1/language.ts +37 -0
  83. package/dist/package/src/rpc/system/admin/v1/base_dict.ts +81 -0
  84. package/dist/package/src/rpc/system/admin/v1/base_translation.ts +117 -0
  85. package/dist/package/src/stores/interface/index.ts +2 -0
  86. package/dist/package/src/stores/modules/config.ts +5 -1
  87. package/dist/package/src/stores/modules/user.ts +2 -1
  88. package/dist/package/src/stores/runtime.ts +1 -0
  89. package/dist/package/src/utils/color.ts +5 -4
  90. package/dist/package/src/utils/dict.ts +27 -4
  91. package/dist/package/src/utils/eleValidate.ts +3 -2
  92. package/dist/package/src/utils/errorHandler.ts +9 -8
  93. package/dist/package/src/utils/index.ts +7 -6
  94. package/dist/package/src/utils/oauthProvider.ts +15 -10
  95. package/dist/package/src/utils/passwordCrypto.ts +3 -2
  96. package/dist/package/src/utils/passwordStrength.ts +1 -16
  97. package/dist/package/src/utils/request.ts +13 -8
  98. package/dist/package/src/views/error/403.vue +3 -1
  99. package/dist/package/src/views/error/404.vue +3 -1
  100. package/dist/package/src/views/error/500.vue +3 -1
  101. package/dist/package/src/views/error/pending.vue +5 -2
  102. package/dist/package/src/views/login/components/LoginForm.vue +53 -27
  103. package/dist/package/src/views/login/index.scss +6 -0
  104. package/dist/package/src/views/login/index.vue +2 -0
  105. package/dist/package/types/generated/auto-imports.d.ts +129 -111
  106. package/dist/package/types/generated/components.d.ts +67 -67
  107. package/package.json +3 -1
  108. package/types/generated/auto-imports.d.ts +129 -111
  109. package/types/generated/components.d.ts +67 -67
  110. package/vite.config.ts +8 -0
@@ -1,9 +1,9 @@
1
1
  <template>
2
2
  <div class="password-strength">
3
3
  <div class="password-strength__header">
4
- <span>密码强度</span>
4
+ <span>{{ t("core.password.strength") }}</span>
5
5
  <strong :class="`password-strength__label password-strength__label--${strength.level}`">
6
- {{ strength.text }}
6
+ {{ t(`core.password.strength.${strength.level}`) }}
7
7
  </strong>
8
8
  </div>
9
9
  <div class="password-strength__bars">
@@ -17,13 +17,16 @@
17
17
  }"
18
18
  />
19
19
  </div>
20
- <p class="password-strength__tip">{{ tip }}</p>
20
+ <p class="password-strength__tip">{{ tip || t("core.password.tip") }}</p>
21
21
  </div>
22
22
  </template>
23
23
 
24
24
  <script setup lang="ts">
25
25
  import { computed } from "vue";
26
- import { getPasswordStrength, PASSWORD_STRENGTH_TIP } from "../../utils/passwordStrength";
26
+ import { getPasswordStrength } from "../../utils/passwordStrength";
27
+ import { useLocaleStore } from "../../locales";
28
+
29
+ const { t } = useLocaleStore();
27
30
 
28
31
  /** 密码强度组件属性。 */
29
32
  interface PasswordStrengthProps {
@@ -35,7 +38,7 @@ interface PasswordStrengthProps {
35
38
 
36
39
  const props = withDefaults(defineProps<PasswordStrengthProps>(), {
37
40
  password: "",
38
- tip: PASSWORD_STRENGTH_TIP
41
+ tip: ""
39
42
  });
40
43
 
41
44
  /** 强度条固定为三段,保持所有页面一致。 */
@@ -1,16 +1,19 @@
1
1
  <template>
2
2
  <div class="dynamic-list">
3
3
  <div v-for="(item, index) in modelValue" :key="index" class="dynamic-list__item">
4
- <el-input v-model="modelValue[index]" v-bind="inputProps" />
4
+ <el-input v-model="modelValue[index]" v-bind="resolvedInputProps" />
5
5
  <el-button :icon="Delete" circle type="danger" plain @click="handleRemove(index)" />
6
6
  </div>
7
- <el-button :icon="Plus" type="primary" plain @click="handleAdd">添加</el-button>
7
+ <el-button :icon="Plus" type="primary" plain @click="handleAdd">{{ t("common.action.create") }}</el-button>
8
8
  </div>
9
9
  </template>
10
10
 
11
11
  <script setup lang="ts" name="DynamicList">
12
12
  import { computed } from "vue";
13
13
  import { Delete, Plus } from "@element-plus/icons-vue";
14
+ import { useLocaleStore } from "../../../locales";
15
+
16
+ const { t } = useLocaleStore();
14
17
 
15
18
  /** 动态字符串列表组件属性。 */
16
19
  interface DynamicListProps {
@@ -20,9 +23,11 @@ interface DynamicListProps {
20
23
 
21
24
  const props = withDefaults(defineProps<DynamicListProps>(), {
22
25
  modelValue: () => [],
23
- inputProps: () => ({ placeholder: "请输入内容" })
26
+ inputProps: () => ({})
24
27
  });
25
28
 
29
+ const resolvedInputProps = computed(() => ({ placeholder: t("common.placeholder.inputContent"), ...props.inputProps }));
30
+
26
31
  const emit = defineEmits<{
27
32
  "update:modelValue": [value: string[]];
28
33
  }>();
@@ -1,17 +1,22 @@
1
1
  <template>
2
2
  <div class="kv-list">
3
3
  <div v-for="(item, index) in modelValue" :key="index" class="kv-list__item">
4
- <el-input v-model="item.key" v-bind="keyInputProps" />
5
- <el-input v-model="item.value" v-bind="valueInputProps" />
4
+ <el-input v-model="item.key" v-bind="resolvedKeyInputProps" />
5
+ <el-input v-model="item.value" v-bind="resolvedValueInputProps" />
6
6
  <el-button :icon="Delete" circle type="danger" plain @click="handleRemove(index)" />
7
7
  </div>
8
- <el-button :icon="Plus" type="primary" plain v-bind="addButtonProps" @click="handleAdd">{{ addText }}</el-button>
8
+ <el-button :icon="Plus" type="primary" plain v-bind="addButtonProps" @click="handleAdd">
9
+ {{ addText || t("common.action.create") }}
10
+ </el-button>
9
11
  </div>
10
12
  </template>
11
13
 
12
14
  <script setup lang="ts" name="KvList">
13
15
  import { computed } from "vue";
14
16
  import { Delete, Plus } from "@element-plus/icons-vue";
17
+ import { useLocaleStore } from "../../../locales";
18
+
19
+ const { t } = useLocaleStore();
15
20
 
16
21
  /** 键值对列表单项。 */
17
22
  interface KvItem {
@@ -30,12 +35,15 @@ interface KvListProps {
30
35
 
31
36
  const props = withDefaults(defineProps<KvListProps>(), {
32
37
  modelValue: () => [],
33
- keyInputProps: () => ({ placeholder: "参数名" }),
34
- valueInputProps: () => ({ placeholder: "参数值" }),
35
- addText: "添加",
38
+ keyInputProps: () => ({}),
39
+ valueInputProps: () => ({}),
40
+ addText: "",
36
41
  addButtonProps: () => ({})
37
42
  });
38
43
 
44
+ const resolvedKeyInputProps = computed(() => ({ placeholder: t("common.field.parameterName"), ...props.keyInputProps }));
45
+ const resolvedValueInputProps = computed(() => ({ placeholder: t("common.field.parameterValue"), ...props.valueInputProps }));
46
+
39
47
  const emit = defineEmits<{
40
48
  "update:modelValue": [value: KvItem[]];
41
49
  }>();
@@ -1,19 +1,19 @@
1
1
  <template>
2
2
  <!-- 列设置 -->
3
- <el-drawer v-model="drawerVisible" title="列设置" size="450px">
3
+ <el-drawer v-model="drawerVisible" :title="t('core.table.columnSetting')" size="450px">
4
4
  <div class="table-main">
5
5
  <el-table :data="colSetting" :border="true" row-key="prop" default-expand-all :tree-props="{ children: '_children' }">
6
- <el-table-column prop="label" align="left" label="列名" />
7
- <el-table-column v-slot="scope" prop="isShow" align="center" label="显示">
6
+ <el-table-column prop="label" align="left" :label="t('core.table.columnName')" />
7
+ <el-table-column v-slot="scope" prop="isShow" align="center" :label="t('core.table.show')">
8
8
  <el-switch v-model="scope.row.isShow"></el-switch>
9
9
  </el-table-column>
10
- <el-table-column v-slot="scope" prop="sortable" align="center" label="排序">
10
+ <el-table-column v-slot="scope" prop="sortable" align="center" :label="t('core.table.sort')">
11
11
  <el-switch v-model="scope.row.sortable"></el-switch>
12
12
  </el-table-column>
13
13
  <template #empty>
14
14
  <div class="table-empty">
15
15
  <img src="../../../assets/images/notData.png" alt="notData" />
16
- <div>暂无可配置列</div>
16
+ <div>{{ t("core.table.noConfigurableColumns") }}</div>
17
17
  </div>
18
18
  </template>
19
19
  </el-table>
@@ -24,10 +24,12 @@
24
24
  <script setup lang="ts" name="ColSetting">
25
25
  import { ref } from "vue";
26
26
  import { ColumnProps } from "../../../components/ProTable/interface";
27
+ import { useLocaleStore } from "../../../locales";
27
28
 
28
29
  defineProps<{ colSetting: ColumnProps[] }>();
29
30
 
30
31
  const drawerVisible = ref<boolean>(false);
32
+ const { t } = useLocaleStore();
31
33
 
32
34
  const openColSetting = () => {
33
35
  drawerVisible.value = true;
@@ -10,6 +10,7 @@ import { ColumnProps, HeaderRenderScope, RenderScope, TableActionProps } from ".
10
10
  import type { TableAlign } from "../../../utils/proTable";
11
11
  import { filterEnum, formatValue, handleProp, handleRowAccordingToProp } from "../../../utils";
12
12
  import { formatPrice } from "../../../utils/utils";
13
+ import { t } from "../../../locales";
13
14
 
14
15
  const props = defineProps<{
15
16
  column: ColumnProps;
@@ -119,7 +120,7 @@ const renderImageCell = (item: ColumnProps, scope: RenderScope<any>) => {
119
120
  }
120
121
  },
121
122
  {
122
- error: () => h(ElText, { type: "info", size: "small" }, () => "无图")
123
+ error: () => h(ElText, { type: "info", size: "small" }, () => t("common.message.noData"))
123
124
  }
124
125
  );
125
126
  };
@@ -31,18 +31,22 @@
31
31
  </div>
32
32
  <div v-if="showToolButtonArea" class="header-button-ri">
33
33
  <slot name="toolButton">
34
- <el-tooltip v-if="showTreeToggleButton" :content="isTreeExpanded ? '折叠全部' : '展开全部'" placement="top">
34
+ <el-tooltip
35
+ v-if="showTreeToggleButton"
36
+ :content="isTreeExpanded ? t('core.table.collapseAll') : t('core.table.expandAll')"
37
+ placement="top"
38
+ >
35
39
  <el-button class="tool-button" :icon="isTreeExpanded ? Fold : Expand" circle @click="toggleTreeExpand" />
36
40
  </el-tooltip>
37
- <el-tooltip v-if="showToolButton('refresh')" content="刷新数据" placement="top">
41
+ <el-tooltip v-if="showToolButton('refresh')" :content="t('core.table.refresh')" placement="top">
38
42
  <el-button class="tool-button" :icon="Refresh" circle @click="handleToolRefresh" />
39
43
  </el-tooltip>
40
- <el-tooltip v-if="showToolButton('setting') && columns.length" content="列设置" placement="top">
44
+ <el-tooltip v-if="showToolButton('setting') && columns.length" :content="t('core.table.columnSetting')" placement="top">
41
45
  <el-button class="tool-button" :icon="Operation" circle @click="openColSetting" />
42
46
  </el-tooltip>
43
47
  <el-tooltip
44
48
  v-if="showToolButton('search') && searchColumns?.length"
45
- :content="isShowSearch ? '隐藏搜索' : '显示搜索'"
49
+ :content="isShowSearch ? t('core.table.hideSearch') : t('core.table.showSearch')"
46
50
  placement="top"
47
51
  >
48
52
  <el-button class="tool-button" :icon="Search" circle @click="isShowSearch = !isShowSearch" />
@@ -104,7 +108,7 @@
104
108
  <div class="table-empty">
105
109
  <slot name="empty">
106
110
  <img src="../../assets/images/notData.png" alt="notData" />
107
- <div>暂无数据</div>
111
+ <div>{{ t("common.message.noData") }}</div>
108
112
  </slot>
109
113
  </div>
110
114
  </template>
@@ -128,7 +132,14 @@ import { ref, watch, provide, onMounted, unref, computed, nextTick, useAttrs, us
128
132
  import { ElTable } from "element-plus";
129
133
  import { useTable } from "../../hooks/useTable";
130
134
  import { useSelection } from "../../hooks/useSelection";
131
- import { ColumnProps, EnumProps, HeaderActionProps, HeaderActionScope, ProTableProps, TypeProps } from "../../components/ProTable/interface";
135
+ import {
136
+ ColumnProps,
137
+ EnumProps,
138
+ HeaderActionProps,
139
+ HeaderActionScope,
140
+ ProTableProps,
141
+ TypeProps
142
+ } from "../../components/ProTable/interface";
132
143
  import { Expand, Fold, Refresh, Operation, Search } from "@element-plus/icons-vue";
133
144
  import { generateUUID, handleProp } from "../../utils";
134
145
  import { resolveTableColumnAlign } from "../../utils/proTable";
@@ -137,6 +148,9 @@ import Pagination from "./components/Pagination.vue";
137
148
  import ColSetting from "./components/ColSetting.vue";
138
149
  import TableColumn from "./components/TableColumn.vue";
139
150
  import Sortable from "sortablejs";
151
+ import { useLocaleStore } from "../../locales";
152
+
153
+ const { t } = useLocaleStore();
140
154
 
141
155
  // 接受父组件参数,配置默认值
142
156
  const props = withDefaults(defineProps<ProTableProps>(), {
@@ -208,8 +222,18 @@ const headerActionScope = computed<HeaderActionScope>(() => ({
208
222
  }));
209
223
 
210
224
  // 表格操作 Hooks
211
- const { loading, tableData, pageable, searchParam, searchInitParam, getTableList, search, reset, handleSizeChange, handleCurrentChange } =
212
- useTable(props.requestApi, props.initParam, props.pagination, props.dataCallback, props.requestError);
225
+ const {
226
+ loading,
227
+ tableData,
228
+ pageable,
229
+ searchParam,
230
+ searchInitParam,
231
+ getTableList,
232
+ search,
233
+ reset,
234
+ handleSizeChange,
235
+ handleCurrentChange
236
+ } = useTable(props.requestApi, props.initParam, props.pagination, props.dataCallback, props.requestError);
213
237
 
214
238
  // 清空选中数据列表
215
239
  const clearSelection = () => tableRef.value!.clearSelection();
@@ -299,10 +323,11 @@ const setEnumMapValue = (prop: string | undefined, data: { [key: string]: any }[
299
323
  * 根据状态开关配置自动生成搜索下拉枚举,避免状态列只配置开关后搜索框无选项。
300
324
  */
301
325
  const buildStatusEnum = (column: ColumnProps): EnumProps[] => {
302
- if (column.enum || column.dictCode || column.cellType !== "status" || column.search?.el !== "select" || !column.statusProps) return [];
326
+ if (column.enum || column.dictCode || column.cellType !== "status" || column.search?.el !== "select" || !column.statusProps)
327
+ return [];
303
328
  return [
304
- { label: column.statusProps.activeText ?? "启用", value: column.statusProps.activeValue },
305
- { label: column.statusProps.inactiveText ?? "禁用", value: column.statusProps.inactiveValue }
329
+ { label: column.statusProps.activeText ?? t("common.status.enabled"), value: column.statusProps.activeValue },
330
+ { label: column.statusProps.inactiveText ?? t("common.status.disabled"), value: column.statusProps.inactiveValue }
306
331
  ];
307
332
  };
308
333
 
@@ -49,6 +49,9 @@ import {
49
49
  import Dict from "../../../components/Dict/index.vue";
50
50
  import { handleProp } from "../../../utils";
51
51
  import { ColumnProps, SearchType } from "../../../components/ProTable/interface";
52
+ import { useLocaleStore } from "../../../locales";
53
+
54
+ const { t } = useLocaleStore();
52
55
 
53
56
  /** 单个搜索表单项组件属性。 */
54
57
  interface SearchFormItem {
@@ -151,12 +154,14 @@ const placeholder = computed(() => {
151
154
  const search = props.column.search;
152
155
  if (["datetimerange", "daterange", "monthrange"].includes(search?.props?.type) || search?.props?.isRange) {
153
156
  return {
154
- rangeSeparator: search?.props?.rangeSeparator ?? "",
155
- startPlaceholder: search?.props?.startPlaceholder ?? "开始时间",
156
- endPlaceholder: search?.props?.endPlaceholder ?? "结束时间"
157
+ rangeSeparator: search?.props?.rangeSeparator ?? "-",
158
+ startPlaceholder: search?.props?.startPlaceholder ?? t("common.field.startTime"),
159
+ endPlaceholder: search?.props?.endPlaceholder ?? t("common.field.endTime")
157
160
  };
158
161
  }
159
- const placeholder = search?.props?.placeholder ?? (search?.el?.includes("input") ? "请输入" : "请选择");
162
+ const placeholder =
163
+ search?.props?.placeholder ??
164
+ (search?.el?.includes("input") ? t("common.placeholder.input") : t("common.placeholder.select"));
160
165
  return { placeholder };
161
166
  });
162
167
 
@@ -18,10 +18,10 @@
18
18
  </GridItem>
19
19
  <GridItem v-if="showOperation" suffix>
20
20
  <div class="operation">
21
- <el-button type="primary" :icon="Search" @click="search"> 搜索 </el-button>
22
- <el-button :icon="Delete" @click="reset"> 重置 </el-button>
21
+ <el-button type="primary" :icon="Search" @click="search">{{ t("common.action.search") }}</el-button>
22
+ <el-button :icon="Delete" @click="reset">{{ t("common.action.reset") }}</el-button>
23
23
  <el-button v-if="showCollapse" type="primary" link class="search-isOpen" @click="collapsed = !collapsed">
24
- {{ collapsed ? "展开" : "合并" }}
24
+ {{ collapsed ? t("common.action.expand") : t("common.action.collapse") }}
25
25
  <el-icon class="el-icon--right">
26
26
  <component :is="collapsed ? ArrowDown : ArrowUp"></component>
27
27
  </el-icon>
@@ -40,6 +40,9 @@ import { Delete, Search, ArrowDown, ArrowUp } from "@element-plus/icons-vue";
40
40
  import SearchFormItem from "./components/SearchFormItem.vue";
41
41
  import Grid from "../../components/Grid/index.vue";
42
42
  import GridItem from "../../components/Grid/components/GridItem.vue";
43
+ import { useLocaleStore } from "../../locales";
44
+
45
+ const { t } = useLocaleStore();
43
46
 
44
47
  /** ProTable 搜索表单组件属性。 */
45
48
  interface ProTableProps {
@@ -4,7 +4,7 @@
4
4
  <div class="select-filter-item-title">
5
5
  <span>{{ item.title }} :</span>
6
6
  </div>
7
- <span v-if="!item.options.length" class="select-filter-notData">暂无数据 ~</span>
7
+ <span v-if="!item.options.length" class="select-filter-notData">{{ t("common.message.noData") }}</span>
8
8
  <el-scrollbar>
9
9
  <ul class="select-filter-list">
10
10
  <li
@@ -32,6 +32,9 @@
32
32
 
33
33
  <script setup lang="ts" name="selectFilter">
34
34
  import { ref, watch } from "vue";
35
+ import { useLocaleStore } from "../../locales";
36
+
37
+ const { t } = useLocaleStore();
35
38
 
36
39
  /** 筛选项候选值。 */
37
40
  interface OptionsProps {
@@ -14,7 +14,7 @@
14
14
  </template>
15
15
  </el-input>
16
16
  <el-dialog v-model="dialogVisible" :title="placeholder" top="50px" width="66%">
17
- <el-input v-model="inputValue" placeholder="搜索图标" size="large" :prefix-icon="Icons.Search" />
17
+ <el-input v-model="inputValue" :placeholder="t('core.icon.search')" size="large" :prefix-icon="Icons.Search" />
18
18
  <el-scrollbar v-if="Object.keys(iconsList).length">
19
19
  <div class="icon-list">
20
20
  <div v-for="item in iconsList" :key="item" class="icon-item" @click="selectIcon(item)">
@@ -23,7 +23,7 @@
23
23
  </div>
24
24
  </div>
25
25
  </el-scrollbar>
26
- <el-empty v-else description="未搜索到您要找的图标~" />
26
+ <el-empty v-else :description="t('core.icon.empty')" />
27
27
  </el-dialog>
28
28
  </div>
29
29
  </template>
@@ -31,6 +31,9 @@
31
31
  <script setup lang="ts" name="SelectIcon">
32
32
  import { ref, computed, watch } from "vue";
33
33
  import * as Icons from "@element-plus/icons-vue";
34
+ import { useLocaleStore } from "../../locales";
35
+
36
+ const { t } = useLocaleStore();
34
37
 
35
38
  /** 图标选择器组件属性。 */
36
39
  interface SelectIconProps {
@@ -42,10 +45,11 @@ interface SelectIconProps {
42
45
 
43
46
  const props = withDefaults(defineProps<SelectIconProps>(), {
44
47
  iconValue: "",
45
- title: "请选择图标",
48
+ title: "",
46
49
  clearable: true,
47
- placeholder: "请选择图标"
50
+ placeholder: ""
48
51
  });
52
+ const placeholder = computed(() => props.placeholder || t("core.icon.placeholder"));
49
53
 
50
54
  // 重新接收一下,防止打包后 clearable 报错
51
55
  const valueIcon = ref(props.iconValue);
@@ -4,14 +4,14 @@
4
4
  {{ title }}
5
5
  </h4>
6
6
  <div class="search">
7
- <el-input v-model="filterText" placeholder="输入关键字进行过滤" clearable />
7
+ <el-input v-model="filterText" :placeholder="t('core.tree.filterPlaceholder')" clearable />
8
8
  <el-dropdown trigger="click">
9
9
  <el-icon size="20"><More /></el-icon>
10
10
  <template #dropdown>
11
11
  <el-dropdown-menu>
12
- <el-dropdown-item v-if="!multiple" @click="resetSelected">重置选择</el-dropdown-item>
13
- <el-dropdown-item @click="toggleTreeNodes(true)">展开全部</el-dropdown-item>
14
- <el-dropdown-item @click="toggleTreeNodes(false)">折叠全部</el-dropdown-item>
12
+ <el-dropdown-item v-if="!multiple" @click="resetSelected">{{ t("core.tree.resetSelection") }}</el-dropdown-item>
13
+ <el-dropdown-item @click="toggleTreeNodes(true)">{{ t("core.table.expandAll") }}</el-dropdown-item>
14
+ <el-dropdown-item @click="toggleTreeNodes(false)">{{ t("core.table.collapseAll") }}</el-dropdown-item>
15
15
  </el-dropdown-menu>
16
16
  </template>
17
17
  </el-dropdown>
@@ -51,6 +51,9 @@
51
51
  <script setup lang="ts" name="TreeFilter">
52
52
  import { ref, watch, onBeforeMount, nextTick } from "vue";
53
53
  import { ElTree } from "element-plus";
54
+ import { useLocaleStore } from "../../locales";
55
+
56
+ const { locale, t } = useLocaleStore();
54
57
 
55
58
  // 接收父组件参数并设置默认值
56
59
  interface TreeFilterProps {
@@ -97,7 +100,7 @@ const normalizeLazyNodes = (nodes: { [key: string]: any }[] = []) =>
97
100
 
98
101
  const updateTreeData = (data: { [key: string]: any }[]) => {
99
102
  treeData.value = props.lazy ? normalizeLazyNodes(data) : data;
100
- const allNode = { id: "", [props.label]: "全部", isLeaf: true };
103
+ const allNode = { id: "", [props.label]: t("common.value.all"), isLeaf: true };
101
104
  treeAllData.value = props.showAll ? [allNode, ...treeData.value] : treeData.value;
102
105
  };
103
106
 
@@ -110,7 +113,10 @@ onBeforeMount(async () => {
110
113
  }
111
114
  });
112
115
 
113
- const loadTreeNode = async (node: { level: number; data?: { [key: string]: any } }, resolve: (data: { [key: string]: any }[]) => void) => {
116
+ const loadTreeNode = async (
117
+ node: { level: number; data?: { [key: string]: any } },
118
+ resolve: (data: { [key: string]: any }[]) => void
119
+ ) => {
114
120
  if (!props.requestApi) {
115
121
  resolve([]);
116
122
  return;
@@ -141,6 +147,8 @@ watch(
141
147
  { deep: true, immediate: true }
142
148
  );
143
149
 
150
+ watch(locale, () => updateTreeData(treeData.value));
151
+
144
152
  const filterText = ref("");
145
153
  watch(filterText, val => {
146
154
  treeRef.value!.filter(val);
@@ -12,20 +12,22 @@
12
12
  :on-error="uploadError"
13
13
  :accept="fileType.join(',')"
14
14
  >
15
- <el-button type="primary" :disabled="selfDisabled">上传文件</el-button>
15
+ <el-button type="primary" :disabled="selfDisabled">{{ t("core.upload.action") }}</el-button>
16
16
  </el-upload>
17
17
 
18
18
  <div v-if="fileInfo?.url" class="file-card">
19
19
  <div class="file-card__main">
20
20
  <el-icon class="file-card__icon"><Document /></el-icon>
21
21
  <div class="file-card__meta">
22
- <div class="file-card__name">{{ fileInfo.name || "未命名文件" }}</div>
22
+ <div class="file-card__name">{{ fileInfo.name || t("core.upload.unnamedFile") }}</div>
23
23
  <div class="file-card__url">{{ fileInfo.url }}</div>
24
24
  </div>
25
25
  </div>
26
26
  <div class="file-card__action">
27
- <el-button link type="primary" :icon="Download" @click.stop="handleDownload">下载</el-button>
28
- <el-button v-if="!selfDisabled" link type="danger" :icon="Delete" @click.stop="handleDelete">删除</el-button>
27
+ <el-button link type="primary" :icon="Download" @click.stop="handleDownload">{{ t("common.action.download") }}</el-button>
28
+ <el-button v-if="!selfDisabled" link type="danger" :icon="Delete" @click.stop="handleDelete">
29
+ {{ t("common.action.delete") }}
30
+ </el-button>
29
31
  </div>
30
32
  </div>
31
33
  </div>
@@ -38,6 +40,9 @@ import { ElNotification, formContextKey, formItemContextKey } from "element-plus
38
40
  import type { UploadProps, UploadRequestOptions, UploadUserFile } from "element-plus";
39
41
  import { defFileService } from "../../api/base/file";
40
42
  import type { FileInfo } from "../../rpc/base/v1/file";
43
+ import { useLocaleStore } from "../../locales";
44
+
45
+ const { t } = useLocaleStore();
41
46
 
42
47
  /** 单文件上传组件属性。 */
43
48
  interface UploadFileProps {
@@ -68,7 +73,7 @@ type UploadRequestError = Parameters<NonNullable<UploadRequestOptions["onError"]
68
73
 
69
74
  /** 兼容 Element Plus 上传组件要求的错误对象结构。 */
70
75
  function buildUploadError(error: unknown): UploadRequestError {
71
- const uploadError = error instanceof Error ? error : new Error("文件上传失败");
76
+ const uploadError = error instanceof Error ? error : new Error(t("core.upload.fileFailed"));
72
77
  return Object.assign(uploadError, {
73
78
  status: 500,
74
79
  method: "POST",
@@ -88,16 +93,16 @@ const beforeUpload: UploadProps["beforeUpload"] = rawFile => {
88
93
 
89
94
  if (!fileTypeValid) {
90
95
  ElNotification({
91
- title: "温馨提示",
92
- message: "上传文件不符合所需的格式!",
96
+ title: t("common.title.warning"),
97
+ message: t("core.upload.fileFormatInvalid"),
93
98
  type: "warning"
94
99
  });
95
100
  }
96
101
 
97
102
  if (!fileSizeValid) {
98
103
  ElNotification({
99
- title: "温馨提示",
100
- message: `上传文件大小不能超过 ${props.fileSize}M!`,
104
+ title: t("common.title.warning"),
105
+ message: t("core.upload.fileSizeExceeded", { size: props.fileSize }),
101
106
  type: "warning"
102
107
  });
103
108
  }
@@ -125,8 +130,8 @@ const uploadSuccess = (response: FileInfo | undefined) => {
125
130
  });
126
131
  formItemContext?.prop && formContext?.validateField([formItemContext.prop as string]);
127
132
  ElNotification({
128
- title: "温馨提示",
129
- message: "文件上传成功!",
133
+ title: t("common.title.notice"),
134
+ message: t("core.upload.fileSuccess"),
130
135
  type: "success"
131
136
  });
132
137
  };
@@ -134,8 +139,8 @@ const uploadSuccess = (response: FileInfo | undefined) => {
134
139
  /** 处理文件上传失败提示。 */
135
140
  const uploadError = () => {
136
141
  ElNotification({
137
- title: "温馨提示",
138
- message: "文件上传失败,请您重新上传!",
142
+ title: t("common.title.warning"),
143
+ message: t("core.upload.fileFailed"),
139
144
  type: "error"
140
145
  });
141
146
  };
@@ -14,7 +14,7 @@
14
14
  :on-exceed="handleExceed"
15
15
  :accept="fileType.join(',')"
16
16
  >
17
- <el-button type="primary" :disabled="selfDisabled">上传文件</el-button>
17
+ <el-button type="primary" :disabled="selfDisabled">{{ t("core.upload.action") }}</el-button>
18
18
  </el-upload>
19
19
 
20
20
  <div v-if="_fileList.length" class="file-list">
@@ -22,13 +22,17 @@
22
22
  <div class="file-card__main">
23
23
  <el-icon class="file-card__icon"><Document /></el-icon>
24
24
  <div class="file-card__meta">
25
- <div class="file-card__name">{{ file.name || "未命名文件" }}</div>
25
+ <div class="file-card__name">{{ file.name || t("core.upload.unnamedFile") }}</div>
26
26
  <div class="file-card__url">{{ file.url }}</div>
27
27
  </div>
28
28
  </div>
29
29
  <div class="file-card__action">
30
- <el-button link type="primary" :icon="Download" @click.stop="handleDownload(file)">下载</el-button>
31
- <el-button v-if="!selfDisabled" link type="danger" :icon="Delete" @click.stop="handleRemove(file)">删除</el-button>
30
+ <el-button link type="primary" :icon="Download" @click.stop="handleDownload(file)">
31
+ {{ t("common.action.download") }}
32
+ </el-button>
33
+ <el-button v-if="!selfDisabled" link type="danger" :icon="Delete" @click.stop="handleRemove(file)">
34
+ {{ t("common.action.delete") }}
35
+ </el-button>
32
36
  </div>
33
37
  </div>
34
38
  </div>
@@ -42,6 +46,9 @@ import { ElNotification, formContextKey, formItemContextKey } from "element-plus
42
46
  import type { UploadProps, UploadRequestOptions, UploadUserFile } from "element-plus";
43
47
  import { defFileService } from "../../api/base/file";
44
48
  import type { FileInfo } from "../../rpc/base/v1/file";
49
+ import { useLocaleStore } from "../../locales";
50
+
51
+ const { t } = useLocaleStore();
45
52
 
46
53
  /** 多文件上传组件属性。 */
47
54
  interface UploadFilesProps {
@@ -75,7 +82,7 @@ type UploadRequestError = Parameters<NonNullable<UploadRequestOptions["onError"]
75
82
 
76
83
  /** 兼容 Element Plus 上传组件要求的错误对象结构。 */
77
84
  function buildUploadError(error: unknown): UploadRequestError {
78
- const uploadError = error instanceof Error ? error : new Error("文件上传失败");
85
+ const uploadError = error instanceof Error ? error : new Error(t("core.upload.fileFailed"));
79
86
  return Object.assign(uploadError, {
80
87
  status: 500,
81
88
  method: "POST",
@@ -102,16 +109,16 @@ const beforeUpload: UploadProps["beforeUpload"] = rawFile => {
102
109
 
103
110
  if (!fileTypeValid) {
104
111
  ElNotification({
105
- title: "温馨提示",
106
- message: "上传文件不符合所需的格式!",
112
+ title: t("common.title.warning"),
113
+ message: t("core.upload.fileFormatInvalid"),
107
114
  type: "warning"
108
115
  });
109
116
  }
110
117
 
111
118
  if (!fileSizeValid) {
112
119
  ElNotification({
113
- title: "温馨提示",
114
- message: `上传文件大小不能超过 ${props.fileSize}M!`,
120
+ title: t("common.title.warning"),
121
+ message: t("core.upload.fileSizeExceeded", { size: props.fileSize }),
115
122
  type: "warning"
116
123
  });
117
124
  }
@@ -143,8 +150,8 @@ const uploadSuccess = (response: FileInfo | undefined) => {
143
150
  emit("update:fileList", _fileList.value);
144
151
  formItemContext?.prop && formContext?.validateField([formItemContext.prop as string]);
145
152
  ElNotification({
146
- title: "温馨提示",
147
- message: "文件上传成功!",
153
+ title: t("common.title.notice"),
154
+ message: t("core.upload.fileSuccess"),
148
155
  type: "success"
149
156
  });
150
157
  };
@@ -152,8 +159,8 @@ const uploadSuccess = (response: FileInfo | undefined) => {
152
159
  /** 处理文件上传失败提示。 */
153
160
  const uploadError = () => {
154
161
  ElNotification({
155
- title: "温馨提示",
156
- message: "文件上传失败,请您重新上传!",
162
+ title: t("common.title.warning"),
163
+ message: t("core.upload.fileFailed"),
157
164
  type: "error"
158
165
  });
159
166
  };
@@ -161,8 +168,8 @@ const uploadError = () => {
161
168
  /** 超出上传数量限制时给出提示。 */
162
169
  function handleExceed() {
163
170
  ElNotification({
164
- title: "温馨提示",
165
- message: `当前最多只能上传 ${props.limit} 个文件,请移除后上传!`,
171
+ title: t("common.title.warning"),
172
+ message: t("core.upload.limitExceeded", { limit: props.limit }),
166
173
  type: "warning"
167
174
  });
168
175
  }