From b6a007d417bf5eea80ec807d3f1201e220e5f651 Mon Sep 17 00:00:00 2001
From: yyb <995253665@qq.com>
Date: 星期三, 13 五月 2026 10:24:33 +0800
Subject: [PATCH] 销售和采购退货

---
 src/views/procurementManagement/purchaseReturnOrder/index.vue |  491 +++++++++++++++++++++++++++++++++++++++++++++++-------
 1 files changed, 426 insertions(+), 65 deletions(-)

diff --git a/src/views/procurementManagement/purchaseReturnOrder/index.vue b/src/views/procurementManagement/purchaseReturnOrder/index.vue
index 4e91e59..3986f03 100644
--- a/src/views/procurementManagement/purchaseReturnOrder/index.vue
+++ b/src/views/procurementManagement/purchaseReturnOrder/index.vue
@@ -1,109 +1,470 @@
 <template>
   <div class="app-container">
     <div class="search_form">
-      <el-form :model="searchForm"
-               :inline="true">
+      <el-form :model="searchForm" :inline="true">
         <el-form-item label="閫�鏂欏崟鍙凤細">
-          <el-input v-model="searchForm.no"
-                    placeholder="璇疯緭鍏�"
-                    clearable
-                    prefix-icon="Search"
-                    @change="handleQuery" />
+          <el-input
+            v-model="searchForm.no"
+            placeholder="璇疯緭鍏�"
+            clearable
+            prefix-icon="Search"
+            @change="handleQuery"
+          />
         </el-form-item>
 
         <el-form-item>
-          <el-button type="primary"
-                     @click="handleQuery"> 鎼滅储 </el-button>
+          <el-button type="primary" @click="handleQuery"> 鎼滅储 </el-button>
         </el-form-item>
       </el-form>
 
       <div>
-        <el-button type="primary" @click="isShowNewModal = true">鏂板</el-button>
+        <el-button type="primary" @click="isShowNewModal = true"
+          >鏂板</el-button
+        >
       </div>
     </div>
 
     <div class="table_list">
-      <el-table :data="tableData" border v-loading="tableLoading" @selection-change="handleSelectionChange" :row-key="row => row.id" style="width: 100%" height="calc(100vh - 18.5em)">
-        <el-table-column align="center" type="selection" width="55" />
-        <el-table-column align="center" label="搴忓彿" type="index" width="60" />
-        <el-table-column label="閫�鏂欏崟鍙�" prop="no" show-overflow-tooltip />
-        <el-table-column label="閫�璐ф柟寮�" prop="returnType" show-overflow-tooltip />
-        <el-table-column label="渚涘簲鍟嗗悕绉�" prop="supplierName" show-overflow-tooltip />
-        <el-table-column label="鍏宠仈鍗曞彿" prop="purchaseContractNumber" show-overflow-tooltip />
-        <el-table-column label="閫�鏂欎汉" prop="returnUserName" show-overflow-tooltip />
-        <el-table-column label="澶囨敞" prop="remark"  show-overflow-tooltip />
-        <el-table-column label="鍒涘缓浜�" prop="createUserName"  show-overflow-tooltip />
-        <el-table-column label="鍒涘缓鏃堕棿" prop="createTime" show-overflow-tooltip />
-        <el-table-column label="鏈�杩戞洿鏂版椂闂�" prop="updateTime" show-overflow-tooltip />
-        <el-table-column fixed="right" label="鎿嶄綔" min-width="60" align="center">
-          <template #default="scope">
-            <el-button link type="primary" size="small">璇︽儏</el-button>
-          </template>
-        </el-table-column>
-      </el-table>
-      <pagination v-show="total > 0" :total="total" layout="total, sizes, prev, pager, next, jumper"
-                  :page="page.current" :limit="page.size" @pagination="paginationChange" />
+      <PIMTable
+        rowKey="id"
+        :column="tableColumn"
+        :tableData="tableData"
+        :tableLoading="tableLoading"
+        :isSelection="true"
+        :page="page"
+        :height="'calc(100vh - 18.5em)'"
+        @selection-change="handleSelectionChange"
+        @pagination="paginationChange"
+      >
+        <template #operation="{ row }">
+          <el-button
+            link
+            type="primary"
+            size="small"
+            style="color: #67c23a"
+            @click="handleDetail(row)"
+            >璇︽儏</el-button
+          >
+          <el-button link size="small" @click="handleDelete(row)"
+            >鍒犻櫎</el-button
+          >
+        </template>
+      </PIMTable>
     </div>
-    <new v-if="isShowNewModal"
-         v-model:visible="isShowNewModal"
-         @completed="handleQuery" />
+    <new
+      v-if="isShowNewModal"
+      v-model:visible="isShowNewModal"
+      @completed="handleQuery"
+    />
+
+    <el-dialog
+      v-model="detailVisible"
+      title="閲囪喘閫�璐ц鎯�"
+      width="1200"
+      destroy-on-close
+    >
+      <div v-loading="detailLoading">
+        <el-descriptions :column="3" border>
+          <el-descriptions-item label="閫�鏂欏崟鍙�">{{
+            detailData.no || "--"
+          }}</el-descriptions-item>
+          <el-descriptions-item label="閫�璐ф柟寮�">{{
+            getReturnTypeLabel(detailData.returnType)
+          }}</el-descriptions-item>
+          <el-descriptions-item label="渚涘簲鍟嗗悕绉�">{{
+            detailData.supplierName || "--"
+          }}</el-descriptions-item>
+          <el-descriptions-item label="椤圭洰闃舵">{{
+            getProjectPhaseLabel(detailData.projectPhase)
+          }}</el-descriptions-item>
+          <el-descriptions-item label="鍏宠仈鐨勯噰璐鍗曞彿">{{
+            detailData.purchaseContractNumber || "--"
+          }}</el-descriptions-item>
+          <el-descriptions-item label="鍒朵綔鏃ユ湡">{{
+            detailData.preparedAt || "--"
+          }}</el-descriptions-item>
+          <el-descriptions-item label="鍒跺崟浜�">{{
+            detailData.preparedUserName || "--"
+          }}</el-descriptions-item>
+          <el-descriptions-item label="閫�鏂欎汉">{{
+            detailData.returnUserName || "--"
+          }}</el-descriptions-item>
+          <el-descriptions-item label="鏁村崟鎶樻墸棰�">{{
+            formatAmount(detailData.totalDiscountAmount)
+          }}</el-descriptions-item>
+          <el-descriptions-item label="鏁村崟鎶樻墸鐜�">{{
+            detailData.totalDiscountRate ?? "--"
+          }}</el-descriptions-item>
+          <el-descriptions-item label="鎴愪氦閲戦">{{
+            formatAmount(detailData.totalAmount)
+          }}</el-descriptions-item>
+          <el-descriptions-item label="鍒涘缓浜�">{{
+            detailData.createUserName || "--"
+          }}</el-descriptions-item>
+          <el-descriptions-item label="鍒涘缓鏃堕棿">{{
+            detailData.createTime || "--"
+          }}</el-descriptions-item>
+          <el-descriptions-item label="鏈�杩戞洿鏂版椂闂�">{{
+            detailData.updateTime || "--"
+          }}</el-descriptions-item>
+          <el-descriptions-item label="澶囨敞" :span="3">{{
+            detailData.remark || "--"
+          }}</el-descriptions-item>
+        </el-descriptions>
+
+        <el-divider content-position="left">浜у搧鍒楄〃</el-divider>
+
+        <el-table
+          :data="detailProducts"
+          border
+          max-height="420"
+          style="width: 100%"
+        >
+          <el-table-column
+            align="center"
+            label="搴忓彿"
+            type="index"
+            width="60"
+          />
+          <el-table-column label="鍏ュ簱鍗曞彿" prop="inboundBatches" width="150" />
+          <el-table-column label="鎵规鍙�" prop="batchNo" width="150" />
+          <el-table-column
+            label="浜у搧澶х被"
+            prop="productCategory"
+            min-width="120"
+            show-overflow-tooltip
+          />
+          <el-table-column
+            label="瑙勬牸鍨嬪彿"
+            prop="specificationModel"
+            min-width="140"
+            show-overflow-tooltip
+          />
+          <el-table-column label="鍗曚綅" prop="unit" width="80" />
+          <el-table-column label="鏁伴噺" prop="stockInNum" width="80" />
+          <el-table-column label="鍙��璐ф暟閲�"
+                           prop="unQuantity"
+                           width="100" />
+          <el-table-column label="宸查��璐ф暟閲�"
+                           prop="totalReturnNum"
+                           width="100" />
+          <!-- <el-table-column label="搴撳瓨棰勮鏁伴噺" prop="warnNum" width="120" /> -->
+          <!-- <el-table-column label="绋庣巼(%)" prop="taxRate" width="90" /> -->
+          <el-table-column
+            label="鍚◣鍗曚环(鍏�)"
+            prop="taxInclusiveUnitPrice"
+            width="130"
+          >
+            <template #default="scope">{{
+              formatAmount(scope.row.taxInclusiveUnitPrice)
+            }}</template>
+          </el-table-column>
+          <!-- <el-table-column
+            label="閫�璐ф�讳环(鍏�)"
+            prop="taxInclusiveTotalPrice"
+            width="130"
+          >
+            <template #default="scope">{{
+              formatAmount(scope.row.taxInclusiveTotalPrice)
+            }}</template>
+          </el-table-column>
+          <el-table-column
+            label="涓嶉��璐ф�讳环(鍏�)"
+            prop="taxExclusiveTotalPrice"
+            width="140"
+          >
+            <template #default="scope">{{
+              formatAmount(scope.row.taxExclusiveTotalPrice)
+            }}</template>
+          </el-table-column> -->
+          <el-table-column
+            label="鏄惁璐ㄦ"
+            prop="isChecked"
+            width="100"
+            align="center"
+          >
+            <template #default="scope">
+              <el-tag :type="scope.row.isChecked ? 'success' : 'info'">
+                {{ scope.row.isChecked ? "鏄�" : "鍚�" }}
+              </el-tag>
+            </template>
+          </el-table-column>
+        </el-table>
+      </div>
+      <template #footer>
+        <el-button @click="detailVisible = false">鍏抽棴</el-button>
+      </template>
+    </el-dialog>
   </div>
 </template>
 
 <script setup>
-import pagination from '@/components/PIMTable/Pagination.vue'
-import { ref, reactive, toRefs, onMounted } from 'vue'
-import {findPurchaseReturnOrderListPage} from "@/api/procurementManagement/purchase_return_order.js";
-const New = defineAsyncComponent(() => import("@/views/procurementManagement/purchaseReturnOrder/New.vue"));
-const tableData = ref([])
-const selectedRows = ref([])
-const tableLoading = ref(false)
+import PIMTable from "@/components/PIMTable/PIMTable.vue";
+import {
+  ref,
+  reactive,
+  toRefs,
+  onMounted,
+  defineAsyncComponent,
+  getCurrentInstance,
+} from "vue";
+const { proxy } = getCurrentInstance();
+import {
+  findPurchaseReturnOrderListPage,
+  getPurchaseReturnOrderDetail,
+  deletePurchaseReturnOrder,
+} from "@/api/procurementManagement/purchase_return_order.js";
+const New = defineAsyncComponent(() =>
+  import("@/views/procurementManagement/purchaseReturnOrder/New.vue")
+);
+const tableData = ref([]);
+const selectedRows = ref([]);
+const tableLoading = ref(false);
 const page = reactive({
   current: 1,
   size: 100,
-})
-const total = ref(0)
+  total: 0,
+});
+const detailVisible = ref(false);
+const detailLoading = ref(false);
+const detailData = ref({});
+const detailProducts = ref([]);
 // 鏄惁鏄剧ず鏂板寮规
-const isShowNewModal = ref(false)
+const isShowNewModal = ref(false);
+const returnTypeOptions = [
+  { label: "閫�璐ч��娆�", value: 0 },
+  { label: "鎷掓敹", value: 1 },
+];
+const projectPhaseOptions = [
+  { label: "绔嬮」", value: 0 },
+  { label: "璁捐", value: 1 },
+  { label: "閲囪喘", value: 2 },
+  { label: "鐢熶骇", value: 3 },
+  { label: "鍑鸿揣", value: 4 },
+];
+const tableColumn = ref([
+  {
+    label: "閫�鏂欏崟鍙�",
+    prop: "no",
+  },
+  {
+    label: "閫�璐ф柟寮�",
+    prop: "returnType",
+    formatData: (val) =>
+      returnTypeOptions.find((item) => item.value === val)?.label || "--",
+  },
+  {
+    label: "渚涘簲鍟嗗悕绉�",
+    prop: "supplierName",
+    width: 180,
+  },
+  {
+    label: "椤圭洰闃舵",
+    prop: "projectPhase",
+    width: 100,
+    formatData: (val) =>
+      projectPhaseOptions.find((item) => String(item.value) === String(val))
+        ?.label || "--",
+  },
+  {
+    label: "鍏宠仈鐨勯噰璐鍗曞彿",
+    prop: "purchaseContractNumber",
+    width: 160,
+  },
+  {
+    label: "鍒朵綔鏃ユ湡",
+    prop: "preparedAt",
+    width: 130,
+  },
+  {
+    label: "鍒跺崟浜�",
+    prop: "preparedUserName",
+    width: 110,
+  },
+  {
+    label: "閫�鏂欎汉",
+    prop: "returnUserName",
+    width: 110,
+  },
+
+  {
+    label: "鏁村崟鎶樻墸棰�",
+    prop: "totalDiscountAmount",
+    width: 120,
+  },
+  {
+    label: "鏁村崟鎶樻墸鐜�",
+    prop: "totalDiscountRate",
+    width: 120,
+  },
+  {
+    label: "鎴愪氦閲戦",
+    prop: "totalAmount",
+    width: 120,
+  },
+  {
+    label: "鍒涘缓浜�",
+    prop: "createUserName",
+    width: 110,
+  },
+  {
+    label: "鍒涘缓鏃堕棿",
+    prop: "createTime",
+    width: 170,
+  },
+  {
+    label: "鏈�杩戞洿鏂版椂闂�",
+    prop: "updateTime",
+    width: 170,
+  },
+  {
+    label: "澶囨敞",
+    prop: "remark",
+    width: 180,
+  },
+  {
+    dataType: "action",
+    width: 120,
+    label: "鎿嶄綔",
+    align: "center",
+    fixed: "right",
+    operation: [
+      {
+        name: "璇︽儏",
+        type: "text",
+        clickFun: (row) => {
+          handleDetail(row);
+        },
+      },
+      {
+        name: "鍒犻櫎",
+        clickFun: (row) => {
+          handleDelete(row);
+        },
+      },
+    ],
+  },
+]);
 const data = reactive({
   searchForm: {
-    no: '',
-  }
-})
-const { searchForm } = toRefs(data)
+    no: "",
+  },
+});
+const { searchForm } = toRefs(data);
 
 // 鏌ヨ鍒楄〃
 /** 鎼滅储鎸夐挳鎿嶄綔 */
 const handleQuery = () => {
-  page.current = 1
-  getList()
-}
+  page.current = 1;
+  getList();
+};
+
+// 鍒犻櫎鎿嶄綔
+const handleDelete = (row) => {
+  console.log("鍒犻櫎琛屾暟鎹細", row);
+  proxy?.$modal
+    ?.confirm("纭畾瑕佸垹闄ゅ悧锛熷垹闄ゅ皢鏃犳硶鎭㈠")
+    .then(() => {
+      // 杩欓噷璋冪敤鍒犻櫎鎺ュ彛锛屼紶鍏� row.id
+      deletePurchaseReturnOrder(row.id)
+        .then(() => {
+          proxy?.$modal?.msgSuccess?.("鍒犻櫎鎴愬姛");
+          getList();
+        })
+        .catch(() => {
+          proxy?.$modal?.msgError?.("鍒犻櫎澶辫触");
+        });
+    })
+    .catch(() => {
+      // 鍙栨秷鍒犻櫎
+      proxy?.$modal?.msgInfo?.("宸插彇娑堝垹闄�");
+    });
+};
+// 鏌ョ湅璇︽儏
+const handleDetail = (row) => {
+  if (!row?.id) {
+    proxy?.$modal?.msgWarning?.("鏈幏鍙栧埌鍗曟嵁ID");
+    return;
+  }
+  detailVisible.value = true;
+  detailLoading.value = true;
+  getPurchaseReturnOrderDetail(row.id)
+    .then((res) => {
+      const payload = res?.data || {};
+      detailData.value = payload;
+      // 鎷兼帴杩炰釜瀵硅薄鎴愪竴涓璞★紝鏂逛究灞曠ず item 鍜� item.salesLedgerProduct 閲岀殑瀛楁
+
+      detailProducts.value =
+        payload.purchaseReturnOrderProductsDetailVoList.map((item) => ({
+          ...item,
+          ...item.salesLedgerProduct,
+        })) || [];
+    })
+    .catch(() => {
+      proxy?.$modal?.msgError?.("鑾峰彇璇︽儏澶辫触");
+    })
+    .finally(() => {
+      detailLoading.value = false;
+    });
+};
 
 const paginationChange = (obj) => {
   page.current = obj.page;
   page.size = obj.limit;
-  getList()
-}
+  getList();
+};
 
 const getList = () => {
-  tableLoading.value = true
-  findPurchaseReturnOrderListPage({ ...searchForm.value, ...page }).then(res => {
-    tableLoading.value = false
-    tableData.value = res.data.records
-    total.value = res.data.total
-  }).catch(() => {
-    tableLoading.value = false
-  })
-}
+  tableLoading.value = true;
+  findPurchaseReturnOrderListPage({ ...searchForm.value, ...page })
+    .then((res) => {
+      tableLoading.value = false;
+      tableData.value = res.data.records;
+      page.total = res.data.total;
+    })
+    .catch(() => {
+      tableLoading.value = false;
+    });
+};
 
 // 琛ㄦ牸閫夋嫨鏁版嵁
 const handleSelectionChange = (selection) => {
   // 杩囨护鎺夊瓙鏁版嵁
-  selectedRows.value = selection.filter(item => item.id);
-}
+  selectedRows.value = selection.filter((item) => item.id);
+};
+
+const getReturnTypeLabel = (value) => {
+  return (
+    returnTypeOptions.find((item) => String(item.value) === String(value))
+      ?.label || "--"
+  );
+};
+
+const getProjectPhaseLabel = (value) => {
+  return (
+    projectPhaseOptions.find((item) => String(item.value) === String(value))
+      ?.label || "--"
+  );
+};
+
+const formatAmount = (value) => {
+  if (value === null || value === undefined || value === "") {
+    return "--";
+  }
+  const num = Number(value);
+  if (Number.isNaN(num)) {
+    return value;
+  }
+  return num.toFixed(2);
+};
 
 onMounted(() => {
-  getList()
-})
+  getList();
+});
 </script>
+<style scoped>
+.table_list {
+  margin-top: unset;
+}
+</style>
 

--
Gitblit v1.9.3