syntec3-0-ui-components-test 1.0.0

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 (99) hide show
  1. package/README.md +5 -0
  2. package/dist/S3_0UC_main.csv +4 -0
  3. package/dist/S3_0UC_sub.csv +2 -0
  4. package/dist/globalVariableS3_0UC.json +1 -0
  5. package/dist/style.css +1 -0
  6. package/dist/syntec3-0-ui-components.es.js +19518 -0
  7. package/dist/syntec3-0-ui-components.es.js.map +1 -0
  8. package/dist/syntec3-0-ui-components.umd.js +23 -0
  9. package/dist/syntec3-0-ui-components.umd.js.map +1 -0
  10. package/dist/vite.svg +1 -0
  11. package/dist/web.config +17 -0
  12. package/package.json +137 -0
  13. package/src/App.vue +31 -0
  14. package/src/assets/fonts/genYoGothicTW-normal.js +7 -0
  15. package/src/assets/image/defaultImage.png +0 -0
  16. package/src/assets/vue.svg +1 -0
  17. package/src/components/Layout/modules/fullPageGlobal.vue +113 -0
  18. package/src/components/Layout/modules/viewFile/config.js +65 -0
  19. package/src/components/Layout/modules/viewFile/createView.vue +1000 -0
  20. package/src/components/Layout/modules/viewFile/filterCriteria.vue +816 -0
  21. package/src/components/Layout/modules/viewFile/viewList.vue +291 -0
  22. package/src/components/Layout/modules/viewFile/viewManageTool.js +271 -0
  23. package/src/components/Layout/modules/viewFile/viewRecord.vue +472 -0
  24. package/src/components/Layout/modules/viewFile/viewTabs.vue +542 -0
  25. package/src/components/Layout/tools/GlobalDialog.vue +115 -0
  26. package/src/components/Pagination.vue +139 -0
  27. package/src/components/columnConfigNext.vue +273 -0
  28. package/src/components/customFilter/customFilter.vue +492 -0
  29. package/src/components/customFilter/filterCriteria.vue +769 -0
  30. package/src/components/customTable/components/headerOperation/index.vue +136 -0
  31. package/src/components/customTable/components/headerTabs/index.vue +171 -0
  32. package/src/components/customTable/components/tableContent/index.vue +440 -0
  33. package/src/components/customTable/index.vue +305 -0
  34. package/src/components/dialog.vue +85 -0
  35. package/src/components/pageContent.vue +48 -0
  36. package/src/components/popover.vue +402 -0
  37. package/src/configFiles/apiFile/baseApiList.json +11 -0
  38. package/src/configFiles/apiFile/coreApiList.json +24 -0
  39. package/src/configFiles/apiFile/mesApiList.json +4 -0
  40. package/src/configFiles/apiFile/mmsApiList.json +3 -0
  41. package/src/configFiles/errorCode.json +291 -0
  42. package/src/configFiles/version.js +2 -0
  43. package/src/i18n/lang/en-us.json +2060 -0
  44. package/src/i18n/lang/errorCodeTranslate.mjs +847 -0
  45. package/src/i18n/lang/zh-cn.json +2062 -0
  46. package/src/i18n/lang/zh-tw.json +2059 -0
  47. package/src/index.js +115 -0
  48. package/src/main.js +51 -0
  49. package/src/plugins/excel.js +88 -0
  50. package/src/router/index.js +41 -0
  51. package/src/scriptFiles/apiConfig/baseApis.js +10 -0
  52. package/src/scriptFiles/apiConfig/mesApis.js +10 -0
  53. package/src/scriptFiles/apiConfig/mmsApis.js +10 -0
  54. package/src/scriptFiles/apiConfig/privateCloudCoreApis.js +13 -0
  55. package/src/scriptFiles/apiConfig/serviceRoute.js +23 -0
  56. package/src/scriptFiles/apis/baseApiFunction.js +63 -0
  57. package/src/scriptFiles/apis/mesApiFunction.js +15 -0
  58. package/src/scriptFiles/apis/mmsApiFunction.js +9 -0
  59. package/src/scriptFiles/apis/privateCloudCoreApiFunction.js +101 -0
  60. package/src/scriptFiles/backendApiFunction.js +11 -0
  61. package/src/scriptFiles/checkApiErrorMechanism.js +137 -0
  62. package/src/scriptFiles/common/objectDataProcessing.js +65 -0
  63. package/src/scss/base/commom.scss +1068 -0
  64. package/src/scss/base/dialog.scss +45 -0
  65. package/src/scss/base/index.scss +3 -0
  66. package/src/scss/base/table.scss +28 -0
  67. package/src/store/index.js +25 -0
  68. package/src/store/module/langStore.js +116 -0
  69. package/src/style.css +52 -0
  70. package/src/utils/excel.js +86 -0
  71. package/src/utils/formula.js +69 -0
  72. package/src/utils/https.js +13 -0
  73. package/src/utils/i18n.js +42 -0
  74. package/src/utils/shiftSelect.js +164 -0
  75. package/src/utils/summation.js +77 -0
  76. package/src/utils/tableWidth.js +29 -0
  77. package/src/utils/toolFun.js +93 -0
  78. package/src/views/productionWorkOrder/components/columnConfig.vue +242 -0
  79. package/src/views/productionWorkOrder/components/docCustomFieldForm.vue +739 -0
  80. package/src/views/productionWorkOrder/components/filePreview.vue +148 -0
  81. package/src/views/productionWorkOrder/components/querySearch.vue +363 -0
  82. package/src/views/productionWorkOrder/configFiles/excelImportErrorCode.json +94 -0
  83. package/src/views/productionWorkOrder/configFiles/pdfDefaultConfig.js +933 -0
  84. package/src/views/productionWorkOrder/configFiles/planMakingScript.js +600 -0
  85. package/src/views/productionWorkOrder/configFiles/productionRelatedScript.js +368 -0
  86. package/src/views/productionWorkOrder/configFiles/rulse.js +23 -0
  87. package/src/views/productionWorkOrder/configFiles/status.js +50 -0
  88. package/src/views/productionWorkOrder/index.vue +2174 -0
  89. package/src/views/productionWorkOrder/productionFlowLabel/component/addCirculationLabel.vue +394 -0
  90. package/src/views/productionWorkOrder/productionFlowLabel/component/circulationLabelTable.vue +124 -0
  91. package/src/views/productionWorkOrder/productionFlowLabel/component/materialPartFilePreview.vue +167 -0
  92. package/src/views/productionWorkOrder/productionFlowLabel/component/workOrderInformation.vue +28 -0
  93. package/src/views/productionWorkOrder/productionFlowLabel/index.vue +604 -0
  94. package/src/views/production_work_order/components/priorityTooltip.vue +53 -0
  95. package/src/views/production_work_order/index.vue +1307 -0
  96. package/src/views/review_record/components/materialInfo.vue +50 -0
  97. package/src/views/review_record/components/rootCause.vue +42 -0
  98. package/src/views/review_record/components/workDetail.vue +115 -0
  99. package/src/views/review_record/index.vue +884 -0
@@ -0,0 +1,45 @@
1
+ .el-overlay-dialog {
2
+ display: flex;
3
+ align-items: center;
4
+ justify-content: center;
5
+ }
6
+ .el-dialog {
7
+ padding: 0;
8
+ border-radius: 10px!important;
9
+ margin: 0 !important;
10
+ display: flex;
11
+ flex-direction: column;
12
+ max-height: calc(100vh - 5rem);
13
+ }
14
+ .el-dialog__header {
15
+ height: 3rem;
16
+ background-color: #4481b8 !important;
17
+ color: white !important;
18
+ padding: 0;
19
+ display: flex;
20
+ align-items: center;
21
+ justify-content: center;
22
+ border-radius: 10px 10px 0 0 !important;
23
+ font-size: 18px;
24
+ font-weight: 600;
25
+ flex-shrink: 0;
26
+ }
27
+ .el-dialog__title {
28
+ color: white !important;
29
+ }
30
+ .el-dialog__body {
31
+ padding: 1rem;
32
+ overflow: hidden;
33
+ flex: 1;
34
+ display: flex;
35
+ flex-direction: column;
36
+ height: 100%;
37
+ overflow-y: auto;
38
+ }
39
+ .el-dialog__footer {
40
+ padding: 0 0 20px 0;
41
+ flex-shrink: 0;
42
+ }
43
+ .el-dialog__close {
44
+ color: white !important;
45
+ }
@@ -0,0 +1,3 @@
1
+ @use './table.scss';
2
+ @use './commom.scss';
3
+ @use './dialog.scss';
@@ -0,0 +1,28 @@
1
+ .table-box{
2
+ border: 1px solid #ebeef5;
3
+ border-bottom: none;
4
+ }
5
+ .no-padding {
6
+ padding: 0!important;
7
+ }
8
+ .commonTable {
9
+ width: 100%;
10
+ border-spacing: 0;
11
+ }
12
+ .commonTable {
13
+ width: 100%;
14
+ margin: 1rem 0;
15
+ }
16
+ :deep(.tableHeader), :deep(.el-table th.el-table__cell.tableHeaderCell) {
17
+ background-color: #edf3f8;
18
+ color: #303133;
19
+ }
20
+
21
+
22
+ :deep(.sub-tableHeader),:deep(.el-table th.el-table__cell.sub-tableHeaderCell) {
23
+ background-color: #f1f2f4;
24
+ color: rgba(0, 0, 0, .6);
25
+ }
26
+ :deep( .el-table__expanded-cell) {
27
+ padding: 0;
28
+ }
@@ -0,0 +1,25 @@
1
+ // store/index.js
2
+ import { createStore } from 'vuex';
3
+ import langStore from './module/langStore';
4
+
5
+ const store = createStore({
6
+ state() {
7
+ return {
8
+ user: {
9
+ synFactoryEmpID: '',
10
+ },
11
+ };
12
+ },
13
+ getters: {
14
+ getEmpID(state) {
15
+ return state.synFactoryEmpID || localStorage.getItem('synFactoryEmpID');
16
+ },
17
+ },
18
+ mutations: {},
19
+ actions: {},
20
+ modules: {
21
+ langStore,
22
+ },
23
+ });
24
+
25
+ export default store;
@@ -0,0 +1,116 @@
1
+ import apiFunction from '@/scriptFiles/checkApiErrorMechanism';
2
+ import i18n from '@/utils/i18n';
3
+ import errorCodeTranslate from '@/i18n/lang/errorCodeTranslate.mjs';
4
+ import zhCnFiles from '@/i18n/lang/zh-cn.json';
5
+ import enUsFiles from '@/i18n/lang/en-us.json';
6
+ import zhTwFiles from '@/i18n/lang/zh-tw.json';
7
+
8
+ const moduleCode = 'S3_0UC_app';
9
+ export default {
10
+ state: {
11
+ langPackage: {},
12
+ },
13
+ getters: {
14
+ getLangPackage(state) {
15
+ return state.langPackage;
16
+ },
17
+ },
18
+ mutations: {
19
+ SET_LANG_PACKAGE(state, val) {
20
+ state.langPackage = val;
21
+ },
22
+ },
23
+ actions: {
24
+ async setLangInfo({ commit }) {
25
+ // 获取系统语系
26
+ let lang = localStorage.getItem('lang') || 'zh-cn';
27
+ // 是否为默认语系
28
+ const isDefaultLang = lang === 'zh-cn' || lang === 'zh-tw' || lang === 'en';
29
+ // 获取errorcode语系
30
+ const errorCodeLang = isDefaultLang ? lang : 'en';
31
+ // 获取本地系统语系
32
+ let localFiles = {};
33
+ if (lang === 'zh-cn') {
34
+ localFiles = { ...zhCnFiles };
35
+ }
36
+ if (lang === 'zh-tw') {
37
+ localFiles = { ...zhTwFiles };
38
+ }
39
+ if (lang === 'en' || !isDefaultLang) {
40
+ localFiles = { ...enUsFiles };
41
+ }
42
+ // 获取element语系
43
+ let elPackage = {};
44
+ const languageModules = import.meta.glob('/node_modules/element-plus/es/locale/lang/*.mjs');
45
+ const langModule = await languageModules[`/node_modules/element-plus/es/locale/lang/${lang}.mjs`]();
46
+ elPackage = langModule.default;
47
+ // 整合语系包
48
+ let langPackage = {
49
+ ...localFiles,
50
+ ...errorCodeTranslate[errorCodeLang],
51
+ el: elPackage,
52
+ };
53
+ let moduleLangFiles = {};
54
+ // 获取系统语系配置
55
+ if (localStorage.getItem('synFactoryEmpID')) {
56
+ if (isDefaultLang) {
57
+ // 请求默认语系
58
+ await apiFunction
59
+ .getModuleLanguage({
60
+ schemaCode: moduleCode,
61
+ languageType: lang,
62
+ })
63
+ .then((res) => {
64
+ if (res.data?.code === 0 && res.data.content.field?.length) {
65
+ res.data.content.field.forEach((element) => {
66
+ moduleLangFiles[element.fieldKey] = element.fieldValue;
67
+ });
68
+ }
69
+ })
70
+ .catch();
71
+ } else {
72
+ // 请求自定义语系
73
+ const promiseList = [];
74
+ // 获取语系配置
75
+ promiseList.push(
76
+ apiFunction.getModuleLanguage({
77
+ schemaCode: moduleCode,
78
+ languageType: lang,
79
+ }),
80
+ );
81
+ // 获取英语语系配置
82
+ promiseList.push(
83
+ apiFunction.getModuleLanguage({
84
+ schemaCode: moduleCode,
85
+ languageType: 'en',
86
+ }),
87
+ );
88
+ const customizeModuleLangFiles = {};
89
+ await Promise.all(promiseList)
90
+ .then((results) => {
91
+ results.forEach((res, index) => {
92
+ if (index === 0 && res.data?.code === 0 && res.data.content.field?.length) {
93
+ res.data.content.field.forEach((element) => {
94
+ customizeModuleLangFiles[element.fieldKey] = element.fieldValue;
95
+ });
96
+ }
97
+ if (index === 1 && res.data?.code === 0 && res.data.content.field?.length) {
98
+ res.data.content.field.forEach((element) => {
99
+ moduleLangFiles[element.fieldKey] =
100
+ customizeModuleLangFiles[element.fieldKey] || element.fieldValue;
101
+ });
102
+ }
103
+ });
104
+ })
105
+ .catch();
106
+ }
107
+ }
108
+ // 整合全部语系包
109
+ langPackage = { ...langPackage, ...moduleLangFiles };
110
+ // 设置语系
111
+ i18n.global.setLocaleMessage(lang, langPackage);
112
+ commit('SET_LANG_PACKAGE', langPackage);
113
+ i18n.global.locale = lang;
114
+ },
115
+ },
116
+ };
package/src/style.css ADDED
@@ -0,0 +1,52 @@
1
+ html {
2
+ font-size: 14px !important;
3
+ }
4
+ body {
5
+ margin: 0;
6
+ background-color: #ffffff;
7
+ }
8
+
9
+ #S3_0UC_app {
10
+ margin: 0;
11
+ width: 100%;
12
+ height: calc(100vh - 5rem);
13
+ position: relative;
14
+ }
15
+ .tableHeaderCell {
16
+ background-color: #EDF3F8 !important;
17
+ }
18
+
19
+ /**修改全局的滚动条*/
20
+ /**滚动条的宽度*/
21
+ ::-webkit-scrollbar {
22
+ width: 8px;
23
+ height: 1px;
24
+ }
25
+ ::-webkit-scrollbar-thumb {
26
+ background-color: #eaecf1;
27
+ border-radius: 3px;
28
+ }
29
+ /*表格*/
30
+ .el-table__body-wrapper::-webkit-scrollbar {
31
+ width: 10px;
32
+ height: 10px;
33
+ }
34
+ .el-table__body-wrapper::-webkit-scrollbar-thumb {
35
+ background-color: #a1a3a9;
36
+ border-radius: 3px;
37
+ }
38
+ /* 提示弹窗 */
39
+ .tip-confirm-dialog {
40
+ .el-message-box__content {
41
+ .el-message-box__container {
42
+ .el-message-box__message {
43
+ p {
44
+ word-break: break-all;
45
+ }
46
+ }
47
+ }
48
+ }
49
+ }
50
+ .tableHeaderCell {
51
+ background-color: #EDF3F8 !important;
52
+ }
@@ -0,0 +1,86 @@
1
+ import { utils } from 'xlsx';
2
+ import * as XLSX from 'xlsx';
3
+
4
+ const EXCEL = {
5
+ // 輸出excel表單
6
+ exportFromArray(option) {
7
+ const config = { name: 'demo', suffix: 'xml', ...option };
8
+ const {
9
+ title, body, name, suffix, wscols,
10
+ } = config;
11
+ const array = [...title, ...body];
12
+ const workBook = utils.book_new();
13
+ const workSheet = utils.aoa_to_sheet(array, { raw: true });
14
+ // 欄位寬度設定
15
+ workSheet['!cols'] = wscols;
16
+ const fileName = `${name}.${suffix}`;
17
+ utils.book_append_sheet(workBook, workSheet, name);
18
+ XLSX.writeFile(workBook, fileName, { bookType: suffix, type: 'buffer', writeFile: true });
19
+ },
20
+ // 輸出批量excel表單
21
+ async exportBatchFromArray(arr, fileName) {
22
+ const workBook = utils.book_new();
23
+ for (let i = 0; i < arr.length; i += 1) {
24
+ const config = { ...arr[i] };
25
+ const {
26
+ title, body, name, wscols, wsmerges, wsrow,
27
+ } = config;
28
+ const array = [...title, ...body];
29
+ const workSheet = utils.aoa_to_sheet(array, { raw: true });
30
+ // 欄位寬度設定
31
+ workSheet['!cols'] = wscols;
32
+ workSheet['!rows'] = wsrow;
33
+ workSheet['!merges'] = wsmerges;
34
+ // eslint-disable-next-line no-await-in-loop
35
+ await utils.book_append_sheet(workBook, workSheet, name);
36
+ }
37
+ // eslint-disable-next-line max-len
38
+ XLSX.writeFile(workBook, `${fileName}.xlsx`, { bookType: 'xlsx', type: 'buffer', writeFile: true });
39
+ },
40
+ // 解析表格數據,返回表格内容,目前不支援導入有單元格合併的表格,data.title為表头、data.body為表格數據
41
+ async importFromLocal(file) {
42
+ const workBook = await this.readerWorkBookFromLocal(file);
43
+ const workSheet = workBook.Sheets[workBook.SheetNames[0]];
44
+ const content = utils.sheet_to_json(workSheet, { defval: '' });
45
+ const contentSort = utils.sheet_to_json(workSheet, { header: 1 });
46
+ if (content.length === 0) {
47
+ return content;
48
+ }
49
+ const data = {};
50
+ data.title = Object.keys(content[0]);
51
+ data.body = content;
52
+ data.titleSort = [...contentSort[0]]; // 记录Excel中的顺序,不会因为数字而导致顺序错乱
53
+ return data;
54
+ },
55
+ // 解析表格數據(第二张Sheet表数据),返回表格内容,目前不支援導入有單元格合併的表格,data.title為表头、data.body為表格數據
56
+ async importInstructionsFromLocal(file) {
57
+ const workBook = await this.readerWorkBookFromLocal(file);
58
+ const workSheet = workBook.Sheets[workBook.SheetNames[1]];
59
+ const content = utils.sheet_to_json(workSheet, { defval: '' });
60
+ if (content.length === 0) {
61
+ return content;
62
+ }
63
+ const data = {};
64
+ data.title = Object.keys(content[0]);
65
+ data.body = content;
66
+ return data;
67
+ },
68
+ // 讀取文件的方法,file為文件Data
69
+ readerWorkBookFromLocal(file) {
70
+ const reader = new FileReader();
71
+ reader.readAsBinaryString(file);
72
+ return new Promise(((resolve, reject) => {
73
+ reader.onload = function (e) {
74
+ const fileData = e.target.result;
75
+ if (reader.readyState === 2) {
76
+ const workBook = XLSX.read(fileData, { type: 'binary' });
77
+ resolve(workBook);
78
+ } else {
79
+ reject(new Error('讀取文件失敗'));
80
+ }
81
+ };
82
+ }));
83
+ },
84
+ };
85
+
86
+ export default EXCEL;
@@ -0,0 +1,69 @@
1
+ import { create, all } from 'mathjs';
2
+
3
+ const SUM = (...numbers) => {
4
+ return numbers.reduce((acc, curr) => acc + curr, 0);
5
+ };
6
+
7
+ const MAX = (...numbers) => {
8
+ return Math.max(...numbers);
9
+ };
10
+
11
+ const MIN = (...numbers) => {
12
+ return Math.min(...numbers);
13
+ };
14
+
15
+ const AVG = (...numbers) => {
16
+ const sum = numbers.reduce((acc, curr) => acc + curr, 0);
17
+ return sum / numbers.length;
18
+ };
19
+
20
+ export const math = create(all);
21
+ math.import({
22
+ SUM,
23
+ MAX,
24
+ MIN,
25
+ AVG,
26
+ }, { override: true });
27
+
28
+ /**
29
+ * @param {number} decimalPlaces - 需要保留几位小数 (0-5)
30
+ * @param {number} value - 需要处理的数字
31
+ * @param {number} type - 0 四舍五入 1 去尾法 2 收尾法
32
+ * @param {number} isThousandSeparator - 是否显示千分位
33
+ * @returns {number} 处理后的数值
34
+ */
35
+ export const formatDecimal = (decimalPlaces, value, type) => {
36
+ if (typeof value !== 'number' || isNaN(value)) {
37
+ throw new Error('value必须是有效数字');
38
+ }
39
+ let processedValue = null;
40
+ const multiplier = Math.pow(10, decimalPlaces);
41
+ switch (type){
42
+ case 0:
43
+ processedValue = Math.round(value * multiplier) / multiplier;
44
+ break;
45
+ case 1:
46
+ processedValue = Math.floor(value * multiplier) / multiplier;
47
+ break;
48
+ case 2:
49
+ processedValue = Math.ceil(value * multiplier) / multiplier;
50
+ break;
51
+ default:
52
+ processedValue = value;
53
+ }
54
+ // 处理浮点数精度问题
55
+ processedValue = parseFloat(processedValue.toFixed(10));
56
+
57
+ // 转换为字符串并确保小数位数
58
+ let resultStr;
59
+
60
+ if (decimalPlaces > 0) {
61
+ // 使用toFixed确保小数位数
62
+ resultStr = processedValue.toFixed(decimalPlaces);
63
+ } else {
64
+ // 小数位数为0时,直接取整
65
+ resultStr = Math.round(processedValue).toString();
66
+ }
67
+ return resultStr;
68
+
69
+ };
@@ -0,0 +1,13 @@
1
+ export default{
2
+ baseURL() {
3
+ if (process.env.NODE_ENV === 'development') {
4
+ return 'http://18.18.1.9/PMS/API/V1/';
5
+ } else if (process.env.NODE_ENV === 'production') {
6
+ // 生产环境
7
+ const { protocol } = window.location;
8
+ const { hostname } = window.location;
9
+ const { port } = window.location;
10
+ return `${protocol}//${hostname}:${port}/PMS/API/V1/`;
11
+ }
12
+ },
13
+ };
@@ -0,0 +1,42 @@
1
+ import { createI18n } from 'vue-i18n';
2
+
3
+ // 导入 element-plus 的国际化文件
4
+ import elementZhCn from 'element-plus/es/locale/lang/zh-cn';
5
+ import elementEn from 'element-plus/es/locale/lang/en';
6
+ import elementZhTw from 'element-plus/es/locale/lang/zh-tw';
7
+
8
+ import zhCnFiles from '../i18n/lang/zh-cn.json';
9
+ import enUsFiles from '../i18n/lang/en-us.json';
10
+ import zhTwFiles from '../i18n/lang/zh-tw.json';
11
+ import errorCodeTranslate from '../i18n/lang/errorCodeTranslate.mjs';
12
+
13
+ const messages = {
14
+ 'zh-cn': {
15
+ ...zhCnFiles,
16
+ ...errorCodeTranslate['zh-cn'],
17
+ el: elementZhCn,
18
+ },
19
+ 'zh-tw': {
20
+ ...zhTwFiles,
21
+ ...errorCodeTranslate['zh-tw'],
22
+ el: elementZhTw,
23
+ },
24
+ 'en': {
25
+ ...enUsFiles,
26
+ ...errorCodeTranslate['en'],
27
+ el: elementEn,
28
+ },
29
+ };
30
+
31
+ const i18n = createI18n({
32
+ locale: localStorage.getItem('lang') || 'zh-cn',
33
+ fallbackLocale: 'zh-cn',
34
+ silentTranslationWarn: true,
35
+ missingWarn: false,
36
+ silentFallbackWarn: true,
37
+ fallbackWarn: false,
38
+ messages,
39
+ });
40
+
41
+ // 创建 i18n 实例并导出
42
+ export default i18n;
@@ -0,0 +1,164 @@
1
+ // directives/shiftSelect.js
2
+ export const vShiftSelect = {
3
+ mounted(el, binding) {
4
+ let lastSelectedIndex = -1;
5
+ let isShiftPressed = false;
6
+ let observer = null;
7
+ const arg = binding.arg;
8
+
9
+ // 监听表格 body 变化
10
+ const tableBody = el.querySelector('tbody');
11
+ if (tableBody) {
12
+ const observer = new MutationObserver((mutations) => {
13
+ mutations.forEach((mutation) => {
14
+ if (mutation.type === 'childList') {
15
+ // 行发生变化,可能是翻页
16
+ lastSelectedIndex = -1;
17
+ }
18
+ });
19
+ });
20
+
21
+ observer.observe(tableBody, {
22
+ childList: true,
23
+ subtree: true,
24
+ });
25
+ }
26
+
27
+ // 获取表格实例
28
+ const getTableInstance = () => {
29
+ if (binding.instance) {
30
+ // 从绑定值获取
31
+ return binding.instance.$refs[arg];
32
+ } else {
33
+ return null;
34
+ }
35
+ // 通过 DOM 查找最近的 Table 组件
36
+ // const tableEl = el.closest('.el-table');
37
+ // if (tableEl && tableEl.__vueParentComponent) {
38
+ // return tableEl.__vueParentComponent.proxy;
39
+ // }
40
+ // return null;
41
+ };
42
+
43
+ // 获取表格数据
44
+ const getTableData = () => {
45
+ const table = getTableInstance();
46
+ return table.data;
47
+ };
48
+
49
+ // 获取所有行 DOM 元素
50
+ const getTableRows = () => {
51
+ return Array.from(el.querySelectorAll('tbody .el-table__row'));
52
+ };
53
+
54
+ // 根据行元素获取数据索引
55
+ const getRowIndex = (rowElement) => {
56
+ const rows = getTableRows();
57
+ const rowIndex = rows.indexOf(rowElement);
58
+ // 如果找不到,尝试通过 data-index 属性
59
+ if (rowIndex === -1 && rowElement.dataset.index) {
60
+ return parseInt(rowElement.dataset.index);
61
+ }
62
+
63
+ return rowIndex;
64
+ };
65
+
66
+ // 处理复选框点击
67
+ const handleCheckboxClick = (e) => {
68
+ // 阻止事件冒泡,防止触发多次
69
+ e.stopPropagation();
70
+ el?.focus();
71
+ const checked = e.target.checked;
72
+ if( checked === undefined )return;
73
+ const checkbox = e.target.closest('.el-checkbox');
74
+
75
+ if (!checkbox) return;
76
+ const rowElement = checkbox.closest('.el-table__row');
77
+
78
+ if (!rowElement) return;
79
+ const table = getTableInstance();
80
+
81
+ if (!table) return;
82
+ const currentIndex = getRowIndex(rowElement);
83
+
84
+ if (isShiftPressed && lastSelectedIndex !== -1 && currentIndex !== -1) {
85
+ // Shift 多选
86
+ e.preventDefault();
87
+ const tableData = getTableData();
88
+ const start = Math.min(lastSelectedIndex, currentIndex);
89
+ const end = Math.max(lastSelectedIndex, currentIndex);
90
+ // 选择范围内的所有行
91
+ for (let i = start; i <= end; i++) {
92
+ const rowData = tableData[i];
93
+ if (rowData) {
94
+ // 使用 setTimeout 避免渲染冲突
95
+ setTimeout(() => {
96
+ table.toggleRowSelection(rowData, checked);
97
+ }, 0);
98
+ }
99
+ }
100
+ // 更新最后选择的索引
101
+ lastSelectedIndex = currentIndex;
102
+ } else {
103
+ lastSelectedIndex = currentIndex;
104
+ }
105
+ };
106
+
107
+ // 处理键盘事件
108
+ const handleKeyDown = (e) => {
109
+ if (e.key === 'Shift') {
110
+ isShiftPressed = true;
111
+ }
112
+ };
113
+
114
+ const handleKeyUp = (e) => {
115
+ if (e.key === 'Shift') {
116
+ isShiftPressed = false;
117
+ }
118
+ };
119
+
120
+ // 添加全局键盘事件监听
121
+ window.addEventListener('keydown', handleKeyDown, true);
122
+ window.addEventListener('keyup', handleKeyUp, true);
123
+
124
+ // 备用的事件委托方法
125
+ const handleTableClick = (e) => {
126
+ el.focus({ preventScroll: true });
127
+ const checkbox = e.target.closest('.el-checkbox');
128
+ const isSelectAllCheckbox = e.target.closest('.el-table__header .el-checkbox');
129
+ if( isSelectAllCheckbox ){
130
+ lastSelectedIndex = -1;
131
+ return;
132
+ }
133
+ if (checkbox) {
134
+ // 使用 setTimeout 确保在 Element Plus 的默认行为之前执行
135
+ setTimeout(() => handleCheckboxClick(e), 0);
136
+ }
137
+ };
138
+ // 使用捕获阶段
139
+ el.addEventListener('click', handleTableClick, true);
140
+ // 清理函数
141
+ el._shiftSelectCleanup = () => {
142
+ observer && observer.disconnect();
143
+ window.removeEventListener('keydown', handleKeyDown, true);
144
+ window.removeEventListener('keyup', handleKeyUp, true);
145
+ el.removeEventListener('click', handleTableClick, true);
146
+ };
147
+ // 设置焦点
148
+ setTimeout(() => {
149
+ if (document.activeElement !== el) {
150
+ el.setAttribute('tabindex', '-1');
151
+ el.focus();
152
+ // 移除焦点时的轮廓
153
+ el.style.outline = 'none';
154
+ }
155
+ }, 500);
156
+
157
+ },
158
+ unmounted(el) {
159
+ if (el._shiftSelectCleanup) {
160
+ el._shiftSelectCleanup();
161
+ delete el._shiftSelectCleanup;
162
+ }
163
+ },
164
+ };