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