kz-ui-base 1.0.149 → 1.0.151

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.
@@ -66,3 +66,20 @@ export function refreshCache() {
66
66
  method: 'delete'
67
67
  })
68
68
  }
69
+ // 批量保存或更新翻译
70
+ export function batchSaveTranslation(data) {
71
+ return request({
72
+ url: '/system/api/i18n/translation/batch-save',
73
+ method: 'post',
74
+ data: data
75
+ })
76
+ }
77
+
78
+ // 批量获取翻译
79
+ export function batchGetTranslation(data) {
80
+ return request({
81
+ url: '/system/api/i18n/translation/batch-get-multi',
82
+ method: 'post',
83
+ data: data
84
+ })
85
+ }
@@ -0,0 +1,245 @@
1
+ <template>
2
+ <el-dialog
3
+ :title="t('config.multi_language_config')"
4
+ :visible.sync="dialogVisible"
5
+ width="900px"
6
+ append-to-body
7
+ v-dialogDrag
8
+ @close="handleDialogClose"
9
+ >
10
+ <div v-for="(columnName, index) in config.dataLangColumnFields" :key="index">
11
+ <el-card :body-style="{ padding: '10px' }" style="margin-bottom: 15px;">
12
+ <div slot="header" class="clearfix">
13
+ <span>{{ getLabelByKey(columnName) }}</span>
14
+ </div>
15
+ <el-table :data="getTableData(columnName)" height="300" border size="small">
16
+ <el-table-column property="value" :label="t('config.value')" />
17
+ <el-table-column v-for="(lang, langIndex) in languages" :key="langIndex">
18
+ <template slot="header">
19
+ <span>{{ lang.label }}</span>
20
+ </template>
21
+ <template slot-scope="scope">
22
+ <el-input
23
+ v-model="scope.row[lang.value]"
24
+ :placeholder="`请输入${lang.label}`"
25
+ size="small"
26
+ />
27
+ </template>
28
+ </el-table-column>
29
+ </el-table>
30
+ </el-card>
31
+ </div>
32
+ <div slot="footer" class="dialog-footer">
33
+ <el-button @click="handleClose">{{ t('config.close') }}</el-button>
34
+ <el-button type="primary" @click="handleSubmit">{{ t('config.confirm') }}</el-button>
35
+ </div>
36
+ </el-dialog>
37
+ </template>
38
+
39
+ <script>
40
+ import request from '@utils/request'
41
+ import { batchSaveTranslation } from './config.js'
42
+
43
+ export default {
44
+ name: "MultiLanguageDialog",
45
+ props: {
46
+ visible: {
47
+ type: Boolean,
48
+ default: false
49
+ },
50
+ config: {
51
+ type: Object,
52
+ default: () => ({
53
+ entityName: 'sys_config',
54
+ dataLangColumnFields: [],
55
+ dataLangIdField: 'id',
56
+ data: []
57
+ })
58
+ }
59
+ },
60
+ data() {
61
+ return {
62
+ dialogVisible: false,
63
+ languages: [],
64
+ tableDataMap: {} // 存储每个字段的表格数据
65
+ }
66
+ },
67
+ watch: {
68
+ visible(val) {
69
+ this.dialogVisible = val
70
+ },
71
+ dialogVisible(val) {
72
+ this.$emit('update:visible', val)
73
+ if (val) {
74
+ // 弹框打开时重新初始化数据
75
+ this.getLanguages()
76
+ }
77
+ }
78
+ },
79
+ methods: {
80
+ t(key) {
81
+ return this.$t(key) || key
82
+ },
83
+ getLabelByKey(key) {
84
+ const labelMap = {
85
+ configName: this.t('config.config_name'),
86
+ configKey: this.t('config.config_key'),
87
+ configValue: this.t('config.config_value'),
88
+ configType: this.t('config.config_type'),
89
+ remark: this.t('config.remark')
90
+ }
91
+ return labelMap[key] || key
92
+ },
93
+ /**
94
+ * 通过 dataLangFieldMap 映射字段名
95
+ * 如果原始字段找不到,尝试通过映射获取值
96
+ * @param {Object} row - 数据行
97
+ * @param {string} field - 原始字段名
98
+ * @returns {any} 字段值
99
+ */
100
+ getFieldValueByMap(row, field) {
101
+ // 如果直接能找到字段,直接返回
102
+ if (row[field] !== undefined && row[field] !== null) {
103
+ return row[field]
104
+ }
105
+ // 如果找不到,尝试通过 dataLangFieldMap 映射
106
+ const fieldMap = this.config.dataLangFieldMap
107
+ if (fieldMap) {
108
+ // 查找映射关系中 value 等于 field 的 key
109
+ const mappedKey = Object.keys(fieldMap).find(key => fieldMap[key] === field)
110
+ if (mappedKey && row[mappedKey] !== undefined && row[mappedKey] !== null) {
111
+ return row[mappedKey]
112
+ }
113
+ }
114
+ return null
115
+ },
116
+ getTableData(columnName) {
117
+ // 如果已经有数据,直接返回(保持响应式)
118
+ if (this.tableDataMap[columnName]) {
119
+ return this.tableDataMap[columnName]
120
+ }
121
+ // 初始化数据
122
+ const data = this.config.data.map((row, index) => {
123
+ const item = {
124
+ id: this.getFieldValueByMap(row, this.config.dataLangIdField) || row.configId,
125
+ value: this.getFieldValueByMap(row, columnName) || '-',
126
+ configKey: row.configKey
127
+ }
128
+ // 为每个语言初始化字段
129
+ this.languages.forEach(lang => {
130
+ item[lang.value] = ''
131
+ })
132
+ return item
133
+ })
134
+ this.tableDataMap[columnName] = data
135
+ return data
136
+ },
137
+ initTableData() {
138
+ // 初始化所有字段的数据
139
+ this.config.dataLangColumnFields.forEach(columnName => {
140
+ this.tableDataMap[columnName] = this.config.data.map((row, index) => {
141
+ const item = {
142
+ id: this.getFieldValueByMap(row, this.config.dataLangIdField) || row.configId,
143
+ value: this.getFieldValueByMap(row, columnName) || '-',
144
+ configKey: row.configKey
145
+ }
146
+ this.languages.forEach(lang => {
147
+ item[lang.value] = ''
148
+ })
149
+ return item
150
+ })
151
+ })
152
+ },
153
+ getLanguages() {
154
+ request({
155
+ url: '/system/api/i18n/locales',
156
+ method: 'get'
157
+ }).then(response => {
158
+ if (response.data) {
159
+ this.languages = Object.keys(response.data).map(key => ({
160
+ label: response.data[key],
161
+ value: key
162
+ }))
163
+ // 语言加载完成后初始化表格数据
164
+ this.initTableData()
165
+ }
166
+ }).catch(error => {
167
+ console.error('获取语言列表失败:', error)
168
+ // 默认使用中英文
169
+ this.languages = [
170
+ { label: '中文 (中国)', value: 'zh_CN' },
171
+ { label: 'English (United States)', value: 'en_US' }
172
+ ]
173
+ // 语言加载完成后初始化表格数据
174
+ this.initTableData()
175
+ })
176
+ },
177
+ handleClose() {
178
+ this.dialogVisible = false
179
+ },
180
+ handleDialogClose() {
181
+ // 弹框关闭时清空数据,确保下次打开时重新初始化
182
+ this.languages = []
183
+ this.tableDataMap = {}
184
+ },
185
+ handleSubmit() {
186
+ // 构建批量保存翻译的请求数据
187
+ const saveData = []
188
+
189
+ this.config.dataLangColumnFields.forEach(columnName => {
190
+ const tableData = this.tableDataMap[columnName] || []
191
+ tableData.forEach((rowData, rowIndex) => {
192
+ const originalRow = this.config.data[rowIndex]
193
+ // 获取实际的记录 ID(通过 dataLangFieldMap 映射)
194
+ const recordId = this.getFieldValueByMap(originalRow, this.config.dataLangIdField) || originalRow.configId
195
+
196
+ this.languages.forEach(lang => {
197
+ const translationValue = rowData[lang.value]
198
+ // 只有当用户填写了翻译内容时才保存
199
+ if (translationValue && translationValue.trim() !== '') {
200
+ // 从 localStorage 获取 userInfo 中的 tenantId
201
+ const userInfo = JSON.parse(localStorage.getItem('userInfo') || '{}')
202
+ saveData.push({
203
+ entityName: this.config.entityName || 'sys_config',
204
+ recordId: String(recordId),
205
+ columnName: columnName,
206
+ locale: lang.value,
207
+ translation: translationValue,
208
+ tenantId: userInfo.tenantId || undefined
209
+ })
210
+ }
211
+ })
212
+ })
213
+ })
214
+
215
+ console.log('保存数据:', saveData)
216
+
217
+ if (saveData.length === 0) {
218
+ this.$message.warning(this.t('config.please_enter_translation'))
219
+ return
220
+ }
221
+
222
+ // 调用批量保存翻译接口
223
+ batchSaveTranslation(saveData).then(response => {
224
+ if (response.code === 200) {
225
+ this.$message.success(this.t('config.translation_save_success'))
226
+ this.$emit('update:visible', false)
227
+ this.$emit('saved')
228
+ } else {
229
+ this.$message.error(response.msg || this.t('config.translation_save_failed'))
230
+ }
231
+ }).catch(error => {
232
+ console.error('批量保存翻译失败:', error)
233
+ this.$message.error(this.t('config.translation_save_failed'))
234
+ })
235
+ }
236
+ }
237
+ }
238
+ </script>
239
+
240
+ <style scoped>
241
+ .clearfix {
242
+ font-weight: bold;
243
+ font-size: 14px;
244
+ }
245
+ </style>
@@ -0,0 +1,85 @@
1
+ import request from '@utils/request'
2
+
3
+ // 查询参数列表
4
+ export function listConfig(query) {
5
+ return request({
6
+ url: '/system/config/list',
7
+ method: 'get',
8
+ params: query
9
+ })
10
+ }
11
+
12
+ // 查询参数详细
13
+ export function getConfig(configId) {
14
+ return request({
15
+ url: '/system/config/' + configId,
16
+ method: 'get'
17
+ })
18
+ }
19
+
20
+ // 根据参数键名查询参数值
21
+ export function getConfigKey(configKey) {
22
+ return request({
23
+ url: '/system/config/configKey/' + configKey,
24
+ method: 'get'
25
+ })
26
+ }
27
+
28
+ // 根据参数键名查询参数值
29
+ export function innerConfigKey(configKey) {
30
+ return request({
31
+ url: '/system/config/innerConfigKey/' + configKey,
32
+ method: 'get'
33
+ })
34
+ }
35
+
36
+ // 新增参数配置
37
+ export function addConfig(data) {
38
+ return request({
39
+ url: '/system/config',
40
+ method: 'post',
41
+ data: data
42
+ })
43
+ }
44
+
45
+ // 修改参数配置
46
+ export function updateConfig(data) {
47
+ return request({
48
+ url: '/system/config',
49
+ method: 'put',
50
+ data: data
51
+ })
52
+ }
53
+
54
+ // 删除参数配置
55
+ export function delConfig(configId) {
56
+ return request({
57
+ url: '/system/config/' + configId,
58
+ method: 'delete'
59
+ })
60
+ }
61
+
62
+ // 刷新参数缓存
63
+ export function refreshCache() {
64
+ return request({
65
+ url: '/system/config/refreshCache',
66
+ method: 'delete'
67
+ })
68
+ }
69
+ // 批量保存或更新翻译
70
+ export function batchSaveTranslation(data) {
71
+ return request({
72
+ url: '/system/api/i18n/translation/batch-save',
73
+ method: 'post',
74
+ data: data
75
+ })
76
+ }
77
+
78
+ // 批量获取翻译
79
+ export function batchGetTranslation(data) {
80
+ return request({
81
+ url: '/system/api/i18n/translation/batch-get-multi',
82
+ method: 'post',
83
+ data: data
84
+ })
85
+ }
@@ -431,6 +431,22 @@
431
431
  </el-dropdown>
432
432
  </el-col>
433
433
 
434
+ <el-col
435
+ :span="1.5"
436
+ v-if="multiLanguageConfig && multiLanguageConfig.entityName && multiLanguageConfig.dataLangColumnFields && multiLanguageConfig.dataLangColumnFields.length > 0"
437
+ >
438
+ <el-button
439
+ type="info"
440
+ plain
441
+ icon="el-icon-connection"
442
+ size="mini"
443
+ :disabled="multiple"
444
+ @click="handleMultiLanguage"
445
+ >
446
+ {{ t('config.switch_multi_language') }}
447
+ </el-button>
448
+ </el-col>
449
+
434
450
  <right-toolbar
435
451
  style="float: right"
436
452
  v-if="showToolBar"
@@ -1235,6 +1251,13 @@
1235
1251
  v-dialogDragHeight
1236
1252
  >
1237
1253
  </printDialog>
1254
+
1255
+ <!-- 多语言配置对话框 -->
1256
+ <MultiLanguageDialog
1257
+ :visible.sync="multiLanguageOpen"
1258
+ :config="multiLanguageConfig"
1259
+ @saved="handleTranslationSaved"
1260
+ />
1238
1261
  </div>
1239
1262
  </template>
1240
1263
  <script lang="ts">
@@ -1282,6 +1305,8 @@ import KZ_Radio from "@srcComponents/customForm/radio.vue";
1282
1305
  import UploadDialog from "@srcComponents/customForm/uploadDialog.vue";
1283
1306
  import PrintDialog from "@srcComponents/customForm/printDialog.vue";
1284
1307
  import KZ_Lookup from "@srcComponents/customForm/lookup.vue";
1308
+ import MultiLanguageDialog from "@srcComponents/base/dialog/MultiLanguageDialog.vue";
1309
+ import { batchGetTranslation } from "@srcComponents/base/dialog/config.js";
1285
1310
  @Component({
1286
1311
  components: {
1287
1312
  // TableDialog,
@@ -1289,6 +1314,7 @@ import KZ_Lookup from "@srcComponents/customForm/lookup.vue";
1289
1314
  EditDialog,
1290
1315
  UploadDialog,
1291
1316
  PrintDialog,
1317
+ MultiLanguageDialog,
1292
1318
  KZ_DropDownList,
1293
1319
  KZ_TextBox,
1294
1320
  KZ_Cascader,
@@ -1368,6 +1394,15 @@ export default class listBasePage extends Vue {
1368
1394
  pkField = "id";
1369
1395
  //当前功能显示文本字段
1370
1396
  displayField = undefined;
1397
+ // 多语言对话框显示
1398
+ multiLanguageOpen = false;
1399
+ // 多语言配置
1400
+ multiLanguageConfig = {
1401
+ entityName: undefined,
1402
+ dataLangColumnFields: [],
1403
+ dataLangIdField: undefined,
1404
+ data: []
1405
+ };
1371
1406
  // 树名称
1372
1407
  treeShapeName = undefined;
1373
1408
  defaultProps = {
@@ -1569,7 +1604,7 @@ export default class listBasePage extends Vue {
1569
1604
  //{ text: `用户账号`, property: "userAccount", visible: true },
1570
1605
  ];
1571
1606
  listSerialNumber = {
1572
- label: '序号',
1607
+ label: (this as any).t('common.serialNumber'),
1573
1608
  width: "50",
1574
1609
  align: "center",
1575
1610
  };
@@ -2159,12 +2194,88 @@ export default class listBasePage extends Vue {
2159
2194
 
2160
2195
  this.listQueryParams.total = Number((response as any).total);
2161
2196
  this.contentLoading = false;
2197
+ // 获取翻译并替换字段
2198
+ this.fetchAndApplyTranslations(this.listData);
2162
2199
  })
2163
2200
  .catch(() => {
2164
2201
  this.contentLoading = false;
2165
2202
  });
2166
2203
  }
2167
2204
 
2205
+ /** 获取并应用翻译 */
2206
+ fetchAndApplyTranslations(dataList) {
2207
+ if (!dataList || dataList.length === 0) {
2208
+ return;
2209
+ }
2210
+ // 检查是否配置了多语言字段
2211
+ if (!this.multiLanguageConfig ||
2212
+ !this.multiLanguageConfig.entityName ||
2213
+ !this.multiLanguageConfig.dataLangIdField ||
2214
+ !this.multiLanguageConfig.dataLangColumnFields ||
2215
+ this.multiLanguageConfig.dataLangColumnFields.length === 0) {
2216
+ return;
2217
+ }
2218
+ // 获取 locale 和 tenantId
2219
+ const locale = (this as any).$cache.local.get('locale') || 'zh_CN';
2220
+ const userInfo = JSON.parse(localStorage.getItem('userInfo') || '{}');
2221
+ const tenantId = userInfo.tenantId;
2222
+
2223
+ // 构建请求参数
2224
+ const recordIds = dataList.map(item => String(item[this.multiLanguageConfig.dataLangIdField]));
2225
+ const columnNames = this.multiLanguageConfig.dataLangColumnFields;
2226
+
2227
+ // 过滤掉没有 dataLangIdField 值的记录
2228
+ const validRecordIds = recordIds.filter(id => id && id !== '' && id !== 'undefined' && id !== 'null');
2229
+ if (validRecordIds.length === 0) {
2230
+ return;
2231
+ }
2232
+
2233
+ const params = {
2234
+ entityName: this.multiLanguageConfig.entityName,
2235
+ recordIds: validRecordIds,
2236
+ columnNames: columnNames,
2237
+ locale: locale,
2238
+ tenantId: tenantId
2239
+ };
2240
+
2241
+ batchGetTranslation(params).then(response => {
2242
+ if ((response as any).code === 200 && response.data) {
2243
+ this.applyTranslations(response.data, dataList);
2244
+ }
2245
+ }).catch(error => {
2246
+ console.error('Failed to fetch translations:', error);
2247
+ });
2248
+ }
2249
+
2250
+ /** 应用翻译到表格数据 */
2251
+ applyTranslations(translationMap, dataList) {
2252
+ // translationMap 格式: {"1001": {"menu_name": "Menu"}, "1002": {"menu_name": "Submenu"}}
2253
+ const idField = this.multiLanguageConfig.dataLangIdField;
2254
+
2255
+ dataList.forEach(row => {
2256
+ const recordId = String(row[idField]);
2257
+ if (translationMap[recordId]) {
2258
+ const translations = translationMap[recordId];
2259
+ // 遍历翻译字段并替换
2260
+ Object.keys(translations).forEach(column => {
2261
+ if (translations[column] && translations[column] !== '') {
2262
+ row[column] = translations[column];
2263
+ }
2264
+ });
2265
+ }
2266
+ });
2267
+ }
2268
+
2269
+ /** 切换多语言按钮操作 */
2270
+ handleMultiLanguage() {
2271
+ this.multiLanguageOpen = true;
2272
+ }
2273
+
2274
+ /** 翻译保存成功后的处理 */
2275
+ handleTranslationSaved() {
2276
+ this.getList();
2277
+ }
2278
+
2168
2279
  isListClass(value, val, va) {
2169
2280
  let dict = JSON.parse(localStorage.getItem("dict"));
2170
2281
  for (const key in dict) {
@@ -2645,6 +2756,8 @@ export default class listBasePage extends Vue {
2645
2756
  //this.setOpMenuEnable();
2646
2757
  this.currentEntities = selection;
2647
2758
  this.setOpMenuEnable();
2759
+ // 更新多语言配置的数据
2760
+ this.multiLanguageConfig.data = selection;
2648
2761
  }
2649
2762
  // 表单重置
2650
2763
  reset() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kz-ui-base",
3
- "version": "1.0.149",
3
+ "version": "1.0.151",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "scripts": {