| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div class="app-container"> |
| | | <el-card class="box-card"> |
| | | <!-- æç´¢åºå --> |
| | | <el-row :gutter="20" class="search-row"> |
| | | <el-col :span="6"> |
| | | <el-input |
| | | v-model="searchForm.quotationNo" |
| | | placeholder="请è¾å
¥æ¥ä»·åå·" |
| | | clearable |
| | | @keyup.enter="handleSearch" |
| | | > |
| | | <template #prefix> |
| | | <el-icon><Search /></el-icon> |
| | | </template> |
| | | </el-input> |
| | | </el-col> |
| | | <el-col :span="6"> |
| | | <el-select v-model="searchForm.customer" placeholder="è¯·éæ©å®¢æ·" clearable> |
| | | <el-option label="䏿µ·ç§ææéå
¬å¸" value="䏿µ·ç§ææéå
¬å¸"></el-option> |
| | | <el-option label="æ·±å³çµåæéå
¬å¸" value="æ·±å³çµåæéå
¬å¸"></el-option> |
| | | <el-option label="å京贸æå
¬å¸" value="å京贸æå
¬å¸"></el-option> |
| | | </el-select> |
| | | </el-col> |
| | | <el-col :span="6"> |
| | | <el-select v-model="searchForm.status" placeholder="è¯·éæ©æ¥ä»·ç¶æ" clearable> |
| | | <el-option label="è稿" value="è稿"></el-option> |
| | | <el-option label="å·²åé" value="å·²åé"></el-option> |
| | | <el-option label="客æ·ç¡®è®¤" value="客æ·ç¡®è®¤"></el-option> |
| | | <el-option label="å·²è¿æ" value="å·²è¿æ"></el-option> |
| | | </el-select> |
| | | </el-col> |
| | | <el-col :span="6"> |
| | | <el-button type="primary" @click="handleSearch">æç´¢</el-button> |
| | | <el-button @click="resetSearch">éç½®</el-button> |
| | | <el-button style="float: right;" type="primary" @click="handleAdd"> |
| | | æ°å¢æ¥ä»· |
| | | </el-button> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <!-- æ¥ä»·å表 --> |
| | | <el-table |
| | | :data="filteredList" |
| | | style="width: 100%" |
| | | v-loading="loading" |
| | | border |
| | | stripe |
| | | height="calc(100vh - 22em)" |
| | | > |
| | | <el-table-column prop="id" label="ID" width="80" align="center"/> |
| | | <el-table-column prop="quotationNo" label="æ¥ä»·åå·" width="150" /> |
| | | <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 prop="validDate" label="æææè³" width="120" /> |
| | | <el-table-column prop="totalAmount" label="æ¥ä»·éé¢" width="120"> |
| | | <template #default="scope"> |
| | | ¥{{ scope.row.totalAmount.toFixed(2) }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="status" label="æ¥ä»·ç¶æ" width="100"> |
| | | <template #default="scope"> |
| | | <el-tag :type="getStatusType(scope.row.status)"> |
| | | {{ scope.row.status }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="æä½" width="250" fixed="right" align="center"> |
| | | <template #default="scope"> |
| | | <el-button link type="primary" @click="handleView(scope.row)">æ¥ç</el-button> |
| | | <el-button link type="primary" @click="handleEdit(scope.row)" v-if="scope.row.status === 'è稿'">ç¼è¾</el-button> |
| | | <el-button link type="danger" @click="handleDelete(scope.row)" v-if="scope.row.status === 'è稿'">å é¤</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | |
| | | <!-- å页 --> |
| | | <pagination |
| | | :total="pagination.total" |
| | | layout="total, sizes, prev, pager, next, jumper" |
| | | :page="pagination.currentPage" |
| | | :limit="pagination.pageSize" |
| | | @pagination="handleCurrentChange" |
| | | /> |
| | | </el-card> |
| | | |
| | | <!-- æ°å¢/ç¼è¾å¯¹è¯æ¡ --> |
| | | <el-dialog v-model="dialogVisible" :title="dialogTitle" width="900px" :close-on-click-modal="false"> |
| | | <el-form :model="form" :rules="rules" ref="formRef" label-width="100px"> |
| | | <!-- åºæ¬ä¿¡æ¯ --> |
| | | <el-card class="form-card" shadow="never"> |
| | | <template #header> |
| | | <span class="card-title">åºæ¬ä¿¡æ¯</span> |
| | | </template> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="客æ·åç§°" prop="customer"> |
| | | <el-select v-model="form.customer" placeholder="è¯·éæ©å®¢æ·" style="width: 100%" @change="handleCustomerChange"> |
| | | <el-option label="䏿µ·ç§ææéå
¬å¸" value="䏿µ·ç§ææéå
¬å¸"></el-option> |
| | | <el-option label="æ·±å³çµåæéå
¬å¸" value="æ·±å³çµåæéå
¬å¸"></el-option> |
| | | <el-option label="å京贸æå
¬å¸" value="å京贸æå
¬å¸"></el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ä¸å¡å" prop="salesperson"> |
| | | <el-select v-model="form.salesperson" placeholder="è¯·éæ©ä¸å¡å" style="width: 100%"> |
| | | <el-option label="éå¿å¼º" value="éå¿å¼º"></el-option> |
| | | <el-option label="åé
å©·" value="åé
å©·"></el-option> |
| | | <el-option label="ç建å½" value="ç建å½"></el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="æ¥ä»·æ¥æ" prop="quotationDate"> |
| | | <el-date-picker |
| | | v-model="form.quotationDate" |
| | | type="date" |
| | | placeholder="éæ©æ¥ä»·æ¥æ" |
| | | style="width: 100%" |
| | | format="YYYY-MM-DD" |
| | | value-format="YYYY-MM-DD" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="æææè³" prop="validDate"> |
| | | <el-date-picker |
| | | v-model="form.validDate" |
| | | type="date" |
| | | placeholder="éæ©æææ" |
| | | style="width: 100%" |
| | | format="YYYY-MM-DD" |
| | | value-format="YYYY-MM-DD" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="仿¬¾æ¹å¼" prop="paymentMethod"> |
| | | <el-select v-model="form.paymentMethod" placeholder="è¯·éæ©ä»æ¬¾æ¹å¼" style="width: 100%"> |
| | | <el-option label="å
¨æ¬¾å°ä»" value="å
¨æ¬¾å°ä»"></el-option> |
| | | <el-option label="åæä»æ¬¾" value="åæä»æ¬¾"></el-option> |
| | | <el-option label="æç»" value="æç»"></el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="交货æ" prop="deliveryPeriod"> |
| | | <el-input v-model="form.deliveryPeriod" placeholder="请è¾å
¥äº¤è´§æ" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-card> |
| | | |
| | | <!-- 产åä¿¡æ¯ --> |
| | | <el-card class="form-card" shadow="never"> |
| | | <template #header> |
| | | <div class="card-header"> |
| | | <span class="card-title">产åä¿¡æ¯</span> |
| | | <el-button type="primary" size="small" @click="addProduct">æ·»å 产å</el-button> |
| | | </div> |
| | | </template> |
| | | <el-table :data="form.products" border style="width: 100%"> |
| | | <el-table-column prop="productName" label="产ååç§°" width="200"> |
| | | <template #default="scope"> |
| | | <el-input v-model="scope.row.productName" placeholder="请è¾å
¥äº§ååç§°" /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="specification" label="è§æ ¼åå·" width="150"> |
| | | <template #default="scope"> |
| | | <el-input v-model="scope.row.specification" placeholder="è§æ ¼åå·" /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="quantity" label="æ°é" width="100"> |
| | | <template #default="scope"> |
| | | <el-input-number v-model="scope.row.quantity" :min="1" :precision="0" style="width: 100%" /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="unit" label="åä½" width="80"> |
| | | <template #default="scope"> |
| | | <el-input v-model="scope.row.unit" placeholder="åä½" /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="unitPrice" label="åä»·" width="120"> |
| | | <template #default="scope"> |
| | | <el-input-number v-model="scope.row.unitPrice" :min="0" :precision="2" style="width: 100%" @change="calculateAmount(scope.row)" /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="amount" label="éé¢" width="120"> |
| | | <template #default="scope"> |
| | | <span>Â¥{{ scope.row.amount.toFixed(2) }}</span> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="æä½" width="80" align="center"> |
| | | <template #default="scope"> |
| | | <el-button link type="danger" @click="removeProduct(scope.$index)">å é¤</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </el-card> |
| | | |
| | | <!-- è´¹ç¨ä¿¡æ¯ --> |
| | | <el-card class="form-card" shadow="never"> |
| | | <template #header> |
| | | <span class="card-title">è´¹ç¨ä¿¡æ¯</span> |
| | | </template> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="8"> |
| | | <el-form-item label="产åå°è®¡"> |
| | | <el-input-number v-model="form.subtotal" :precision="2" :min="0" style="width: 100%" readonly /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="8"> |
| | | <el-form-item label="è¿è´¹"> |
| | | <el-input-number v-model="form.freight" :precision="2" :min="0" style="width: 100%" @change="calculateTotal" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="8"> |
| | | <el-form-item label="å
¶ä»è´¹ç¨"> |
| | | <el-input-number v-model="form.otherFee" :precision="2" :min="0" style="width: 100%" @change="calculateTotal" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="8"> |
| | | <el-form-item label="ææ£ç(%)"> |
| | | <el-input-number v-model="form.discountRate" :precision="2" :min="0" :max="100" style="width: 100%" @change="calculateTotal" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="8"> |
| | | <el-form-item label="ææ£éé¢"> |
| | | <el-input-number v-model="form.discountAmount" :precision="2" :min="0" style="width: 100%" readonly /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="8"> |
| | | <el-form-item label="æ¥ä»·æ»é¢"> |
| | | <el-input-number v-model="form.totalAmount" :precision="2" :min="0" style="width: 100%" readonly /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-card> |
| | | |
| | | <!-- 夿³¨ä¿¡æ¯ --> |
| | | <el-card class="form-card" shadow="never"> |
| | | <template #header> |
| | | <span class="card-title">夿³¨ä¿¡æ¯</span> |
| | | </template> |
| | | <el-form-item label="夿³¨" prop="remark"> |
| | | <el-input type="textarea" v-model="form.remark" placeholder="请è¾å
¥å¤æ³¨ä¿¡æ¯" rows="3"></el-input> |
| | | </el-form-item> |
| | | </el-card> |
| | | </el-form> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button @click="dialogVisible = false">å æ¶</el-button> |
| | | <el-button type="primary" @click="handleSubmit">ç¡® å®</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | |
| | | <!-- æ¥ç详æ
å¯¹è¯æ¡ --> |
| | | <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.customer }}</el-descriptions-item> |
| | | <el-descriptions-item label="ä¸å¡å">{{ currentQuotation.salesperson }}</el-descriptions-item> |
| | | <el-descriptions-item label="æ¥ä»·æ¥æ">{{ currentQuotation.quotationDate }}</el-descriptions-item> |
| | | <el-descriptions-item label="æææè³">{{ currentQuotation.validDate }}</el-descriptions-item> |
| | | <el-descriptions-item label="仿¬¾æ¹å¼">{{ currentQuotation.paymentMethod }}</el-descriptions-item> |
| | | <el-descriptions-item label="交货æ">{{ currentQuotation.deliveryPeriod }}</el-descriptions-item> |
| | | <el-descriptions-item label="æ¥ä»·ç¶æ"> |
| | | <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(2) }}</span> |
| | | </el-descriptions-item> |
| | | </el-descriptions> |
| | | |
| | | <div style="margin-top: 20px;"> |
| | | <h4>产åæç»</h4> |
| | | <el-table :data="currentQuotation.products" border style="width: 100%"> |
| | | <el-table-column prop="productName" label="产ååç§°" /> |
| | | <el-table-column prop="specification" label="è§æ ¼åå·" /> |
| | | <el-table-column prop="quantity" label="æ°é" /> |
| | | <el-table-column prop="unit" label="åä½" /> |
| | | <el-table-column prop="unitPrice" label="åä»·"> |
| | | <template #default="scope"> |
| | | ¥{{ scope.row.unitPrice.toFixed(2) }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="amount" label="éé¢"> |
| | | <template #default="scope"> |
| | | ¥{{ scope.row.amount.toFixed(2) }} |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </div> |
| | | |
| | | <div v-if="currentQuotation.remark" style="margin-top: 20px;"> |
| | | <h4>夿³¨</h4> |
| | | <p>{{ currentQuotation.remark }}</p> |
| | | </div> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, reactive, computed } from 'vue' |
| | | import { ElMessage, ElMessageBox } from 'element-plus' |
| | | import { Search } from '@element-plus/icons-vue' |
| | | import Pagination from '@/components/PIMTable/Pagination.vue' |
| | | |
| | | // ååºå¼æ°æ® |
| | | const loading = ref(false) |
| | | const searchForm = reactive({ |
| | | quotationNo: '', |
| | | customer: '', |
| | | status: '' |
| | | }) |
| | | |
| | | const quotationList = ref([ |
| | | { |
| | | id: 1, |
| | | quotationNo: 'QT202312001', |
| | | customer: '䏿µ·ç§ææéå
¬å¸', |
| | | salesperson: 'éå¿å¼º', |
| | | quotationDate: '2023-12-01', |
| | | validDate: '2023-12-31', |
| | | totalAmount: 50000.00, |
| | | paymentMethod: 'å
¨æ¬¾å°ä»', |
| | | deliveryPeriod: '30天', |
| | | status: 'å·²åé', |
| | | remark: 'éè¦å®¢æ·æ¥ä»·', |
| | | products: [ |
| | | { productName: 'å·¥ä¸ä¼ æå¨', specification: 'SEN-001', quantity: 10, unit: '个', unitPrice: 5000, amount: 50000 } |
| | | ] |
| | | }, |
| | | { |
| | | id: 2, |
| | | quotationNo: 'QT202312002', |
| | | customer: 'æ·±å³çµåæéå
¬å¸', |
| | | salesperson: 'åé
å©·', |
| | | quotationDate: '2023-12-02', |
| | | validDate: '2023-12-31', |
| | | totalAmount: 35000.00, |
| | | paymentMethod: 'åæä»æ¬¾', |
| | | deliveryPeriod: '20天', |
| | | status: '客æ·ç¡®è®¤', |
| | | remark: 'å¸¸è§æ¥ä»·', |
| | | products: [ |
| | | { productName: 'æ§å¶æ¨¡å', specification: 'CTL-002', quantity: 5, unit: '个', unitPrice: 7000, amount: 35000 } |
| | | ] |
| | | }, |
| | | { |
| | | id: 3, |
| | | quotationNo: 'QT202312003', |
| | | customer: 'å京贸æå
¬å¸', |
| | | salesperson: 'ç建å½', |
| | | quotationDate: '2023-12-03', |
| | | validDate: '2023-12-31', |
| | | totalAmount: 28000.00, |
| | | paymentMethod: 'æç»', |
| | | deliveryPeriod: '15天', |
| | | status: 'è稿', |
| | | remark: 'æ°å®¢æ·æ¥ä»·', |
| | | products: [ |
| | | { productName: 'æ°æ®ééå¨', specification: 'DAQ-003', quantity: 4, unit: '个', unitPrice: 7000, amount: 28000 } |
| | | ] |
| | | } |
| | | ]) |
| | | |
| | | const pagination = reactive({ |
| | | total: 3, |
| | | currentPage: 1, |
| | | pageSize: 10 |
| | | }) |
| | | |
| | | const dialogVisible = ref(false) |
| | | const viewDialogVisible = ref(false) |
| | | const dialogTitle = ref('æ°å¢æ¥ä»·') |
| | | const form = reactive({ |
| | | customer: '', |
| | | salesperson: '', |
| | | quotationDate: '', |
| | | validDate: '', |
| | | paymentMethod: '', |
| | | deliveryPeriod: '', |
| | | status: 'è稿', |
| | | remark: '', |
| | | products: [], |
| | | subtotal: 0, |
| | | freight: 0, |
| | | otherFee: 0, |
| | | discountRate: 0, |
| | | discountAmount: 0, |
| | | totalAmount: 0 |
| | | }) |
| | | |
| | | const rules = { |
| | | customer: [{ required: true, message: 'è¯·éæ©å®¢æ·', trigger: 'change' }], |
| | | salesperson: [{ required: true, message: 'è¯·éæ©ä¸å¡å', trigger: 'change' }], |
| | | quotationDate: [{ required: true, message: 'è¯·éæ©æ¥ä»·æ¥æ', trigger: 'change' }], |
| | | validDate: [{ required: true, message: 'è¯·éæ©æææ', trigger: 'change' }], |
| | | paymentMethod: [{ required: true, message: 'è¯·éæ©ä»æ¬¾æ¹å¼', trigger: 'change' }], |
| | | deliveryPeriod: [{ required: true, message: '请è¾å
¥äº¤è´§æ', trigger: 'blur' }] |
| | | } |
| | | |
| | | const isEdit = ref(false) |
| | | const editId = ref(null) |
| | | const currentQuotation = ref({}) |
| | | const formRef = ref() |
| | | |
| | | // 计ç®å±æ§ |
| | | const filteredList = computed(() => { |
| | | let list = quotationList.value |
| | | if (searchForm.quotationNo) { |
| | | list = list.filter(item => item.quotationNo.includes(searchForm.quotationNo)) |
| | | } |
| | | if (searchForm.customer) { |
| | | list = list.filter(item => item.customer === searchForm.customer) |
| | | } |
| | | if (searchForm.status) { |
| | | list = list.filter(item => item.status === searchForm.status) |
| | | } |
| | | return list |
| | | }) |
| | | |
| | | // æ¹æ³ |
| | | const getStatusType = (status) => { |
| | | const statusMap = { |
| | | 'è稿': 'info', |
| | | 'å·²åé': 'primary', |
| | | '客æ·ç¡®è®¤': 'success', |
| | | 'å·²è¿æ': 'danger' |
| | | } |
| | | return statusMap[status] || 'info' |
| | | } |
| | | |
| | | const handleSearch = () => { |
| | | // æç´¢é»è¾å·²å¨computedä¸å¤ç |
| | | } |
| | | |
| | | const resetSearch = () => { |
| | | searchForm.quotationNo = '' |
| | | searchForm.customer = '' |
| | | searchForm.status = '' |
| | | } |
| | | |
| | | const handleAdd = () => { |
| | | dialogTitle.value = 'æ°å¢æ¥ä»·' |
| | | isEdit.value = false |
| | | resetForm() |
| | | dialogVisible.value = true |
| | | } |
| | | |
| | | const handleView = (row) => { |
| | | currentQuotation.value = row |
| | | viewDialogVisible.value = true |
| | | } |
| | | |
| | | const handleEdit = (row) => { |
| | | dialogTitle.value = 'ç¼è¾æ¥ä»·' |
| | | isEdit.value = true |
| | | editId.value = row.id |
| | | Object.assign(form, row) |
| | | dialogVisible.value = true |
| | | } |
| | | |
| | | |
| | | const handleDelete = (row) => { |
| | | ElMessageBox.confirm('确认å é¤è¯¥æ¥ä»·ååï¼', 'æç¤º', { |
| | | confirmButtonText: 'ç¡®å®', |
| | | cancelButtonText: 'åæ¶', |
| | | type: 'warning' |
| | | }).then(() => { |
| | | const index = quotationList.value.findIndex(item => item.id === row.id) |
| | | if (index > -1) { |
| | | quotationList.value.splice(index, 1) |
| | | pagination.total-- |
| | | ElMessage.success('å 餿å') |
| | | } |
| | | }) |
| | | } |
| | | |
| | | const resetForm = () => { |
| | | form.customer = '' |
| | | form.salesperson = '' |
| | | form.quotationDate = '' |
| | | form.validDate = '' |
| | | form.paymentMethod = '' |
| | | form.deliveryPeriod = '' |
| | | form.status = 'è稿' |
| | | form.remark = '' |
| | | form.products = [] |
| | | form.subtotal = 0 |
| | | form.freight = 0 |
| | | form.otherFee = 0 |
| | | form.discountRate = 0 |
| | | form.discountAmount = 0 |
| | | form.totalAmount = 0 |
| | | } |
| | | |
| | | const addProduct = () => { |
| | | form.products.push({ |
| | | productName: '', |
| | | specification: '', |
| | | quantity: 1, |
| | | unit: '', |
| | | unitPrice: 0, |
| | | amount: 0 |
| | | }) |
| | | } |
| | | |
| | | const removeProduct = (index) => { |
| | | form.products.splice(index, 1) |
| | | calculateSubtotal() |
| | | } |
| | | |
| | | const calculateAmount = (product) => { |
| | | product.amount = product.quantity * product.unitPrice |
| | | calculateSubtotal() |
| | | } |
| | | |
| | | const calculateSubtotal = () => { |
| | | form.subtotal = form.products.reduce((sum, product) => sum + product.amount, 0) |
| | | calculateTotal() |
| | | } |
| | | |
| | | const calculateTotal = () => { |
| | | form.discountAmount = form.subtotal * (form.discountRate / 100) |
| | | form.totalAmount = form.subtotal + form.freight + form.otherFee - form.discountAmount |
| | | } |
| | | |
| | | const handleCustomerChange = () => { |
| | | // å¯ä»¥æ ¹æ®å®¢æ·ä¿¡æ¯èªå¨å¡«å
ä¸äºé»è®¤å¼ |
| | | } |
| | | |
| | | const handleSubmit = () => { |
| | | formRef.value.validate((valid) => { |
| | | if (valid) { |
| | | if (form.products.length === 0) { |
| | | ElMessage.warning('请è³å°æ·»å ä¸ä¸ªäº§å') |
| | | return |
| | | } |
| | | |
| | | if (isEdit.value) { |
| | | // ç¼è¾ |
| | | const index = quotationList.value.findIndex(item => item.id === editId.value) |
| | | if (index > -1) { |
| | | quotationList.value[index] = { ...form, id: editId.value } |
| | | ElMessage.success('ç¼è¾æå') |
| | | } |
| | | } else { |
| | | // æ°å¢ |
| | | const newId = Math.max(...quotationList.value.map(item => item.id)) + 1 |
| | | const quotationNo = `QT${new Date().getFullYear()}${String(new Date().getMonth() + 1).padStart(2, '0')}${String(new Date().getDate()).padStart(2, '0')}${String(newId).padStart(3, '0')}` |
| | | quotationList.value.push({ |
| | | ...form, |
| | | id: newId, |
| | | quotationNo: quotationNo |
| | | }) |
| | | pagination.total++ |
| | | ElMessage.success('æ°å¢æå') |
| | | } |
| | | dialogVisible.value = false |
| | | } |
| | | }) |
| | | } |
| | | |
| | | const handleCurrentChange = (val) => { |
| | | pagination.currentPage = val.page |
| | | pagination.pageSize = val.limit |
| | | } |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .search-row { |
| | | margin-bottom: 20px; |
| | | } |
| | | |
| | | .form-card { |
| | | margin-bottom: 20px; |
| | | } |
| | | |
| | | .card-title { |
| | | font-weight: bold; |
| | | color: #303133; |
| | | } |
| | | |
| | | .card-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | } |
| | | |
| | | .dialog-footer { |
| | | text-align: right; |
| | | } |
| | | </style> |