feat(contract): 替换产品内容组件为订单详情组件并优化表单字段
重构合同预览和订单详情展示,使用新的OrderDetail组件替代原有的ProductContent组件 调整订单详情表单字段,增加宽度、厚度等必要字段,移除不必要字段 优化表单验证规则和显示逻辑
This commit is contained in:
@@ -14,8 +14,10 @@
|
||||
|
||||
<el-table v-loading="loading" :data="orderItemList">
|
||||
<el-table-column label="产品类型" align="center" prop="productType" />
|
||||
<el-table-column label="成品宽度" align="center" prop="width" />
|
||||
<el-table-column label="成品厚度" align="center" prop="thickness" />
|
||||
<el-table-column label="成品规格" align="center" prop="finishedProductSpec" />
|
||||
<el-table-column label="原料规格" align="center" prop="rawMaterialSpec" />
|
||||
<!-- <el-table-column label="原料规格" align="center" prop="rawMaterialSpec" /> -->
|
||||
<el-table-column label="宽度公差" align="center" prop="widthTolerance" />
|
||||
<el-table-column label="厚度公差" align="center" prop="thicknessTolerance" />
|
||||
|
||||
@@ -29,6 +31,12 @@
|
||||
</el-table-column>
|
||||
<el-table-column label="无税单价(元/吨)" align="center" prop="itemAmount" />
|
||||
<el-table-column label="卷数" align="center" prop="productNum" />
|
||||
<el-table-column label="表面处理" align="center" prop="surfaceTreatment" />
|
||||
<el-table-column label="包装要求" align="center" prop="packagingReq" />
|
||||
<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" />
|
||||
@@ -50,18 +58,15 @@
|
||||
<el-form-item label="产品类型" prop="productType">
|
||||
<el-input v-model="form.productType" placeholder="请输入产品类型" />
|
||||
</el-form-item>
|
||||
<!-- <el-form-item label="产品数量" prop="productNum">
|
||||
<el-input v-model="form.productNum" placeholder="请输入产品数量" />
|
||||
</el-form-item> -->
|
||||
<!-- <el-form-item label="明细金额" prop="itemAmount">
|
||||
<el-input size="mini" v-model="form.itemAmount" placeholder="请输入明细金额" />
|
||||
</el-form-item> -->
|
||||
<el-form-item label="原料规格" prop="rawMaterialSpec">
|
||||
<el-input v-model="form.rawMaterialSpec" placeholder="请输入原料规格" />
|
||||
</el-form-item>
|
||||
<el-form-item label="成品规格" prop="finishedProductSpec">
|
||||
<el-input v-model="form.finishedProductSpec" placeholder="请输入成品规格" />
|
||||
</el-form-item>
|
||||
<el-form-item label="成品宽度" prop="width">
|
||||
<el-input v-model="form.width" placeholder="请输入宽度" />
|
||||
</el-form-item>
|
||||
<el-form-item label="成品厚度" prop="thickness">
|
||||
<el-input v-model="form.thickness" placeholder="请输入厚度" />
|
||||
</el-form-item>
|
||||
<el-form-item label="宽度公差" prop="widthTolerance">
|
||||
<el-input v-model="form.widthTolerance" placeholder="请输入宽度公差" />
|
||||
</el-form-item>
|
||||
@@ -71,23 +76,34 @@
|
||||
<el-form-item label="材质" prop="material">
|
||||
<el-input v-model="form.material" placeholder="请输入材质" />
|
||||
</el-form-item>
|
||||
<el-form-item label="等级" prop="grade">
|
||||
<el-input v-model="form.grade" placeholder="请输入等级" />
|
||||
</el-form-item>
|
||||
<el-form-item label="重量" prop="weight">
|
||||
<el-input v-model="form.weight" placeholder="请输入重量" />
|
||||
</el-form-item>
|
||||
<el-form-item label="合同定价" prop="contractPrice">
|
||||
<el-input v-model="form.contractPrice" placeholder="请输入合同定价" />
|
||||
<el-form-item label="含税单价(元/吨)" prop="contractPrice">
|
||||
<el-input v-model="form.contractPrice" placeholder="请输入含税单价" />
|
||||
</el-form-item>
|
||||
<el-form-item label="定制人" prop="customizer">
|
||||
<el-input v-model="form.customizer" placeholder="请输入定制人" />
|
||||
<el-form-item label="无税单价(元/吨)" prop="itemAmount">
|
||||
<el-input v-model="form.itemAmount" placeholder="请输入无税单价" />
|
||||
</el-form-item>
|
||||
<el-form-item label="发货人" prop="shipper">
|
||||
<el-input v-model="form.shipper" placeholder="请输入发货人" />
|
||||
|
||||
<el-form-item label="卷数" prop="productNum">
|
||||
<el-input v-model="form.productNum" placeholder="请输入卷数" />
|
||||
</el-form-item>
|
||||
<el-form-item label="排产批次" prop="productionBatch">
|
||||
<el-input v-model="form.productionBatch" placeholder="请输入排产批次" />
|
||||
<el-form-item label="表面处理" prop="surfaceTreatment">
|
||||
<el-input v-model="form.surfaceTreatment" placeholder="请输入表面处理" />
|
||||
</el-form-item>
|
||||
<el-form-item label="包装要求" prop="packagingReq">
|
||||
<el-input v-model="form.packagingReq" placeholder="请输入包装要求" />
|
||||
</el-form-item>
|
||||
<el-form-item label="切边要求" prop="edgeCuttingReq">
|
||||
<el-input v-model="form.edgeCuttingReq" placeholder="请输入切边要求" />
|
||||
</el-form-item>
|
||||
<el-form-item label="用途" prop="purpose">
|
||||
<el-input v-model="form.purpose" placeholder="请输入用途" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="特殊要求" prop="specialRequire">
|
||||
<el-input v-model="form.specialRequire" placeholder="请输入特殊要求" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="备注" prop="remark">
|
||||
@@ -170,29 +186,29 @@ 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" }
|
||||
],
|
||||
// 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"
|
||||
}
|
||||
],
|
||||
// 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" },
|
||||
// 必须是数字,最多两位小数,使用自定义的校验规则
|
||||
|
||||
@@ -27,12 +27,12 @@
|
||||
|
||||
<div style="margin-top: 20px;">
|
||||
<h4 style="margin-bottom: 10px; color: #606266;">一、产品内容</h4>
|
||||
<ProductContent v-model="contract.productContent" readonly />
|
||||
<OrderDetail :orderId="contract.orderId" :remark="contract.remark" readonly />
|
||||
<!-- <ProductContent v-model="contract.productContent" readonly /> -->
|
||||
<!-- <div v-html="contract.productContent" style="border: 1px solid #e4e7ed; padding: 10px; border-radius: 4px;"></div> -->
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<!-- <h4 style="margin-bottom: 10px; color: #606266;">合同内容</h4> -->
|
||||
<div v-html="contract.contractContent" style="border: 1px solid #e4e7ed; padding: 10px; border-radius: 4px;"></div>
|
||||
</div>
|
||||
|
||||
@@ -61,11 +61,13 @@
|
||||
|
||||
<script>
|
||||
import ProductContent from './ProductContent.vue';
|
||||
import OrderDetail from './OrderDetail.vue';
|
||||
|
||||
export default {
|
||||
name: "ContractPreview",
|
||||
components: {
|
||||
ProductContent
|
||||
ProductContent,
|
||||
OrderDetail
|
||||
},
|
||||
props: {
|
||||
contract: {
|
||||
|
||||
307
klp-ui/src/views/crm/contract/components/OrderDetail.vue
Normal file
307
klp-ui/src/views/crm/contract/components/OrderDetail.vue
Normal file
@@ -0,0 +1,307 @@
|
||||
<template>
|
||||
<div v-loading="loading">
|
||||
<!-- 网格布局实现的表格,共8列 -->
|
||||
<div class="product-content">
|
||||
<!-- 第一行合并所有八个单元格,内容为:嘉祥科伦普重工有限公司 -->
|
||||
<div class="table-row table-header">
|
||||
<div class="table-cell" colspan="3">
|
||||
<div class="company-name">产品名称:{{ productName }}</div>
|
||||
</div>
|
||||
<div class="table-cell" colspan="5">
|
||||
<div class="company-name">生产厂家:嘉祥科伦普重工有限公司</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 第二行为表头 -->
|
||||
<div class="table-row">
|
||||
<div class="table-cell">序号</div>
|
||||
<div class="table-cell">规格(mm)</div>
|
||||
<div class="table-cell">材质</div>
|
||||
<div class="table-cell">数量(吨)</div>
|
||||
<div class="table-cell">含税单价(元/吨)</div>
|
||||
<div class="table-cell">不含税单价(元/吨)</div>
|
||||
<div class="table-cell">含税总额(元)</div>
|
||||
<div class="table-cell">备注</div>
|
||||
</div>
|
||||
|
||||
<!-- 产品行 -->
|
||||
<div
|
||||
v-for="(item, index) in products"
|
||||
:key="index"
|
||||
class="table-row"
|
||||
:class="{ 'table-row-hover': !readonly }"
|
||||
>
|
||||
<div class="table-cell">
|
||||
<div class="serial-number">
|
||||
<span>{{ index + 1 }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="table-cell">
|
||||
{{ item.finishedProductSpec }}
|
||||
</div>
|
||||
<div class="table-cell">
|
||||
{{ item.material }}
|
||||
</div>
|
||||
<div class="table-cell">
|
||||
{{ item.weight }}
|
||||
</div>
|
||||
<div class="table-cell">
|
||||
{{ item.contractPrice }}
|
||||
</div>
|
||||
<div class="table-cell">
|
||||
{{ item.itemAmount }}
|
||||
</div>
|
||||
<div class="table-cell">
|
||||
{{ item.contractPrice * item.weight }}
|
||||
</div>
|
||||
<div class="table-cell">
|
||||
{{ item.remark }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 合计行 -->
|
||||
<div class="table-row table-total-row">
|
||||
<div class="table-cell" colspan="3">合计</div>
|
||||
<div class="table-cell">{{ totalQuantity }}</div>
|
||||
<div class="table-cell"></div>
|
||||
<div class="table-cell"></div>
|
||||
<div class="table-cell">{{ totalTaxTotal }}</div>
|
||||
<div class="table-cell"></div>
|
||||
</div>
|
||||
|
||||
<!-- 合计人民币(大写) -->
|
||||
<div class="table-row">
|
||||
<div class="table-cell" colspan="8">
|
||||
<span>合计人民币(大写):</span>
|
||||
<span>{{ totalAmountInWords }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 备注 -->
|
||||
<div class="table-row">
|
||||
<div class="table-cell" colspan="8">
|
||||
<span>备注:</span>
|
||||
<pre>{{ remark }}</pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { listOrderItem } from '@/api/crm/orderItem'
|
||||
|
||||
export default {
|
||||
name: 'ProductContent',
|
||||
props: {
|
||||
orderId: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
remark: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
readonly: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
products: [],
|
||||
productName: ''
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
// 计算总数量(吨)
|
||||
totalQuantity() {
|
||||
return this.products.reduce((sum, item) => sum + (Number(item.weight) || 0), 0)
|
||||
},
|
||||
// 计算含税总额(元)
|
||||
totalTaxTotal() {
|
||||
return this.products.reduce((sum, item) => sum + (Number(item.contractPrice) || 0) * (Number(item.weight) || 0), 0)
|
||||
},
|
||||
// 计算合计人民币(大写)
|
||||
totalAmountInWords() {
|
||||
const amount = this.totalTaxTotal
|
||||
if (amount === 0) return '零元整'
|
||||
|
||||
const digits = ['零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖']
|
||||
const units = ['', '拾', '佰', '仟']
|
||||
const bigUnits = ['', '万', '亿']
|
||||
|
||||
let integerPart = Math.floor(amount)
|
||||
let decimalPart = Math.round((amount - integerPart) * 100)
|
||||
|
||||
let result = ''
|
||||
let unitIndex = 0
|
||||
let bigUnitIndex = 0
|
||||
|
||||
if (integerPart === 0) {
|
||||
result = '零'
|
||||
} else {
|
||||
while (integerPart > 0) {
|
||||
let section = integerPart % 10000
|
||||
if (section > 0) {
|
||||
let sectionResult = ''
|
||||
let sectionUnitIndex = 0
|
||||
|
||||
while (section > 0) {
|
||||
let digit = section % 10
|
||||
if (digit > 0) {
|
||||
sectionResult = digits[digit] + units[sectionUnitIndex] + sectionResult
|
||||
} else if (sectionResult && !sectionResult.startsWith('零')) {
|
||||
sectionResult = '零' + sectionResult
|
||||
}
|
||||
section = Math.floor(section / 10)
|
||||
sectionUnitIndex++
|
||||
}
|
||||
|
||||
result = sectionResult + bigUnits[bigUnitIndex] + result
|
||||
}
|
||||
integerPart = Math.floor(integerPart / 10000)
|
||||
bigUnitIndex++
|
||||
}
|
||||
}
|
||||
|
||||
result += '元'
|
||||
|
||||
if (decimalPart === 0) {
|
||||
result += '整'
|
||||
} else {
|
||||
const jiao = Math.floor(decimalPart / 10)
|
||||
const fen = decimalPart % 10
|
||||
if (jiao > 0) {
|
||||
result += digits[jiao] + '角'
|
||||
}
|
||||
if (fen > 0) {
|
||||
result += digits[fen] + '分'
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
// 监听 orderId 变化,重新获取订单商品列表
|
||||
orderId: {
|
||||
handler(newVal) {
|
||||
if (newVal) {
|
||||
this.getOrderItems()
|
||||
} else {
|
||||
this.products = []
|
||||
this.productName = ''
|
||||
}
|
||||
},
|
||||
immediate: true
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 获取订单商品列表
|
||||
async getOrderItems() {
|
||||
this.loading = true
|
||||
try {
|
||||
const res = await listOrderItem({
|
||||
orderId: this.orderId
|
||||
})
|
||||
if (res.code === 200) {
|
||||
this.products = res.rows || []
|
||||
this.productName = res.rows[0]?.productType || ''
|
||||
} else {
|
||||
this.products = []
|
||||
this.productName = ''
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取订单商品列表失败:', error)
|
||||
this.products = []
|
||||
this.productName = ''
|
||||
} finally {
|
||||
this.loading = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.product-content {
|
||||
border: 1px solid #e4e7ed;
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.table-header {
|
||||
background-color: #f5f7fa;
|
||||
text-align: center;
|
||||
border-bottom: 1px solid #e4e7ed;
|
||||
}
|
||||
|
||||
.company-name {
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.table-row {
|
||||
display: grid;
|
||||
grid-template-columns: 80px 150px 120px 100px 140px 150px 120px 1fr;
|
||||
border-bottom: 1px solid #e4e7ed;
|
||||
}
|
||||
|
||||
.table-row-hover:hover {
|
||||
background-color: #f5f7fa;
|
||||
}
|
||||
|
||||
.table-header-row {
|
||||
background-color: #f5f7fa;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.table-total-row {
|
||||
background-color: #f5f7fa;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.table-cell {
|
||||
padding: 8px;
|
||||
border-right: 1px solid #e4e7ed;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.table-cell:last-child {
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
.table-cell[colspan="3"] {
|
||||
grid-column: span 3;
|
||||
}
|
||||
|
||||
.table-cell[colspan="5"] {
|
||||
grid-column: span 5;
|
||||
}
|
||||
|
||||
.table-cell[colspan="8"] {
|
||||
grid-column: span 8;
|
||||
}
|
||||
|
||||
.serial-number {
|
||||
position: relative;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.delete-btn {
|
||||
opacity: 0;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.serial-number:hover .delete-btn {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.el-input {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
@@ -81,9 +81,9 @@
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-form-item label="产品内容">
|
||||
<!-- <el-form-item label="产品内容">
|
||||
<ProductContent v-model="form.productContent" :readonly="false" />
|
||||
</el-form-item>
|
||||
</el-form-item> -->
|
||||
<el-form-item label="合同内容">
|
||||
<editor v-model="form.contractContent" :min-height="192" />
|
||||
</el-form-item>
|
||||
|
||||
Reference in New Issue
Block a user