gaoluyang
10 小时以前 6ae6ee885f0acb59f4c8b2d2439fb58a0a345701
feat: support formatted inspection values
已添加1个文件
已修改4个文件
94 ■■■■■ 文件已修改
package.json 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Excel/luckysheet.vue 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/inspectionValueFormat.js 58 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/business/inspectionTask/inspection.vue 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/standard/model/index.vue 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
package.json
@@ -34,6 +34,7 @@
    "html2canvas": "^1.4.1",
    "js-beautify": "1.15.4",
    "js-cookie": "3.0.5",
    "jsbarcode": "^3.12.3",
    "jsencrypt": "3.3.2",
    "jspdf": "^2.5.2",
    "mammoth": "^1.13.0",
src/components/Excel/luckysheet.vue
@@ -51,6 +51,13 @@
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1024 1024'%3E%3Cpath d='M512 64a448 448 0 1 1 0 896 448 448 0 0 1 0-896m0 192a58.43 58.43 0 0 0-58.24 63.744l23.36 256.384a35.072 35.072 0 0 0 69.76 0l23.296-256.384A58.43 58.43 0 0 0 512 256m0 512a51.2 51.2 0 1 0 0-102.4 51.2 51.2 0 0 0 0 102.4'/%3E%3C/svg%3E") center/contain no-repeat;
}
/* Luckysheet çš„工具栏下拉菜单(批注、字体颜色等)是挂在 body ä¸Šçš„,
   é»˜è®¤ z-index åªæœ‰ 1004;上面 #luckysheet æŠ¬åˆ°äº† 99999,会把这些菜单整个盖住,
   è¡¨çŽ°ä¸ºâ€œç‚¹æ‰¹æ³¨æ²¡ååº”â€ã€‚æŠŠ body çº§èœå•抬到容器之上。 */
.luckysheet-cols-menu {
  z-index: 100001 !important;
}
#luckysheet .save:hover {
  opacity: 0.8;
}
src/utils/inspectionValueFormat.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,58 @@
/**
 * è§£æžåŽŸå§‹è®°å½•æ¨¡æ¿ä¸­çš„æ£€éªŒå€¼æ‰¹æ³¨ã€‚
 * å…¼å®¹æ—§æ ¼å¼â€œæ£€éªŒå€¼â€ï¼Œå¹¶æ”¯æŒï¼šæ£€éªŒå€¼ï¼Œ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 decimalPlaces = parts[1] === '' || parts[1] == null ? null : Number(parts[1]);
  if (decimalPlaces != null && (!Number.isInteger(decimalPlaces) || decimalPlaces < 0 || decimalPlaces > 15)) {
    return { error: '小数位数必须是 0 åˆ° 15 çš„æ•´æ•°' };
  }
  const displayMode = parts.slice(2).includes('科学计数法') ? '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(2).filter(item => item && item !== '科学计数法' && !roundingNames[item]);
  if (unsupported.length || parts.length > 4) {
    return { error: '检验值批注格式应为:检验值,2,四舍五入 æˆ– æ£€éªŒå€¼ï¼Œ2,科学计数法,四舍五入' };
  }
  return { decimalPlaces, displayMode, 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;
  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;
  return config.displayMode === 'SCIENTIFIC'
    ? rounded.toExponential(config.decimalPlaces)
    : rounded.toFixed(config.decimalPlaces);
}
export function validateInspectionValueAnnotation(annotation) {
  const config = parseInspectionValueAnnotation(annotation);
  return config && config.error ? config.error : null;
}
src/views/business/inspectionTask/inspection.vue
@@ -521,6 +521,7 @@
import { mapGetters } from "@/utils/store-compat";
import viewManHourDia from "@/views/business/inspectionTask/components/viewManHourDia.vue";
import {getDicts} from "@/api/system/dict/data";
import { parseInspectionValueAnnotation, formatInspectionValue } from "@/utils/inspectionValueFormat";
export default {
  name: 'Inspection',
  components: {
@@ -1575,6 +1576,17 @@
    // æ£€éªŒå€¼è¾“入后触发的函数
    changeInput(m, code, n) {
      if (n) {
        const config = parseInspectionValueAnnotation(n.v && n.v.ps && n.v.ps.value);
        if (config && !config.error && config.decimalPlaces != null && typeof n.v.v === 'string') {
          const numericPattern = config.displayMode === 'SCIENTIFIC'
            ? /^[+-]?(?:\d+\.?\d*|\.\d+)(?:[eE][+-]?\d+)?$/
            : /^[+-]?\d*\.?\d+$/;
          if (n.v.v.trim() && !numericPattern.test(n.v.v.trim())) {
            this.$message.warning('该检验值必须填写数字');
            return;
          }
          n.v.v = formatInspectionValue(n.v.v, config);
        }
        // å®šä¹‰ä¸€ä¸ªå‡½æ•°æ¥éªŒè¯åˆ†æ•°æ˜¯å¦æœ‰æ•ˆ
        if (typeof n.v.v == "string") {
          function isValidFraction(fraction) {
@@ -1705,7 +1717,7 @@
        const v = n.v.v;
        // èƒ½åŠ›èŒƒå›´å·²åºŸå¼ƒ,检验值类型不再作为判断依据。整串只由算式字符组成时才规范化格式,
        // å‡ºçŽ°ä¸­æ–‡ç­‰å…¶å®ƒå­—ç¬¦å³æŒ‰æ–‡æœ¬å¤„ç†åŽŸæ ·ä¿ç•™,否则文字会被逐字删掉
        if (typeof v !== "string" || /[^\d.^e>>≥≤<<断裂脆化\-/+]/.test(v)) {
        if (typeof v !== "string" || /[^\d.^eE>>≥≤<<断裂脆化\-/+]/.test(v)) {
          return;
        }
        n.v.v = v
src/views/standard/model/index.vue
@@ -64,6 +64,7 @@
  delStandardTemplate,
  getEditTemplatePreparation,
} from "@/api/standard/model";
import { validateInspectionValueAnnotation } from "@/utils/inspectionValueFormat";
export default {
  name: 'Model',
  components: {
@@ -349,7 +350,12 @@
          }
        }
      }
      let annotationError = null;
      data.data[0].celldata.forEach((a) => {
        if (a.v && a.v.ps && typeof a.v.ps.value === "string") {
          const error = validateInspectionValueAnnotation(a.v.ps.value);
          if (!annotationError && error) annotationError = `单元格(${a.r + 1}行${a.c + 1}列):${error}`;
        }
        if (
          a.v.ps != undefined &&
          (a.v.ps.value === "检验值" ||
@@ -362,6 +368,11 @@
          }
        }
      });
      if (annotationError) {
        this.loading = false;
        this.$message.error(annotationError);
        return;
      }
      upStandardTemplate({
        id: this.row.id,
        thing: JSON.stringify(data),
@@ -370,6 +381,9 @@
        this.loading = false;
        this.$message.success("已保存");
        this.isShow = false;
      }).catch((error) => {
        this.loading = false;
        this.$message.error(error.message || "模板保存失败");
      });
    },
    isClose(done) {