From c65e1446d2d386c4e6baef2fcc606bdd6de90576 Mon Sep 17 00:00:00 2001 From: spring <2396852758@qq.com> Date: 星期四, 28 八月 2025 14:02:59 +0800 Subject: [PATCH] 采购退货单 --- src/views/sales/components/GenerateReturnDialog.vue | 528 +++++++++++++++++ src/views/sales/purchaseReturn.vue | 462 +++++++++++++++ src/views/sales/components/PurchaseReturnDialog.vue | 453 +++++++++++++++ src/views/sales/components/PurchaseReturnViewDialog.vue | 324 ++++++++++ 4 files changed, 1,767 insertions(+), 0 deletions(-) diff --git a/src/views/sales/components/GenerateReturnDialog.vue b/src/views/sales/components/GenerateReturnDialog.vue new file mode 100644 index 0000000..ff6a7bd --- /dev/null +++ b/src/views/sales/components/GenerateReturnDialog.vue @@ -0,0 +1,528 @@ +<template> + <el-dialog + :model-value="dialogGenerateVisible" + @update:model-value="$emit('update:dialogGenerateVisible', $event)" + title="涓�閿敓鎴愰��璐у崟" + width="1000px" + :close-on-click-modal="false" + > + <div class="generate-container"> + <!-- 閫夋嫨閲囪喘璁㈠崟 --> + <el-card class="select-card" shadow="never"> + <template #header> + <div class="card-header"> + <span>閫夋嫨閲囪喘璁㈠崟</span> + </div> + </template> + + <el-form :inline="true" :model="searchForm" class="search-form"> + <el-form-item label="渚涘簲鍟�"> + <el-select + v-model="searchForm.supplierId" + placeholder="璇烽�夋嫨渚涘簲鍟�" + clearable + style="width: 200px" + @change="handleSupplierChange" + > + <el-option + :label="item.label" + v-for="item in supplierList" + :key="item.value" + :value="item.value" + /> + </el-select> + </el-form-item> + <el-form-item label="璁㈠崟鐘舵��"> + <el-select + v-model="searchForm.orderStatus" + placeholder="璇烽�夋嫨璁㈠崟鐘舵��" + clearable + style="width: 150px" + > + <el-option + :label="item.label" + v-for="item in orderStatusList" + :key="item.value" + :value="item.value" + /> + </el-select> + </el-form-item> + <el-form-item> + <el-button type="primary" @click="searchOrders">鏌ヨ</el-button> + <el-button @click="resetSearch">閲嶇疆</el-button> + </el-form-item> + </el-form> + + <el-table + :data="orderList" + @selection-change="handleOrderSelectionChange" + border + style="width: 100%" + max-height="300" + > + <el-table-column type="selection" width="55" /> + <el-table-column label="璁㈠崟鍙�" prop="orderNo" width="180" /> + <el-table-column label="渚涘簲鍟�" prop="supplierName" width="150" /> + <el-table-column label="璁㈠崟鏃ユ湡" prop="orderDate" width="120" /> + <el-table-column label="鍟嗗搧鍚嶇О" prop="coalName" width="150" /> + <el-table-column label="璁㈠崟鏁伴噺" prop="orderQuantity" width="100"> + <template #default="scope"> + {{ scope.row.orderQuantity }} 鍚� + </template> + </el-table-column> + <el-table-column label="宸叉敹璐ф暟閲�" prop="receivedQuantity" width="100"> + <template #default="scope"> + {{ scope.row.receivedQuantity }} 鍚� + </template> + </el-table-column> + <el-table-column label="鐘舵��" prop="status" width="100"> + <template #default="scope"> + <el-tag :type="getOrderStatusType(scope.row.status)"> + {{ getOrderStatusText(scope.row.status) }} + </el-tag> + </template> + </el-table-column> + </el-table> + </el-card> + + <!-- 閫�璐т俊鎭厤缃� --> + <el-card class="config-card" shadow="never"> + <template #header> + <div class="card-header"> + <span>閫�璐т俊鎭厤缃�</span> + </div> + </template> + + <el-form :model="returnConfig" label-width="120px" class="config-form"> + <el-row :gutter="20"> + <el-col :span="12"> + <el-form-item label="閫�璐у師鍥�" prop="returnReason"> + <el-select + v-model="returnConfig.returnReason" + placeholder="璇烽�夋嫨閫�璐у師鍥�" + style="width: 100%" + filterable + allow-create + > + <el-option + :label="item.label" + v-for="item in returnReasonList" + :key="item.value" + :value="item.value" + /> + </el-select> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="鎿嶄綔鍛�" prop="operatorId"> + <el-select + v-model="returnConfig.operatorId" + placeholder="璇烽�夋嫨鎿嶄綔鍛�" + style="width: 100%" + filterable + > + <el-option + :label="item.label" + v-for="item in operatorList" + :key="item.value" + :value="item.value" + /> + </el-select> + </el-form-item> + </el-col> + </el-row> + + <el-form-item label="澶囨敞" prop="remark"> + <el-input + v-model="returnConfig.remark" + type="textarea" + :rows="3" + placeholder="璇疯緭鍏ュ娉ㄤ俊鎭�" + /> + </el-form-item> + </el-form> + </el-card> + + <!-- 棰勮閫�璐у崟 --> + <el-card class="preview-card" shadow="never"> + <template #header> + <div class="card-header"> + <span>棰勮閫�璐у崟</span> + </div> + </template> + + <div v-if="selectedOrders.length === 0" class="no-selection"> + <el-empty description="璇峰厛閫夋嫨瑕侀��璐х殑閲囪喘璁㈠崟" /> + </div> + + <div v-else class="preview-content"> + <el-table :data="previewReturnItems" border style="width: 100%"> + <el-table-column label="璁㈠崟鍙�" prop="orderNo" width="150" /> + <el-table-column label="鍟嗗搧鍚嶇О" prop="coalName" width="150" /> + <el-table-column label="閫�璐ф暟閲�" width="120"> + <template #default="scope"> + <el-input + v-model.number="scope.row.returnQuantity" + placeholder="閫�璐ф暟閲�" + type="number" + @input="updateReturnQuantity(scope.$index)" + > + <template v-slot:suffix> + <span>鍚�</span> + </template> + </el-input> + </template> + </el-table-column> + <el-table-column label="鍗曚环" prop="unitPrice" width="120"> + <template #default="scope"> + {{ scope.row.unitPrice }} 鍏�/鍚� + </template> + </el-table-column> + <el-table-column label="灏忚" width="120"> + <template #default="scope"> + {{ (scope.row.returnQuantity * scope.row.unitPrice).toFixed(2) }} 鍏� + </template> + </el-table-column> + </el-table> + + <div class="preview-summary"> + <span class="summary-item"> + 鎬绘暟閲忥細<strong>{{ getTotalReturnQuantity() }} 鍚�</strong> + </span> + <span class="summary-item"> + 鎬婚噾棰濓細<strong>{{ getTotalReturnAmount() }} 鍏�</strong> + </span> + </div> + </div> + </el-card> + </div> + + <template #footer> + <div class="dialog-footer"> + <el-button @click="handleClose">鍙栨秷</el-button> + <el-button + type="primary" + @click="generateReturnOrder" + :loading="generateLoading" + :disabled="selectedOrders.length === 0" + > + 鐢熸垚閫�璐у崟 + </el-button> + </div> + </template> + </el-dialog> +</template> + +<script setup> +import { ref, reactive, computed, watch } from "vue"; +import { ElMessage } from "element-plus"; + +// Props +const props = defineProps({ + dialogGenerateVisible: { + type: Boolean, + default: false + } +}); + +// Emits +const emit = defineEmits(['update:dialogGenerateVisible', 'success']); + +// 鍝嶅簲寮忔暟鎹� +const searchForm = reactive({ + supplierId: "", + orderStatus: "" +}); + +const returnConfig = reactive({ + returnReason: "", + operatorId: "", + remark: "" +}); + +const orderList = ref([]); +const selectedOrders = ref([]); +const generateLoading = ref(false); + +// 渚涘簲鍟嗗垪琛� +const supplierList = ref([ + { value: "1", label: "渚涘簲鍟咥" }, + { value: "2", label: "渚涘簲鍟咮" }, + { value: "3", label: "渚涘簲鍟咰" } +]); + +// 璁㈠崟鐘舵�佸垪琛� +const orderStatusList = ref([ + { value: "received", label: "宸叉敹璐�" }, + { value: "partial_received", label: "閮ㄥ垎鏀惰揣" }, + { value: "quality_issue", label: "璐ㄩ噺闂" } +]); + +// 閫�璐у師鍥犲垪琛� +const returnReasonList = ref([ + { value: "璐ㄩ噺涓嶅悎鏍�", label: "璐ㄩ噺涓嶅悎鏍�" }, + { value: "浜よ揣婊炲悗", label: "浜よ揣婊炲悗" }, + { value: "瑙勬牸涓嶇", label: "瑙勬牸涓嶇" }, + { value: "鏁伴噺涓嶇", label: "鏁伴噺涓嶇" }, + { value: "鍏朵粬鍘熷洜", label: "鍏朵粬鍘熷洜" } +]); + +// 鎿嶄綔鍛樺垪琛� +const operatorList = ref([ + { value: "1", label: "闄堝織寮�" }, + { value: "2", label: "鍒樼編鐜�" }, + { value: "3", label: "鐜嬪缓鍥�" } +]); + +// 妯℃嫙閲囪喘璁㈠崟鏁版嵁 +const mockOrderData = [ + { + id: "1", + orderNo: "CG20241201001", + supplierName: "渚涘簲鍟咥", + orderDate: "2024-12-01", + coalName: "鏃犵儫鐓�", + orderQuantity: 100, + receivedQuantity: 80, + status: "partial_received", + unitPrice: 800 + }, + { + id: "2", + orderNo: "CG20241201002", + supplierName: "渚涘簲鍟咥", + orderDate: "2024-12-01", + coalName: "鐑熺叅", + orderQuantity: 50, + receivedQuantity: 50, + status: "quality_issue", + unitPrice: 750 + }, + { + id: "3", + orderNo: "CG20241201003", + supplierName: "渚涘簲鍟咮", + orderDate: "2024-12-01", + coalName: "瑜愮叅", + orderQuantity: 80, + receivedQuantity: 60, + status: "partial_received", + unitPrice: 600 + } +]; + +// 鑾峰彇璁㈠崟鐘舵�佺被鍨� +const getOrderStatusType = (status) => { + const statusMap = { + received: "success", + partial_received: "warning", + quality_issue: "danger" + }; + return statusMap[status] || ""; +}; + +// 鑾峰彇璁㈠崟鐘舵�佹枃鏈� +const getOrderStatusText = (status) => { + const statusMap = { + received: "宸叉敹璐�", + partial_received: "閮ㄥ垎鏀惰揣", + quality_issue: "璐ㄩ噺闂" + }; + return statusMap[status] || status; +}; + +// 渚涘簲鍟嗗彉鍖栧鐞� +const handleSupplierChange = () => { + searchOrders(); +}; + +// 鏌ヨ璁㈠崟 +const searchOrders = () => { + // 妯℃嫙API璋冪敤 + orderList.value = mockOrderData.filter(order => { + if (searchForm.supplierId && order.supplierName !== supplierList.value.find(s => s.value === searchForm.supplierId)?.label) { + return false; + } + if (searchForm.orderStatus && order.status !== searchForm.orderStatus) { + return false; + } + return true; + }); +}; + +// 閲嶇疆鎼滅储 +const resetSearch = () => { + Object.assign(searchForm, { + supplierId: "", + orderStatus: "" + }); + searchOrders(); +}; + +// 璁㈠崟閫夋嫨鍙樺寲 +const handleOrderSelectionChange = (selection) => { + selectedOrders.value = selection; +}; + +// 棰勮閫�璐у晢鍝� +const previewReturnItems = computed(() => { + return selectedOrders.value.map(order => ({ + ...order, + returnQuantity: order.status === 'quality_issue' ? order.receivedQuantity : (order.orderQuantity - order.receivedQuantity) + })); +}); + +// 鏇存柊閫�璐ф暟閲� +const updateReturnQuantity = (index) => { + const item = previewReturnItems.value[index]; + if (item.returnQuantity > item.receivedQuantity) { + item.returnQuantity = item.receivedQuantity; + ElMessage.warning("閫�璐ф暟閲忎笉鑳借秴杩囧凡鏀惰揣鏁伴噺"); + } +}; + +// 璁$畻鎬婚��璐ф暟閲� +const getTotalReturnQuantity = () => { + return previewReturnItems.value.reduce((total, item) => total + (item.returnQuantity || 0), 0); +}; + +// 璁$畻鎬婚��璐ч噾棰� +const getTotalReturnAmount = () => { + return previewReturnItems.value.reduce((total, item) => { + return total + ((item.returnQuantity || 0) * item.unitPrice); + }, 0).toFixed(2); +}; + +// 鐢熸垚閫�璐у崟 +const generateReturnOrder = async () => { + if (!returnConfig.returnReason) { + ElMessage.warning("璇烽�夋嫨閫�璐у師鍥�"); + return; + } + if (!returnConfig.operatorId) { + ElMessage.warning("璇烽�夋嫨鎿嶄綔鍛�"); + return; + } + + generateLoading.value = true; + + try { + // 妯℃嫙鐢熸垚閫�璐у崟 + await new Promise(resolve => setTimeout(resolve, 1000)); + + const returnOrder = { + returnNo: `TH${Date.now()}`, + supplierName: selectedOrders.value[0]?.supplierName, + returnDate: new Date().toISOString().split('T')[0], + operatorName: operatorList.value.find(op => op.value === returnConfig.operatorId)?.label, + returnReason: returnConfig.returnReason, + returnQuantity: getTotalReturnQuantity(), + returnAmount: getTotalReturnAmount(), + status: "draft", + createTime: new Date().toLocaleString(), + remark: returnConfig.remark, + returnItems: previewReturnItems.value.map(item => ({ + coalId: item.id, + coalName: item.coalName, + specification: "鏍囧噯瑙勬牸", + quantity: item.returnQuantity, + unitPrice: item.unitPrice + })) + }; + + ElMessage.success("閫�璐у崟鐢熸垚鎴愬姛"); + emit('success', returnOrder); + handleClose(); + } catch (error) { + ElMessage.error("鐢熸垚閫�璐у崟澶辫触"); + } finally { + generateLoading.value = false; + } +}; + +// 鍏抽棴瀵硅瘽妗� +const handleClose = () => { + emit('update:dialogGenerateVisible', false); + // 閲嶇疆鏁版嵁 + Object.assign(searchForm, { + supplierId: "", + orderStatus: "" + }); + Object.assign(returnConfig, { + returnReason: "", + operatorId: "", + remark: "" + }); + selectedOrders.value = []; + orderList.value = mockOrderData; +}; + +// 鍒濆鍖栨暟鎹� +watch(() => props.dialogGenerateVisible, (visible) => { + if (visible) { + orderList.value = mockOrderData; + } +}, { immediate: true }); +</script> + +<style scoped> +.generate-container { + padding: 0; +} + +.select-card, +.config-card, +.preview-card { + margin-bottom: 20px; +} + +.select-card:last-child, +.config-card:last-child, +.preview-card:last-child { + margin-bottom: 0; +} + +.card-header { + font-weight: bold; + font-size: 16px; +} + +.search-form { + margin-bottom: 20px; +} + +.config-form { + padding: 20px 0; +} + +.no-selection { + text-align: center; + padding: 40px 0; +} + +.preview-content { + padding: 20px 0; +} + +.preview-summary { + margin-top: 15px; + text-align: right; + padding: 10px; + background-color: #f5f7fa; + border-radius: 4px; +} + +.summary-item { + margin-left: 20px; + font-size: 14px; +} + +.summary-item strong { + color: #409eff; + font-size: 16px; +} + +.dialog-footer { + text-align: right; +} +</style> diff --git a/src/views/sales/components/PurchaseReturnDialog.vue b/src/views/sales/components/PurchaseReturnDialog.vue new file mode 100644 index 0000000..3914ad7 --- /dev/null +++ b/src/views/sales/components/PurchaseReturnDialog.vue @@ -0,0 +1,453 @@ +<template> + <el-dialog + :model-value="dialogFormVisible" + @update:model-value="$emit('update:dialogFormVisible', $event)" + :title="title" + width="1000px" + :close-on-click-modal="false" + @close="handleClose" + > + <el-form + ref="formRef" + :model="formData" + :rules="rules" + label-width="120px" + class="purchase-return-form" + > + <el-row :gutter="20"> + <el-col :span="12"> + <el-form-item label="渚涘簲鍟�" prop="supplierId"> + <el-select + v-model="formData.supplierId" + placeholder="璇烽�夋嫨渚涘簲鍟�" + style="width: 100%" + filterable + > + <el-option + :label="item.label" + v-for="item in supplierList" + :key="item.value" + :value="item.value" + /> + </el-select> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="鍗曟嵁鏃ユ湡" prop="returnDate"> + <el-date-picker + v-model="formData.returnDate" + type="date" + placeholder="璇烽�夋嫨鍗曟嵁鏃ユ湡" + format="YYYY-MM-DD" + value-format="YYYY-MM-DD" + style="width: 100%" + /> + </el-form-item> + </el-col> + </el-row> + + <el-row :gutter="20"> + <el-col :span="12"> + <el-form-item label="鎿嶄綔鍛�" prop="operatorId"> + <el-select + v-model="formData.operatorId" + placeholder="璇烽�夋嫨鎿嶄綔鍛�" + style="width: 100%" + filterable + > + <el-option + :label="item.label" + v-for="item in operatorList" + :key="item.value" + :value="item.value" + /> + </el-select> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="閫�璐у師鍥�" prop="returnReason"> + <el-select + v-model="formData.returnReason" + placeholder="璇烽�夋嫨閫�璐у師鍥�" + style="width: 100%" + filterable + allow-create + > + <el-option + :label="item.label" + v-for="item in returnReasonList" + :key="item.value" + :value="item.value" + /> + </el-select> + </el-form-item> + </el-col> + </el-row> + + <el-row :gutter="20"> + <el-col :span="12"> + <el-form-item label="閫�璐ф暟閲�" prop="returnQuantity"> + <el-input + v-model.number="formData.returnQuantity" + placeholder="璇疯緭鍏ラ��璐ф暟閲�" + style="width: 100%" + > + <template v-slot:suffix> + <span>鍚�</span> + </template> + </el-input> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="閫�璐ч噾棰�" prop="returnAmount"> + <el-input + v-model.number="formData.returnAmount" + placeholder="璇疯緭鍏ラ��璐ч噾棰�" + style="width: 100%" + > + <template v-slot:suffix> + <span>鍏�</span> + </template> + </el-input> + </el-form-item> + </el-col> + </el-row> + + <el-form-item label="閫�璐у晢鍝佷俊鎭�" prop="returnItems"> + <div class="return-items-container"> + <div class="return-items-header"> + <span>鍟嗗搧鏄庣粏</span> + <el-button type="primary" size="small" @click="addReturnItem"> + 娣诲姞鍟嗗搧 + </el-button> + </div> + <el-table :data="formData.returnItems" border style="width: 100%"> + <el-table-column label="鍟嗗搧鍚嶇О" width="180"> + <template #default="scope"> + <el-select + v-model="scope.row.coalId" + placeholder="璇烽�夋嫨鍟嗗搧" + style="width: 100%" + filterable + > + <el-option + :label="item.label" + v-for="item in coalList" + :key="item.value" + :value="item.value" + /> + </el-select> + </template> + </el-table-column> + <el-table-column label="瑙勬牸鍨嬪彿" width="120"> + <template #default="scope"> + <el-input + v-model="scope.row.specification" + placeholder="瑙勬牸鍨嬪彿" + /> + </template> + </el-table-column> + <el-table-column label="鏁伴噺" width="120"> + <template #default="scope"> + <el-input + v-model.number="scope.row.quantity" + placeholder="鏁伴噺" + type="number" + > + <template v-slot:suffix> + <span>鍚�</span> + </template> + </el-input> + </template> + </el-table-column> + <el-table-column label="鍗曚环" width="120"> + <template #default="scope"> + <el-input + v-model.number="scope.row.unitPrice" + placeholder="鍗曚环" + type="number" + > + <template v-slot:suffix> + <span>鍏�/鍚�</span> + </template> + </el-input> + </template> + </el-table-column> + <el-table-column label="灏忚" width="120"> + <template #default="scope"> + <span>{{ (scope.row.quantity * scope.row.unitPrice).toFixed(2) }} 鍏�</span> + </template> + </el-table-column> + <el-table-column label="鎿嶄綔" width="80"> + <template #default="scope"> + <el-button + type="danger" + size="small" + @click="removeReturnItem(scope.$index)" + > + 鍒犻櫎 + </el-button> + </template> + </el-table-column> + </el-table> + </div> + </el-form-item> + + <el-form-item label="澶囨敞" prop="remark"> + <el-input + v-model="formData.remark" + type="textarea" + :rows="3" + placeholder="璇疯緭鍏ュ娉ㄤ俊鎭�" + /> + </el-form-item> + </el-form> + + <template #footer> + <div class="dialog-footer"> + <el-button @click="handleClose">鍙栨秷</el-button> + <el-button type="primary" @click="handleSubmit" :loading="submitLoading"> + 鎻愪氦瀹℃牳 + </el-button> + </div> + </template> + </el-dialog> +</template> + +<script setup> +import { ref, reactive, watch, nextTick } from "vue"; +import { ElMessage } from "element-plus"; + +// Props +const props = defineProps({ + dialogFormVisible: { + type: Boolean, + default: false + }, + form: { + type: Object, + default: () => ({}) + }, + title: { + type: String, + default: "" + }, + isEdit: { + type: Boolean, + default: false + } +}); + +// Emits +const emit = defineEmits(['update:dialogFormVisible', 'update:form', 'submit', 'success']); + +// 鍝嶅簲寮忔暟鎹� +const formRef = ref(null); +const submitLoading = ref(false); + +// 琛ㄥ崟鏁版嵁 +const formData = reactive({ + supplierId: "", + returnDate: "", + operatorId: "", + returnReason: "", + returnQuantity: "", + returnAmount: "", + returnItems: [], + remark: "" +}); + +// 鍒濆鍖栬〃鍗曟暟鎹� +const initFormData = () => { + Object.assign(formData, { + supplierId: "", + returnDate: "", + operatorId: "", + returnReason: "", + returnQuantity: "", + returnAmount: "", + returnItems: [], + remark: "" + }); +}; + +// 渚涘簲鍟嗗垪琛� +const supplierList = ref([ + { value: "1", label: "渚涘簲鍟咥" }, + { value: "2", label: "渚涘簲鍟咮" }, + { value: "3", label: "渚涘簲鍟咰" } +]); + +// 鎿嶄綔鍛樺垪琛� +const operatorList = ref([ + { value: "1", label: "闄堝織寮�" }, + { value: "2", label: "鍒樼編鐜�" }, + { value: "3", label: "鐜嬪缓鍥�" } +]); + +// 閫�璐у師鍥犲垪琛� +const returnReasonList = ref([ + { value: "璐ㄩ噺涓嶅悎鏍�", label: "璐ㄩ噺涓嶅悎鏍�" }, + { value: "浜よ揣婊炲悗", label: "浜よ揣婊炲悗" }, + { value: "瑙勬牸涓嶇", label: "瑙勬牸涓嶇" }, + { value: "鏁伴噺涓嶇", label: "鏁伴噺涓嶇" }, + { value: "鍏朵粬鍘熷洜", label: "鍏朵粬鍘熷洜" } +]); + +// 鍟嗗搧鍒楄〃 +const coalList = ref([ + { value: "1", label: "鏃犵儫鐓�" }, + { value: "2", label: "鐑熺叅" }, + { value: "3", label: "瑜愮叅" }, + { value: "4", label: "鐒︾叅" } +]); + +// 琛ㄥ崟楠岃瘉瑙勫垯 +const rules = { + supplierId: [ + { required: true, message: "璇烽�夋嫨渚涘簲鍟�", trigger: "change" } + ], + returnDate: [ + { required: true, message: "璇烽�夋嫨鍗曟嵁鏃ユ湡", trigger: "change" } + ], + operatorId: [ + { required: true, message: "璇烽�夋嫨鎿嶄綔鍛�", trigger: "change" } + ], + returnReason: [ + { required: true, message: "璇烽�夋嫨閫�璐у師鍥�", trigger: "change" } + ], + returnQuantity: [ + { required: true, message: "璇疯緭鍏ラ��璐ф暟閲�", trigger: "blur" }, + { type: "number", min: 0, message: "鏁伴噺蹇呴』澶т簬0", trigger: "blur" } + ], + returnItems: [ + { + type: "array", + required: true, + message: "璇疯嚦灏戞坊鍔犱竴涓��璐у晢鍝�", + trigger: "change", + validator: (rule, value, callback) => { + if (!value || value.length === 0) { + callback(new Error("璇疯嚦灏戞坊鍔犱竴涓��璐у晢鍝�")); + } else { + callback(); + } + } + } + ] +}; + +// 鐩戝惉琛ㄥ崟鏁版嵁鍙樺寲 +watch(() => props.form, (newVal) => { + Object.assign(formData, newVal); + if (!formData.returnItems || formData.returnItems.length === 0) { + formData.returnItems = []; + } +}, { deep: true, immediate: true }); + +// 娣诲姞閫�璐у晢鍝� +const addReturnItem = () => { + formData.returnItems.push({ + coalId: "", + specification: "", + quantity: 0, + unitPrice: 0 + }); +}; + +// 鍒犻櫎閫�璐у晢鍝� +const removeReturnItem = (index) => { + formData.returnItems.splice(index, 1); +}; + +// 鍏抽棴瀵硅瘽妗� +const handleClose = () => { + emit('update:dialogFormVisible', false); + formRef.value?.resetFields(); +}; + +// 鎻愪氦琛ㄥ崟 +const handleSubmit = async () => { + if (!formRef.value) return; + + try { + await formRef.value.validate(); + + // 楠岃瘉閫�璐у晢鍝佷俊鎭� + if (formData.returnItems.length === 0) { + ElMessage.warning("璇疯嚦灏戞坊鍔犱竴涓��璐у晢鍝�"); + return; + } + + for (let item of formData.returnItems) { + if (!item.coalId) { + ElMessage.warning("璇烽�夋嫨鍟嗗搧"); + return; + } + if (!item.quantity || item.quantity <= 0) { + ElMessage.warning("璇疯緭鍏ユ湁鏁堢殑鍟嗗搧鏁伴噺"); + return; + } + } + + submitLoading.value = true; + + // 妯℃嫙鎻愪氦 + setTimeout(() => { + submitLoading.value = false; + ElMessage.success("鎻愪氦鎴愬姛"); + emit('submit', { ...formData }); + handleClose(); + }, 1000); + + } catch (error) { + console.error('琛ㄥ崟楠岃瘉澶辫触:', error); + } +}; + +// 璁$畻鎬绘暟閲� +const calculateTotalQuantity = () => { + return formData.returnItems.reduce((total, item) => total + (item.quantity || 0), 0); +}; + +// 璁$畻鎬婚噾棰� +const calculateTotalAmount = () => { + return formData.returnItems.reduce((total, item) => { + return total + ((item.quantity || 0) * (item.unitPrice || 0)); + }, 0); +}; + +// 鐩戝惉閫�璐у晢鍝佸彉鍖栵紝鑷姩璁$畻鎬绘暟閲忓拰鎬婚噾棰� +watch(() => formData.returnItems, () => { + formData.returnQuantity = calculateTotalQuantity(); + formData.returnAmount = calculateTotalAmount(); +}, { deep: true }); +</script> + +<style scoped> +.purchase-return-form { + padding: 20px 0; +} + +.return-items-container { + border: 1px solid #dcdfe6; + border-radius: 4px; + padding: 15px; +} + +.return-items-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 15px; + font-weight: bold; +} + +.dialog-footer { + text-align: right; +} + +.el-table { + margin-top: 10px; +} +</style> diff --git a/src/views/sales/components/PurchaseReturnViewDialog.vue b/src/views/sales/components/PurchaseReturnViewDialog.vue new file mode 100644 index 0000000..529b682 --- /dev/null +++ b/src/views/sales/components/PurchaseReturnViewDialog.vue @@ -0,0 +1,324 @@ +<template> + <el-dialog + :model-value="dialogViewVisible" + @update:model-value="$emit('update:dialogViewVisible', $event)" + :title="title" + width="900px" + :close-on-click-modal="false" + > + <div class="view-container"> + <!-- 鍩烘湰淇℃伅 --> + <el-card class="info-card" shadow="never"> + <template #header> + <div class="card-header"> + <span>鍩烘湰淇℃伅</span> + </div> + </template> + <el-descriptions :column="2" border> + <el-descriptions-item label="閫�璐у崟鍙�"> + {{ form.returnNo || '-' }} + </el-descriptions-item> + <el-descriptions-item label="渚涘簲鍟�"> + {{ form.supplierName || '-' }} + </el-descriptions-item> + <el-descriptions-item label="鍗曟嵁鏃ユ湡"> + {{ form.returnDate || '-' }} + </el-descriptions-item> + <el-descriptions-item label="鎿嶄綔鍛�"> + {{ form.operatorName || '-' }} + </el-descriptions-item> + <el-descriptions-item label="閫�璐у師鍥�"> + {{ form.returnReason || '-' }} + </el-descriptions-item> + <el-descriptions-item label="鐘舵��"> + <el-tag :type="getStatusType(form.status)"> + {{ getStatusText(form.status) }} + </el-tag> + </el-descriptions-item> + <el-descriptions-item label="閫�璐ф暟閲�"> + {{ form.returnQuantity || 0 }} 鍚� + </el-descriptions-item> + <el-descriptions-item label="閫�璐ч噾棰�"> + {{ form.returnAmount || 0 }} 鍏� + </el-descriptions-item> + <el-descriptions-item label="鍒涘缓鏃堕棿" :span="2"> + {{ form.createTime || '-' }} + </el-descriptions-item> + <el-descriptions-item label="澶囨敞" :span="2"> + {{ form.remark || '-' }} + </el-descriptions-item> + </el-descriptions> + </el-card> + + <!-- 閫�璐у晢鍝佹槑缁� --> + <el-card class="info-card" shadow="never"> + <template #header> + <div class="card-header"> + <span>閫�璐у晢鍝佹槑缁�</span> + </div> + </template> + <el-table :data="form.returnItems || []" border style="width: 100%"> + <el-table-column label="搴忓彿" type="index" width="60" /> + <el-table-column label="鍟嗗搧鍚嶇О" prop="coalName" width="150" /> + <el-table-column label="瑙勬牸鍨嬪彿" prop="specification" width="150" /> + <el-table-column label="鏁伴噺" prop="quantity" width="100"> + <template #default="scope"> + {{ scope.row.quantity || 0 }} 鍚� + </template> + </el-table-column> + <el-table-column label="鍗曚环" prop="unitPrice" width="120"> + <template #default="scope"> + {{ scope.row.unitPrice || 0 }} 鍏�/鍚� + </template> + </el-table-column> + <el-table-column label="灏忚" width="120"> + <template #default="scope"> + {{ ((scope.row.quantity || 0) * (scope.row.unitPrice || 0)).toFixed(2) }} 鍏� + </template> + </el-table-column> + </el-table> + <div class="table-summary"> + <span class="summary-item"> + 鎬绘暟閲忥細<strong>{{ getTotalQuantity() }} 鍚�</strong> + </span> + <span class="summary-item"> + 鎬婚噾棰濓細<strong>{{ getTotalAmount() }} 鍏�</strong> + </span> + </div> + </el-card> + + <!-- 瀹℃壒娴佺▼ --> + <el-card class="info-card" shadow="never"> + <template #header> + <div class="card-header"> + <span>瀹℃壒娴佺▼</span> + </div> + </template> + <el-timeline> + <el-timeline-item + v-for="(activity, index) in approvalFlow" + :key="index" + :timestamp="activity.timestamp" + :type="activity.type" + > + <h4>{{ activity.title }}</h4> + <p>{{ activity.content }}</p> + <p v-if="activity.operator">鎿嶄綔浜猴細{{ activity.operator }}</p> + </el-timeline-item> + </el-timeline> + </el-card> + </div> + + <template #footer> + <div class="dialog-footer"> + <el-button @click="handleClose">鍏抽棴</el-button> + </div> + </template> + </el-dialog> +</template> + +<script setup> +import { computed } from "vue"; + +// Props +const props = defineProps({ + dialogViewVisible: { + type: Boolean, + default: false + }, + form: { + type: Object, + default: () => ({}) + }, + title: { + type: String, + default: "閫�璐у崟璇︽儏" + } +}); + +// Emits +const emit = defineEmits(['update:dialogViewVisible']); + +// 鑾峰彇鐘舵�佺被鍨� +const getStatusType = (status) => { + const statusMap = { + draft: "", + pending: "warning", + approved: "success", + rejected: "danger", + completed: "info" + }; + return statusMap[status] || ""; +}; + +// 鑾峰彇鐘舵�佹枃鏈� +const getStatusText = (status) => { + const statusMap = { + draft: "鑽夌", + pending: "寰呭鏍�", + approved: "宸插鏍�", + rejected: "宸叉嫆缁�", + completed: "宸插畬鎴�" + }; + return statusMap[status] || status; +}; + +// 璁$畻鎬绘暟閲� +const getTotalQuantity = () => { + if (!props.form.returnItems || props.form.returnItems.length === 0) { + return 0; + } + return props.form.returnItems.reduce((total, item) => total + (item.quantity || 0), 0); +}; + +// 璁$畻鎬婚噾棰� +const getTotalAmount = () => { + if (!props.form.returnItems || props.form.returnItems.length === 0) { + return 0; + } + return props.form.returnItems.reduce((total, item) => { + return total + ((item.quantity || 0) * (item.unitPrice || 0)); + }, 0).toFixed(2); +}; + +// 瀹℃壒娴佺▼鏁版嵁 +const approvalFlow = computed(() => { + const flow = []; + + // 鍒涘缓 + flow.push({ + title: "鍒涘缓閫�璐у崟", + content: "閫�璐у崟宸插垱寤猴紝绛夊緟鎻愪氦瀹℃牳", + timestamp: props.form.createTime || new Date().toLocaleString(), + operator: props.form.operatorName || "绯荤粺", + type: "primary" + }); + + // 鏍规嵁鐘舵�佹坊鍔犲鎵规祦绋� + if (props.form.status === "pending") { + flow.push({ + title: "鎻愪氦瀹℃牳", + content: "閫�璐у崟宸叉彁浜わ紝绛夊緟瀹℃牳", + timestamp: new Date().toLocaleString(), + operator: props.form.operatorName || "绯荤粺", + type: "warning" + }); + } else if (props.form.status === "approved") { + flow.push({ + title: "鎻愪氦瀹℃牳", + content: "閫�璐у崟宸叉彁浜わ紝绛夊緟瀹℃牳", + timestamp: new Date().toLocaleString(), + operator: props.form.operatorName || "绯荤粺", + type: "warning" + }); + flow.push({ + title: "瀹℃牳閫氳繃", + content: "閫�璐у崟瀹℃牳閫氳繃", + timestamp: new Date().toLocaleString(), + operator: "瀹℃牳鍛�", + type: "success" + }); + } else if (props.form.status === "rejected") { + flow.push({ + title: "鎻愪氦瀹℃牳", + content: "閫�璐у崟宸叉彁浜わ紝绛夊緟瀹℃牳", + timestamp: new Date().toLocaleString(), + operator: props.form.operatorName || "绯荤粺", + type: "warning" + }); + flow.push({ + title: "瀹℃牳鎷掔粷", + content: "閫�璐у崟瀹℃牳琚嫆缁�", + timestamp: new Date().toLocaleString(), + operator: "瀹℃牳鍛�", + type: "danger" + }); + } else if (props.form.status === "completed") { + flow.push({ + title: "鎻愪氦瀹℃牳", + content: "閫�璐у崟宸叉彁浜わ紝绛夊緟瀹℃牳", + timestamp: new Date().toLocaleString(), + operator: props.form.operatorName || "绯荤粺", + type: "warning" + }); + flow.push({ + title: "瀹℃牳閫氳繃", + content: "閫�璐у崟瀹℃牳閫氳繃", + timestamp: new Date().toLocaleString(), + operator: "瀹℃牳鍛�", + type: "success" + }); + flow.push({ + title: "閫�璐у畬鎴�", + content: "閫�璐ф祦绋嬪凡瀹屾垚", + timestamp: new Date().toLocaleString(), + operator: "绯荤粺", + type: "info" + }); + } + + return flow; +}); + +// 鍏抽棴瀵硅瘽妗� +const handleClose = () => { + emit('update:dialogViewVisible', false); +}; +</script> + +<style scoped> +.view-container { + padding: 0; +} + +.info-card { + margin-bottom: 20px; +} + +.info-card:last-child { + margin-bottom: 0; +} + +.card-header { + font-weight: bold; + font-size: 16px; +} + +.table-summary { + margin-top: 15px; + text-align: right; + padding: 10px; + background-color: #f5f7fa; + border-radius: 4px; +} + +.summary-item { + margin-left: 20px; + font-size: 14px; +} + +.summary-item strong { + color: #409eff; + font-size: 16px; +} + +.dialog-footer { + text-align: right; +} + +.el-timeline { + padding: 20px; +} + +.el-timeline-item h4 { + margin: 0 0 8px 0; + font-size: 14px; + color: #303133; +} + +.el-timeline-item p { + margin: 4px 0; + font-size: 12px; + color: #606266; +} +</style> diff --git a/src/views/sales/purchaseReturn.vue b/src/views/sales/purchaseReturn.vue new file mode 100644 index 0000000..b84cc10 --- /dev/null +++ b/src/views/sales/purchaseReturn.vue @@ -0,0 +1,462 @@ +<template> + <div class="app-container"> + <el-form :inline="true" :model="queryParams" class="search-form"> + <el-form-item label="閫�璐у崟鍙�"> + <el-input + v-model="queryParams.returnNo" + placeholder="璇疯緭鍏ラ��璐у崟鍙�" + clearable + :style="{ width: '200px' }" + /> + </el-form-item> + <el-form-item label="渚涘簲鍟�"> + <el-select + v-model="queryParams.supplierId" + placeholder="璇烽�夋嫨渚涘簲鍟�" + clearable + :style="{ width: '200px' }" + > + <el-option + :label="item.label" + v-for="item in supplierList" + :key="item.value" + :value="item.value" + /> + </el-select> + </el-form-item> + <el-form-item label="鐘舵��"> + <el-select + v-model="queryParams.status" + placeholder="璇烽�夋嫨鐘舵��" + clearable + :style="{ width: '150px' }" + > + <el-option + :label="item.label" + v-for="item in statusList" + :key="item.value" + :value="item.value" + /> + </el-select> + </el-form-item> + <el-form-item label="鍗曟嵁鏃ユ湡"> + <el-date-picker + v-model="queryParams.dateRange" + type="daterange" + range-separator="鑷�" + start-placeholder="寮�濮嬫棩鏈�" + end-placeholder="缁撴潫鏃ユ湡" + format="YYYY-MM-DD" + value-format="YYYY-MM-DD" + :style="{ width: '240px' }" + /> + </el-form-item> + <el-form-item> + <el-button type="primary" @click="handleQuery">鏌ヨ</el-button> + <el-button @click="resetQuery">閲嶇疆</el-button> + </el-form-item> + </el-form> + + <el-card> + <!-- 鎿嶄綔鎸夐挳鍖� --> + <el-row :gutter="24" class="table-toolbar" justify="space-between"> + <el-button type="primary" :icon="Plus" @click="handleAdd"> + 鏂板閫�璐у崟 + </el-button> + <el-button type="success" :icon="Refresh" @click="handleGenerateReturn"> + 涓�閿敓鎴愰��璐у崟 + </el-button> + <el-button type="danger" :icon="Delete" @click="handleBatchDelete" :disabled="selectedIds.length === 0"> + 鎵归噺鍒犻櫎 + </el-button> + </el-row> + + <!-- 琛ㄦ牸缁勪欢 --> + <el-table + v-loading="loading" + :data="tableData" + @selection-change="handleSelectionChange" + border + style="width: 100%" + > + <el-table-column type="selection" width="55" /> + <el-table-column label="閫�璐у崟鍙�" prop="returnNo" width="180" /> + <el-table-column label="渚涘簲鍟�" prop="supplierName" width="200" /> + <el-table-column label="鍗曟嵁鏃ユ湡" prop="returnDate" width="120" /> + <el-table-column label="鎿嶄綔鍛�" prop="operatorName" width="120" /> + <el-table-column label="閫�璐у師鍥�" prop="returnReason" width="200" show-overflow-tooltip /> + <el-table-column label="閫�璐ф暟閲�" prop="returnQuantity" width="120"> + <template #default="scope"> + {{ scope.row.returnQuantity }} 鍚� + </template> + </el-table-column> + <el-table-column label="鐘舵��" prop="status" width="100"> + <template #default="scope"> + <el-tag :type="getStatusType(scope.row.status)"> + {{ getStatusText(scope.row.status) }} + </el-tag> + </template> + </el-table-column> + <el-table-column label="鍒涘缓鏃堕棿" prop="createTime" width="160" /> + <el-table-column label="鎿嶄綔" width="200" fixed="right"> + <template #default="scope"> + <el-button + size="small" + type="primary" + @click="handleView(scope.row)" + > + 鏌ョ湅 + </el-button> + <el-button + size="small" + type="warning" + @click="handleEdit(scope.row)" + v-if="scope.row.status === 'draft'" + > + 缂栬緫 + </el-button> + <el-button + size="small" + type="danger" + @click="handleDelete(scope.row)" + v-if="scope.row.status === 'draft'" + > + 鍒犻櫎 + </el-button> + </template> + </el-table-column> + </el-table> + + <!-- 鍒嗛〉缁勪欢 --> + <pagination + v-if="total > 0" + :page="current" + :limit="pageSize" + :total="total" + @pagination="handlePagination" + :layout="'total, prev, pager, next, jumper'" + /> + </el-card> + + <!-- 鏂板/缂栬緫瀵硅瘽妗� --> + <PurchaseReturnDialog + v-model:dialogFormVisible="dialogFormVisible" + v-model:form="form" + :title="title" + :is-edit="isEdit" + @submit="handleSubmit" + @success="handleSuccess" + ref="purchaseReturnDialog" + /> + + <!-- 鏌ョ湅璇︽儏瀵硅瘽妗� --> + <PurchaseReturnViewDialog + v-model:dialogViewVisible="dialogViewVisible" + :form="viewForm" + title="閫�璐у崟璇︽儏" + /> + + <!-- 涓�閿敓鎴愰��璐у崟瀵硅瘽妗� --> + <GenerateReturnDialog + v-model:dialogGenerateVisible="dialogGenerateVisible" + @success="handleGenerateSuccess" + /> + </div> +</template> + +<script setup> +import { ref, reactive, onMounted, getCurrentInstance } from "vue"; +import { ElMessage, ElMessageBox } from "element-plus"; +import { Plus, Edit, Delete, Refresh, View } from "@element-plus/icons-vue"; +import Pagination from "@/components/Pagination"; +import PurchaseReturnDialog from "./components/PurchaseReturnDialog.vue"; +import PurchaseReturnViewDialog from "./components/PurchaseReturnViewDialog.vue"; +import GenerateReturnDialog from "./components/GenerateReturnDialog.vue"; + +// 鍝嶅簲寮忔暟鎹� +const loading = ref(false); +const tableData = ref([]); +const selectedIds = ref([]); +const current = ref(1); +const pageSize = ref(10); +const total = ref(0); +const dialogFormVisible = ref(false); +const dialogViewVisible = ref(false); +const dialogGenerateVisible = ref(false); +const isEdit = ref(false); +const title = ref(""); +const form = ref({}); +const viewForm = ref({}); + +// 鏌ヨ鍙傛暟 +const queryParams = reactive({ + returnNo: "", + supplierId: "", + status: "", + dateRange: [] +}); + +// 渚涘簲鍟嗗垪琛� +const supplierList = ref([ + { value: "1", label: "渚涘簲鍟咥" }, + { value: "2", label: "渚涘簲鍟咮" }, + { value: "3", label: "渚涘簲鍟咰" } +]); + +// 鐘舵�佸垪琛� +const statusList = ref([ + { value: "draft", label: "鑽夌" }, + { value: "pending", label: "寰呭鏍�" }, + { value: "approved", label: "宸插鏍�" }, + { value: "rejected", label: "宸叉嫆缁�" }, + { value: "completed", label: "宸插畬鎴�" } +]); + +// 妯℃嫙鏁版嵁 +const mockData = [ + { + id: "1", + returnNo: "TH20241201001", + supplierName: "渚涘簲鍟咥", + returnDate: "2024-12-01", + operatorName: "闄堝織寮�", + returnReason: "璐ㄩ噺涓嶅悎鏍硷紝鐓よ川涓嶇鍚堣姹�", + returnQuantity: 50, + status: "pending", + createTime: "2024-12-01 10:00:00" + }, + { + id: "2", + returnNo: "TH20241201002", + supplierName: "渚涘簲鍟咮", + returnDate: "2024-12-01", + operatorName: "鍒樼編鐜�", + returnReason: "浜よ揣婊炲悗锛屽奖鍝嶇敓浜ц鍒�", + returnQuantity: 30, + status: "approved", + createTime: "2024-12-01 14:30:00" + } +]; + +// 鑾峰彇鐘舵�佺被鍨� +const getStatusType = (status) => { + const statusMap = { + draft: "", + pending: "warning", + approved: "success", + rejected: "danger", + completed: "info" + }; + return statusMap[status] || ""; +}; + +// 鑾峰彇鐘舵�佹枃鏈� +const getStatusText = (status) => { + const statusMap = { + draft: "鑽夌", + pending: "寰呭鏍�", + approved: "宸插鏍�", + rejected: "宸叉嫆缁�", + completed: "宸插畬鎴�" + }; + return statusMap[status] || status; +}; + +// 鏌ヨ +const handleQuery = () => { + current.value = 1; + loadData(); +}; + +// 閲嶇疆鏌ヨ +const resetQuery = () => { + Object.assign(queryParams, { + returnNo: "", + supplierId: "", + status: "", + dateRange: [] + }); + handleQuery(); +}; + +// 鍔犺浇鏁版嵁 +const loadData = () => { + loading.value = true; + // 妯℃嫙API璋冪敤 + setTimeout(() => { + tableData.value = mockData; + total.value = mockData.length; + loading.value = false; + }, 500); +}; + +// 鍒嗛〉澶勭悊 +const handlePagination = (pagination) => { + current.value = pagination.page; + pageSize.value = pagination.limit; + loadData(); +}; + +// 閫夋嫨鍙樺寲 +const handleSelectionChange = (selection) => { + selectedIds.value = selection.map(item => item.id); +}; + +// 鏂板 +const handleAdd = () => { + isEdit.value = false; + title.value = "鏂板閫�璐у崟"; + form.value = { + supplierId: "", + returnDate: "", + operatorId: "", + returnReason: "", + returnQuantity: "", + returnAmount: "", + returnItems: [], + remark: "" + }; + dialogFormVisible.value = true; +}; + +// 缂栬緫 +const handleEdit = (row) => { + isEdit.value = true; + title.value = "缂栬緫閫�璐у崟"; + form.value = { ...row }; + dialogFormVisible.value = true; +}; + +// 鏌ョ湅 +const handleView = (row) => { + viewForm.value = { ...row }; + dialogViewVisible.value = true; +}; + +// 鍒犻櫎 +const handleDelete = (row) => { + ElMessageBox.confirm( + `纭畾瑕佸垹闄ら��璐у崟 ${row.returnNo} 鍚楋紵`, + "鎻愮ず", + { + confirmButtonText: "纭畾", + cancelButtonText: "鍙栨秷", + type: "warning" + } + ).then(() => { + // 妯℃嫙鍒犻櫎 + const index = tableData.value.findIndex(item => item.id === row.id); + if (index > -1) { + tableData.value.splice(index, 1); + total.value--; + ElMessage.success("鍒犻櫎鎴愬姛"); + } + }); +}; + +// 鎵归噺鍒犻櫎 +const handleBatchDelete = () => { + if (selectedIds.value.length === 0) { + ElMessage.warning("璇烽�夋嫨瑕佸垹闄ょ殑璁板綍"); + return; + } + + ElMessageBox.confirm( + `纭畾瑕佸垹闄ら�変腑鐨� ${selectedIds.value.length} 鏉¤褰曞悧锛焋, + "鎻愮ず", + { + confirmButtonText: "纭畾", + cancelButtonText: "鍙栨秷", + type: "warning" + } + ).then(() => { + // 妯℃嫙鎵归噺鍒犻櫎 + tableData.value = tableData.value.filter(item => !selectedIds.value.includes(item.id)); + total.value = tableData.value.length; + selectedIds.value = []; + ElMessage.success("鎵归噺鍒犻櫎鎴愬姛"); + }); +}; + +// 涓�閿敓鎴愰��璐у崟 +const handleGenerateReturn = () => { + dialogGenerateVisible.value = true; +}; + +// 鎻愪氦琛ㄥ崟 +const handleSubmit = (formData) => { + if (isEdit.value) { + // 缂栬緫 + const index = tableData.value.findIndex(item => item.id === formData.id); + if (index > -1) { + tableData.value[index] = { ...formData }; + ElMessage.success("缂栬緫鎴愬姛"); + } + } else { + // 鏂板 + const newItem = { + id: Date.now().toString(), + returnNo: `TH${Date.now()}`, + supplierName: supplierList.value.find(item => item.value === formData.supplierId)?.label || "", + returnDate: formData.returnDate, + operatorName: "褰撳墠鐢ㄦ埛", + returnReason: formData.returnReason, + returnQuantity: formData.returnQuantity, + status: "draft", + createTime: new Date().toLocaleString() + }; + tableData.value.unshift(newItem); + total.value++; + ElMessage.success("鏂板鎴愬姛"); + } + dialogFormVisible.value = false; +}; + +// 琛ㄥ崟鎴愬姛鍥炶皟 +const handleSuccess = () => { + loadData(); +}; + +// 鐢熸垚閫�璐у崟鎴愬姛鍥炶皟 +const handleGenerateSuccess = (returnOrder) => { + dialogGenerateVisible.value = false; + // 灏嗙敓鎴愮殑閫�璐у崟娣诲姞鍒板垪琛ㄤ腑 + if (returnOrder) { + const newItem = { + id: Date.now().toString(), + returnNo: returnOrder.returnNo, + supplierName: returnOrder.supplierName, + returnDate: returnOrder.returnDate, + operatorName: returnOrder.operatorName, + returnReason: returnOrder.returnReason, + returnQuantity: returnOrder.returnQuantity, + status: returnOrder.status, + createTime: returnOrder.createTime, + returnItems: returnOrder.returnItems + }; + tableData.value.unshift(newItem); + total.value++; + } + loadData(); + ElMessage.success("閫�璐у崟鐢熸垚鎴愬姛"); +}; + +// 椤甸潰鍔犺浇 +onMounted(() => { + loadData(); +}); +</script> + +<style scoped> +.search-form { + margin-bottom: 20px; +} + +.table-toolbar { + margin-bottom: 20px; +} + +.el-card { + margin-bottom: 20px; +} +</style> -- Gitblit v1.9.3