feat(utils): 添加数字格式化工具函数并应用至多个组件

添加 formatDecimal 函数用于格式化小数显示,去除末尾无效0和孤立小数点
在库存管理、采购、出入库等模块中应用该格式化函数,统一数字显示格式
调整仪表盘统计数据的精度显示为整数
优化采购截止日期的显示逻辑,增加状态判断和剩余天数计算
This commit is contained in:
砂糖
2026-01-31 14:39:53 +08:00
parent 42f6f83c3a
commit b4beb49f91
11 changed files with 175 additions and 30 deletions

View File

@@ -18,8 +18,12 @@
<el-table-column prop="spec" label="配料规格" min-width="100" align="center" />
<el-table-column prop="model" label="配料型号" min-width="100" align="center" />
<el-table-column prop="factory" label="生产厂家" min-width="120" align="center" />
<el-table-column prop="currentStock" label="现存库存" min-width="80" align="center" />
<el-table-column prop="unit" label="计量单位" width="80" align="center" />
<el-table-column prop="currentStock" label="现存库存" min-width="80" align="center">
<template #default="scope">
{{ formatDecimal(scope.row.currentStock) }}
</template>
</el-table-column>
<el-table-column prop="unit" label="计量单位" width="80" align="center" :formatter="formatUnit" />
</el-table>
<!-- 分页组件 -->
@@ -39,6 +43,7 @@
import { ref, computed, watch, onMounted } from 'vue';
import { listMaterial, getMaterial } from '@/api/mat/material';
import { ElMessage } from 'element-plus';
import { formatDecimal } from '@/utils/gear'
// 双向绑定物料ID
const materialId = defineModel({

View File

@@ -8,7 +8,7 @@
<el-descriptions-item label="配料规格">{{ formattedData.spec }}</el-descriptions-item>
<el-descriptions-item label="配料型号">{{ formattedData.model }}</el-descriptions-item>
<el-descriptions-item label="厂家">{{ formattedData.factory }}</el-descriptions-item>
<el-descriptions-item label="现存库存">{{ formattedData.currentStock }}</el-descriptions-item>
<el-descriptions-item label="现存库存">{{ formatDecimal(formattedData.currentStock) }}</el-descriptions-item>
<el-descriptions-item label="计量单位">{{ formattedData.unit }}</el-descriptions-item>
<el-descriptions-item label="备注" :span="2">{{ formattedData.remark }}</el-descriptions-item>
</el-descriptions>
@@ -17,6 +17,7 @@
<script setup>
import { getMaterial } from '@/api/mat/material'
import { formatDecimal } from '@/utils/gear'
const props = defineProps({
data: {

View File

@@ -226,3 +226,21 @@ export function getNormalPath(p) {
export function blobValidate(data) {
return data.type !== 'application/json'
}
/**
* 格式化小数(兼容数字/字符串输入去除末尾所有0末尾仅余小数点则去除
* @param {number|string} num - 输入值(数字/合法数字字符串如123.4500、"99.000"、"66"
* @returns {string} 格式化后的字符串,非法输入返回空字符串
*/
export function formatDecimal(num) {
// 1. 统一转字符串并去除首尾空格,兼容带空格的输入
const str = String(num).trim();
// 2. 合法性校验:仅匹配 正负整数/小数(拒绝非数字、科学计数法等非法输入)
const validReg = /^-?\d+(\.\d+)?$/;
if (!validReg.test(str)) {
return ''; // 非法输入返回空字符串,也可根据需求改为抛出错误
}
// 3. 核心格式化先去末尾0再处理末尾孤立的小数点
// 正则1匹配小数点后有效数字+末尾0保留有效数字去0正则2去掉末尾仅存的小数点
return str.replace(/(\.\d*?)0*$/, '$1').replace(/\.$/, '');
}

View File

@@ -25,7 +25,11 @@
<raw :data="scope.row" :materialId="scope.row.materialId" />
</template>
</el-table-column>
<el-table-column label="所需数量" align="center" prop="materialNum" />
<el-table-column label="所需数量" align="center" prop="materialNum">
<template #default="scope">
{{ formatDecimal(scope.row.materialNum) }}
</template>
</el-table-column>
<!-- <el-table-column label="配料排序 用于前端展示顺序" align="center" prop="sort" /> -->
<el-table-column label="备注" align="center" prop="remark" />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
@@ -73,6 +77,8 @@
import { listProductMaterialRelation, getProductMaterialRelation, delProductMaterialRelation, addProductMaterialRelation, updateProductMaterialRelation } from "@/api/mat/productMaterialRelation";
import RawSelector from '@/components/RawSelector/index.vue'
import Raw from '@/components/Renderer/Raw.vue'
import { formatDecimal } from '@/utils/gear'
const { proxy } = getCurrentInstance();
const productMaterialRelationList = ref([]);

View File

@@ -22,9 +22,21 @@
<raw :data="scope.row" />
</template>
</el-table-column>
<el-table-column label="入库数量" align="center" prop="inNum" />
<el-table-column label="入库单价" align="center" prop="inPrice" />
<el-table-column label="入库金额" align="center" prop="inAmount" />
<el-table-column label="入库数量" align="center" prop="inNum">
<template #default="scope">
{{ formatDecimal(scope.row.inNum) }}
</template>
</el-table-column>
<el-table-column label="入库单价" align="center" prop="inPrice">
<template #default="scope">
{{ formatDecimal(scope.row.inPrice) }}
</template>
</el-table-column>
<el-table-column label="入库金额" align="center" prop="inAmount">
<template #default="scope">
{{ formatDecimal(scope.row.inAmount) }}
</template>
</el-table-column>
<el-table-column label="入库时间" align="center" prop="inTime" width="180">
<template #default="scope">
<span>{{ formatterTime(scope.row.inTime) }}</span>
@@ -88,6 +100,8 @@
import { listPurchaseInDetail, getPurchaseInDetail, delPurchaseInDetail, addPurchaseInDetail, updatePurchaseInDetail } from "@/api/mat/purchaseInDetail";
import useUserStore from '@/store/modules/user'
import Raw from '@/components/Renderer/Raw.vue'
import { formatDecimal } from '@/utils/gear'
const props = defineProps({
purchaseId: {

View File

@@ -9,7 +9,7 @@
<el-statistic
:title="item.title"
:value="item.value"
:precision="item.precision || 2"
:precision="item.precision || 0"
:suffix="item.suffix"
/>
</el-card>
@@ -57,9 +57,16 @@
<el-table-column
prop="currentStock"
label="当前库存"
align="center"
/>
<el-table-column prop="inTransitNum" label="在途数" align="center" />
align="center">
<template #default="scope">
{{ formatDecimal(scope.row.currentStock) }}
</template>
</el-table-column>
<el-table-column prop="inTransitNum" label="在途数" align="center">
<template #default="scope">
{{ formatDecimal(scope.row.inTransitNum) }}
</template>
</el-table-column>
<!-- <el-table-column prop="planNum" label="计划数" align="center" /> -->
</el-table>
@@ -93,6 +100,8 @@ import { listMaterial } from "@/api/mat/material";
import FactoryBarChart from '../components/charts/FactoryBarChart.vue'
import StockTrendChart from '../components/charts/StockTrendChart.vue'
import InOutCompareChart from '../components/charts/InOutCompareChart.vue'
import { formatDecimal } from '@/utils/gear'
// 响应式数据:接口返回列表
const materialList = ref([]) // 材料列表
@@ -121,10 +130,10 @@ const paginationMaterialList = computed(() => {
// 指标卡数据:库存总量、材料类型数、库存操作数、库存变化量
const statCards = ref([
{ title: '库存总量', value: 0, suffix: '件', precision: 2, key: 'totalStock' },
{ title: '库存总量', value: 0, suffix: '件', precision: 0, key: 'totalStock' },
{ title: '材料类型数量', value: 0, key: 'materialTypeCount', precision: 0 },
{ title: '库存操作数', value: 0, key: 'stockOperateCount', precision: 0 },
{ title: '库存变化量', value: 0, suffix: '件', precision: 2, key: 'stockChange' }
{ title: '库存变化量', value: 0, suffix: '件', precision: 0, key: 'stockChange' }
])
// 图表数据源(供子组件使用)

View File

@@ -44,9 +44,21 @@
<raw :data="scope.row" />
</template>
</el-table-column>
<el-table-column label="入库数量" align="center" prop="inNum" />
<el-table-column label="入库单价" align="center" prop="inPrice" />
<el-table-column label="入库金额" align="center" prop="inAmount" />
<el-table-column label="入库数量" align="center" prop="inNum">
<template #default="scope">
{{ formatDecimal(scope.row.inNum) }}
</template>
</el-table-column>
<el-table-column label="入库单价" align="center" prop="inPrice">
<template #default="scope">
{{ formatDecimal(scope.row.inPrice) }}
</template>
</el-table-column>
<el-table-column label="入库金额" align="center" prop="inAmount">
<template #default="scope">
{{ formatDecimal(scope.row.inAmount) }}
</template>
</el-table-column>
<el-table-column label="入库时间" align="center" prop="inTime" width="180">
<template #default="scope">
<span>{{ formatterTime(scope.row.inTime) }}</span>
@@ -111,6 +123,7 @@ import { listPurchaseInDetail, getPurchaseInDetail, delPurchaseInDetail, addPurc
import useUserStore from '@/store/modules/user'
import RawSelector from '@/components/RawSelector/index.vue'
import Raw from '@/components/Renderer/Raw.vue'
import { formatDecimal } from '@/utils/gear'
const userStore = useUserStore()

View File

@@ -47,7 +47,11 @@
<raw :data="scope.row" />
</template>
</el-table-column>
<el-table-column label="出库数量" align="center" prop="outNum" />
<el-table-column label="出库数量" align="center" prop="outNum">
<template #default="scope">
{{ formatDecimal(scope.row.outNum) }}
</template>
</el-table-column>
<el-table-column label="出库原因" align="center" prop="outReason" />
<el-table-column label="操作人" align="center" prop="operator" />
<el-table-column label="出库时间" align="center" prop="outTime" width="180">
@@ -111,6 +115,7 @@ import useUserStore from '@/store/modules/user'
import { computed } from "vue";
import RawSelector from '@/components/RawSelector/index.vue'
import Raw from '@/components/Renderer/Raw.vue'
import { formatDecimal } from '@/utils/gear'
const userStore = useUserStore()

View File

@@ -39,7 +39,11 @@
<el-table-column label="产品名称" align="center" prop="productName" />
<el-table-column label="产品规格" align="center" prop="spec" />
<el-table-column label="产品型号" align="center" prop="model" />
<el-table-column label="产品单价" align="center" prop="unitPrice" />
<el-table-column label="产品单价" align="center" prop="unitPrice">
<template #default="scope">
{{ formatDecimal(scope.row.unitPrice) }}
</template>
</el-table-column>
<el-table-column label="备注" align="center" prop="remark" />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template #default="scope">
@@ -95,7 +99,11 @@
<el-table-column label="配料型号" align="center" prop="model" />
<el-table-column label="厂家" align="center" prop="factory" />
<el-table-column label="计量单位" align="center" prop="unit" />
<el-table-column label="现存库存" align="center" prop="currentStock" />
<el-table-column label="现存库存" align="center" prop="currentStock">
<template #default="scope">
{{ formatDecimal(scope.row.currentStock) }}
</template>
</el-table-column>
<el-table-column label="备注" align="center" prop="remark" />
</el-table>
</div>
@@ -109,6 +117,7 @@
import { listProduct, getProduct, delProduct, addProduct, updateProduct } from "@/api/mat/product";
import bom from "@/views/mat/components/bom.vue";
import StickyDragContainer from "@/components/StickyDragContainer/index.vue";
import { formatDecimal } from '@/utils/gear'
const bomOpen = ref(false);

View File

@@ -8,7 +8,8 @@
<el-input v-model="queryParams.factory" placeholder="请输入供应商" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="配料" prop="materialId">
<raw-selector ref="rawSelector" v-model="queryParams.materialId" placeholder="请选择配料" clearable @keyup.enter="handleQuery" />
<raw-selector ref="rawSelector" v-model="queryParams.materialId" placeholder="请选择配料" clearable
@keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="采购状态" prop="status">
<el-select style="width: 120px" v-model="queryParams.status" placeholder="请选择采购状态" clearable>
@@ -51,13 +52,32 @@
<raw :data="scope.row" />
</template>
</el-table-column>
<el-table-column label="采购总数" align="center" prop="planNum" />
<el-table-column label="已收数量" align="center" prop="receivedNum" />
<el-table-column label="在途数量" align="center" prop="inTransitNum" />
<el-table-column label="采购单价" align="center" prop="purchasePrice" />
<el-table-column label="采购总数" align="center" prop="planNum">
<template #default="scope">
{{ formatDecimal(scope.row.planNum) }}
</template>
</el-table-column>
<el-table-column label="已收数量" align="center" prop="receivedNum">
<template #default="scope">
{{ formatDecimal(scope.row.receivedNum) }}
</template>
</el-table-column>
<el-table-column label="在途数量" align="center" prop="inTransitNum">
<template #default="scope">
{{ formatDecimal(scope.row.inTransitNum) }}
</template>
</el-table-column>
<el-table-column label="采购单价" align="center" prop="purchasePrice">
<template #default="scope">
{{ formatDecimal(scope.row.purchasePrice) }}
</template>
</el-table-column>
<el-table-column label="截止日期" align="center" prop="deadline" width="180">
<template #default="scope">
<span>{{ formatterTime(scope.row.deadline) }}</span>
<!-- 动态绑定样式status为2时显示绿色结合格式化方法传参 -->
<span :class="{ 'deadline-green': scope.row.status === 2 }">
{{ formatterTime(scope.row.deadline, scope.row.status) }}
</span>
</template>
</el-table-column>
<el-table-column label="采购状态" align="center" prop="status">
@@ -139,7 +159,8 @@
<el-input v-model="inForm.materialId" placeholder="请输入配料" />
</el-form-item> -->
<el-form-item label="入库数量" prop="inNum">
<el-input-number style="width: 100%" v-model="inForm.inNum" :placeholder="'请输入入库数量,最大数量为' + maxInNum" :max="maxInNum" :controls="false" />
<el-input-number style="width: 100%" v-model="inForm.inNum" :placeholder="'请输入入库数量,最大数量为' + maxInNum"
:max="maxInNum" :controls="false" />
</el-form-item>
<el-form-item label="入库单价" prop="inPrice">
<el-input v-model="inForm.inPrice" placeholder="请输入入库单价" />
@@ -180,6 +201,7 @@ import RawSelector from '@/components/RawSelector/index.vue'; // 引入组件
import Raw from "@/components/Renderer/Raw.vue"
import useUserStore from '@/store/modules/user'
import { computed } from "vue";
import { formatDecimal } from '@/utils/gear'
// 采购的四个状态
// 1. 在途(刚创建的)
@@ -202,10 +224,44 @@ const total = ref(0);
const title = ref("");
const currentPurchaseId = ref('');
const formatterTime = (time) => {
return proxy.parseTime(time, '{y}-{m}-{d}')
/**
* 截止日期格式化方法
* @param {string/Date} deadline - 截止日期支持YYYY-MM-DD字符串/Date对象
* @param {number} status - 状态值
* @returns {string} 格式化后的显示文本
*/
const formatterTime = (deadline, status) => {
// 边界处理:截止日期为空时返回提示
if (!deadline) return '无截止日期'
// 统一转换为Date对象兼容字符串格式
const deadlineDate = new Date(deadline)
// 时间有效性校验:无效时间返回原数据
if (isNaN(deadlineDate.getTime())) return deadline
// 状态为2时返回格式化的原截止日期YYYY-MM-DD+ 绿色样式由css控制
if (status === 2) {
const year = deadlineDate.getFullYear()
const month = String(deadlineDate.getMonth() + 1).padStart(2, '0')
const day = String(deadlineDate.getDate()).padStart(2, '0')
return `${year}-${month}-${day}`
}
// 状态非2时计算剩余天数并格式化显示
// 获取当前时间取当天0点避免时分秒干扰天数计算
const now = new Date()
const today = new Date(now.getFullYear(), now.getMonth(), now.getDate())
// 计算时间差毫秒转换为天数1天=86400000毫秒
const timeDiff = deadlineDate.getTime() - today.getTime()
const dayDiff = Math.floor(timeDiff / 86400000)
// 按天数分场景显示
if (dayDiff > 0) return `剩余${dayDiff}`
if (dayDiff === 0) return '今日截止'
return `已过期${Math.abs(dayDiff)}`
}
const data = reactive({
form: {},
queryParams: {

View File

@@ -49,8 +49,16 @@
<el-table-column label="配料型号" align="center" prop="model" />
<el-table-column label="厂家" align="center" prop="factory" />
<el-table-column label="计量单位" align="center" prop="unit" />
<el-table-column label="现存库存" align="center" prop="currentStock" />
<el-table-column label="在途数量" align="center" prop="inTransitNum" />
<el-table-column label="现存库存" align="center" prop="currentStock">
<template #default="scope">
{{ formatDecimal(scope.row.currentStock) }}
</template>
</el-table-column>
<el-table-column label="在途数量" align="center" prop="inTransitNum">
<template #default="scope">
{{ formatDecimal(scope.row.inTransitNum) }}
</template>
</el-table-column>
<el-table-column label="备注" align="center" prop="remark" />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template #default="scope">
@@ -174,6 +182,7 @@ import { addPurchaseInDetail } from "@/api/mat/purchaseInDetail";
import { addMaterialOut } from "@/api/mat/materialOut";
import Price from "@/views/mat/components/price.vue";
import RawSelector from "@/components/RawSelector/index.vue";
import { formatDecimal } from '@/utils/gear'
import useUserStore from '@/store/modules/user'