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/GenerateReturnDialog.vue |  528 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 528 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>

--
Gitblit v1.9.3