yh-i18n 2.2.21 → 2.2.22

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 (3) hide show
  1. package/excelTool.ts +35 -21
  2. package/list.vue +70 -66
  3. package/package.json +1 -1
package/excelTool.ts CHANGED
@@ -5,6 +5,33 @@ import http from '@/libs/api.request';
5
5
  import {useI18nStore} from './index';
6
6
 
7
7
  const verificationCode = 'lkyhtranslateexcel';
8
+
9
+ /**
10
+ * 解析翻译内容,将 JSON 字符串解析并合并到 item 对象中
11
+ * @param item 翻译项对象
12
+ * @param localKeys 本地语言键列表
13
+ * @returns 处理后的翻译项对象
14
+ */
15
+ export function parseTranslateContent(item: any, localKeys: string[]): any {
16
+ try {
17
+ let content = JSON.parse(item.content);
18
+ let keys = Object.keys(content);
19
+
20
+ keys.forEach((key) => {
21
+ let val = content[key];
22
+ item[key] = val;
23
+ });
24
+
25
+ localKeys.forEach((k) => {
26
+ if (!keys.includes(k)) {
27
+ item[k] = '';
28
+ }
29
+ });
30
+ } catch (error) {
31
+ console.error('解析翻译内容失败:', error);
32
+ }
33
+ return item;
34
+ }
8
35
  export async function exportExcel(total) {
9
36
  const loading = ElLoading.service({
10
37
  lock: true,
@@ -24,23 +51,7 @@ export async function exportExcel(total) {
24
51
  .then((res) => {
25
52
  let localKeys = i18nStore.localList.map((item) => item.value);
26
53
  let {records} = res.data.data;
27
- records = records.map((item) => {
28
- try {
29
- let content = JSON.parse(item.content);
30
- let keys = Object.keys(content);
31
-
32
- keys.forEach((key) => {
33
- let val = content[key];
34
- item[key] = val;
35
- });
36
- localKeys.forEach((k) => {
37
- if (!keys.includes(k)) {
38
- item[k] = '';
39
- }
40
- });
41
- } catch (error) {}
42
- return item;
43
- });
54
+ records = records.map((item) => parseTranslateContent(item, localKeys));
44
55
  return records;
45
56
  });
46
57
  loading.setText('正在序列化表格数据……');
@@ -77,8 +88,8 @@ export async function exportExcel(total) {
77
88
  sheet.addRow(title);
78
89
  sheet.addRows(
79
90
  records.map((item) => {
80
- let {adTranslateId, tKey} = item;
81
- let row = [adTranslateId, tKey];
91
+ let {id, name} = item;
92
+ let row = [id, name];
82
93
  Config.i18nList.forEach((valKey) => {
83
94
  row.push(item[valKey]);
84
95
  });
@@ -201,6 +212,7 @@ export async function importExcel(e, getDataList) {
201
212
  message: '您选择的文件不是系统导出的文件',
202
213
  type: 'warning',
203
214
  });
215
+ e.target.value = '';
204
216
  return false;
205
217
  }
206
218
  const loading = ElLoading.service({
@@ -215,14 +227,14 @@ export async function importExcel(e, getDataList) {
215
227
  let dataList: any[] = [];
216
228
  sheet.getRows(2, len)?.forEach((row) => {
217
229
  let id = row.getCell(1).value;
218
- let tKey = row.getCell(2).value;
230
+ let name = row.getCell(2).value;
219
231
  let content: any = {};
220
232
  Config.i18nList.forEach((item, index) => {
221
233
  content[item] = row.getCell(index + 3).value;
222
234
  });
223
235
  dataList.push({
224
236
  id,
225
- tKey,
237
+ name,
226
238
  content: JSON.stringify(content),
227
239
  });
228
240
  });
@@ -250,6 +262,8 @@ export async function importExcel(e, getDataList) {
250
262
  getDataList();
251
263
  } catch (error) {
252
264
  ElMessage.error('导入保存翻译数据遇到错误:', error.message);
265
+ } finally {
266
+ e.target.value = '';
253
267
  }
254
268
  }
255
269
  }
package/list.vue CHANGED
@@ -5,7 +5,7 @@
5
5
  <el-form inline>
6
6
  <el-form-item :label="ct('翻译键名')">
7
7
  <el-input
8
- v-model="listForm.tKey"
8
+ v-model="listForm.name"
9
9
  @keyup.enter.stop.prevent="getDataList(true)"
10
10
  :placeholder="ct('键入以筛选键名')"></el-input>
11
11
  </el-form-item>
@@ -48,7 +48,7 @@
48
48
  ref="i18nList"
49
49
  stripe
50
50
  :data="dataList"
51
- row-key="adTranslateId"
51
+ row-key="id"
52
52
  @row-click="rowClickHandler">
53
53
  <el-table-column
54
54
  type="selection"
@@ -76,13 +76,13 @@
76
76
  <el-button
77
77
  link
78
78
  type="danger"
79
- @click="delOne(row.adTranslateId)">
79
+ @click="delOne(row.id)">
80
80
  {{ ct('删除') }}
81
81
  </el-button>
82
82
  </template>
83
83
  </el-table-column>
84
84
  <el-table-column
85
- prop="tkey"
85
+ prop="name"
86
86
  min-width="140"
87
87
  fixed="left"
88
88
  :label="ct('翻译键名')"></el-table-column>
@@ -107,7 +107,7 @@
107
107
  @close="cancelForm"
108
108
  :close-on-click-modal="false"
109
109
  draggable
110
- :title="formData.adTranslateId ? ct('编辑翻译') : ct('新增翻译')">
110
+ :title="formData.id ? ct('编辑翻译') : ct('新增翻译')">
111
111
  <vxe-form
112
112
  title-align="right"
113
113
  title-width="100px"
@@ -115,7 +115,7 @@
115
115
  title-colon
116
116
  :data="formData"
117
117
  :items="formItems"
118
- :rules="fromRules"></vxe-form>
118
+ :rules="formRules"></vxe-form>
119
119
  <template #footer>
120
120
  <div class="yh-i18n-form-actions">
121
121
  <el-button
@@ -146,16 +146,16 @@
146
146
  </el-dialog>
147
147
  </template>
148
148
  <script setup lang="ts">
149
- import {reactive, ref, onMounted, watch} from 'vue';
149
+ import {reactive, ref, onMounted, onUnmounted, watch} from 'vue';
150
150
  import {ElLoadingService, ElMessage, ElMessageBox} from 'element-plus';
151
151
  import {useI18nStore, ct} from 'yh-i18n';
152
152
  import http from '@/libs/api.request';
153
153
  import {VxeFormInstance, VxeFormPropTypes} from 'vxe-table';
154
- import {exportExcel, importExcel} from './excelTool';
154
+ import {exportExcel, importExcel, parseTranslateContent} from './excelTool';
155
155
 
156
156
  interface TranslateItem {
157
- adTranslateId?: string;
158
- tKey: string;
157
+ id?: string;
158
+ name: string;
159
159
  content: string;
160
160
  [key: string]: any;
161
161
  }
@@ -167,7 +167,7 @@ interface ListColumn {
167
167
  }
168
168
 
169
169
  interface SaveData {
170
- tKey: string;
170
+ name: string;
171
171
  content: Record<string, string> | string;
172
172
  id?: string;
173
173
  }
@@ -180,7 +180,7 @@ const deleteUrl = '/translate/deleteTranslate';
180
180
 
181
181
  const i18nList = ref();
182
182
  const listForm = reactive({
183
- tKey: '',
183
+ name: '',
184
184
  pageNum: 1,
185
185
  pageSize: 10,
186
186
  total: 0,
@@ -188,7 +188,7 @@ const listForm = reactive({
188
188
  const listColumns = reactive<ListColumn[]>([]);
189
189
  const dataList = ref<TranslateItem[]>([]);
190
190
  function getDataList(isReset = false) {
191
- let {tKey, pageNum, pageSize} = listForm;
191
+ let {name, pageNum, pageSize} = listForm;
192
192
  if (isReset) {
193
193
  pageNum = 1;
194
194
  }
@@ -200,7 +200,7 @@ function getDataList(isReset = false) {
200
200
  url: '/translate/select',
201
201
  method: 'post',
202
202
  data: {
203
- tKey,
203
+ name,
204
204
  pageNum,
205
205
  pageSize,
206
206
  },
@@ -208,28 +208,14 @@ function getDataList(isReset = false) {
208
208
  .then((res) => {
209
209
  let localKeys = i18nStore.localList.map((item) => item.value);
210
210
  let {records, total} = res.data.data;
211
- records = records.map((item) => {
212
- try {
213
- let content = JSON.parse(item.content);
214
- let keys = Object.keys(content);
215
-
216
- keys.forEach((key) => {
217
- let val = content[key];
218
- item[key] = val;
219
- });
220
- localKeys.forEach((k) => {
221
- if (!keys.includes(k)) {
222
- item[k] = '';
223
- }
224
- });
225
- } catch (error) {
226
- console.error('解析翻译内容失败:', error);
227
- }
228
- return item;
229
- });
211
+ records = records.map((item) => parseTranslateContent(item, localKeys));
230
212
  dataList.value = records;
231
213
  listForm.total = total;
232
214
  })
215
+ .catch((error) => {
216
+ ElMessage.error('获取数据失败');
217
+ console.error('获取列表数据失败:', error);
218
+ })
233
219
  .finally(() => {
234
220
  loading.close();
235
221
  });
@@ -253,7 +239,7 @@ function rowClickHandler(row) {
253
239
  }
254
240
 
255
241
  function resetList() {
256
- listForm.tKey = '';
242
+ listForm.name = '';
257
243
  listForm.pageNum = 1;
258
244
  listForm.total = 0;
259
245
  getDataList();
@@ -262,16 +248,16 @@ function resetList() {
262
248
  const langList = Object.keys(i18nStore.langList);
263
249
  const formDataIndex = ref<number>();
264
250
  const formData = reactive<TranslateItem>({
265
- tKey: '',
251
+ name: '',
266
252
  content: '',
267
253
  });
268
254
  const formShow = ref(false);
269
- let inputs: HTMLInputElement[] = [];
255
+
270
256
  function cancelForm() {
271
257
  vxeFormRef?.value?.reset();
272
258
  vxeFormRef?.value?.clearValidate();
273
259
  formDataIndex.value = void 0;
274
- formData.id = null;
260
+ formData.id = undefined;
275
261
  formShow.value = false;
276
262
  }
277
263
 
@@ -289,6 +275,13 @@ function prevOne() {
289
275
 
290
276
  function editOne(item, index) {
291
277
  formDataIndex.value = index;
278
+ // 先清空表单数据,除了 id
279
+ for (const key in formData) {
280
+ if (key !== 'id') {
281
+ delete formData[key];
282
+ }
283
+ }
284
+ // 然后将新项目的数据复制到表单
292
285
  for (const key in item) {
293
286
  if (Object.prototype.hasOwnProperty.call(item, key)) {
294
287
  const val = item[key];
@@ -311,18 +304,18 @@ function nextOne() {
311
304
  }
312
305
 
313
306
  function saveOne() {
314
- let isAdd = !formData.adTranslateId;
307
+ let isAdd = !formData.id;
315
308
  let url = updateUrl;
316
309
  vxeFormRef?.value?.validate().then((errMap) => {
317
310
  if (!errMap) {
318
311
  let data: SaveData = {
319
- key: formData.tkey,
312
+ name: formData.name,
320
313
  content: {},
321
314
  };
322
315
  if (isAdd) {
323
316
  url = insertUrl;
324
317
  } else {
325
- data.id = formData.adTranslateId;
318
+ data.id = formData.id;
326
319
  }
327
320
  for (const key in formData) {
328
321
  if (key !== 'key' && langList.includes(key)) {
@@ -344,10 +337,12 @@ function saveOne() {
344
337
  getDataList();
345
338
  cancelForm();
346
339
  } else {
347
- dataList.value[formDataIndex.value] = {
348
- ...formData,
349
- };
350
- nextOne();
340
+ if (formDataIndex.value !== undefined && formDataIndex.value !== null) {
341
+ dataList.value[formDataIndex.value] = {
342
+ ...formData,
343
+ };
344
+ nextOne();
345
+ }
351
346
  }
352
347
  } else {
353
348
  ElMessage.error(res.data.msg);
@@ -380,7 +375,8 @@ function delOne(id) {
380
375
 
381
376
  function delMore() {
382
377
  ElMessageBox.confirm('确认删除选中的翻译记录吗?').then(async () => {
383
- let ids = i18nList.value?.getSelectionRows().map((row) => row.adTranslateId);
378
+ const selectedRows = i18nList.value?.getSelectionRows();
379
+ const ids = selectedRows?.map((row) => row.id) || [];
384
380
  if (ids && ids.length) {
385
381
  let len = ids.length;
386
382
  let loading = ElLoadingService({
@@ -399,9 +395,11 @@ function delMore() {
399
395
  });
400
396
  } catch (error) {
401
397
  ElMessage.error(`删除第 ${i + 1} 条记录失败`);
398
+ console.error(`删除第 ${i + 1} 条记录失败:`, error);
402
399
  }
403
400
  }
404
401
  loading.close();
402
+ ElMessage.success(`删除完成,共 ${len} 条记录`);
405
403
  getDataList();
406
404
  }
407
405
  });
@@ -409,7 +407,7 @@ function delMore() {
409
407
 
410
408
  const formItems = reactive<VxeFormPropTypes.Items>([
411
409
  {
412
- field: 'tkey',
410
+ field: 'name',
413
411
  span: 24,
414
412
  title: '翻译键值',
415
413
  itemRender: {
@@ -419,8 +417,8 @@ const formItems = reactive<VxeFormPropTypes.Items>([
419
417
  },
420
418
  ]);
421
419
 
422
- const fromRules = reactive<VxeFormPropTypes.Rules>({
423
- tkey: [{required: true, type: 'string', message: '请输入翻译键值'}],
420
+ const formRules = reactive<VxeFormPropTypes.Rules>({
421
+ name: [{required: true, type: 'string', message: '请输入翻译键值'}],
424
422
  });
425
423
 
426
424
  let needInit = true;
@@ -453,26 +451,32 @@ watch(
453
451
  }
454
452
  );
455
453
 
454
+ const handleKeydown = (e: KeyboardEvent) => {
455
+ let {key, ctrlKey, altKey} = e;
456
+ if (key === 's' && ctrlKey) {
457
+ e.preventDefault();
458
+ e.stopPropagation();
459
+ saveOne();
460
+ }
461
+ if (key === 'ArrowRight' && (ctrlKey || altKey)) {
462
+ e.preventDefault();
463
+ e.stopPropagation();
464
+ nextOne();
465
+ }
466
+ if (key === 'ArrowLeft' && (ctrlKey || altKey)) {
467
+ e.preventDefault();
468
+ e.stopPropagation();
469
+ prevOne();
470
+ }
471
+ };
472
+
456
473
  onMounted(() => {
457
474
  getDataList();
458
- window.addEventListener('keydown', (e) => {
459
- let {key, ctrlKey, altKey} = e;
460
- if (key === 's' && ctrlKey) {
461
- e.preventDefault();
462
- e.stopPropagation();
463
- saveOne();
464
- }
465
- if (key === 'ArrowRight' && (ctrlKey || altKey)) {
466
- e.preventDefault();
467
- e.stopPropagation();
468
- nextOne();
469
- }
470
- if (key === 'ArrowLeft' && (ctrlKey || altKey)) {
471
- e.preventDefault();
472
- e.stopPropagation();
473
- prevOne();
474
- }
475
- });
475
+ window.addEventListener('keydown', handleKeydown);
476
+ });
477
+
478
+ onUnmounted(() => {
479
+ window.removeEventListener('keydown', handleKeydown);
476
480
  });
477
481
  </script>
478
482
  <style lang="scss">
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "yh-i18n",
3
- "version": "2.2.21",
3
+ "version": "2.2.22",
4
4
  "description": "对于国际化的封装",
5
5
  "main": "index.js",
6
6
  "scripts": {