| | |
| | | > |
| | | <el-table-column align="center" label="序号" type="index" width="60" /> |
| | | <el-table-column prop="quotationNo" label="报价单号" /> |
| | | <el-table-column prop="masterContractNo" label="总合同号" width="150" show-overflow-tooltip /> |
| | | <el-table-column prop="customer" label="客户名称" /> |
| | | <el-table-column prop="salesperson" label="业务员" width="100" /> |
| | | <el-table-column prop="quotationDate" label="报价日期" width="120" /> |
| | |
| | | </el-table-column> |
| | | <el-table-column label="操作" width="200" fixed="right" align="center"> |
| | | <template #default="scope"> |
| | | <el-button link type="primary" @click="handleEdit(scope.row)" :disabled="!['待审批','拒绝'].includes(scope.row.status)">编辑</el-button> |
| | | <el-button link type="primary" @click="handleEdit(scope.row)">编辑</el-button> |
| | | <el-button link type="primary" @click="handleView(scope.row)" style="color: #67C23A">查看</el-button> |
| | | <el-button link type="danger" @click="handleDelete(scope.row)">删除</el-button> |
| | | <el-button link type="danger" @click="handleDelete(scope.row)" v-hasPermi="['salesManagement:salesQuotation:remove']">删除</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | |
| | | <el-row :gutter="24"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="客户名称" prop="customerId"> |
| | | <el-select v-model="form.customerId" placeholder="请选择客户" style="width: 100%" clearable filterable> |
| | | <el-select v-model="form.customerId" placeholder="请选择客户" style="width: 100%" clearable filterable @change="handleCustomerChange"> |
| | | <el-option v-for="item in customerOption" :key="item.id" :label="item.customerName" :value="item.id"></el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="总合同号"> |
| | | <el-select v-model="form.masterContractNo" placeholder="请先选择客户" style="width: 100%" clearable filterable :disabled="!form.customerId"> |
| | | <el-option v-for="item in contractList" :key="item.id" :label="item.masterContractNo" :value="item.masterContractNo"></el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="24"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="业务员" prop="salesperson"> |
| | | <el-select v-model="form.salesperson" placeholder="请选择业务员" style="width: 100%" clearable filterable> |
| | |
| | | <el-row :gutter="24"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="付款方式" prop="paymentMethod"> |
| | | <el-input v-model="form.paymentMethod" placeholder="请输入付款方式" clearable /> |
| | | <el-select v-model="form.paymentMethod" placeholder="请选择付款方式" clearable style="width: 100%"> |
| | | <el-option label="现金" value="现金" /> |
| | | <el-option label="电汇" value="电汇" /> |
| | | <el-option label="微信" value="微信" /> |
| | | <el-option label="支付宝" value="支付宝" /> |
| | | <el-option label="支票" value="支票" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | |
| | | <el-dialog v-model="viewDialogVisible" title="报价详情" width="800px"> |
| | | <el-descriptions :column="2" border> |
| | | <el-descriptions-item label="报价单号">{{ currentQuotation.quotationNo }}</el-descriptions-item> |
| | | <el-descriptions-item label="总合同号">{{ currentQuotation.masterContractNo || '--' }}</el-descriptions-item> |
| | | <el-descriptions-item label="客户名称">{{ currentQuotation.customer }}</el-descriptions-item> |
| | | <el-descriptions-item label="业务员">{{ currentQuotation.salesperson }}</el-descriptions-item> |
| | | <el-descriptions-item label="报价日期">{{ currentQuotation.quotationDate }}</el-descriptions-item> |
| | |
| | | import {modelList, productTreeList} from "@/api/basicData/product.js"; |
| | | import {listCustomer} from "@/api/basicData/customer.js"; |
| | | import { userListNoPage } from "@/api/system/user.js"; |
| | | import { getCustomerContractList } from "@/api/basicData/customerContract.js"; |
| | | |
| | | // 响应式数据 |
| | | const loading = ref(false) |
| | |
| | | const userList = ref([]) |
| | | const productOptions = ref([]); |
| | | const modelOptions = ref([]); |
| | | const contractList = ref([]); |
| | | const pagination = reactive({ |
| | | total: 3, |
| | | currentPage: 1, |
| | |
| | | paymentMethod: '', |
| | | status: '草稿', |
| | | remark: '', |
| | | masterContractNo: '', |
| | | products: [], |
| | | subtotal: 0, |
| | | freight: 0, |
| | | otherFee: 0, |
| | | discountRate: 0, |
| | | discountAmount: 0, |
| | | totalAmount: 0 |
| | | }) |
| | | |
| | |
| | | salesperson: [{ required: true, message: '请选择业务员', trigger: 'change' }], |
| | | quotationDate: [{ required: true, message: '请选择报价日期', trigger: 'change' }], |
| | | validDate: [{ required: true, message: '请选择有效期', trigger: 'change' }], |
| | | paymentMethod: [{ required: true, message: '请输入付款方式', trigger: 'blur' }] |
| | | paymentMethod: [{ required: true, message: '请选择付款方式', trigger: 'change' }] |
| | | } |
| | | |
| | | const productRowRules = { |
| | |
| | | // 计算属性 |
| | | const filteredList = computed(() => { |
| | | let list = quotationList.value |
| | | console.log(list) |
| | | return list |
| | | }) |
| | | |
| | |
| | | customerOption.value = res.data.records; |
| | | }); |
| | | } |
| | | |
| | | // 客户选择变化时,加载该客户的合同列表 |
| | | const handleCustomerChange = async (customerId) => { |
| | | form.masterContractNo = ''; |
| | | contractList.value = []; |
| | | if (!customerId) return; |
| | | |
| | | try { |
| | | const res = await getCustomerContractList(customerId); |
| | | if (res.code === 200) { |
| | | contractList.value = res.data || []; |
| | | } |
| | | } catch (error) { |
| | | console.error('获取客户合同列表失败:', error); |
| | | } |
| | | }; |
| | | |
| | | const getProductOptions = () => { |
| | | // 返回 Promise,便于编辑时 await 确保能反显 |
| | | return productTreeList().then((res) => { |
| | |
| | | quotationDate: row.quotationDate || '', |
| | | validDate: row.validDate || '', |
| | | paymentMethod: row.paymentMethod || '', |
| | | masterContractNo: row.masterContractNo || '', |
| | | status: row.status || '', |
| | | remark: row.remark || '', |
| | | products: row.products ? row.products.map(product => ({ |
| | |
| | | form.paymentMethod = row.paymentMethod || '' |
| | | form.status = row.status || '草稿' |
| | | form.remark = row.remark || '' |
| | | |
| | | // 编辑时加载客户的合同列表以便回显总合同号 |
| | | if (row.customerId) { |
| | | try { |
| | | const contractRes = await getCustomerContractList(row.customerId); |
| | | if (contractRes.code === 200) { |
| | | contractList.value = contractRes.data || []; |
| | | } |
| | | } catch (error) { |
| | | console.error('获取客户合同列表失败:', error); |
| | | } |
| | | } |
| | | |
| | | // 兼容后端返回的 masterContractNo 或 master_contract_no,放在合同列表加载后设置 |
| | | form.masterContractNo = row.masterContractNo || row.master_contract_no || '' |
| | | |
| | | form.products = row.products ? await Promise.all(row.products.map(async (product) => { |
| | | const productName = product.product || product.productName || '' |
| | | // 优先用 productId;如果只有名称,尝试反查 id 以便树选择器反显 |
| | |
| | | } |
| | | })) : [] |
| | | form.subtotal = row.subtotal || 0 |
| | | form.freight = row.freight || 0 |
| | | form.otherFee = row.otherFee || 0 |
| | | form.discountRate = row.discountRate || 0 |
| | | form.discountAmount = row.discountAmount || 0 |
| | | form.totalAmount = row.totalAmount || 0 |
| | | |
| | | dialogVisible.value = true |
| | |
| | | form.paymentMethod = '' |
| | | form.status = '草稿' |
| | | form.remark = '' |
| | | form.masterContractNo = '' |
| | | form.products = [] |
| | | form.subtotal = 0 |
| | | form.freight = 0 |
| | | form.otherFee = 0 |
| | | form.discountRate = 0 |
| | | form.discountAmount = 0 |
| | | form.totalAmount = 0 |
| | | contractList.value = [] |
| | | } |
| | | |
| | | const addProduct = () => { |
| | |
| | | }, 0) |
| | | |
| | | form.customer = customerOption.value.find(item => item.id === form.customerId)?.customerName || '' |
| | | |
| | | // 剔除 products 中的 modelOptions 字段,以及 form 中的 subtotal、freight 字段 |
| | | const { subtotal, freight, ...formWithoutSubtotal } = form |
| | | const submitData = { |
| | | ...formWithoutSubtotal, |
| | | products: form.products.map(({ modelOptions, ...rest }) => rest) |
| | | } |
| | | |
| | | if (isEdit.value) { |
| | | // 编辑 |
| | | const index = quotationList.value.findIndex(item => item.id === editId.value) |
| | | if (index > -1) { |
| | | updateQuotation(form).then(res=>{ |
| | | updateQuotation(submitData).then(res=>{ |
| | | // console.log(res) |
| | | if(res.code===200){ |
| | | ElMessage.success('编辑成功') |
| | |
| | | } |
| | | } else { |
| | | // 新增 |
| | | addQuotation(form).then(res=>{ |
| | | addQuotation(submitData).then(res=>{ |
| | | if(res.code===200){ |
| | | ElMessage.success('新增成功') |
| | | dialogVisible.value = false |
| | |
| | | customer: item.customer || '', |
| | | customerId: item.customerId || undefined, |
| | | salesperson: item.salesperson || '', |
| | | masterContractNo: item.masterContractNo || '', |
| | | quotationDate: item.quotationDate || '', |
| | | validDate: item.validDate || '', |
| | | paymentMethod: item.paymentMethod || '', |
| | |
| | | })) : [], |
| | | subtotal: item.subtotal || 0, |
| | | freight: item.freight || 0, |
| | | otherFee: item.otherFee || 0, |
| | | discountRate: item.discountRate || 0, |
| | | discountAmount: item.discountAmount || 0, |
| | | totalAmount: item.totalAmount || 0 |
| | | })) |
| | | pagination.total = res.data.total |