From ea6ad9ddc3d5b33897e93276282245f7023836ff Mon Sep 17 00:00:00 2001 From: spring <2396852758@qq.com> Date: 星期四, 28 八月 2025 17:45:28 +0800 Subject: [PATCH] 大数据市场分析 --- src/views/sales/components/PurchaseReturnDialog.vue | 453 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 453 insertions(+), 0 deletions(-) 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> -- Gitblit v1.9.3