feat: 添加数字格式化工具,支持去掉小数末尾多余的 0 和四舍五入功能
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | /** |
| | | * æ°åå±ç¤ºæ ¼å¼åå·¥å
· |
| | | * |
| | | * 说æï¼å端éé¢/æ°éåæ®µç»ä¸æ 6 ä½å°æ°è¿åï¼å¦ 52333.580000ï¼ï¼ |
| | | * ç´æ¥å±ç¤ºä¼åºç°å¤§éæ æä¹çç»å°¾ 0ï¼è¿éç»ä¸åå±ç¤ºå±å¤çã |
| | | */ |
| | | |
| | | /** |
| | | * 廿尿°æ«å°¾å¤ä½ç 0ï¼æå¤ä¿ç maxDecimals ä½å°æ°ï¼ |
| | | * ä¾ï¼52333.580000 -> 52333.58 ï¼100.000000 -> 100 ï¼0.000000 -> 0 |
| | | * 474235.654230 -> 474235.65423 |
| | | * @param {string|number} value åå§å¼ |
| | | * @param {number} maxDecimals æå¤ä¿ççå°æ°ä½ï¼é»è®¤ 6 |
| | | * @returns {string} æ ¼å¼ååçå符串 |
| | | */ |
| | | export const trimZeros = (value, maxDecimals = 6) => { |
| | | if (value === undefined || value === null || value === "") { |
| | | return "0"; |
| | | } |
| | | const num = typeof value === "number" ? value : Number(value); |
| | | // éæ°åï¼å¦ "-"ã"--"ï¼åæ ·è¿åï¼é¿å
æå ä½ç¬¦æ¾ç¤ºæ 0 |
| | | if (!Number.isFinite(num)) { |
| | | return String(value); |
| | | } |
| | | const decimals = Math.min(20, Math.max(0, Math.floor(maxDecimals))); |
| | | let text = num.toFixed(decimals); |
| | | if (decimals > 0 && text.includes(".")) { |
| | | text = text.replace(/0+$/, "").replace(/\.$/, ""); |
| | | } |
| | | // å¤ç -0.000000 è¿ç±»ç»æ |
| | | if (text === "" || text === "-" || text === "-0") { |
| | | text = "0"; |
| | | } |
| | | return text; |
| | | }; |
| | | |
| | | /** |
| | | * åèäºå
¥å°æå®å°æ°ä½ï¼æåè¿å¶è¯ä¹ï¼ |
| | | * JS åçç toFixed ä¼åäºè¿å¶æµ®ç¹å½±åï¼ä¾å¦ (926163.765).toFixed(2) å¾å° "926163.76"ï¼ |
| | | * èæåè¿å¶åèäºå
¥åºä¸º 926163.77ï¼è¿éç»ä¸æä¸æ°æ®åº ROUND ä¸è´çç»æã |
| | | * @param {string|number} value åå§å¼ |
| | | * @param {number} decimals å°æ°ä½æ°ï¼é»è®¤ 2 |
| | | * @returns {number} åèäºå
¥åçæ°å |
| | | */ |
| | | export const roundHalfUp = (value, decimals = 2) => { |
| | | const num = Number(value); |
| | | const digits = Math.min(20, Math.max(0, Math.floor(decimals))); |
| | | if (!Number.isFinite(num)) { |
| | | return 0; |
| | | } |
| | | // ç§å¦è®¡æ°æ³ï¼å¦ 1e-7ï¼èµ°åç toFixedï¼é¿å
åç¬¦ä¸²æ¼æ¥åº "1e-7e2" |
| | | const text = String(num); |
| | | if (text.includes("e") || text.includes("E")) { |
| | | return Number(num.toFixed(digits)); |
| | | } |
| | | return Number(`${Math.round(Number(`${text}e${digits}`))}e-${digits}`); |
| | | }; |
| | | |
| | | /** |
| | | * åºå®ä¿çæå®å°æ°ä½ï¼ä¸è¶³è¡¥ 0ï¼ |
| | | * ä¾ï¼2296268.351 -> 2296268.35 ï¼decimals = 2ï¼ |
| | | * @param {string|number} value åå§å¼ |
| | | * @param {number} decimals å°æ°ä½æ°ï¼é»è®¤ 2 |
| | | * @returns {string} æ ¼å¼ååçå符串 |
| | | */ |
| | | export const toFixedNumber = (value, decimals = 2) => { |
| | | const num = Number(value); |
| | | const digits = Math.min(20, Math.max(0, Math.floor(decimals))); |
| | | if (!Number.isFinite(num)) { |
| | | return (0).toFixed(digits); |
| | | } |
| | | const text = num.toFixed(digits); |
| | | // é¿å
åºç° "-0.00" è¿ç±»è´é¶æ¾ç¤º |
| | | return parseFloat(text) === 0 ? text.replace(/^-/, "") : text; |
| | | }; |
| | |
| | | import { trimZeros, roundHalfUp } from "./formatNumber.js"; |
| | | |
| | | /** |
| | | * éç¨çè¡¨æ ¼åè®¡æ¹æ³ |
| | | * @param {Object} param - å
å«è¡¨æ ¼åé
ç½®åæ°æ®æºç对象 |
| | | * @param {Array<string>} summaryProps - éè¦æ±æ»çåæ®µåæ°ç» |
| | | * @param {Object} specialFormat - ç¹æ®æ ¼å¼åè§åï¼å段å -> æ ¼å¼åé项ï¼å¦æ¯å¦å»æå°æ°ï¼ |
| | | * æ¯æ { noDecimal: true } åæ´æ¾ç¤º |
| | | * { trimZeros: true, decimalPlaces: 6 } æå¤ä¿ç 6 ä½å°æ°å¹¶å»ææ«å°¾å¤ä½ç 0 |
| | | * { roundEach: 2 } æ¯è¡å
æ 2 ä½å°æ°åèäºå
¥åæ±åï¼ |
| | | * ç¨äºéé¢åï¼ä¿è¯å计ä¸åå
å±ç¤ºå¼ç¸å å®å
¨ä¸è´ |
| | | * { formatter: fn } èªå®ä¹æ ¼å¼å彿°ï¼ä¼å
级æé« |
| | | * { decimalPlaces: 2 } åºå®ä¿ç 2 ä½å°æ°ï¼é»è®¤ï¼ |
| | | * @returns {Array} åè®¡è¡æ°æ® |
| | | */ |
| | | const summarizeTable = (param, summaryProps, specialFormat = {}) => { |
| | |
| | | } |
| | | const prop = column.property; |
| | | if (summaryProps.includes(prop)) { |
| | | const values = data.map((item) => Number(item[prop])); |
| | | const rule = specialFormat[prop]; |
| | | const values = data.map((item) => { |
| | | const val = Number(item[prop]); |
| | | // NaN ä¿æ NaNï¼ä¾¿äºä¸é¢å¤æãæ´åé½ä¸æ¯æ°åã |
| | | if (Number.isNaN(val)) return NaN; |
| | | return rule && rule.roundEach != null |
| | | ? roundHalfUp(val, rule.roundEach) |
| | | : val; |
| | | }); |
| | | // åªå¯¹æææ°åè¿è¡æ±å |
| | | if (!values.every(isNaN)) { |
| | | const sum = values.reduce( |
| | |
| | | if (specialFormat[prop] && specialFormat[prop].noDecimal) { |
| | | // 妿æå®äºä¸éè¦ä¿çå°æ°ï¼åç´æ¥è½¬æ¢ä¸ºæ´æ° |
| | | sums[index] = Math.round(sum).toString(); |
| | | } else if ( |
| | | specialFormat[prop] && |
| | | typeof specialFormat[prop].formatter === "function" |
| | | ) { |
| | | // èªå®ä¹æ ¼å¼å彿°ä¼å
|
| | | sums[index] = specialFormat[prop].formatter(sum); |
| | | } else if (specialFormat[prop] && specialFormat[prop].trimZeros) { |
| | | // æå®äºå»ææ«å°¾å¤ä½ç 0ï¼æå¤ä¿ç decimalPlaces ä½ï¼é»è®¤ 6 ä½ï¼ |
| | | sums[index] = trimZeros(sum, specialFormat[prop].decimalPlaces ?? 6); |
| | | } else { |
| | | // é»è®¤ä¿ç两ä½å°æ° |
| | | sums[index] = parseFloat(sum).toFixed( |
| | |
| | | import { QuestionFilled, TrendCharts, Sell } from "@element-plus/icons-vue"; |
| | | import Echarts from "@/components/Echarts/echarts.vue"; |
| | | import { accountStatementDetailsByMonth } from "@/api/financialManagement/financialStatements"; |
| | | import { toFixedNumber } from "@/utils/formatNumber.js"; |
| | | import dayjs from "dayjs"; |
| | | |
| | | const { proxy } = getCurrentInstance(); |
| | |
| | | }, |
| | | ]); |
| | | const barYAxis = [{ type: "value", name: "éé¢ (å
)" }]; |
| | | const barTooltip = { trigger: "axis", axisPointer: { type: "shadow" } }; |
| | | const barTooltip = { |
| | | trigger: "axis", |
| | | axisPointer: { type: "shadow" }, |
| | | valueFormatter: value => formatMoney(value), |
| | | }; |
| | | const barSeries = computed(() => [ |
| | | { |
| | | name: "åºæ¶è´¦æ¬¾", |
| | |
| | | }, |
| | | ]); |
| | | const trendYAxis = [{ type: "value", name: "éé¢ (å
)" }]; |
| | | const trendTooltip = { trigger: "axis" }; |
| | | const trendTooltip = { |
| | | trigger: "axis", |
| | | valueFormatter: value => formatMoney(value), |
| | | }; |
| | | const trendSeries = computed(() => [ |
| | | { |
| | | name: "æ»è¥æ¶", |
| | |
| | | ]); |
| | | |
| | | // --- å
¬ç¨é»è¾ --- |
| | | // éé¢ç»ä¸æ 2 ä½å°æ°å±ç¤ºï¼ä¸åæ¥å£è¿å精度影åï¼ |
| | | const formatMoney = val => { |
| | | return val; |
| | | return toFixedNumber(val, 2); |
| | | }; |
| | | |
| | | const handleDateChange = val => { |
| | |
| | | <el-table-column label="åºä»éé¢(å
)" |
| | | prop="payableAmount" |
| | | show-overflow-tooltip> |
| | | <template #default="{ row, column }"> |
| | | <template #default="{ row }"> |
| | | <el-text type="danger"> |
| | | {{ formattedNumber(row, column, row.payableAmount) }} |
| | | {{ formatPayable(row.payableAmount) }} |
| | | </el-text> |
| | | </template> |
| | | </el-table-column> |
| | |
| | | @pagination="sonPaginationSearch"> |
| | | <template #payableAmountSlot="{ row }"> |
| | | <el-text type="danger"> |
| | | {{ parseFloat(row.payableAmount).toFixed(6) }} |
| | | {{ formatPayable(row.payableAmount) }} |
| | | </el-text> |
| | | </template> |
| | | <template #paymentActionSlot="{ row }"> |
| | |
| | | </el-form-item> |
| | | <el-form-item label="仿¬¾éé¢ï¼" prop="paymentAmount"> |
| | | <el-input-number style="width:100%" v-model="paymentForm.paymentAmount" :min="0" :precision="6" :max="Math.max(0,Number(currentPaymentRow.payableAmount)||0)" placeholder="请è¾å
¥ä»æ¬¾éé¢" controls-position="right" /> |
| | | <div style="color:#e6a23c;font-size:12px;margin-top:4px">å½åå¯ä»æ¬¾ä½é¢ï¼{{ Math.max(0,Number(currentPaymentRow.payableAmount)||0).toFixed(6) }} å
</div> |
| | | <div style="color:#e6a23c;font-size:12px;margin-top:4px">å½åå¯ä»æ¬¾ä½é¢ï¼{{ formatPayable(Math.max(0,Number(currentPaymentRow.payableAmount)||0)) }} å
</div> |
| | | </el-form-item> |
| | | <el-form-item label="仿¬¾æ¹å¼ï¼" prop="paymentMethod"> |
| | | <el-select v-model="paymentForm.paymentMethod" placeholder="è¯·éæ©ä»æ¬¾æ¹å¼" style="width:100%" clearable> |
| | |
| | | savePayment, |
| | | } from "@/api/procurementManagement/paymentLedger.js"; |
| | | import Pagination from "../../../components/PIMTable/Pagination.vue"; |
| | | import { trimZeros, roundHalfUp } from "@/utils/formatNumber.js"; |
| | | |
| | | const tableData = ref([]); |
| | | const tableLoading = ref(false); |
| | |
| | | prop: "contractAmount", |
| | | width: 200, |
| | | formatData: params => { |
| | | return params ? parseFloat(params).toFixed(6) : 0; |
| | | return trimZeros(params, 6); |
| | | }, |
| | | }, |
| | | { |
| | |
| | | prop: "paymentAmount", |
| | | width: 200, |
| | | formatData: params => { |
| | | return params ? parseFloat(params).toFixed(6) : 0; |
| | | return trimZeros(params, 6); |
| | | }, |
| | | }, |
| | | { |
| | |
| | | const currentPaymentRow = ref({}); |
| | | const paymentFormRef = ref(null); |
| | | const paymentForm = reactive({ paymentDate:"", paymentAmount:undefined, paymentMethod:"", remark:"" }); |
| | | const validatePaymentAmount = (_,v,cb) => { if(!v) return cb(new Error("请è¾å
¥ä»æ¬¾éé¢")); const m=Math.max(0,Number(currentPaymentRow.value.payableAmount)||0); if(v>m) return cb(new Error(`仿¬¾éé¢ä¸è½è¶
è¿å¯ä»æ¬¾ä½é¢ ${m.toFixed(6)} å
`)); cb(); }; |
| | | const validatePaymentAmount = (_,v,cb) => { if(!v) return cb(new Error("请è¾å
¥ä»æ¬¾éé¢")); const m=Math.max(0,Number(currentPaymentRow.value.payableAmount)||0); if(v>m) return cb(new Error(`仿¬¾éé¢ä¸è½è¶
è¿å¯ä»æ¬¾ä½é¢ ${trimZeros(m, 6)} å
`)); cb(); }; |
| | | const paymentRules = { paymentDate:[{required:true,message:"è¯·éæ©ä»æ¬¾æ¥æ",trigger:"change"}], paymentAmount:[{required:true,validator:validatePaymentAmount,trigger:"blur"}], paymentMethod:[{required:true,message:"è¯·éæ©ä»æ¬¾æ¹å¼",trigger:"change"}] }; |
| | | const openPaymentDialog = r => { currentPaymentRow.value=r; paymentForm.paymentDate=""; paymentForm.paymentAmount=undefined; paymentForm.paymentMethod=""; paymentForm.remark=""; paymentDialogVisible.value=true; }; |
| | | const closePaymentDialog = () => { paymentFormRef.value?.resetFields(); paymentDialogVisible.value=false; }; |
| | |
| | | param, |
| | | ["contractAmounts", "paymentAmount", "payableAmount"], |
| | | { |
| | | contractAmounts: { decimalPlaces: 6 }, |
| | | paymentAmount: { decimalPlaces: 6 }, |
| | | payableAmount: { decimalPlaces: 6 }, |
| | | contractAmounts: { decimalPlaces: 6, trimZeros: true }, |
| | | paymentAmount: { decimalPlaces: 6, trimZeros: true }, |
| | | // åºä»éé¢éè¡æååæ´ååæ±åï¼ä¿è¯å计 = åå
å±ç¤ºå¼ä¹å |
| | | payableAmount: { roundEach: 2, formatter: formatPayable }, |
| | | ticketsNum: { noDecimal: true }, // ä¸ä¿çå°æ° |
| | | futureTickets: { noDecimal: true }, // ä¸ä¿çå°æ° |
| | | } |
| | |
| | | }; |
| | | // å表åè®¡æ¹æ³ |
| | | const summarizeMainTable1 = param => { |
| | | let summarizeTable = proxy.summarizeTable( |
| | | return proxy.summarizeTable( |
| | | param, |
| | | ["contractAmount", "invoiceAmount", "paymentAmount"], |
| | | ["contractAmount", "invoiceAmount", "paymentAmount", "payableAmount"], |
| | | { |
| | | contractAmount: { decimalPlaces: 6 }, |
| | | invoiceAmount: { decimalPlaces: 6 }, |
| | | paymentAmount: { decimalPlaces: 6 }, |
| | | contractAmount: { decimalPlaces: 6, trimZeros: true }, |
| | | invoiceAmount: { decimalPlaces: 6, trimZeros: true }, |
| | | paymentAmount: { decimalPlaces: 6, trimZeros: true }, |
| | | // åºä»éé¢éè¡æååæ´ååæ±åï¼ä¿è¯å计 = åå
å±ç¤ºå¼ä¹å |
| | | payableAmount: { roundEach: 2, formatter: formatPayable }, |
| | | ticketsNum: { noDecimal: true }, // ä¸ä¿çå°æ° |
| | | futureTickets: { noDecimal: true }, // ä¸ä¿çå°æ° |
| | | } |
| | | ); |
| | | if (originalTableDataSon.value.length > 0) { |
| | | summarizeTable[summarizeTable.length - 1] = |
| | | originalTableDataSon.value[ |
| | | originalTableDataSon.value.length - 1 |
| | | ].payableAmount.toFixed(6); |
| | | } else { |
| | | summarizeTable[summarizeTable.length - 1] = 0.0; |
| | | } |
| | | return summarizeTable; |
| | | }; |
| | | /** æç´¢æé®æä½ */ |
| | | const handleQuery = () => { |
| | |
| | | }; |
| | | const formattedNumber = (row, column, cellValue) => { |
| | | if (column.property !== "supplierName") { |
| | | return parseFloat(cellValue).toFixed(6); |
| | | return trimZeros(cellValue, 6); |
| | | } else { |
| | | return cellValue; |
| | | } |
| | | }; |
| | | // åºä»é颿¯éé¢åæ®µï¼æå¤ä¿ç 2 ä½å°æ°ï¼åèäºå
¥å°åï¼ã |
| | | // åºä»éé¢ = å(å
¥åºéé¢, ååéé¢)è¾å°è
â 已仿¬¾ â éè´§éé¢ï¼å
¶ä¸å
¥åºéé¢ç± 6 ä½å°æ°çå«ç¨åä»·ç´¯å èæ¥ï¼ |
| | | // ä¼å¸¦åºãåãå以ä¸çå°æ°ï¼é¡µé¢ä¸ç»ä¸æåå±ç¤ºã |
| | | const formatPayable = value => { |
| | | return trimZeros(roundHalfUp(value, 2), 2); |
| | | }; |
| | | getList(); |
| | | </script> |
| | | |
| | |
| | | import { modelList, productTreeList } from "@/api/basicData/product.js"; |
| | | import dayjs from "dayjs"; |
| | | import FileUpload from "@/components/AttachmentUpload/file/index.vue"; |
| | | import { trimZeros } from "@/utils/formatNumber.js"; |
| | | |
| | | const userStore = useUserStore(); |
| | | |
| | |
| | | }; |
| | | |
| | | const formattedNumber = (row, column, cellValue) => { |
| | | return parseFloat(cellValue).toFixed(6); |
| | | return trimZeros(cellValue, 6); |
| | | }; |
| | | // æ¥è¯¢å表 |
| | | /** æç´¢æé®æä½ */ |
| | |
| | | "futureTicketsAmount", |
| | | ], |
| | | { |
| | | taxInclusiveUnitPrice: { decimalPlaces: 6 }, |
| | | taxInclusiveTotalPrice: { decimalPlaces: 6 }, |
| | | taxExclusiveTotalPrice: { decimalPlaces: 6 }, |
| | | ticketsAmount: { decimalPlaces: 6 }, |
| | | futureTicketsAmount: { decimalPlaces: 6 }, |
| | | taxInclusiveUnitPrice: { decimalPlaces: 6, trimZeros: true }, |
| | | taxInclusiveTotalPrice: { decimalPlaces: 6, trimZeros: true }, |
| | | taxExclusiveTotalPrice: { decimalPlaces: 6, trimZeros: true }, |
| | | ticketsAmount: { decimalPlaces: 6, trimZeros: true }, |
| | | futureTicketsAmount: { decimalPlaces: 6, trimZeros: true }, |
| | | ticketsNum: { noDecimal: true }, // ä¸ä¿çå°æ° |
| | | futureTickets: { noDecimal: true }, // ä¸ä¿çå°æ° |
| | | } |
| | |
| | | param, |
| | | ["contractAmount", "netContractAmount"], |
| | | { |
| | | contractAmount: { decimalPlaces: 6 }, |
| | | netContractAmount: { decimalPlaces: 6 }, |
| | | contractAmount: { decimalPlaces: 6, trimZeros: true }, |
| | | netContractAmount: { decimalPlaces: 6, trimZeros: true }, |
| | | } |
| | | ); |
| | | }; |
| | |
| | | "taxExclusiveTotalPrice", |
| | | ], |
| | | { |
| | | taxInclusiveUnitPrice: { decimalPlaces: 6 }, |
| | | taxInclusiveTotalPrice: { decimalPlaces: 6 }, |
| | | taxExclusiveTotalPrice: { decimalPlaces: 6 }, |
| | | taxInclusiveUnitPrice: { decimalPlaces: 6, trimZeros: true }, |
| | | taxInclusiveTotalPrice: { decimalPlaces: 6, trimZeros: true }, |
| | | taxExclusiveTotalPrice: { decimalPlaces: 6, trimZeros: true }, |
| | | } |
| | | ); |
| | | }; |
| | |
| | | prop="receiptableAmount" |
| | | show-overflow-tooltip |
| | | width="200"> |
| | | <template #default="{ row, column }"> |
| | | <template #default="{ row }"> |
| | | <el-text type="danger"> |
| | | {{ formattedNumber(row, column, row.receiptableAmount) }} |
| | | {{ formatReceivable(row.receiptableAmount) }} |
| | | </el-text> |
| | | </template> |
| | | </el-table-column> |
| | |
| | | prop="receiptableAmount" |
| | | show-overflow-tooltip |
| | | width="200"> |
| | | <template #default="{ row, column }"> |
| | | <template #default="{ row }"> |
| | | <el-text type="danger"> |
| | | {{ formattedNumber(row, column, row.receiptableAmount) }} |
| | | {{ formatReceivable(row.receiptableAmount) }} |
| | | </el-text> |
| | | </template> |
| | | </el-table-column> |
| | |
| | | saveReceiptPayment, |
| | | } from "@/api/salesManagement/indicatorStats.js"; |
| | | import Pagination from "../../../components/PIMTable/Pagination.vue"; |
| | | import { trimZeros } from "@/utils/formatNumber.js"; |
| | | const { proxy } = getCurrentInstance(); |
| | | const tableData = ref([]); |
| | | const receiptRecord = ref([]); |
| | |
| | | const currentRow = ref({}); |
| | | const receiptFormRef = ref(null); |
| | | const receiptForm = reactive({ paymentDate:"", paymentAmount:undefined, paymentMethod:"", remark:"" }); |
| | | const validatePaymentAmount = (_,v,cb) => { if(!v) return cb(new Error("请è¾å
¥å款éé¢")); const m=Math.max(0,(Number(currentRow.value.receiptableAmount)||0)-(Number(currentRow.value.receiptPaymentAmount)||0)); if(v>m) return cb(new Error(`忬¾éé¢ä¸è½è¶
è¿å¯å款ä½é¢ ${m.toFixed(6)} å
`)); cb(); }; |
| | | const validatePaymentAmount = (_,v,cb) => { if(!v) return cb(new Error("请è¾å
¥å款éé¢")); const m=Math.max(0,(Number(currentRow.value.receiptableAmount)||0)-(Number(currentRow.value.receiptPaymentAmount)||0)); if(v>m) return cb(new Error(`忬¾éé¢ä¸è½è¶
è¿å¯å款ä½é¢ ${trimZeros(m, 6)} å
`)); cb(); }; |
| | | const receiptRules = { paymentDate:[{required:true,message:"è¯·éæ©åæ¬¾æ¥æ",trigger:"change"}], paymentAmount:[{required:true,validator:validatePaymentAmount,trigger:"blur"}], paymentMethod:[{required:true,message:"è¯·éæ©åæ¬¾æ¹å¼",trigger:"change"}] }; |
| | | const openReceiptDialog = r => { currentRow.value=r; receiptForm.paymentDate=""; receiptForm.paymentAmount=undefined; receiptForm.paymentMethod=""; receiptForm.remark=""; receiptDialogVisible.value=true; }; |
| | | const closeReceiptDialog = () => { receiptFormRef.value?.resetFields(); receiptDialogVisible.value=false; }; |
| | |
| | | }); |
| | | }; |
| | | const formattedNumber = (row, column, cellValue) => { |
| | | return cellValue ? parseFloat(cellValue).toFixed(6) : "0.000000"; |
| | | return trimZeros(cellValue, 6); |
| | | }; |
| | | // åºæ¶éé¢ = å·²åºåºéé¢ â å·²é货款 â 已忬¾éé¢ã |
| | | // åºåºéé¢ç± 6 ä½å°æ°çå«ç¨åä»·ç´¯å èæ¥ï¼ä¼æ®çãåã以ä¸çé¶å¤´ï¼å¦ 0.0045ã0.004ï¼ï¼ |
| | | // è忬¾æ¯æåå½å
¥çæ´æ°éé¢ï¼ç¸ååå°±ä¼åºç°è¿äºæ æä¹ç尾差ã |
| | | // åºæ¶é颿¬èº«åªç²¾ç¡®å°åï¼å以ä¸ç尾差ä¸è®¡å
¥ï¼ç»ä¸æ 0 å±ç¤ºï¼å端 SQL ä¹åäºåæ ·å¤çï¼ã |
| | | const formatReceivable = value => { |
| | | const num = Number(value); |
| | | if (!Number.isFinite(num) || Math.abs(num) < 0.01) { |
| | | return "0"; |
| | | } |
| | | return trimZeros(num, 6); |
| | | }; |
| | | // 主表åè®¡æ¹æ³ |
| | | const summarizeMainTable = param => { |
| | |
| | | param, |
| | | ["invoiceTotal", "receiptPaymentAmount", "unReceiptPaymentAmount"], |
| | | { |
| | | invoiceTotal: { decimalPlaces: 6 }, |
| | | receiptPaymentAmount: { decimalPlaces: 6 }, |
| | | unReceiptPaymentAmount: { decimalPlaces: 6 }, |
| | | invoiceTotal: { decimalPlaces: 6, trimZeros: true }, |
| | | receiptPaymentAmount: { decimalPlaces: 6, trimZeros: true }, |
| | | unReceiptPaymentAmount: { decimalPlaces: 6, trimZeros: true }, |
| | | ticketsNum: { noDecimal: true }, // ä¸ä¿çå°æ° |
| | | futureTickets: { noDecimal: true }, // ä¸ä¿çå°æ° |
| | | } |
| | |
| | | param, |
| | | ["contractAmount", "receiptPaymentAmount", "receiptableAmount"], |
| | | { |
| | | contractAmount: { decimalPlaces: 6 }, |
| | | receiptPaymentAmount: { decimalPlaces: 6 }, |
| | | receiptableAmount: { decimalPlaces: 6 }, |
| | | contractAmount: { decimalPlaces: 6, trimZeros: true }, |
| | | receiptPaymentAmount: { decimalPlaces: 6, trimZeros: true }, |
| | | receiptableAmount: { formatter: formatReceivable }, |
| | | ticketsNum: { noDecimal: true }, // ä¸ä¿çå°æ° |
| | | futureTickets: { noDecimal: true }, // ä¸ä¿çå°æ° |
| | | } |
| | |
| | | align="right" |
| | | > |
| | | <template #default="scope"> |
| | | {{ Number(scope.row.totalAmount ?? 0).toFixed(6) }} |
| | | {{ trimZeros(scope.row.totalAmount, 6) }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column fixed="right" label="æä½" width="120" align="center"> |
| | |
| | | <td>{{ product.productCategory || "" }}</td> |
| | | <td>{{ product.specificationModel || "" }}</td> |
| | | <td>{{ product.unit || "" }}</td> |
| | | <td>{{ product.taxInclusiveUnitPrice || "0" }}</td> |
| | | <td>{{ product.quantity || "0" }}</td> |
| | | <td>{{ product.taxInclusiveTotalPrice || "0" }}</td> |
| | | <td>{{ trimZeros(product.taxInclusiveUnitPrice, 6) }}</td> |
| | | <td>{{ trimZeros(product.quantity, 6) }}</td> |
| | | <td> |
| | | {{ trimZeros(product.taxInclusiveTotalPrice, 6) }} |
| | | </td> |
| | | </tr> |
| | | <tr v-if="!item.products || item.products.length === 0"> |
| | | <td colspan="6" style="text-align: center; color: #999"> |
| | |
| | | import FileUpload from "@/components/AttachmentUpload/file/index.vue"; |
| | | import ImageUpload from "@/components/AttachmentUpload/image/index.vue"; |
| | | import { getCurrentDate } from "@/utils/index.js"; |
| | | import { trimZeros } from "@/utils/formatNumber.js"; |
| | | import { listCustomer } from "@/api/basicData/customer.js"; |
| | | |
| | | const FileList = defineAsyncComponent(() => |
| | |
| | | }); |
| | | }; |
| | | const formattedNumber = (row, column, cellValue) => { |
| | | if (cellValue === undefined || cellValue === null || cellValue === "") { |
| | | return "0.000000"; |
| | | } |
| | | return parseFloat(cellValue).toFixed(6); |
| | | return trimZeros(cellValue, 6); |
| | | }; |
| | | const findLedgerRecordByRow = (row) => { |
| | | if (!row) return null; |
| | |
| | | param, |
| | | ["contractAmount", "taxInclusiveTotalPrice", "taxExclusiveTotalPrice"], |
| | | { |
| | | contractAmount: { decimalPlaces: 6 }, |
| | | taxInclusiveTotalPrice: { decimalPlaces: 6 }, |
| | | taxExclusiveTotalPrice: { decimalPlaces: 6 }, |
| | | contractAmount: { decimalPlaces: 6, trimZeros: true }, |
| | | taxInclusiveTotalPrice: { decimalPlaces: 6, trimZeros: true }, |
| | | taxExclusiveTotalPrice: { decimalPlaces: 6, trimZeros: true }, |
| | | } |
| | | ); |
| | | }; |
| | |
| | | "taxExclusiveTotalPrice", |
| | | ], |
| | | { |
| | | taxInclusiveUnitPrice: { decimalPlaces: 6 }, |
| | | taxInclusiveTotalPrice: { decimalPlaces: 6 }, |
| | | taxExclusiveTotalPrice: { decimalPlaces: 6 }, |
| | | taxInclusiveUnitPrice: { decimalPlaces: 6, trimZeros: true }, |
| | | taxInclusiveTotalPrice: { decimalPlaces: 6, trimZeros: true }, |
| | | taxExclusiveTotalPrice: { decimalPlaces: 6, trimZeros: true }, |
| | | } |
| | | ); |
| | | }; |
| | |
| | | const total = products.reduce((sum, product) => { |
| | | return sum + (parseFloat(product.quantity) || 0); |
| | | }, 0); |
| | | return total.toFixed(6); |
| | | return trimZeros(total, 6); |
| | | }; |
| | | |
| | | // 计ç®äº§åæ»éé¢ |
| | |
| | | const total = products.reduce((sum, product) => { |
| | | return sum + (parseFloat(product.taxInclusiveTotalPrice) || 0); |
| | | }, 0); |
| | | return total.toFixed(6); |
| | | return trimZeros(total, 6); |
| | | }; |
| | | |
| | | // ç¨äºæå°ç计ç®å½æ° |
| | |
| | | const total = products.reduce((sum, product) => { |
| | | return sum + (parseFloat(product.quantity) || 0); |
| | | }, 0); |
| | | return total.toFixed(6); |
| | | return trimZeros(total, 6); |
| | | }; |
| | | |
| | | const getTotalAmountForPrint = (products) => { |
| | |
| | | const total = products.reduce((sum, product) => { |
| | | return sum + (parseFloat(product.taxInclusiveTotalPrice) || 0); |
| | | }, 0); |
| | | return total.toFixed(6); |
| | | return trimZeros(total, 6); |
| | | }; |
| | | |
| | | const mathNum = () => { |
| | |
| | | </el-table-column> |
| | | <el-table-column prop="totalAmount" label="æ¥ä»·éé¢" width="120"> |
| | | <template #default="scope"> |
| | | ¥{{ scope.row.totalAmount.toFixed(6) }} |
| | | ¥{{ trimZeros(scope.row.totalAmount, 6) }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="æä½" width="200" fixed="right" align="center"> |
| | |
| | | <!-- <el-tag :type="getStatusType(currentQuotation.status)">{{ currentQuotation.status }}</el-tag>--> |
| | | <!-- </el-descriptions-item>--> |
| | | <el-descriptions-item label="æ¥ä»·æ»é¢" :span="2"> |
| | | <span style="font-size: 18px; color: #e6a23c; font-weight: bold;">Â¥{{ currentQuotation.totalAmount?.toFixed(6) }}</span> |
| | | <span style="font-size: 18px; color: #e6a23c; font-weight: bold;">Â¥{{ trimZeros(currentQuotation.totalAmount, 6) }}</span> |
| | | </el-descriptions-item> |
| | | </el-descriptions> |
| | | |
| | |
| | | <el-table-column prop="unit" label="åä½" /> |
| | | <el-table-column prop="unitPrice" label="åä»·"> |
| | | <template #default="scope"> |
| | | ¥{{ scope.row.unitPrice.toFixed(6) }} |
| | | ¥{{ trimZeros(scope.row.unitPrice, 6) }} |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | |
| | | import {modelList, productTreeList} from "@/api/basicData/product.js"; |
| | | import {listCustomer} from "@/api/basicData/customer.js"; |
| | | import { userListNoPage } from "@/api/system/user.js"; |
| | | import { trimZeros } from "@/utils/formatNumber.js"; |
| | | |
| | | // ååºå¼æ°æ® |
| | | const loading = ref(false) |