@nstc-business/imes 1.0.0 → 1.0.2

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": "@nstc-business/imes",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "private": false,
5
5
  "main": "src/index.js",
6
6
  "scripts": {
@@ -24,7 +24,6 @@
24
24
  "element-ui": "^2.15.6",
25
25
  "jquery": "^3.6.0",
26
26
  "moment": "^2.30.1",
27
- "n20-common-lib": "2.5.18",
28
27
  "qrcode": "^1.5.0",
29
28
  "resize-detector": "^0.3.0",
30
29
  "swiper": "^11.1.14",
@@ -40,6 +39,7 @@
40
39
  "src/index.js"
41
40
  ],
42
41
  "devDependencies": {
42
+ "n20-common-lib": "2.5.18",
43
43
  "@babel/plugin-proposal-optional-chaining": "^7.14.5",
44
44
  "@babel/plugin-transform-flow-comments": "^7.14.5",
45
45
  "@vue/cli-plugin-babel": "~4.5.0",
@@ -1,138 +1,4 @@
1
- import { N } from 'n20-common-lib'
2
-
3
- export function formatDate(date, fmt) {
4
- date = new Date(date)
5
- if (/(y+)/.test(fmt)) {
6
- fmt = fmt.replace(
7
- RegExp.$1,
8
- (date.getFullYear() + '').substr(4 - RegExp.$1.length)
9
- )
10
- }
11
- let o = {
12
- 'M+': date.getMonth() + 1,
13
- 'd+': date.getDate(),
14
- 'h+': date.getHours(),
15
- 'm+': date.getMinutes(),
16
- 's+': date.getSeconds()
17
- }
18
- for (let k in o) {
19
- if (new RegExp(`(${k})`).test(fmt)) {
20
- let str = o[k] + ''
21
- fmt = fmt.replace(
22
- RegExp.$1,
23
- RegExp.$1.length === 1 ? str : padLeftZero(str)
24
- )
25
- }
26
- }
27
- return fmt
28
- }
29
- function padLeftZero(str) {
30
- return ('00' + str).substr(str.length)
31
- }
32
-
33
- /**
34
- * 公式转换,支持复杂运算逻辑
35
- * @param {array} statisticItems 数据映射数组
36
- * @param {string} formula 公式
37
- * @returns {object} codeFormula cod公式,randomFormula 随机数公式
38
- */
39
- export const replaceStatsNameWithCode = (statisticItems, formula) => {
40
- // 创建statsName到code的映射
41
- const nameToCodeMap = statisticItems.reduce((map, item) => {
42
- if (item.formula) {
43
- map[item.statsName] = {
44
- formula: item.formula
45
- }
46
- } else {
47
- map[item.statsName] = item.code
48
- }
49
-
50
- return map
51
- }, {})
52
-
53
- // 创建statsName到随机数的映射
54
- const nameToRandomMap = statisticItems.reduce((map, item) => {
55
- if (item.formula) {
56
- map[item.statsName] = {
57
- formula: item.formula
58
- }
59
- } else {
60
- map[item.statsName] = Math.random().toFixed(10)
61
- }
62
- return map
63
- }, {})
64
-
65
- // 增强的正则表达式,支持多层嵌套的复杂表达式
66
- const complexPattern =
67
- /(?:\([^()]*\)|[\u4e00-\u9fa5a-zA-Z0-9-]+)(?:\s*[+\-*/]\s*(?:\([^()]*\)|[\u4e00-\u9fa5a-zA-Z0-9-]+))*/g
68
-
69
- // 生成code公式
70
- const codeFormula = formula.replace(complexPattern, match => {
71
- // 处理带括号的表达式
72
- const hasParentheses = match.startsWith('(') && match.endsWith(')')
73
- const content = hasParentheses ? match.slice(1, -1) : match
74
-
75
- // 先替换括号内的内容
76
- const innerReplaced = content.replace(
77
- /[\u4e00-\u9fa5a-zA-Z0-9-]+/g,
78
- part =>
79
- typeof nameToCodeMap[part] === 'object'
80
- ? nameToCodeMap[part]?.formula
81
- : nameToCodeMap[part] === undefined
82
- ? part
83
- : `#${nameToCodeMap[part]}#`
84
- )
85
-
86
- // 再处理运算符
87
- const result = innerReplaced
88
- .split(/([+\-*/()])/)
89
- .map(part => {
90
- const trimmed = part.trim()
91
- return nameToCodeMap[trimmed] ? `#${nameToCodeMap[trimmed]}#` : part
92
- })
93
- .join('')
94
-
95
- return hasParentheses ? `(${result})` : result
96
- })
97
-
98
- // 生成随机数公式
99
- const randomFormula = formula.replace(complexPattern, match => {
100
- // 处理带括号的表达式
101
- const hasParentheses = match.startsWith('(') && match.endsWith(')')
102
- const content = hasParentheses ? match.slice(1, -1) : match
103
-
104
- // 先替换括号内的内容
105
- const innerReplaced = content.replace(
106
- /[\u4e00-\u9fa5a-zA-Z0-9-]+/g,
107
- part => {
108
- const random = nameToRandomMap[part]
109
- return typeof random === 'object'
110
- ? random.formula
111
- : random === undefined
112
- ? part
113
- : random
114
- }
115
- )
116
-
117
- // 再处理运算符
118
- const result = innerReplaced
119
- .split(/([+\-*/()])/)
120
- .map(part => {
121
- const trimmed = part.trim()
122
- const random = nameToRandomMap[trimmed]
123
- return random === undefined ? part : random
124
- })
125
- .join('')
126
-
127
- return hasParentheses ? `(${result})` : result
128
- })
129
-
130
- return {
131
- codeFormula,
132
- randomFormula
133
- }
134
- }
135
-
1
+ import {N} from 'n20-common-lib'
136
2
  /**
137
3
  * 设置表格合并行的公共方法
138
4
  * @param {any[]} list 表格数据
@@ -142,6 +8,8 @@ export const replaceStatsNameWithCode = (statisticItems, formula) => {
142
8
  * @param {String} field 表头取值的字段名
143
9
  */
144
10
 
11
+
12
+
145
13
  export function setMergeCells({
146
14
  list = [],
147
15
  columns = [],
@@ -224,146 +92,6 @@ export const formatFloat2 = (num, digit3 = 2) => {
224
92
  return parseFloat(N.subFixed(num, digit3))
225
93
  }
226
94
 
227
- /**
228
- * 校验Table每行字段是否为空
229
- * @param {Object} requiredFields 字段映射对象,例:{minVal: '最小值', maxVal: '最大值', score: '分数'}
230
- * @param {Array} data 要验证的数据数组
231
- * @returns {Error|null} 验证通过返回null,失败返回Error对象
232
- */
233
- export const validateFieldPresence = (requiredFields = {}, data = []) => {
234
- // 添加参数有效性检查
235
- if (!Array.isArray(data)) return new Error('数据参数必须为数组')
236
-
237
- for (const [index, row] of data.entries()) {
238
- // 遍历字段映射对象的键
239
- for (const field of Object.keys(requiredFields)) {
240
- // 添加字段存在性检查
241
- if (!Object.prototype.hasOwnProperty.call(row, field)) {
242
- return new Error(`第${index + 1}条规则:当前行缺少必要字段[${field}]`)
243
- }
244
-
245
- // 加强空值判断
246
- if (row[field] === '' || row[field] == null) {
247
- return new Error(
248
- `第${index + 1}条规则:${requiredFields[field] || field}不能为空`
249
- )
250
- }
251
- }
252
- }
253
-
254
- // 明确返回验证通过状态
255
- return null
256
- }
257
-
258
- /**
259
- * 校验数字格式
260
- * @param {Object} options 配置项
261
- * @param {Object} options.requiredFields 字段映射对象 {minVal: '最小值', maxVal: '最大值'}
262
- * @param {Array} options.data 要验证的数据数组
263
- * @param {RegExp} options.validRegex 验证正则,默认/^-?\d+(?:\.\d{1,6})?$/
264
- * @returns {Error|null}
265
- */
266
- export const validateNumberFormat = ({
267
- requiredFields = {},
268
- data = [],
269
- validRegex = /^-?\d+(?:\.\d{1,6})?$/
270
- } = {}) => {
271
- if (!Array.isArray(data)) return new Error('数据参数必须为数组')
272
-
273
- for (const [index, row] of data.entries()) {
274
- for (const [field, fieldName] of Object.entries(requiredFields)) {
275
- const value = String(row[field] ?? '') // 处理undefined/null
276
-
277
- if (!validRegex.test(value)) {
278
- return new Error(`第${index + 1}条规则:${fieldName}格式不正确`)
279
- }
280
- }
281
- }
282
- return null
283
- }
284
-
285
- /**
286
- * 校验区间重叠
287
- * @param {Array} data
288
- * @param {Object} requiredFields = {},
289
- * @returns
290
- */
291
- export const validateRangeOverlap = (
292
- data = [],
293
- requiredFields = {
294
- minVal: '下限',
295
- maxVal: '上限'
296
- }
297
- ) => {
298
- if (!Array.isArray(data)) return new Error('数据参数必须为数组')
299
- // 增强参数校验
300
- const fields = Object.keys(requiredFields)
301
- if (fields.length !== 2) {
302
- return new Error('字段映射对象必须且只能包含两个字段[minKey, maxKey]')
303
- }
304
- const [minKey, maxKey] = fields
305
-
306
- for (let i = 0; i < data.length; i++) {
307
- const current = data[i]
308
-
309
- // 合并字段存在性检查
310
- for (const key of [minKey, maxKey]) {
311
- // 修复属性检查方式,增加对象类型判断
312
- if (
313
- !current ||
314
- typeof current !== 'object' ||
315
- !Object.prototype.hasOwnProperty.call(current, key)
316
- ) {
317
- return new Error(`第${i + 1}条规则:缺少${requiredFields[key]}字段`)
318
- }
319
- // 空值检查添加到此处
320
- if (current[key] === '' || current[key] == null) {
321
- return new Error(`第${i + 1}条规则:${requiredFields[key]}不能为空`)
322
- }
323
- }
324
- // 增强数值转换
325
- const [minVal, maxVal] = [Number(current[minKey]), Number(current[maxKey])]
326
- if (isNaN(minVal)) {
327
- return new Error(`第${i + 1}条规则:${requiredFields[minKey]}值无效`)
328
- }
329
- if (isNaN(maxVal)) {
330
- return new Error(`第${i + 1}条规则:${requiredFields[maxKey]}值无效`)
331
- }
332
- if (minVal >= maxVal) {
333
- return new Error(
334
- `第${i + 1}条规则:${requiredFields[minKey]}不能大于等于${requiredFields[maxKey]}`
335
- )
336
- }
337
-
338
- // 优化区间检查性能
339
- for (let j = i + 1; j < data.length; j++) {
340
- const other = data[j]
341
- // 添加对other行的校验
342
- if ([minKey, maxKey].some(k => !Object.prototype.hasOwnProperty.call(other, k))) continue
343
-
344
- if (isRangeOverlap(current, other, minKey, maxKey)) {
345
- return new Error(`第${i + 1}条和第${j + 1}条规则存在区间重叠`)
346
- }
347
- }
348
- }
349
- return null
350
- }
351
-
352
- export const isRangeOverlap = (a, b, minKey = 'minVal', maxKey = 'maxVal') => {
353
- const aMin = Number(a[minKey])
354
- const aMax = Number(a[maxKey])
355
- const bMin = Number(b[minKey])
356
- const bMax = Number(b[maxKey])
357
-
358
- return (
359
- !isNaN(aMin) &&
360
- !isNaN(aMax) &&
361
- !isNaN(bMin) &&
362
- !isNaN(bMax) &&
363
- Math.max(aMin, bMin) < Math.min(aMax, bMax)
364
- )
365
- }
366
-
367
95
  export function toFixedTrunc(num, decimals) {
368
96
  if (isNaN(num) || num === undefined || num === null) return num
369
97
 
@@ -379,41 +107,4 @@ export function toFixedTrunc(num, decimals) {
379
107
 
380
108
  export function addThousands(data) {
381
109
  return N.addThousands(data)
382
- }
383
-
384
- /**
385
- * 深度克隆
386
- * @param target
387
- * @return {}
388
- */
389
- export const deepClone = (target, map = new Map()) => {
390
- // 检测数据的类型
391
- if (typeof target === 'object' && target !== null) {
392
- // 克隆数据之前, 进行判断, 数据之前是否克隆过
393
- const cache = map.get(target)
394
- if (cache) {
395
- return cache
396
- }
397
- // 判断目标数据的类型
398
- const isArray = Array.isArray(target)
399
- // 创建一个容器
400
- const result = isArray ? [] : {}
401
- // 将新的结果存入到容器中
402
- map.set(target, result)
403
- // 如果目标数据为数组
404
- if (isArray) {
405
- // forEach 遍历
406
- target.forEach((item, index) => {
407
- result[index] = deepClone(item, map)
408
- })
409
- } else {
410
- // 如果是对象, 获取所有的键名, 然后 forEach 遍历
411
- Object.keys(target).forEach((key) => {
412
- result[key] = deepClone(target[key], map)
413
- })
414
- }
415
- return result
416
- } else {
417
- return target
418
- }
419
- }
110
+ }
@@ -51,8 +51,8 @@
51
51
 
52
52
  <script>
53
53
  import {N, Page, ExpandablePane, Descriptions} from 'n20-common-lib'
54
- import tree from './tree.vue'
55
- import modelCalcTest from './modelCalcTest.vue'
54
+ import tree from './model-calculate/tree.vue'
55
+ import modelCalcTest from './model-calculate/modelCalcTest.vue'
56
56
 
57
57
  export default {
58
58
  props: {