feat(contract): 启用产品内容组件并优化合同相关功能

- 在合同页面启用ProductContent组件替代注释代码
- 优化ProductContent组件数值计算和空值处理
- 修改ContractList组件从productContent字段获取数据
- 在OrderDetail组件添加"写入合同"功能
- 优化ReceiveTable组件未收款金额计算逻辑
This commit is contained in:
2026-04-23 11:47:30 +08:00
parent 8897a2ad9f
commit 84c26a2990
6 changed files with 186 additions and 89 deletions

View File

@@ -20,12 +20,12 @@
<!-- <el-table-column label="原料规格" align="center" prop="rawMaterialSpec" /> -->
<el-table-column label="宽度公差" align="center" prop="widthTolerance" />
<el-table-column label="厚度公差" align="center" prop="thicknessTolerance" />
<el-table-column label="材质" align="center" prop="material" />
<el-table-column label="重量" align="center" prop="weight" />
<el-table-column label="含税单价(元/吨)" align="center" prop="contractPrice" />
<el-table-column label="含税总额" align="center">
<template slot-scope="scope">
<template slot-scope="scope">
{{ scope.row.weight * scope.row.contractPrice }}
</template>
</el-table-column>
@@ -36,12 +36,14 @@
<el-table-column label="切边要求" align="center" prop="edgeCuttingReq" />
<el-table-column label="用途" align="center" prop="purpose" />
<el-table-column label="特殊要求" align="center" prop="specialRequire" />
<el-table-column label="备注" align="center" prop="remark" />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" v-if="editable">
<template slot-scope="scope">
<el-button size="mini" type="text" icon="el-icon-plus"
@click="handleWriteToContract(scope.row)">写入合同</el-button>
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)">修改</el-button>
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)">删除</el-button>
</template>
@@ -77,17 +79,17 @@
<el-input v-model="form.material" placeholder="请输入材质" />
</el-form-item>
<el-form-item label="重量" prop="weight">
<el-input v-model="form.weight" placeholder="请输入重量" />
<el-input type="number" v-model="form.weight" placeholder="请输入重量" />
</el-form-item>
<el-form-item label="含税单价(元/吨)" prop="contractPrice">
<el-input v-model="form.contractPrice" placeholder="请输入含税单价" />
<el-input type="number" v-model="form.contractPrice" placeholder="请输入含税单价" />
</el-form-item>
<el-form-item label="无税单价(元/吨)" prop="itemAmount">
<el-input v-model="form.itemAmount" placeholder="请输入无税单价" />
<el-input type="number" v-model="form.itemAmount" placeholder="请输入无税单价" />
</el-form-item>
<el-form-item label="卷数" prop="productNum">
<el-input v-model="form.productNum" placeholder="请输入卷数" />
<el-input type="number" v-model="form.productNum" placeholder="请输入卷数" />
</el-form-item>
<el-form-item label="表面处理" prop="surfaceTreatment">
<el-input v-model="form.surfaceTreatment" placeholder="请输入表面处理" />
@@ -129,7 +131,7 @@
<script>
import { listOrderItem, getOrderItem } from "@/api/crm/orderItem";
import { actions, ORDER_ACTIONS } from "../js/actions";
import { getOrder } from "@/api/crm/order";
import { getOrder, updateOrder } from "@/api/crm/order";
import OrderPrinter from "./OrderPrinter.vue";
export default {
@@ -186,41 +188,9 @@ export default {
productType: [
{ required: true, message: "请输入产品类型", trigger: "blur" }
],
// productNum: [
// { required: true, message: "请输入产品数量", trigger: "blur" }
// ],
// rawMaterialSpec: [
// { required: true, message: "请输入原料规格", trigger: "blur" }
// ],
// finishedProductSpec: [
// { required: true, message: "请输入成品规格", trigger: "blur" }
// ],
// 重量和合同定价不能为空,且必须是数字,最多两位小数
// weight: [
// { required: true, message: "请输入重量", trigger: "blur" },
// // 必须是数字,最多两位小数,使用自定义的校验规则
// {
// validator: (rule, value, callback) => {
// if (!/^\d+(\.\d{1,2,3})?$/.test(value)) {
// callback(new Error("请输入最多三位小数的数字"));
// } else {
// callback();
// }
// }, trigger: "change"
// }
// ],
contractPrice: [
{ required: true, message: "请输入合同定价", trigger: "blur" },
// 必须是数字,最多两位小数,使用自定义的校验规则
{
validator: (rule, value, callback) => {
if (!/^\d+(\.\d{1,2,3})?$/.test(value)) {
callback(new Error("请输入最多三位小数的数字"));
} else {
callback();
}
}, trigger: "change"
}
],
},
orderContent: {},
@@ -234,6 +204,9 @@ export default {
// if (newVal !== oldVal) {
this.queryParams.orderId = newVal;
this.getList();
getOrder(this.orderId).then(response => {
this.orderContent = response.data;
});
// }
},
immediate: true
@@ -301,6 +274,127 @@ export default {
this.orderLoading = false;
});
},
// 计算大写金额
totalAmountInWords(amountStr) {
const amount = parseFloat(amountStr);
if (isNaN(amount)) return '无效的金额格式';
if (amount === 0) return '零元整';
const digits = ['零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖'];
const units = ['', '拾', '佰', '仟'];
const bigUnits = ['', '万', '亿'];
let integerPart = Math.floor(amount);
let decimalPart = Math.round((amount - integerPart) * 100);
let result = '';
// 处理整数部分
if (integerPart > 0) {
let unitIndex = 0;
let bigUnitIndex = 0;
while (integerPart > 0) {
let section = integerPart % 10000;
if (section > 0) {
let sectionResult = '';
let temp = section;
let unitIndexInSection = 0;
while (temp > 0) {
let digit = temp % 10;
if (digit > 0) {
sectionResult = digits[digit] + units[unitIndexInSection] + sectionResult;
} else {
// 避免连续的零
if (sectionResult && !sectionResult.startsWith('零')) {
sectionResult = '零' + sectionResult;
}
}
temp = Math.floor(temp / 10);
unitIndexInSection++;
}
result = sectionResult + bigUnits[bigUnitIndex] + result;
}
integerPart = Math.floor(integerPart / 10000);
bigUnitIndex++;
}
result += '元';
}
// 处理小数部分
if (decimalPart === 0) {
result += '整';
} else {
if (decimalPart >= 10) {
result += digits[Math.floor(decimalPart / 10)] + '角';
}
if (decimalPart % 10 > 0) {
result += digits[decimalPart % 10] + '分';
}
}
return result;
},
async handleWriteToContract(row) {
const { data } = await getOrder(this.orderId);
let productContent = data.productContent;
try {
if (!productContent) {
productContent = {
productName: '',
products: [{
spec: row.finishedProductSpec || '',
material: row.material || '',
quantity: parseFloat(row.weight) || 0,
taxPrice: parseFloat(row.contractPrice) || 0,
noTaxPrice: parseFloat(row.itemAmount) || 0,
taxTotal: parseFloat(row.contractPrice) || 0 * (parseFloat(row.weight) || 0),
remark: row.remark || ''
}],
remark: '',
totalQuantity: parseFloat(row.weight) || 0,
totalTaxTotal: parseFloat(row.contractPrice) || 0 * (parseFloat(row.weight) || 0),
totalAmountInWords: this.totalAmountInWords(parseFloat(row.contractPrice) || 0 * (parseFloat(row.weight) || 0)).toString()
};
} else {
productContent = JSON.parse(productContent);
productContent.products.push({
spec: row.finishedProductSpec || '',
material: row.material || '',
quantity: parseFloat(row.weight) || 0,
taxPrice: parseFloat(row.contractPrice) || 0,
noTaxPrice: parseFloat(row.itemAmount) || 0,
taxTotal: parseFloat(row.contractPrice) || 0 * (parseFloat(row.weight) || 0),
remark: row.remark || ''
});
// 将现有的全部加和计算
productContent.totalQuantity = productContent.products.reduce((acc, cur) => acc + (parseFloat(cur.quantity) || 0), 0);
console.log(productContent.totalQuantity);
productContent.totalTaxTotal = productContent.products.reduce((acc, cur) => acc + (parseFloat(cur.taxTotal) || 0), 0);
productContent.totalAmountInWords = this.totalAmountInWords(productContent.totalTaxTotal).toString();
}
console.log(productContent);
const jsonContent = JSON.stringify(productContent, null, 2);
console.log(jsonContent);
updateOrder({
...this.orderContent,
productContent: jsonContent
}).then(response => {
this.$modal.msgSuccess("写入成功,请刷新合同内容查看");
});
} catch (error) {
console.error(error);
this.$modal.msgError("产品内容格式错误");
return;
}
console.log(productContent.products);
},
printOrder() {
this.$refs["printer"].print();
this.orderOpen = false;

View File

@@ -162,7 +162,6 @@ export default {
return this.receivableList.reduce((total, item) => total + parseFloat(item.amount), 0);
},
unreceivedAmount() {
// return this.order ? this.order.totalAmount - this.order.receivedAmount : 0;
return this.order ? this.order.orderAmount - this.receivedAmount : 0;
},
},
@@ -232,14 +231,6 @@ export default {
this.receivableList = response.rows;
this.total = response.total;
this.loading = false;
if (this.isFirst) {
this.isFirst = false;
return;
}
updateOrder({
orderId: this.orderId,
unpaidAmount: this.unreceivedAmount,
})
});
},
// 取消按钮