n20-common-lib 2.22.45 → 2.22.47

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "n20-common-lib",
3
- "version": "2.22.45",
3
+ "version": "2.22.47",
4
4
  "private": false,
5
5
  "scripts": {
6
6
  "serve": "vue-cli-service serve",
@@ -15,19 +15,14 @@
15
15
  }"
16
16
  show-header-overflow
17
17
  show-overflow
18
- :row-config="{
19
- isHover: true,
20
- useKey: true,
21
- ...$attrs.rowConfig,
22
- ...$attrs['row-config']
23
- }"
18
+ :row-config="computedRowConfig"
24
19
  :column-config="{
25
20
  resizable: true,
26
21
  useKey: true,
27
22
  ...$attrs.columnConfig,
28
23
  ...$attrs['column-config']
29
24
  }"
30
- :scroll-y="scrollY"
25
+ :scroll-y="computedScrollY"
31
26
  :sort-config="{
32
27
  multiple: false,
33
28
  remote: true,
@@ -43,7 +38,7 @@
43
38
  iconMatch: 'n20-icon-xiala-moren'
44
39
  }"
45
40
  :merge-cells="mergeCells"
46
- v-bind="Object.assign({ size: size }, $attrs, sizeBind, $attrs.small)"
41
+ v-bind="computedTableAttrs"
47
42
  v-on="$listeners"
48
43
  @sort-change="(val) => customSortMethod(val)"
49
44
  @filter-change="filterChange"
@@ -144,7 +139,6 @@
144
139
  import empty from '../Empty'
145
140
  import tableSetSize from '../TableSetSize/index.vue'
146
141
  import { $lc } from '../../utils/i18n/index.js'
147
- import XEUtils from 'xe-utils'
148
142
 
149
143
  /** 将 Element 表格风格的 show-overflow-tooltip 转为 vxe-column 的 show-overflow */
150
144
  function hasOverflowTooltipKey(item) {
@@ -186,6 +180,13 @@ function mapColumnOverflowForVxe(item) {
186
180
  }
187
181
  return applyTooltipToShowOverflow(item)
188
182
  }
183
+ const DEFAULT_SCROLL_Y = { enabled: true, oSize: 20, gt: 30 }
184
+ const VXE_ROW_HEIGHT_MAP = {
185
+ default: 48,
186
+ medium: 44,
187
+ small: 40,
188
+ mini: 36
189
+ }
189
190
  const renderer = {
190
191
  name: 'renderer',
191
192
  props: {
@@ -211,9 +212,13 @@ export default {
211
212
  scrollY: {
212
213
  type: Object,
213
214
  default: () => {
214
- return { enabled: true, oSize: 20, gt: 30 }
215
+ return { ...DEFAULT_SCROLL_Y }
215
216
  }
216
217
  },
218
+ dynamicRowHeight: {
219
+ type: Boolean,
220
+ default: false
221
+ },
217
222
  data: {
218
223
  type: Array,
219
224
  default: undefined
@@ -284,6 +289,45 @@ export default {
284
289
  }
285
290
  },
286
291
  computed: {
292
+ tableBindSource() {
293
+ const attrs = { ...this.$attrs }
294
+ const small = attrs.small
295
+ delete attrs.rowConfig
296
+ delete attrs['row-config']
297
+ delete attrs.scrollY
298
+ delete attrs['scroll-y']
299
+ delete attrs.small
300
+ return Object.assign({ size: this.sizeC || this.size }, attrs, this.sizeBind, small)
301
+ },
302
+ computedTableAttrs() {
303
+ return this.tableBindSource
304
+ },
305
+ computedRowConfig() {
306
+ const rowConfig = {
307
+ isHover: true,
308
+ useKey: true,
309
+ ...this.$attrs.rowConfig,
310
+ ...this.$attrs['row-config']
311
+ }
312
+ if (!this.dynamicRowHeight && rowConfig.height === undefined) {
313
+ rowConfig.height = this.getVirtualRowHeight()
314
+ }
315
+ return rowConfig
316
+ },
317
+ computedScrollY() {
318
+ const scrollY = {
319
+ ...DEFAULT_SCROLL_Y,
320
+ ...(this.scrollY || {})
321
+ }
322
+ if (this.dynamicRowHeight) {
323
+ scrollY.enabled = false
324
+ return scrollY
325
+ }
326
+ if (scrollY.rHeight === undefined) {
327
+ scrollY.rHeight = this.getVirtualRowHeight()
328
+ }
329
+ return scrollY
330
+ },
287
331
  _columns() {
288
332
  const raw = this.isAutoWidth ? this.calcColumnWidth(this.columns) : this.columns
289
333
  return raw.map(mapColumnOverflowForVxe)
@@ -292,9 +336,11 @@ export default {
292
336
  watch: {
293
337
  columns() {
294
338
  this.colsKey = this.colsKey + 1
339
+ this.refreshTableLayout()
295
340
  },
296
341
  size(val) {
297
342
  this.sizeC = val
343
+ this.refreshTableLayout()
298
344
  },
299
345
  data() {
300
346
  // 翻页清除选中
@@ -307,6 +353,7 @@ export default {
307
353
  if (this.mergeCells && this.mergeCells.length > 0 && this.$refs.vxeTable) {
308
354
  this.$refs.vxeTable.setMergeCells(this.mergeCells)
309
355
  }
356
+ this.refreshTableLayout()
310
357
  })
311
358
  }
312
359
  },
@@ -317,9 +364,36 @@ export default {
317
364
  if (this.mergeCells && this.mergeCells.length > 0 && this.$refs.vxeTable) {
318
365
  this.$refs.vxeTable.setMergeCells(this.mergeCells)
319
366
  }
367
+ this.refreshTableLayout()
320
368
  })
321
369
  },
322
370
  methods: {
371
+ getVirtualRowHeight() {
372
+ const rowConfig = {
373
+ ...this.$attrs.rowConfig,
374
+ ...this.$attrs['row-config']
375
+ }
376
+ if (rowConfig.height !== undefined) {
377
+ return rowConfig.height
378
+ }
379
+ if (this.scrollY && this.scrollY.rHeight !== undefined) {
380
+ return this.scrollY.rHeight
381
+ }
382
+ const tableSize = this.tableBindSource.size || this.sizeC || 'default'
383
+ return VXE_ROW_HEIGHT_MAP[tableSize] || VXE_ROW_HEIGHT_MAP.default
384
+ },
385
+ refreshTableLayout() {
386
+ this.$nextTick(() => {
387
+ const xTable = this.$refs.vxeTable
388
+ if (!xTable) return
389
+ const recalculate = typeof xTable.recalculate === 'function' ? xTable.recalculate(true) : Promise.resolve()
390
+ Promise.resolve(recalculate).then(() => {
391
+ if (xTable && typeof xTable.refreshScroll === 'function') {
392
+ xTable.refreshScroll()
393
+ }
394
+ })
395
+ })
396
+ },
323
397
  // 全选/反选
324
398
  toggleAllSelection() {
325
399
  if (!this.$refs.vxeTable) return
@@ -524,9 +598,11 @@ export default {
524
598
  sizeUp(size) {
525
599
  this.sizeC = size
526
600
  this.$emit('update:size', size)
601
+ this.refreshTableLayout()
527
602
  },
528
603
  sizeSet(el) {
529
604
  this.sizeBind = el
605
+ this.refreshTableLayout()
530
606
  },
531
607
  // 计算列宽
532
608
  calcColumnWidth(columns) {
@@ -28,142 +28,205 @@ IWSASetTimeOut(6000)
28
28
  // console.warn(version)
29
29
  // })
30
30
 
31
+ /**
32
+ * 从 sessionStorage 安全获取用户 DN
33
+ * @returns {string} 用户 DN,获取失败时返回空字符串
34
+ */
31
35
  function getDN() {
32
- let dn = ''
33
- let userInfo = JSON.parse(sessionStorage.getItem('userInfo'))
34
- if (userInfo && userInfo.dn) {
35
- dn = userInfo.dn
36
+ try {
37
+ const userInfo = JSON.parse(sessionStorage.getItem('userInfo'))
38
+ return userInfo && userInfo.dn ? userInfo.dn : ''
39
+ } catch (e) {
40
+ return ''
41
+ }
42
+ }
43
+
44
+ /**
45
+ * 获取用户编号
46
+ * @param {string} [uno] - 可选的用户编号
47
+ * @returns {string} 用户编号
48
+ */
49
+ function getUserNo(uno) {
50
+ return uno || sessionStorage.getItem('userNo')
51
+ }
52
+
53
+ /**
54
+ * 根据算法标识获取 RSA 密钥长度
55
+ * @param {string} alg - 算法标识
56
+ * @returns {string} 密钥长度
57
+ */
58
+ function getRSAKeySize(alg) {
59
+ if (alg === 'RSA_1024') return '1024'
60
+ if (alg === 'RSA_2048') return '2048'
61
+ return '1024'
62
+ }
63
+
64
+ /**
65
+ * 构建证书请求 DTO
66
+ * @param {Object} certData - 原始证书数据
67
+ * @param {Array} p10Result - P10 生成结果 [code, container, publicKey]
68
+ * @returns {Object} 证书请求 DTO
69
+ */
70
+ function buildCertDTO(certData, p10Result) {
71
+ return {
72
+ ...certData,
73
+ publicKey: p10Result[2],
74
+ tmpPubKey: p10Result[1] || ''
75
+ }
76
+ }
77
+
78
+ /**
79
+ * 处理证书导入结果提示
80
+ * @param {string} certCode - 证书导入结果码
81
+ * @returns {boolean} 导入是否成功
82
+ */
83
+ function handleCertImportResult(certCode) {
84
+ if (certCode === '0') {
85
+ Message.success('证书导入成功')
86
+ return true
87
+ } else {
88
+ Message.error('导入证书失败,错误码:' + certCode)
89
+ return false
36
90
  }
37
- return dn
38
91
  }
39
92
 
40
- function getDnCertBase64(dn, res) {
41
- axios
42
- .post(`/bems/prod_1.0/dssc/sign/getDnCertBase64`, {
43
- userDn: dn,
44
- p10: res[2]
93
+ /**
94
+ * 同步证书到期日到服务端
95
+ * @param {string} dn - 用户DN
96
+ * @param {string} dnExpiryDate - 证书到期日(yyyy-MM-dd)
97
+ */
98
+ async function syncDnValidDate(dn, dnExpiryDate) {
99
+ if (!dn || !dnExpiryDate) return
100
+ try {
101
+ await axios.post('/bems/prod_1.0/user/wfMasterUser/updateDnValidDate', {
102
+ dn,
103
+ dnValidDate: dnExpiryDate
45
104
  })
46
- .then(({ data }) => {
47
- if (data) {
48
- let list = JSON.parse(data)
49
- if (list[0]?.errNum === '0') {
50
- let code = IWSA_rsa_csp_importSignP7Cert(res[1], list[0]?.cert)
51
- if (code === '0') {
52
- return Message.success('证书导入成功')
53
- }
54
- }
55
- }
105
+ } catch (error) {
106
+ console.error('同步证书到期日失败:', error)
107
+ }
108
+ }
109
+
110
+ /**
111
+ * RSA 算法生成容器 P10 并导入签名证书
112
+ * @param {Object} certData - 证书数据
113
+ */
114
+ async function generateRSACert(certData, dn) {
115
+ // 设置提供者 Microsoft Base Cryptographic Provider v1.0
116
+ IWSA_rsa_csp_setProvider('Microsoft Base Cryptographic Provider v1.0')
117
+ // 设置同步模式
118
+ IWSASetAsyncMode(false)
119
+
120
+ const alg = getRSAKeySize(certData.alg)
121
+ /**
122
+ * (方法 RSA)生成 P10 包,新容器
123
+ * 参数一:签名密钥或加密密钥标识, "true"/"false"
124
+ * 参数二:密钥长度 512,1024,2048,4096
125
+ * 参数三:主题 DN,空值 DN 请赋值""空串
126
+ * 参数四:摘要算法 OID,使用默认值请赋值""空串
127
+ * 参数五:公钥算法 OID,使用默认值请赋值""空串
128
+ * 参数六:签名算法 OID,使用默认值请赋值""空串
129
+ * 参数七:私钥是否可导出, "true"/"false"
130
+ * 参数八:是否启用增强密钥保护, "true"/"false"
131
+ */
132
+ const res = IWSA_rsa_csp_genContainerP10('true', alg, '', '', '', '', 'false', 'false')
133
+ if (res[0] !== '0') {
134
+ Message.error('产生 P10失败,错误码:' + res[0])
135
+ return
136
+ }
137
+
138
+ const dto = buildCertDTO(certData, res)
139
+ const { code, data } = await axios.post('/bems/prod_1.0/dssc/sign/getRadsCert', dto)
140
+ if (code !== 200) return
141
+
142
+ /**
143
+ * (方法 RSA)导入签名证书 X509
144
+ * 参数一:容器名,支持"":使用产生 P10 时的容器
145
+ * 参数二:X509 证书,Base64 编码
146
+ */
147
+ const certCode = IWSA_rsa_csp_importSignX509Cert(res[1], data.signCer)
148
+ if (handleCertImportResult(certCode)) {
149
+ // 证书导入成功后同步到期日
150
+ await syncDnValidDate(dn, data.dnExpiryDate)
151
+ }
152
+ }
153
+
154
+ /**
155
+ * SM2 国密算法生成容器 P10 并导入签名证书
156
+ * @param {Object} certData - 证书数据
157
+ */
158
+ async function generateSM2Cert(certData, dn) {
159
+ // 设置同步模式
160
+ IWSASetAsyncMode(false)
161
+
162
+ const providerList = IWSA_sm2_skf_getProviderList()
163
+ if (providerList.length === 0) {
164
+ Message.error('请检查ukey是否正常')
165
+ return
166
+ }
167
+ const deviceList = IWSA_sm2_skf_getDeviceList(providerList[0].Provider)
168
+ if (deviceList.length === 0) {
169
+ Message.error('未获取到SM2设备')
170
+ return
171
+ }
172
+ const applicationList = IWSA_sm2_skf_getApplicationList(providerList[0].Provider, deviceList[0].Device)
173
+ if (applicationList.length === 0) {
174
+ Message.error('未获取到SM2应用')
175
+ return
176
+ }
177
+ IWSA_sm2_skf_setDevice(providerList[0].Provider, deviceList[0].Device, applicationList[0].Application)
178
+
179
+ let pin
180
+ try {
181
+ const result = await MessageBox.prompt('请输入PIN码', '提示', {
182
+ confirmButtonText: '确定',
183
+ cancelButtonText: '取消',
184
+ closeOnClickModal: false,
185
+ inputType: 'password'
56
186
  })
187
+ pin = result.value
188
+ } catch (e) {
189
+ // 用户取消输入
190
+ return
191
+ }
192
+
193
+ /**
194
+ * (方法 SM2)生成 P10 包,新容器
195
+ * 参数一:主题 DN,空值 DN 请赋值""空串
196
+ */
197
+ const res = IWSA_sm2_skf_genContainerP10(pin, '', '', 'true')
198
+ if (res[0] !== '0') {
199
+ Message.error('产生 P10失败,错误码:' + res[0])
200
+ return
201
+ }
202
+
203
+ const dto = buildCertDTO(certData, res)
204
+ const { code, data } = await axios.post('/bems/prod_1.0/dssc/sign/getRadsCert', dto)
205
+ if (code !== 200) return
206
+
207
+ const certCode = IWSA_sm2_skf_importSignX509Cert(pin, res[1], data.signCer)
208
+ if (handleCertImportResult(certCode)) {
209
+ // 证书导入成功后同步到期日
210
+ await syncDnValidDate(dn, data.dnExpiryDate)
211
+ }
57
212
  }
58
213
 
59
- function getUserCert(uno) {
60
- uno = uno || sessionStorage.getItem('userNo')
61
- axios.post(`/bems/prod_1.0/dssc/sign/updateCert_direct/${uno}`).then(async ({ code, data }) => {
62
- if (code === 200) {
63
- // 非国密
64
- if (data.alg !== 'SM2') {
65
- // 设置提供者 Microsoft Base Cryptographic Provider v1.0
66
- IWSA_rsa_csp_setProvider('Microsoft Base Cryptographic Provider v1.0')
67
- // 设置同步模式
68
- IWSASetAsyncMode(false)
69
- let alg = data.alg === 'RSA_1024' ? '1024' : data.alg === 'RSA_2048' ? '2048' : '1024'
70
- /**
71
- * (方法 RSA)生成 P10 包,新容器
72
- * 参数一:签名密钥或加密密钥标识,”true”/”false”
73
- * 参数二:密钥长度 512,1024, 2048,4096
74
- * 参数三:主题 DN,空值 DN 请赋值””空串
75
- * 参数四:摘要算法 OID,使用默认值请赋值””空串
76
- * 参数五:公钥算法 OID,,使用默认值请赋值””空串
77
- * 参数六:签名算法 OID,,使用默认值请赋值””空串
78
- * 参数七:私钥是否可导出,”true”/”false”
79
- * 参数八:是否启用增强密钥保护,”true”/”false”
80
- */
81
- const res = IWSA_rsa_csp_genContainerP10('true', alg, '', '', '', '', 'false', 'false')
82
- if (res[0] === '0') {
83
- let dto = {
84
- ...data,
85
- publicKey: res[2],
86
- tmpPubKey: res[1] || ''
87
- }
88
- axios.post(`/bems/prod_1.0/dssc/sign/getRadsCert`, dto).then(({ code, data }) => {
89
- if (code === 200) {
90
- /**
91
- * (方法 RSA)导入签名证书 X509
92
- * 参数一:容器名,支持””:使用产生 P10 时的容器
93
- * 参数二:X509 证书,Base64 编码
94
- */
214
+ /**
215
+ * 海港版本获取并导入用户证书
216
+ * @param {string} uno - 用户编号
217
+ */
218
+ async function getUserCert(uno) {
219
+ const userNo = getUserNo(uno)
220
+ const { code, data } = await axios.post(`/bems/prod_1.0/dssc/sign/updateCert_direct/${userNo}`)
221
+ if (code !== 200) return
95
222
 
96
- const certData = IWSA_rsa_csp_importSignX509Cert(res[1], data.signCer)
97
- if (certData[0] === '0') {
98
- Message.success('证书导入成功')
99
- } else {
100
- Message.error('导入证书失败,错误码::' + certData[0])
101
- }
102
- }
103
- })
104
- } else {
105
- Message.error('产生 P10失败,错误码::' + data[0])
106
- }
107
- // 国密
108
- } else {
109
- /**
110
- * (方法 SM2)生成 P10 包,新容器
111
- * 参数y一:主题 DN,空值 DN 请赋值””空串
112
- */
113
- // 设置同步模式
114
- IWSASetAsyncMode(false)
115
- const roviderList = IWSA_sm2_skf_getProviderList()
116
- console.log(roviderList)
117
- if (roviderList.length === 0) {
118
- Message.error('请检查ukey是否正常')
119
- return
120
- }
121
- const providerList = IWSA_sm2_skf_getDeviceList(roviderList[0].Provider)
122
- if (providerList.length === 0) {
123
- Message.error('未获取到SM2设备')
124
- return
125
- }
126
- const applicationList = IWSA_sm2_skf_getApplicationList(roviderList[0].Provider, providerList[0].Device)
127
- if (applicationList.length === 0) {
128
- Message.error('未获取到SM2应用')
129
- return
130
- }
131
- IWSA_sm2_skf_setDevice(roviderList[0].Provider, providerList[0].Device, applicationList[0].Application)
132
- await MessageBox.prompt('请输入PIN码', '提示', {
133
- confirmButtonText: '确定',
134
- cancelButtonText: '取消',
135
- closeOnClickModal: false,
136
- inputType: 'password'
137
- }).then(({ value }) => {
138
- const res = IWSA_sm2_skf_genContainerP10(value, '', '', 'true')
139
- if (res[0] === '0') {
140
- let dto = {
141
- ...data,
142
- publicKey: res[2],
143
- tmpPubKey: res[1] || ''
144
- }
145
- axios.post(`/bems/prod_1.0/dssc/sign/getRadsCert`, dto).then(({ code, data }) => {
146
- if (code === 200) {
147
- /**
148
- * (方法 RSA)导入签名证书 X509
149
- * 参数一:容器名,支持””:使用产生 P10 时的容器
150
- * 参数二:X509 证书,Base64 编码
151
- */
152
- const certData = IWSA_sm2_skf_importSignX509Cert(value, res[1], data.signCer)
153
- if (certData[0] === '0') {
154
- Message.success('证书导入成功')
155
- } else {
156
- Message.error('导入证书失败,错误码::' + certData[0])
157
- }
158
- }
159
- })
160
- } else {
161
- Message.error('产生 P10失败,错误码::' + data[0])
162
- }
163
- })
164
- }
165
- }
166
- })
223
+ const dn = getDN()
224
+ // 非国密走 RSA,国密走 SM2
225
+ if (data.alg !== 'SM2') {
226
+ await generateRSACert(data, dn)
227
+ } else {
228
+ await generateSM2Cert(data, dn)
229
+ }
167
230
  }
168
231
 
169
232
  /**
@@ -234,26 +297,25 @@ export function updateCert(cspName, onSuccess, dnInfo) {
234
297
  Message.error('容器生成失败,请联系管理员,错误码为' + res[0])
235
298
  }
236
299
  }
237
- function GetDateNotAfter(res, dn) {
238
- if (res[0] === '0') {
239
- getDnCertBase64(dn, res)
240
- }
241
- }
242
-
243
300
  /**
244
301
  * 海港版本证书自动更新
245
- * @param {*} cspName
246
- * @returns
302
+ * @param {string} uno - 用户编号
303
+ * @returns {Promise<void>}
247
304
  */
248
305
  export function updateCertHG(uno) {
249
- getUserCert(uno)
306
+ return getUserCert(uno).catch((error) => {
307
+ console.error('海港证书更新失败:', error)
308
+ })
250
309
  }
251
310
 
311
+ /**
312
+ * 比较 DN 是否匹配(单向包含匹配)
313
+ * @param {string} dn1 - 证书 DN
314
+ * @param {string} dn2 - 目标 DN
315
+ * @returns {boolean}
316
+ */
252
317
  function compareDN(dn1, dn2) {
253
- let dn1Arr = dn1.split(',').map((c) => c.trim())
254
- let dn2Arr = dn2.split(',').map((c) => c.trim())
255
- if (dn1Arr.every((dnAttr) => dn2Arr.includes(dnAttr))) {
256
- return true
257
- }
258
- return false
318
+ const dn1Arr = dn1.split(',').map((c) => c.trim())
319
+ const dn2Arr = dn2.split(',').map((c) => c.trim())
320
+ return dn1Arr.every((dnAttr) => dn2Arr.includes(dnAttr))
259
321
  }
@@ -95,7 +95,7 @@ export function getCert(dn) {
95
95
  let signType = window.sessionStorage.getItem('signType')
96
96
  console.log('signType', signType)
97
97
  return new Promise((resolve, reject) => {
98
- if (signType === 'inetSign' /* 信安CA */) {
98
+ if (signType === 'inetSign' || signType === 'signV3' /* 信安CA */) {
99
99
  // 是否使用信安3.0版本sdk (默认使用2.0版本)
100
100
  if (window.NetSignVersion === 'signV3') {
101
101
  importG('inetSign', () => import(/*webpackChunkName: "inetSign"*/ './signV3/sign.js')).then(