n20-common-lib 2.9.13 → 2.9.14

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 (130) hide show
  1. package/nstc-g6/components/NstcCharts/NstcCharts.vue +16 -8
  2. package/package.json +8 -5
  3. package/src/assets/css/approve-card.scss +1 -1
  4. package/src/assets/css/date-quarter.scss +8 -0
  5. package/src/assets/css/expandable-pane.scss +7 -0
  6. package/src/assets/css/file-upload-table.scss +2 -3
  7. package/src/assets/css/font-icon.scss +3 -1
  8. package/src/assets/css/message.scss +6 -6
  9. package/src/assets/css/normalize.scss +4 -1
  10. package/src/assets/css/table.scss +16 -11
  11. package/src/assets/iconFont/SIMSUN.ttf +0 -0
  12. package/src/assets/iconFont/font.css +4 -0
  13. package/src/components/AIButton/index.vue +101 -0
  14. package/src/components/AdvancedFilter/formItemRender.vue +7 -4
  15. package/src/components/AdvancedFilter/index.vue +6 -7
  16. package/src/components/Anchor/index.vue +1 -0
  17. package/src/components/ApprovalButtons/index.vue +404 -82
  18. package/src/components/ApprovalButtons/indexApp.vue +1102 -0
  19. package/src/components/ApprovalButtons/selectSpr.vue +128 -0
  20. package/src/components/ApprovalButtons/setCarboncopyProp.vue +1 -1
  21. package/src/components/ApprovalButtons/setRejectToProp.vue +45 -5
  22. package/src/components/ApprovalButtons/showAppOpi.vue +265 -8
  23. package/src/components/ApprovalButtons/showOtherAttrNew.vue +161 -0
  24. package/src/components/ApprovalCard/index.vue +190 -44
  25. package/src/components/ApprovalCard/indexApp.vue +592 -0
  26. package/src/components/ApprovalRecord/approvalImgPro/child.vue +1 -1
  27. package/src/components/ApprovalRecord/approvalImgPro/index.vue +42 -5
  28. package/src/components/ApprovalRecord/index.vue +23 -6
  29. package/src/components/ApprovalRecord/indexApp.vue +79 -0
  30. package/src/components/AttachmentPass/index.vue +286 -0
  31. package/src/components/Button/button-group.vue +3 -1
  32. package/src/components/CascaderArea/index.vue +5 -6
  33. package/src/components/DatePicker/por.vue +31 -1
  34. package/src/components/DateSelect/quarterDatePicker.vue +23 -1
  35. package/src/components/Descriptions/index.vue +7 -3
  36. package/src/components/Dialog/index.vue +4 -0
  37. package/src/components/Diff/index.vue +4 -2
  38. package/src/components/DynamicField/DynamicField.vue +29 -6
  39. package/src/components/DynamicField/DynamicFieldMixin.js +13 -5
  40. package/src/components/DynamicField/DynamicFieldOptions.vue +135 -62
  41. package/src/components/DynamicField/DynamicTable.vue +11 -1
  42. package/src/components/DynamicField/contentPop.vue +110 -0
  43. package/src/components/DynamicField/tableList.vue +5 -1
  44. package/src/components/DynamicField/tableView.vue +143 -0
  45. package/src/components/ECharts/index.vue +15 -9
  46. package/src/components/Expandable/main.vue +17 -2
  47. package/src/components/FileImport/index.vue +4 -5
  48. package/src/components/FileUploadTable/FileUploadTableV3.vue +937 -0
  49. package/src/components/FileUploadTable/aiCheckDialog.vue +139 -0
  50. package/src/components/FileUploadTable/index.vue +251 -33
  51. package/src/components/FileUploadTable/jytg.svg +6 -0
  52. package/src/components/FileUploadTable/wsc.svg +3 -0
  53. package/src/components/FileUploadTable/ysc.svg +3 -0
  54. package/src/components/HandlingAdvice/index.vue +191 -0
  55. package/src/components/InputAccount/index.vue +105 -0
  56. package/src/components/InputNumber/index.vue +16 -4
  57. package/src/components/InputNumber/numberRange.vue +14 -0
  58. package/src/components/InputSearch/index.vue +8 -0
  59. package/src/components/Layout/HeaderWrap/changePwd.vue +50 -23
  60. package/src/components/Layout/HeaderWrap/index.vue +2 -2
  61. package/src/components/Layout/HeaderWrap/indexN.vue +296 -119
  62. package/src/components/Layout/SubContent/index.vue +45 -14
  63. package/src/components/Layout/indexN.vue +26 -5
  64. package/src/components/LoginTemporary/form.vue +126 -34
  65. package/src/components/LoginTemporary/index.vue +14 -3
  66. package/src/components/LoginTemporary/indexN.vue +35 -13
  67. package/src/components/Preview/index.vue +199 -0
  68. package/src/components/SelectDatePickerPro/customDatePicker.vue +7 -0
  69. package/src/components/SelectDatePickerPro/halfYearPicker.vue +165 -0
  70. package/src/components/SelectDatePickerPro/index.vue +44 -4
  71. package/src/components/SelectDatePickerPro/quarterDatePicker.vue +32 -10
  72. package/src/components/SelectTree/index.vue +10 -4
  73. package/src/components/SelectTree/pro.vue +3 -0
  74. package/src/components/ShowColumn/index copy 2.vue +545 -0
  75. package/src/components/ShowColumn/index copy.vue +566 -0
  76. package/src/components/ShowColumn/index.vue +11 -7
  77. package/src/components/Statis/statisItem.vue +8 -7
  78. package/src/components/Table/filters.js +13 -0
  79. package/src/components/Table/index.vue +4 -4
  80. package/src/components/TablePro/filterContent.vue +18 -8
  81. package/src/components/TablePro/index.js +41 -1
  82. package/src/components/TablePro/index.vue +117 -6
  83. package/src/components/TableProOperateColumn/OperateBtns.vue +11 -53
  84. package/src/components/TableProOperateColumn/OperateBtns_copy.vue +141 -0
  85. package/src/components/TableProOperateColumn/childrenOperateBtn.vue +108 -0
  86. package/src/components/TableProOperateColumn/index.vue +3 -6
  87. package/src/components/TableSetSize/index.vue +1 -1
  88. package/src/components/Tree/index.vue +21 -5
  89. package/src/components/Upload/index.vue +25 -10
  90. package/src/components/Upload/uploadMsg.vue +30 -25
  91. package/src/components/operatingStatus/index.vue +3 -4
  92. package/src/directives/VTitle/index.js +15 -5
  93. package/src/directives/watermark/index.js +140 -56
  94. package/src/i18n.json +146 -18
  95. package/src/index.js +31 -3
  96. package/src/plugins/Sign/CaMap.js +47 -8
  97. package/src/plugins/Sign/Itrus/index.js +1 -1
  98. package/src/plugins/Sign/Itrus/sign_3720.js +2 -1
  99. package/src/plugins/Sign/NetSM3/index.js +20 -11
  100. package/src/plugins/Sign/NetV3/index.js +163 -22
  101. package/src/plugins/Sign/SkfSign/index.js +55 -52
  102. package/src/plugins/Sign/bjca/index.js +229 -9
  103. package/src/plugins/Sign/hnca/index.js +5064 -0
  104. package/src/plugins/Sign/index.js +155 -103
  105. package/src/plugins/Sign/kySign/base64.js +160 -0
  106. package/src/plugins/Sign/kySign/hex.js +92 -0
  107. package/src/plugins/Sign/kySign/index.js +186 -0
  108. package/src/plugins/Sign/kySign/skf.js +937 -0
  109. package/src/plugins/Sign/kySign/test.html +463 -0
  110. package/src/plugins/Sign/sdca/index.js +73 -0
  111. package/src/plugins/Sign/sign.js +72 -52
  112. package/src/plugins/Sign/signV3/InfosecNetSignCNGAgent.min.js +1 -0
  113. package/src/plugins/Sign/signV3/sign.js +187 -0
  114. package/src/plugins/Sign/sign_back.js +172 -0
  115. package/src/utils/accountFormat.js +7 -0
  116. package/src/utils/asyncGetRelaNos.js +79 -46
  117. package/src/utils/axios.js +3 -5
  118. package/src/utils/i18n/index.js +1 -1
  119. package/src/utils/importGlobal.js +23 -12
  120. package/style/fonts/SIMSUN.5e0c362c.ttf +0 -0
  121. package/style/index.css +2 -2
  122. package/theme/blue.css +2 -2
  123. package/theme/cctcRed.css +2 -2
  124. package/theme/fonts/SIMSUN.5e0c362c.ttf +0 -0
  125. package/theme/green.css +2 -2
  126. package/theme/lightBlue.css +2 -2
  127. package/theme/orange.css +2 -2
  128. package/theme/purple.css +2 -2
  129. package/theme/red.css +2 -2
  130. package/theme/yellow.css +2 -2
@@ -0,0 +1,172 @@
1
+ // Attached方式签名
2
+ import { Message, Notification } from 'element-ui'
3
+ import { IWSAgent } from './InfosecNetSignCNGAgent.min.js'
4
+
5
+ const {
6
+ IWSASetTimeOut,
7
+ IWSAAttachedSign,
8
+ IWSAAttachedVerify,
9
+ IWSASendAvailable,
10
+ IWSAGetAvailable,
11
+ IWSAGetAllCertsListInfoByCertDN
12
+ } = new IWSAgent()
13
+ IWSASetTimeOut(6000)
14
+
15
+ function getDN() {
16
+ let dn
17
+ let userInfo = JSON.parse(sessionStorage.getItem('userInfo'))
18
+ if (userInfo && userInfo.dn) {
19
+ dn = userInfo.dn
20
+ }
21
+ return dn
22
+ }
23
+
24
+ /* 检测本地签名端口是否可用 */
25
+ export function availableSign(fn, url) {
26
+ let available = IWSAGetAvailable()
27
+ if (available) {
28
+ fn && fn(available)
29
+ } else {
30
+ IWSASendAvailable()
31
+ url || (url = '/portal/NetSignCNG-v2.1.152.2.exe')
32
+ let count = 0
33
+ checkAvailable(fn, url, count)
34
+ }
35
+ }
36
+
37
+ function checkAvailable(fn, url, count) {
38
+ let name = window.NetSignDownloadName || 'NetSignCNG签名助手'
39
+ let available = IWSAGetAvailable()
40
+ if (available) {
41
+ fn && fn(available)
42
+ } else if (count == 10) {
43
+ fn && fn(available)
44
+ Notification({
45
+ title: '提示',
46
+ dangerouslyUseHTMLString: true,
47
+ message: `<div>检测到您的电脑中没有安装签名助手,为了不影响使用请使用管理员权限<a class="color-primary" href="${url}" download>下载安装</a>${name}</div>`,
48
+ duration: 5000
49
+ })
50
+ } else {
51
+ count++
52
+ setTimeout(() => {
53
+ checkAvailable(fn, url, count)
54
+ }, 200)
55
+ }
56
+ }
57
+
58
+ /* 签名解签 */
59
+ export function verifySign(signedMsg) {
60
+ let plainText
61
+ IWSAAttachedVerify('1', signedMsg, (errorCode, PlainText, SigncertDN) => {
62
+ if (errorCode === 0 || errorCode === '0') {
63
+ plainText = PlainText
64
+ } else {
65
+ Message.error('签名解签失败!')
66
+ }
67
+ })
68
+ return plainText
69
+ }
70
+
71
+ /* 给对象或字符串签名 */
72
+ export async function getSign(plain, dn) {
73
+ let index = await getCertInfo(dn)
74
+ if (index === -1 || ['dnListEmpty', 'dnIsEmpty', 'Empty'].includes(index)) {
75
+ switch (index) {
76
+ case 'dnListEmpty':
77
+ Message.warning('没有匹配到证书!')
78
+ break
79
+ case 'dnIsEmpty':
80
+ Message.warning('DN参数为空!')
81
+ break
82
+ case 'Empty':
83
+ Message.warning('当前Ukey不匹配!')
84
+ break
85
+ default:
86
+ Message.warning('没有匹配到证书!')
87
+ }
88
+ return ''
89
+ }
90
+ let plainText = ''
91
+ if (typeof plain === 'object') {
92
+ plainText = JSON.stringify(plain)
93
+ } else {
94
+ plainText = plain
95
+ }
96
+ return await performSign(plainText, index)
97
+ }
98
+
99
+ /**
100
+ * 获取证书信息
101
+ * @param dn
102
+ * @returns {*|string|boolean}
103
+ */
104
+ export function getCertInfo(dn) {
105
+ if (dn === undefined) {
106
+ dn = getDN()
107
+ }
108
+ if (!dn) {
109
+ Message.error('签名参数DN错误!')
110
+ return false
111
+ }
112
+ return new Promise((resolve, reject) => {
113
+ let certInfo
114
+ IWSAGetAllCertsListInfoByCertDN('', 'Sign', parseCA(dn), 0, (dnList) => {
115
+ certInfo = verifyDn(dnList, dn)
116
+ resolve(certInfo)
117
+ })
118
+ })
119
+ }
120
+
121
+ /**
122
+ * 执行签名
123
+ * @param plain
124
+ * @param index
125
+ * @returns {*|string}
126
+ */
127
+ export async function performSign(plain, index) {
128
+ return new Promise((resolve, reject) => {
129
+ let answer
130
+ IWSAAttachedSign('1', plain, index, 'SHA1', (errorCode, signedData) => {
131
+ if (errorCode === 0 || errorCode === '0') {
132
+ resolve(signedData)
133
+ } else {
134
+ Message.error('签名失败!')
135
+ reject()
136
+ }
137
+ })
138
+ })
139
+ }
140
+
141
+ function parseCA(dn) {
142
+ const mark = /^CN=/
143
+ let cn = ''
144
+ if (dn == null) return cn
145
+
146
+ let booked = dn.split(',')
147
+ let dnC = booked.find((b) => mark.test(b))
148
+ dnC && (cn = dnC.replace(mark, ''))
149
+ return cn
150
+ }
151
+
152
+ function verifyDn(dnList, dn) {
153
+ if (dnList.length === 0) return 'dnListEmpty'
154
+ if (!dnList) return 'Empty'
155
+ if (!dn) return 'dnIsEmpty'
156
+
157
+ let userDnAttrsArr = dn.split(',').map((c) => c.trim())
158
+
159
+ let isIn = false
160
+ let index = 0
161
+ dnList.find((C, i) => {
162
+ let dnAttrsArr = C.certDN.split(',').map((c) => c.trim())
163
+ if (dnAttrsArr.every((dnAttr) => userDnAttrsArr.includes(dnAttr))) {
164
+ index = i
165
+ return (isIn = true)
166
+ }
167
+ })
168
+ if (!isIn) {
169
+ index = -1
170
+ }
171
+ return index
172
+ }
@@ -0,0 +1,7 @@
1
+ export const accountFormat = (account, options = {}) => {
2
+ if (account === undefined || account === null) {
3
+ return account
4
+ } else {
5
+ return String(account).replace(/(.{4})/g, '$1 ')
6
+ }
7
+ }
@@ -1,64 +1,97 @@
1
1
  import axios from './axios'
2
2
  import { getItem, setItem } from './storageEdit'
3
- // 按需/按模块 加载权限
3
+
4
+ /**
5
+ * @description: 按需/按模块 加载权限
6
+ * @param {string} appNo 模块标识
7
+ * @param {string|string[]} rns 权限编码
8
+ * @return {Promise<void>}
9
+ */
4
10
  async function asyncGetRelaNos(appNo, rns) {
11
+ // 获取当前用户的 userNo
5
12
  let uno = sessionStorage.getItem('userNo')
6
- // if (['system1', 'audit1'].includes(uno)) return
7
13
 
14
+ // 获取已经加载过的模块
8
15
  let RLFM = JSON.parse(sessionStorage.getItem('relanosLoadModiles')) || []
16
+
17
+ // 如果已经加载过当前模块,则直接返回
9
18
  if (RLFM.includes(appNo)) return
10
- RLFM.push(appNo)
11
- sessionStorage.setItem('relanosLoadModiles', JSON.stringify(RLFM))
12
19
 
13
- let { data } = await axios.post(
14
- '/bems/prod_1.0/user/api/userController/qryBusyInfoNo?r=' + Math.random(),
15
- {
16
- uno: uno,
17
- appNo: appNo,
18
- relaNos: rns
19
- },
20
- { loading: false, noMsg: true }
21
- )
20
+ try {
21
+ // 获取当前模块的权限列表
22
+ let { data } = await axios.post(
23
+ '/bems/prod_1.0/user/api/userController/qryBusyInfoNo?r=' + Math.random(),
24
+ {
25
+ uno: uno,
26
+ appNo: appNo,
27
+ relaNos: rns
28
+ },
29
+ { loading: false, noMsg: true }
30
+ )
22
31
 
23
- let ssRelaNos = getItem('relaNos') // JSON.parse(sessionStorage.getItem('relaNos'))
24
- let ssCltrelaNos = getItem('cltrelaNos') // JSON.parse(sessionStorage.getItem('cltrelaNos'))
32
+ // 如果没有加载过当前模块,则将当前模块加入到已经加载过的模块中
33
+ RLFM.push(appNo)
34
+ // 将已经加载过的模块写回到 sessionStorage 中
35
+ sessionStorage.setItem('relanosLoadModiles', JSON.stringify(RLFM))
25
36
 
26
- let rnObj = ssRelaNos.find((el) => el.appNo === appNo)
27
- if (!rnObj) {
28
- rnObj = { appNo: appNo || 'null', relaNos: [] }
29
- ssRelaNos.push(rnObj)
30
- }
31
- let oRelaNos = []
32
- data?.forEach((el) => {
33
- if (ssCltrelaNos[el.cltNo]) {
34
- ssCltrelaNos[el.cltNo].push(...el.relaNos)
35
- } else {
36
- ssCltrelaNos[el.cltNo] = el.relaNos
37
+ // 获取当前模块的权限列表
38
+ let ssRelaNos = getItem('relaNos')
39
+ let ssCltrelaNos = getItem('cltrelaNos')
40
+
41
+ // 如果当前模块的权限列表没有找到,则创建一个新的权限列表
42
+ let rnObj = ssRelaNos.find((el) => el.appNo === appNo)
43
+
44
+ if (!rnObj) {
45
+ rnObj = { appNo: appNo || 'null', relaNos: [] }
46
+ ssRelaNos.push(rnObj)
37
47
  }
38
- oRelaNos.push(...el.relaNos)
39
- })
40
- oRelaNos = [...new Set(oRelaNos)]
41
- rnObj.relaNos = oRelaNos
42
48
 
43
- let syncArr = window._keep_syncStorageAppNos
44
- let isSync = false
45
- if (syncArr) {
46
- if (syncArr.includes('ALL')) {
47
- isSync = true
48
- } else if (appNo && syncArr.includes(appNo)) {
49
- isSync = true
49
+ // 遍历 data,并将每个元素的 relaNos push oRelaNos 中
50
+ let oRelaNos = []
51
+ data?.forEach((el) => {
52
+ if (ssCltrelaNos[el.cltNo]) {
53
+ ssCltrelaNos[el.cltNo].push(...el.relaNos)
54
+ } else {
55
+ ssCltrelaNos[el.cltNo] = el.relaNos
56
+ }
57
+ oRelaNos.push(...el.relaNos)
58
+ })
59
+ // 将 oRelaNos 重新赋值成一个不重复的数组
60
+ oRelaNos = [...new Set(oRelaNos)]
61
+ // 将 oRelaNos 赋值给 rnObj.relaNos
62
+ rnObj.relaNos = oRelaNos
63
+
64
+ // 获取window._keep_syncStorageAppNos,并判断是否需要同步
65
+ let syncArr = window._keep_syncStorageAppNos
66
+ let isSync = false
67
+ if (syncArr) {
68
+ if (syncArr.includes('ALL')) {
69
+ isSync = true
70
+ } else if (appNo && syncArr.includes(appNo)) {
71
+ isSync = true
72
+ }
50
73
  }
51
- }
52
74
 
53
- // sessionStorage.setItem('relaNos', JSON.stringify(ssRelaNos))
54
- setItem('relaNos', ssRelaNos, isSync)
55
- // sessionStorage.setItem('cltrelaNos', JSON.stringify(ssCltrelaNos))
56
- setItem('cltrelaNos', ssCltrelaNos, isSync)
75
+ // 将 rnObj 重新赋值给 ssRelaNos ,并将 ssRelaNos 重新写回到 sessionStorage
76
+ // 将 ssCltrelaNos 重新赋值给 ssCltrelaNos ,并将 ssCltrelaNos 重新写回到 sessionStorage 中
77
+ // 将 oRelaNos 重新赋值给 ssRelaNosG ,并将 ssRelaNosG 重新写回到 sessionStorage
78
+ // 如果需要同步,则将 isSync 写回到 sessionStorage
79
+ setItem('relaNos', ssRelaNos, isSync)
80
+ setItem('cltrelaNos', ssCltrelaNos, isSync)
57
81
 
58
- let ssRelaNosG = getItem('relaNosGlobal')
59
- ssRelaNosG.push(...oRelaNos)
60
- setItem('relaNosGlobal', ssRelaNosG, isSync)
61
- isSync && sessionStorage.setItem('isSync', isSync)
82
+ let ssRelaNosG = getItem('relaNosGlobal')
83
+ ssRelaNosG.push(...oRelaNos)
84
+ setItem('relaNosGlobal', ssRelaNosG, isSync)
85
+ isSync && sessionStorage.setItem('isSync', isSync)
86
+ } catch (error) {
87
+ // 如果请求失败,从已加载列表中移除该模块
88
+ const index = RLFM.indexOf(appNo)
89
+ if (index > -1) {
90
+ RLFM.splice(index, 1)
91
+ sessionStorage.setItem('relanosLoadModiles', JSON.stringify(RLFM))
92
+ }
93
+ throw error
94
+ }
62
95
  }
63
96
 
64
97
  export default asyncGetRelaNos
@@ -93,20 +93,19 @@ axios.interceptors.request.use((opt) => {
93
93
  })
94
94
 
95
95
  function errorFn(status, msg, noMsg, isErr, res) {
96
- if (status === 401) {
96
+ if (status === 401 || msg === 'Request failed with status code 401') {
97
97
  noMsg || showMsg($lc('超时未操作,请重新登录!'))
98
98
  setTimeout(() => {
99
99
  if (navigator.userAgent.includes('NSTC-WebEntry')) {
100
100
  localStorage.clear()
101
101
  sessionStorage.clear()
102
- // window.top.webQuit()
103
102
  } else {
104
103
  auth.removeToken()
105
104
  }
106
105
  }, 1000)
107
- } else if (status === 400 ) {
106
+ } else if (status === 400) {
108
107
  noMsg || showMsg($lc('400,参数错误!'))
109
- } else if (status === 404 ) {
108
+ } else if (status === 404 || msg === 'Request failed with status code 404') {
110
109
  noMsg || showMsg($lc('404,网络连接失败!'))
111
110
  } else if (status === 500) {
112
111
  noMsg || showMsg($lc('500,服务器链接失败!'))
@@ -174,7 +173,6 @@ function request(opt) {
174
173
  res.data = new Blob([res.data], { type: type })
175
174
  }
176
175
  }
177
-
178
176
  res.data.name = filename
179
177
  }
180
178
  if (res.data.size === 0) {
@@ -10,7 +10,7 @@ import zhHk from './cn2hk.json' // 简体繁体映射
10
10
  // const langEm = { 中文: 'zh', 中文简体: 'zh-cn', 中文繁体: 'zh-hk', 英文: 'en', 德文: 'de', 法文: 'fr' }
11
11
 
12
12
  let pageLang = window.localStorage.getItem('pageLang') // 当前页面的语言
13
- let $i18n_map_root = undefined // 全局的国际化
13
+ let $i18n_map_root = {} // 全局的国际化
14
14
 
15
15
  export function $l(zh, map = {}, arg) {
16
16
  let val = ''
@@ -1,16 +1,27 @@
1
- window._g_import_g_ || (window._g_import_g_ = {})
1
+ // 全局模块缓存对象
2
+ const globalModuleCache = window._g_import_g_ || (window._g_import_g_ = {});
2
3
 
3
- function importG(name, ipt) {
4
- return new Promise((resolve, reject) => {
5
- if (window._g_import_g_[name]) {
6
- resolve(window._g_import_g_[name])
7
- } else {
8
- ipt().then((_module) => {
9
- window._g_import_g_[name] = _module
10
- resolve(_module)
11
- })
4
+ /**
5
+ * 异步导入模块并缓存
6
+ * @param {string} name - 模块名称
7
+ * @param {Function} importPromise - 返回 import promise 的函数
8
+ * @returns {Promise} 返回模块的 Promise
9
+ */
10
+ async function importG(name, importPromise) {
11
+ try {
12
+ // 如果模块已经被缓存,直接返回
13
+ if (globalModuleCache[name]) {
14
+ return globalModuleCache[name];
12
15
  }
13
- })
16
+
17
+ // 导入模块并缓存
18
+ const module = await importPromise();
19
+ globalModuleCache[name] = module;
20
+ return module;
21
+ } catch (error) {
22
+ console.error(`模块 ${name} 导入失败:`, error);
23
+ throw error;
24
+ }
14
25
  }
15
26
 
16
- export default importG
27
+ export default importG;
Binary file