Explorar o código

fix(订单表单): 修复浮点数输入验证并优化格式化逻辑

yz hai 2 semanas
pai
achega
35c955cf70

+ 42 - 22
src/components/order-form/material-detail-table.vue

@@ -58,7 +58,7 @@
             style="width: 100%"
             placeholder="请输入单价"
             @input="validateFloatInput($event, scope.row, 'unitPrice')"
-            @blur="handleUnitPriceChange(scope.row, scope.$index)"
+            @blur="validateAndFormatFloatOnBlur(scope.row, 'unitPrice'); handleUnitPriceChange(scope.row, scope.$index)"
           />
           <span v-else>{{ formatUnitPrice(scope.row.unitPrice) }}</span>
         </template>
@@ -85,7 +85,7 @@
             style="width: 100%"
             placeholder="请输入税率"
             @input="validateFloatInput($event, scope.row, 'taxRate', 0, 100)"
-            @blur="handleTaxRateChange(scope.row, scope.$index)"
+            @blur="validateAndFormatFloatOnBlur(scope.row, 'taxRate', 0, 100); handleTaxRateChange(scope.row, scope.$index)"
           />
           <span v-else>{{ formatQuantity(scope.row.taxRate) }}%</span>
         </template>
@@ -99,7 +99,7 @@
             style="width: 100%"
             placeholder="请输入税额"
             @input="validateFloatInput($event, scope.row, 'taxAmount')"
-            @blur="handleTaxAmountChange(scope.row, scope.$index)"
+            @blur="validateAndFormatFloatOnBlur(scope.row, 'taxAmount'); handleTaxAmountChange(scope.row, scope.$index)"
           />
           <span v-else>{{ formatAmount(scope.row.taxAmount, false) }}</span>
         </template>
@@ -113,7 +113,7 @@
             style="width: 100%"
             placeholder="请输入总金额"
             @input="validateFloatInput($event, scope.row, 'totalAmount')"
-            @blur="handleTotalAmountChange(scope.row, scope.$index)"
+            @blur="validateAndFormatFloatOnBlur(scope.row, 'totalAmount'); handleTotalAmountChange(scope.row, scope.$index)"
           />
           <span v-else>{{ formatAmount(scope.row.totalAmount, false) }}</span>
         </template>
@@ -391,7 +391,7 @@ export default {
       },
       
       /**
-       * 验证浮点数输入
+       * 验证浮点数输入(输入时验证)
        * @param {string} value - 输入值
        * @param {Object} row - 当前行数据
        * @param {string} field - 字段名
@@ -399,8 +399,9 @@ export default {
        * @param {number} max - 最大值
        */
       validateFloatInput(value, row, field, min = 0, max = 999999.99) {
-        // 允许空值和部分输入
-        if (value === '' || value === '-' || value === '.') {
+        // 允许空值和部分输入(包括单独的小数点、负号等)
+        if (value === '' || value === '-' || value === '.' || value === '-.') {
+          row[field] = value
           return
         }
         
@@ -418,25 +419,44 @@ export default {
           cleanValue = parts[0] + '.' + parts.slice(1).join('')
         }
         
-        // 限制小数位数为2位
+        // 限制小数位数为2位(但允许继续输入)
         if (parts.length === 2 && parts[1].length > 2) {
           cleanValue = parts[0] + '.' + parts[1].substring(0, 2)
         }
         
-        // 如果有有效数值,进行范围检查
-        if (cleanValue !== '' && cleanValue !== '-' && cleanValue !== '.') {
-          const numValue = parseFloat(cleanValue)
-          if (!isNaN(numValue)) {
-            if (numValue < min) {
-              row[field] = min
-            } else if (numValue > max) {
-              row[field] = max
-            } else {
-              // 限制为2位小数
-              const roundedValue = Math.round(numValue * 100) / 100
-              row[field] = roundedValue
-            }
-          }
+        // 更新字段值,但不进行范围检查(留到blur时处理)
+        row[field] = cleanValue
+      },
+
+      /**
+       * 验证并格式化浮点数(失焦时验证)
+       * @param {Object} row - 当前行数据
+       * @param {string} field - 字段名
+       * @param {number} min - 最小值
+       * @param {number} max - 最大值
+       * @param {number} precision - 小数位数,默认2位
+       */
+      validateAndFormatFloatOnBlur(row, field, min = 0, max = 999999.99, precision = 2) {
+        const value = row[field]
+        
+        // 如果是空值或无效输入,设置为最小值
+        if (value === '' || value === '.' || value === '-' || value === '-.' || isNaN(parseFloat(value))) {
+          row[field] = min
+          return
+        }
+        
+        const numValue = parseFloat(value)
+        
+        // 范围检查
+        if (numValue < min) {
+          row[field] = min
+        } else if (numValue > max) {
+          row[field] = max
+        } else {
+          // 格式化为指定小数位数
+          const multiplier = Math.pow(10, precision)
+          const roundedValue = Math.round(numValue * multiplier) / multiplier
+          row[field] = roundedValue
         }
       },
 

+ 2 - 2
src/components/order-form/material-import-dialog.vue

@@ -514,8 +514,8 @@ export default {
             availableQuantity: availableQuantityValidation.isValid ? preciseRound(availableQuantityValidation.value, 4) : 0,
             orderQuantity: 1, // 默认订单数量为1
             confirmQuantity: 1,
-            unitPrice: 0, // 默认单价为0,4位浮点型
-            taxRate: 0, // 默认税率为0,4位浮点型
+            unitPrice: 0, // 默认单价为0,2位浮点型
+            taxRate: 0, // 默认税率为0,2位浮点型
             taxAmount: 0, // 默认税额为0,2位小数
             totalAmount: 0, // 默认总金额为0,2位小数
             status: MaterialDetailStatus.PENDING,