n20-common-lib 2.22.56 → 2.22.57

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.56",
3
+ "version": "2.22.57",
4
4
  "private": false,
5
5
  "scripts": {
6
6
  "serve": "vue-cli-service serve",
@@ -17,6 +17,7 @@
17
17
 
18
18
  <script>
19
19
  import importGlobal from '../../utils/importGlobal.js'
20
+ import { $lc } from '../../utils/i18n/index.js'
20
21
  export default {
21
22
  name: 'FilterItem',
22
23
  components: {
@@ -8,6 +8,7 @@
8
8
 
9
9
  <script>
10
10
  import axios from '../../utils/axios'
11
+ import { $lc } from '../../utils/i18n/index.js'
11
12
  import flowImg from './approvalImgPro/index.vue'
12
13
  let hasQ004_1 = true
13
14
 
@@ -47,7 +48,7 @@ export default {
47
48
  )
48
49
  .then(({ data }) => {
49
50
  if (data) {
50
- let file = new File([data], $lc("流程图.svg"), {
51
+ let file = new File([data], $lc('流程图.svg'), {
51
52
  type: 'image/svg+xml'
52
53
  })
53
54
  this.blobUrl = URL.createObjectURL(file)
@@ -71,7 +71,9 @@
71
71
  prop="LOGIN_BG_TYPE"
72
72
  :rules="{ required: true, message: $lc('背景模式不能为空'), trigger: 'change' }"
73
73
  >
74
- <label class="m-r"><span class="m-r-ss" style="color: var(--color-danger)">*</span>{{ $lc('背景模式') }}</label>
74
+ <label class="m-r"
75
+ ><span class="m-r-ss" style="color: var(--color-danger)">*</span>{{ $lc('背景模式') }}</label
76
+ >
75
77
  <el-radio-group v-model="form.LOGIN_BG_TYPE">
76
78
  <el-radio label="dark">{{ $lc('深色背景') }}</el-radio>
77
79
  <el-radio label="light">{{ $lc('浅色背景') }}</el-radio>
@@ -179,7 +181,7 @@
179
181
  >
180
182
  <span slot="label"
181
183
  ><span>{{ '登录方式设置' | $lc }}</span
182
- ><span class="color-danger m-l-s f-s-s">({{ $lc('至少选择一种登录方式') | $lc }})</span></span
184
+ ><span class="color-danger m-l-s f-s-s">({{ $lc('至少选择一种登录方式') }})</span></span
183
185
  >
184
186
  <el-checkbox-group v-model="systemItem.LOGIN_MODE">
185
187
  <el-checkbox v-for="item in plainOptions" :key="item.value" :label="item.value">{{
@@ -239,56 +241,56 @@ export default {
239
241
  SYSTEM_LIST: [
240
242
  {
241
243
  NO: 'CSZHYW',
242
- NAME: $lc("财司综合业务系统"),
244
+ NAME: $lc('财司综合业务系统'),
243
245
  ICON: '',
244
246
  LOGIN_MODE: [],
245
247
  OPEN: true
246
248
  },
247
249
  {
248
250
  NO: 'CSYWGL',
249
- NAME: $lc("财司业务管理系统"),
251
+ NAME: $lc('财司业务管理系统'),
250
252
  ICON: '',
251
253
  LOGIN_MODE: [],
252
254
  OPEN: false
253
255
  },
254
256
  {
255
257
  NO: 'CSFZJC',
256
- NAME: $lc("财司辅助决策系统"),
258
+ NAME: $lc('财司辅助决策系统'),
257
259
  ICON: '',
258
260
  LOGIN_MODE: [],
259
261
  OPEN: false
260
262
  },
261
263
  {
262
264
  NO: 'CSWY',
263
- NAME: $lc("财司网银系统"),
265
+ NAME: $lc('财司网银系统'),
264
266
  ICON: '',
265
267
  LOGIN_MODE: [],
266
268
  OPEN: false
267
269
  },
268
270
  {
269
271
  NO: 'JTZL',
270
- NAME: $lc("财司直连平台系统"),
272
+ NAME: $lc('财司直连平台系统'),
271
273
  ICON: '',
272
274
  LOGIN_MODE: [],
273
275
  OPEN: false
274
276
  },
275
277
  {
276
278
  NO: 'JRWG',
277
- NAME: $lc("金融网关系统"),
279
+ NAME: $lc('金融网关系统'),
278
280
  ICON: '',
279
281
  LOGIN_MODE: [],
280
282
  OPEN: false
281
283
  },
282
284
  {
283
285
  NO: 'JTSKYWGK',
284
- NAME: $lc("集团司库业务管控系统"),
286
+ NAME: $lc('集团司库业务管控系统'),
285
287
  ICON: '',
286
288
  LOGIN_MODE: [],
287
289
  OPEN: false
288
290
  },
289
291
  {
290
292
  NO: 'JTSKSJFX',
291
- NAME: $lc("集团数据分析系统"),
293
+ NAME: $lc('集团数据分析系统'),
292
294
  ICON: '',
293
295
  LOGIN_MODE: [],
294
296
  OPEN: false
@@ -296,10 +298,10 @@ export default {
296
298
  ]
297
299
  },
298
300
  plainOptions: [
299
- { label: $lc("账户密码登录"), value: 'account' },
300
- { label: $lc("手机验证码登录"), value: 'pthon' },
301
- { label: $lc("二维码扫码登录"), value: 'qrcode' },
302
- { label: $lc("账户密码验证码登录"), value: 'accountPthon' }
301
+ { label: $lc('账户密码登录'), value: 'account' },
302
+ { label: $lc('手机验证码登录'), value: 'pthon' },
303
+ { label: $lc('二维码扫码登录'), value: 'qrcode' },
304
+ { label: $lc('账户密码验证码登录'), value: 'accountPthon' }
303
305
  ],
304
306
  systemItem: undefined,
305
307
  key_1: 0,
@@ -332,7 +334,7 @@ export default {
332
334
  try {
333
335
  this.form[k] = k === 'LOGIN_URL' ? obj.pmValue : JSON.parse(obj.pmValue)
334
336
  } catch (error) {
335
- console.error(k + $lc("解析错误"))
337
+ console.error(k + $lc('解析错误'))
336
338
  }
337
339
  }
338
340
  } else {
@@ -343,7 +345,7 @@ export default {
343
345
  try {
344
346
  this.$set(this.form.SYSTEM_LIST, i, JSON.parse(obj.pmValue))
345
347
  } catch (error) {
346
- console.error('SYSTEM_LIST[' + item.NO + $lc("]解析错误"))
348
+ console.error('SYSTEM_LIST[' + item.NO + $lc(']解析错误'))
347
349
  }
348
350
  }
349
351
  })
@@ -361,7 +363,7 @@ export default {
361
363
  async save() {
362
364
  let vPro = this.$refs['form'].validate()
363
365
  vPro.catch(() => {
364
- this.$message.error($lc("必填项不能为空"))
366
+ this.$message.error($lc('必填项不能为空'))
365
367
  })
366
368
  await vPro
367
369
  let data = []
@@ -400,7 +402,7 @@ export default {
400
402
  let secondsToGo = 5
401
403
  this.$message({
402
404
  type: 'success',
403
- message: `${$lc("设置成功,系统将在")} ${secondsToGo} ${$lc("秒后退出到登录页面.")}`
405
+ message: `${$lc('设置成功,系统将在')} ${secondsToGo} ${$lc('秒后退出到登录页面.')}`
404
406
  })
405
407
  const interval = setInterval(() => {
406
408
  secondsToGo -= 1
@@ -1,5 +1,6 @@
1
1
  import axios from './axios'
2
2
  import { getItem, setItem } from './storageEdit'
3
+ import { persistPermissionItems } from './permissionStorage'
3
4
 
4
5
  /**
5
6
  * @description: 按需/按模块 加载权限
@@ -76,13 +77,21 @@ async function asyncGetRelaNos(appNo, rns) {
76
77
  // 将 ssCltrelaNos 重新赋值给 ssCltrelaNos ,并将 ssCltrelaNos 重新写回到 sessionStorage 中
77
78
  // 将 oRelaNos 重新赋值给 ssRelaNosG ,并将 ssRelaNosG 重新写回到 sessionStorage 中
78
79
  // 如果需要同步,则将 isSync 写回到 sessionStorage 中
79
- setItem('relaNos', ssRelaNos, isSync)
80
- setItem('cltrelaNos', ssCltrelaNos, isSync)
81
-
82
80
  let ssRelaNosG = getItem('relaNosGlobal')
83
81
  ssRelaNosG.push(...oRelaNos)
84
- setItem('relaNosGlobal', ssRelaNosG, isSync)
85
- isSync && sessionStorage.setItem('isSync', isSync)
82
+
83
+ if (isSync) {
84
+ await persistPermissionItems([
85
+ { key: 'relaNos', value: ssRelaNos },
86
+ { key: 'cltrelaNos', value: ssCltrelaNos },
87
+ { key: 'relaNosGlobal', value: ssRelaNosG }
88
+ ])
89
+ sessionStorage.setItem('isSync', isSync)
90
+ } else {
91
+ setItem('relaNos', ssRelaNos, false)
92
+ setItem('cltrelaNos', ssCltrelaNos, false)
93
+ setItem('relaNosGlobal', ssRelaNosG, false)
94
+ }
86
95
  } catch (error) {
87
96
  // 如果请求失败,从已加载列表中移除该模块
88
97
  const index = RLFM.indexOf(appNo)
@@ -0,0 +1,23 @@
1
+ import LZString from 'lz-string'
2
+
3
+ self.onmessage = function ({ data }) {
4
+ if (
5
+ !data ||
6
+ (typeof data.id !== 'number' && typeof data.id !== 'string') ||
7
+ typeof data.value !== 'string'
8
+ ) {
9
+ return
10
+ }
11
+
12
+ try {
13
+ self.postMessage({
14
+ id: data.id,
15
+ compressed: LZString.compressToBase64(data.value)
16
+ })
17
+ } catch (error) {
18
+ self.postMessage({
19
+ id: data.id,
20
+ error: error && error.message ? error.message : 'Compression failed'
21
+ })
22
+ }
23
+ }
@@ -0,0 +1,138 @@
1
+ import PermissionStorageWorker from 'worker-loader?filename=js/permission-storage-worker.[contenthash:8].js!./permission-storage-worker.v1.js'
2
+ import { setItem } from './storageEdit'
3
+
4
+ const LARGE_STORAGE_THRESHOLD = 524288
5
+ const WORKER_TIMEOUT = 30000
6
+ let compressionWorker = null
7
+ let requestSequence = 0
8
+ const pendingRequests = new Map()
9
+
10
+ function rejectPendingRequests(error) {
11
+ pendingRequests.forEach(({ reject, timeoutId }) => {
12
+ clearTimeout(timeoutId)
13
+ reject(error)
14
+ })
15
+ pendingRequests.clear()
16
+ }
17
+
18
+ function disposeWorker(error) {
19
+ if (compressionWorker) {
20
+ compressionWorker.terminate()
21
+ compressionWorker = null
22
+ }
23
+ rejectPendingRequests(error)
24
+ }
25
+
26
+ function getCompressionWorker() {
27
+ if (compressionWorker) return compressionWorker
28
+ if (typeof Worker === 'undefined') return null
29
+
30
+ try {
31
+ compressionWorker = new PermissionStorageWorker()
32
+ } catch (error) {
33
+ compressionWorker = null
34
+ return null
35
+ }
36
+
37
+ compressionWorker.onmessage = ({ data }) => {
38
+ if (!data) return
39
+
40
+ const pending = pendingRequests.get(data.id)
41
+ if (!pending) return
42
+
43
+ clearTimeout(pending.timeoutId)
44
+ pendingRequests.delete(data.id)
45
+
46
+ if (data.error || typeof data.compressed !== 'string') {
47
+ pending.reject(new Error(data.error || 'Invalid compression result'))
48
+ return
49
+ }
50
+
51
+ pending.resolve(data.compressed)
52
+ }
53
+
54
+ compressionWorker.onerror = () => {
55
+ disposeWorker(new Error('Permission compression worker failed'))
56
+ }
57
+
58
+ return compressionWorker
59
+ }
60
+
61
+ function compressInWorker(value) {
62
+ const worker = getCompressionWorker()
63
+ if (!worker) {
64
+ return Promise.reject(
65
+ new Error('Permission compression worker is unavailable')
66
+ )
67
+ }
68
+
69
+ return new Promise((resolve, reject) => {
70
+ const id = ++requestSequence
71
+ const timeoutId = setTimeout(() => {
72
+ if (!pendingRequests.has(id)) return
73
+ disposeWorker(new Error('Permission compression worker timed out'))
74
+ }, WORKER_TIMEOUT)
75
+
76
+ pendingRequests.set(id, { resolve, reject, timeoutId })
77
+ worker.postMessage({ id, value })
78
+ })
79
+ }
80
+
81
+ function writeCompressedValue(key, compressed) {
82
+ const storage = window.sessionStorage
83
+ const rawSetItem = storage._setItem
84
+ const rawRemoveItem = storage._removeItem
85
+
86
+ if (
87
+ typeof rawSetItem !== 'function' ||
88
+ typeof rawRemoveItem !== 'function'
89
+ ) {
90
+ throw new Error('Extended Storage API is unavailable')
91
+ }
92
+
93
+ try {
94
+ rawSetItem.call(storage, `${key}:[LZ]`, compressed)
95
+ rawRemoveItem.call(storage, key)
96
+ } catch (error) {
97
+ // A previous uncompressed value can consume the remaining quota.
98
+ rawRemoveItem.call(storage, key)
99
+ rawSetItem.call(storage, `${key}:[LZ]`, compressed)
100
+ }
101
+ }
102
+
103
+ async function persistItem({ key, value, serialized }) {
104
+ if (
105
+ typeof serialized !== 'string' ||
106
+ serialized.length <= LARGE_STORAGE_THRESHOLD
107
+ ) {
108
+ window.sessionStorage.setItem(key, serialized)
109
+ return
110
+ }
111
+
112
+ try {
113
+ const compressed = await compressInWorker(serialized)
114
+ writeCompressedValue(key, compressed)
115
+ } catch (error) {
116
+ // Preserve the existing synchronous behavior when Worker is unavailable.
117
+ setItem(key, value, true)
118
+ }
119
+ }
120
+
121
+ /**
122
+ * Persist permission objects with the same cache keys and LZ storage format
123
+ * used by n20-common-lib, while moving large compression work off main thread.
124
+ */
125
+ export async function persistPermissionItems(items) {
126
+ const serializedItems = items.map(({ key, value }) => {
127
+ window[`_keep_${key}`] = value
128
+ return {
129
+ key,
130
+ value,
131
+ serialized: JSON.stringify(value)
132
+ }
133
+ })
134
+
135
+ for (const item of serializedItems) {
136
+ await persistItem(item)
137
+ }
138
+ }
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file