gaoluyang
9 小时以前 29be8639dc16b5d82bddc6099b1fa5cdca75f77a
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
/**
 * 解析原始记录模板中的检验值批注。
 * 兼容旧格式“检验值”,并支持:检验值,2、检验值,2,科学计数法。
 */
export function parseInspectionValueAnnotation(annotation) {
  if (typeof annotation !== 'string' || !annotation.includes('检验值')) return null;
  // 批注允许中文逗号、英文逗号以及“和”连接格式参数。
  const parts = annotation
    .replace(/,/g, ',')
    .replace(/\s+/g, '')
    .replace(/和/g, ',')
    .split(',')
    .map(item => item.trim())
    .filter(Boolean);
  const decimalIndex = parts.findIndex((item, index) => index > 0 && /^\d+$/.test(item));
  const decimalPlaces = decimalIndex < 0 ? null : Number(parts[decimalIndex]);
  if (decimalPlaces != null && (!Number.isInteger(decimalPlaces) || decimalPlaces < 0 || decimalPlaces > 15)) {
    return { error: '小数位数必须是 0 到 15 的整数' };
  }
  const scientificIndex = parts.findIndex((item, index) => index > 0 && item === '科学计数法');
  const displayMode = scientificIndex >= 0 ? 'SCIENTIFIC' : 'NORMAL';
  const roundingNames = {
    '四舍五入': 'HALF_UP',
    '四舍六入': 'HALF_UP_6',
    '向上舍入': 'CEILING',
    '向下舍入': 'FLOOR',
    '截断': 'DOWN'
  };
  const roundingPart = parts.slice(2).find(item => Object.prototype.hasOwnProperty.call(roundingNames, item));
  const unsupported = parts.slice(1).filter((item, index) =>
    item && index + 1 !== decimalIndex && item !== '科学计数法' && !roundingNames[item]
  );
  if (unsupported.length || parts.length > 4) {
    return { error: '检验值批注格式应为:检验值,2,四舍五入 或 检验值,2,科学计数法,四舍五入' };
  }
  return {
    decimalPlaces,
    displayMode,
    // 参数顺序决定处理顺序:科学计数法在小数位前表示先转科学计数法。
    scientificFirst: displayMode === 'SCIENTIFIC' && scientificIndex < decimalIndex,
    roundingMode: roundingPart ? roundingNames[roundingPart] : 'HALF_UP'
  };
}
 
export function formatInspectionValue(value, config) {
  if (!config || config.error || config.decimalPlaces == null || value === '' || value == null) return value;
  const number = Number(value);
  if (!Number.isFinite(number)) return value;
  // 科学计数法在批注中排在小数位数前时,先转科学计数法再保留尾数位数。
  if (config.displayMode === 'SCIENTIFIC' && config.scientificFirst) {
    const scientific = number.toExponential(config.decimalPlaces);
    return scientific.replace('e', 'E');
  }
  const factor = 10 ** config.decimalPlaces;
  let rounded;
  if (config.roundingMode === 'CEILING') rounded = Math.ceil(number * factor) / factor;
  else if (config.roundingMode === 'FLOOR') rounded = Math.floor(number * factor) / factor;
  else if (config.roundingMode === 'DOWN') rounded = (number < 0 ? Math.ceil(number * factor) : Math.floor(number * factor)) / factor;
  else if (config.roundingMode === 'HALF_UP_6') {
    const absolute = Math.abs(number) * factor;
    const base = Math.floor(absolute);
    const fraction = absolute - base;
    rounded = (number < 0 ? -1 : 1) * ((fraction >= 0.6 ? base + 1 : base) / factor);
  } else rounded = Math.round((number + (number >= 0 ? Number.EPSILON : -Number.EPSILON)) * factor) / factor;
  const fixed = rounded.toFixed(config.decimalPlaces);
  if (config.displayMode === 'SCIENTIFIC') return Number(fixed).toExponential(config.decimalPlaces).replace('e', 'E');
  return fixed;
}
 
export function validateInspectionValueAnnotation(annotation) {
  const config = parseInspectionValueAnnotation(annotation);
  return config && config.error ? config.error : null;
}