From 1f2e6aa18522e47cdebe0d5f380958a8111c6fe8 Mon Sep 17 00:00:00 2001
From: 张诺 <zhang_12370@163.com>
Date: 星期二, 06 一月 2026 17:58:12 +0800
Subject: [PATCH] 进销存·华玺砂浆》销售台账对出库后提交发货申请完成 进销存·华玺砂浆》发货审核页面开发完成

---
 src/api/collaborativeApproval/shipmentReview.js             |   21 ++
 src/views/collaborativeApproval/shipmentReview/fileList.vue |   43 ++++
 src/views/collaborativeApproval/shipmentReview/index.vue    |  340 +++++++++++++++++++++++++++++++++++++
 src/views/salesManagement/salesLedger/index.vue             |  124 ++++++++++---
 4 files changed, 496 insertions(+), 32 deletions(-)

diff --git a/src/api/collaborativeApproval/shipmentReview.js b/src/api/collaborativeApproval/shipmentReview.js
new file mode 100644
index 0000000..64fac69
--- /dev/null
+++ b/src/api/collaborativeApproval/shipmentReview.js
@@ -0,0 +1,21 @@
+// 鍙戣揣瀹℃壒
+import request from "@/utils/request";
+
+// 鑾峰彇鍙戣揣瀹℃壒鍒楄〃
+export function getShipmentApprovalList(query) {
+    return request({
+        url: '/shipmentApproval/listPage',
+        method: 'get',
+        params: query,
+    })
+}
+
+// 鍙戣揣鐢宠鎵瑰噯
+// /shipmentApproval/update
+export function approveShipment(query) {
+    return request({
+        url: '/shipmentApproval/update',
+        method: 'post',
+        data: query,
+    })
+}
\ No newline at end of file
diff --git a/src/views/collaborativeApproval/shipmentReview/fileList.vue b/src/views/collaborativeApproval/shipmentReview/fileList.vue
new file mode 100644
index 0000000..da37db2
--- /dev/null
+++ b/src/views/collaborativeApproval/shipmentReview/fileList.vue
@@ -0,0 +1,43 @@
+<template>
+  <el-dialog v-model="dialogVisible" title="闄勪欢" width="40%" :before-close="handleClose">
+    <el-table :data="tableData" border height="40vh">
+      <el-table-column label="闄勪欢鍚嶇О" prop="name" min-width="400" show-overflow-tooltip />
+      <el-table-column fixed="right" label="鎿嶄綔" width="100" align="center">
+        <template #default="scope">
+          <el-button link type="primary" size="small" @click="downLoadFile(scope.row)">涓嬭浇</el-button>
+          <el-button link type="primary" size="small" @click="lookFile(scope.row)">棰勮</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+  </el-dialog>
+  <filePreview ref="filePreviewRef" />
+</template>
+
+<script setup>
+import { ref } from 'vue'
+import filePreview from '@/components/filePreview/index.vue'
+
+const dialogVisible = ref(false)
+const tableData = ref([])
+const { proxy } = getCurrentInstance();
+const filePreviewRef = ref()
+const handleClose = () => {
+  dialogVisible.value = false
+}
+const open = (list) => {
+  dialogVisible.value = true
+  tableData.value = list
+}
+const downLoadFile = (row) => {
+  proxy.$download.name(row.url);
+
+}
+const lookFile = (row) => {
+  filePreviewRef.value.open(row.url)
+}
+defineExpose({
+  open
+})
+</script>
+
+<style></style>
\ No newline at end of file
diff --git a/src/views/collaborativeApproval/shipmentReview/index.vue b/src/views/collaborativeApproval/shipmentReview/index.vue
new file mode 100644
index 0000000..ac2b790
--- /dev/null
+++ b/src/views/collaborativeApproval/shipmentReview/index.vue
@@ -0,0 +1,340 @@
+<template>
+  <div class="app-container">
+    <div class="search_form">
+      <div>
+        <span class="search_title">閿�鍞悎鍚屽彿锛�</span>
+        <el-input
+            v-model="searchForm.salesContractNo"
+            style="width: 240px"
+            placeholder="璇疯緭鍏ラ攢鍞悎鍚屽彿鎼滅储"
+            @change="handleQuery"
+            clearable
+            :prefix-icon="Search"
+        />
+        <span class="search_title ml10">瀹℃壒鐘舵�侊細</span>
+        <el-select v-model="searchForm.approveStatus" clearable @change="handleQuery" style="width: 240px">
+          <el-option label="寰呭鏍�" :value="2" />
+          <el-option label="瀹℃牳鎴愬姛" :value="3" />
+          <el-option label="瀹℃牳澶辫触" :value="4" />
+        </el-select>
+        <el-button type="primary" @click="handleQuery" style="margin-left: 10px"
+        >鎼滅储</el-button
+        >
+      </div>
+      <div>
+<!--        <el-button type="primary" @click="openForm('add')">鏂板</el-button>-->
+        <el-button @click="handleOut">瀵煎嚭</el-button>
+<!--        <el-button type="danger" plain @click="handleDelete">鍒犻櫎</el-button>-->
+      </div>
+    </div>
+    <div class="table_list">
+      <PIMTable
+          rowKey="id"
+          :column="tableColumn"
+          :tableData="tableData"
+          :page="page"
+          :isSelection="true"
+          @selection-change="handleSelectionChange"
+          :tableLoading="tableLoading"
+          @pagination="pagination"
+          :total="page.total"
+      ></PIMTable>
+    </div>
+    <info-form-dia ref="infoFormDia" @close="handleQuery" :approveType="approveType"></info-form-dia>
+    <approval-dia ref="approvalDia" @close="handleQuery"></approval-dia>
+    <FileList ref="fileListRef" />
+  </div>
+</template>
+
+<script setup>
+import FileList from "./fileList.vue";
+import { Search } from "@element-plus/icons-vue";
+import {onMounted, ref} from "vue";
+import {ElMessageBox} from "element-plus";
+import InfoFormDia from "@/views/collaborativeApproval/approvalProcess/components/infoFormDia.vue";
+import ApprovalDia from "@/views/collaborativeApproval/approvalProcess/components/approvalDia.vue";
+import {getShipmentApprovalList, approveShipment} from "@/api/collaborativeApproval/shipmentReview.js";
+// import {approveProcessDelete, approveProcessListPage} from "@/api/collaborativeApproval/approvalProcess.js";
+import useUserStore from "@/store/modules/user";
+import { userListNoPage } from "@/api/system/user.js";
+
+// 瀹氫箟缁勪欢鎺ユ敹鐨刾rops
+const props = defineProps({
+  approveType: {
+    type: [Number, String],
+    default: 6
+  }
+});
+
+const userList = ref([]);
+
+const userStore = useUserStore();
+
+
+const data = reactive({
+  searchForm: {
+    approveId: "",
+    approveStatus: "",
+  },
+});
+const { searchForm } = toRefs(data);
+const tableColumn = ref([
+  {
+    label: "瀹℃壒鐘舵��",
+    prop: "approveStatus",
+    dataType: "tag",
+    width: 100,
+    formatData: (params) => {
+      if (params === 2) {
+        return "寰呭鏍�";
+      } else if (params === 3) {
+        return "瀹℃牳瀹屾垚";
+      } else if (params === 4) {
+        return "瀹℃牳椹冲洖";
+      } else {
+        return '鏈煡鐘舵��';
+      }
+    },
+    formatType: (params) => {
+      if (params === 0) {
+        return "warning";
+      } else if (params === 2) {
+        return "info";
+      } else if (params === 3) {
+        return "success";
+      } else if (params === 4) {
+        return "danger";
+      } else {
+        return 'danger';
+      }
+    },
+  },
+  {
+    label: "閿�鍞悎鍚屽彿",
+    prop: "salesContractNo",
+    width: 170
+  },
+  {
+    label: "瀹㈡埛鍚嶇О",
+    prop: "customerName",
+    width: 200
+  },
+  {
+    label: "浜у搧澶х被",
+    prop: "productCategory",
+    width: 200
+  },
+  {
+    label: "瑙勬牸鍨嬪彿",
+    prop: "specificationModel",
+    width: 220
+  },
+  {
+    label: "鐢宠浜�",
+    prop: "approveUserId",
+    width: 120,
+    align: "center",
+    formatData:(params)=>{
+      const user = userList.value.find(item => item.userId === params)
+      return user ? user.nickName : '--'
+    }
+  },
+  {
+    label: "杞︾墝鍙�",
+    prop: "shippingCarNumber",
+    width: 120,
+  },
+  {
+    label: "鐢宠浜�",
+    prop: "approveUserId",
+    width: 120,
+  },
+  {
+    label: "鐢宠鏃ユ湡",
+    prop: "executionDate",
+    width: 200
+  },
+  {
+    label: "褰撳墠瀹℃壒浜�",
+    prop: "salesman",
+    width: 120
+  },
+  {
+    dataType: "action",
+    label: "鎿嶄綔",
+    align: "center",
+    fixed: "right",
+    width: 120,
+    operation: [
+      {
+        name: "閫氳繃",
+        type: "text",
+        clickFun: (row) => {
+          handleApproval("閫氳繃", row);
+        },
+        disabled: (row) => row.approveStatus !== 2
+      },
+      {
+        name: "椹冲洖",
+        type: "text",
+        clickFun: (row) => {
+          handleApproval("椹冲洖", row);
+        },
+        disabled: (row) => row.approveStatus !== 2
+      },
+      // {
+      //   name: "缂栬緫",
+      //   type: "text",
+      //   clickFun: (row) => {
+      //     openForm("edit", row);
+      //   },
+      //   disabled: (row) => row.approveStatus == 2 || row.approveStatus == 1 || row.approveStatus == 4
+      // },
+      // {
+      //   name: "瀹℃牳",
+      //   type: "text",
+      //   clickFun: (row) => {
+      //     openApprovalDia("approval", row);
+      //   },
+      //   disabled: (row) => row.approveUserCurrentId == null || row.approveStatus == 2 || row.approveStatus == 3 || row.approveStatus == 4 || row.approveUserCurrentId !== userStore.id
+      // },
+      // {
+      //   name: "璇︽儏",
+      //   type: "text",
+      //   clickFun: (row) => {
+      //     openApprovalDia('view', row);
+      //   },
+      // },
+      // {
+      //   name: "闄勪欢",
+      //   type: "text",
+      //   clickFun: (row) => {
+      //     downLoadFile(row);
+      //   },
+      // },
+    ],
+  },
+]);
+const tableData = ref([]);
+const selectedRows = ref([]);
+const tableLoading = ref(false);
+const page = reactive({
+  current: 1,
+  size: 100,
+  total: 0
+});
+const infoFormDia = ref()
+const approvalDia = ref()
+const { proxy } = getCurrentInstance()
+
+// 鏌ヨ鍒楄〃
+/** 鎼滅储鎸夐挳鎿嶄綔 */
+const handleQuery = () => {
+  page.current = 1;
+  getList();
+};
+const fileListRef = ref(null)
+const downLoadFile = (row) => {
+  fileListRef.value.open(row.commonFileList)
+
+}
+const pagination = (obj) => {
+  page.current = obj.page;
+  page.size = obj.limit;
+  getList();
+};
+const getList =async () => {
+  let userLists = await userListNoPage();
+  userList.value = userLists.data;
+  tableLoading.value = true;
+  getShipmentApprovalList({...page, ...searchForm.value,approveType:props.approveType}).then(res => {
+    tableLoading.value = false;
+    tableData.value = res.data.records
+    page.total = res.data.total;
+  }).catch(err => {
+    tableLoading.value = false;
+  })
+};
+// 瀵煎嚭
+const handleOut = () => {
+  const type = Number(props.approveType || 6)
+  const urlMap = {
+    0: "/shipmentApproval/export",
+  }
+  const url = urlMap[type] || urlMap[0]
+  const nameMap = {
+    0: "鍙戣揣瀹℃牳琛�",
+  }
+  const fileName = nameMap[type] || nameMap[0]
+  proxy.download(url, {}, `${fileName}.xlsx`)
+}
+// 琛ㄦ牸閫夋嫨鏁版嵁
+const handleSelectionChange = (selection) => {
+  selectedRows.value = selection;
+};
+
+// 鎵撳紑鏂板銆佺紪杈戝脊妗�
+const openForm = (type, row) => {
+  nextTick(() => {
+    infoFormDia.value?.openDialog(type, row)
+  })
+};
+// 鎵撳紑鏂板妫�楠屽脊妗�
+const openApprovalDia = (type, row) => {
+  nextTick(() => {
+    approvalDia.value?.openDialog(type, row)
+  })
+};
+
+// 瀹℃牳閫氳繃/椹冲洖
+const handleApproval = (name = "瀹℃牳",row) => {
+  ElMessageBox.confirm(`閫変腑鐨勫唴瀹瑰皢琚�${name}锛屾槸鍚︾‘璁�${name}锛焋, "鎻愮ず", {
+    confirmButtonText: "纭",
+    cancelButtonText: "鍙栨秷",
+    type: "warning",
+  }).then(async()=>{
+    let res = await approveShipment({
+      id: row.id,
+      approveStatus: name === "閫氳繃" ? 3 : 4
+    });
+    if(res.code === 200){
+      proxy.$modal.msgSuccess(`${name}鎴愬姛`);
+    }else{
+      proxy.$modal.msgError(`${name}澶辫触`);
+    }
+    await getList()
+  }).catch(err=>{
+    proxy.$modal.msgError(`鏈煡閿欒,璇疯仈绯荤鐞嗗憳`);
+  })
+};
+
+// 鍒犻櫎
+const handleDelete = () => {
+  let ids = [];
+  if (selectedRows.value.length > 0) {
+    ids = selectedRows.value.map((item) => item.approveId);
+  } else {
+    proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
+    return;
+  }
+  ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "瀵煎嚭", {
+    confirmButtonText: "纭",
+    cancelButtonText: "鍙栨秷",
+    type: "warning",
+  })
+      .then(() => {
+        approveProcessDelete(ids).then((res) => {
+          proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+          getList();
+        });
+      })
+      .catch(() => {
+        proxy.$modal.msg("宸插彇娑�");
+      });
+};
+onMounted(() => {
+  getList();
+});
+</script>
+
+<style scoped></style>
diff --git a/src/views/salesManagement/salesLedger/index.vue b/src/views/salesManagement/salesLedger/index.vue
index 94af430..5c05457 100644
--- a/src/views/salesManagement/salesLedger/index.vue
+++ b/src/views/salesManagement/salesLedger/index.vue
@@ -50,11 +50,50 @@
               <el-table-column label="浜у搧澶х被" prop="productCategory" />
               <el-table-column label="瑙勬牸鍨嬪彿" prop="specificationModel" />
               <el-table-column label="鍗曚綅" prop="unit" />
+              <el-table-column label="鐢熶骇鐘舵��" width="100px" align="center">
+                <template #default="scope">
+                  <el-tag v-if="scope.row.productionStatus === '宸插畬鎴�'" type="success">宸插畬鎴�</el-tag>
+                  <el-tag v-if="scope.row.productionStatus === '鐢熶骇涓�'" type="warning">鐢熶骇涓�</el-tag>
+                  <el-tag v-if="scope.row.productionStatus === '鏈紑濮�'" type="danger">鏈紑濮�</el-tag>
+                  <el-tag v-if="!scope.row.productionStatus" type="info">鏆傛棤鐘舵��</el-tag>
+                </template>
+              </el-table-column>
+              <el-table-column label="浜у搧鐘舵��" width="100px" align="center">
+                <template #default="scope">
+                  <el-tag v-if="scope.row.approveStatus === 0" type="info">鏈嚭搴�</el-tag>
+                  <el-tag v-if="scope.row.approveStatus === 1" type="success">宸插嚭搴�</el-tag>
+                  <el-tag v-if="scope.row.approveStatus === 2" type="warning">瀹℃牳涓�</el-tag>
+                  <el-tag v-if="scope.row.approveStatus === 3" type="success">瀹℃牳鎴愬姛</el-tag>
+                  <el-tag v-if="scope.row.approveStatus === 4" type="danger">瀹℃牳澶辫触</el-tag>
+                </template>
+              </el-table-column>
+              <el-table-column label="鍙戣揣杞︾墝" minWidth="100px" align="center">
+                <template #default="scope">
+                  <div>
+                    <el-tag type="success" v-if="scope.row.shippingCarNumber">{{ scope.row.shippingCarNumber }}</el-tag>
+                    <el-tag v-else type="info">鏈彂璐�</el-tag>
+                  </div>
+                </template>
+              </el-table-column>
+              <el-table-column label="鍙戣揣鏃ユ湡" minWidth="100px" align="center">
+                <template #default="scope">
+                  <div>
+                    <div v-if="scope.row.shippingDate">{{ scope.row.shippingDate }}</div>
+                    <el-tag v-else type="info">鏈彂璐�</el-tag>
+                  </div>
+                </template>
+              </el-table-column>
               <el-table-column label="鏁伴噺" prop="quantity" />
               <el-table-column label="绋庣巼(%)" prop="taxRate" />
               <el-table-column label="鍚◣鍗曚环(鍏�)" prop="taxInclusiveUnitPrice" :formatter="formattedNumber" />
               <el-table-column label="鍚◣鎬讳环(鍏�)" prop="taxInclusiveTotalPrice" :formatter="formattedNumber" />
               <el-table-column label="涓嶅惈绋庢�讳环(鍏�)" prop="taxExclusiveTotalPrice" :formatter="formattedNumber" />
+            <!--鎿嶄綔-->
+              <el-table-column Width="60px" label="鎿嶄綔" align="center">
+                <template #default="scope">
+                  <el-button :disabled="scope.row.approveStatus===2 || scope.row.approveStatus===5" link type="primary" size="small" @click="openDeliveryForm(scope.row)">鍙戣揣</el-button>
+                </template>
+              </el-table-column>
             </el-table>
           </template>
         </el-table-column>
@@ -70,12 +109,12 @@
         <el-table-column label="褰曞叆浜�" prop="entryPersonName" width="100" show-overflow-tooltip />
         <el-table-column label="褰曞叆鏃ユ湡" prop="entryDate" width="120" show-overflow-tooltip />
         <el-table-column label="绛捐鏃ユ湡" prop="executionDate" width="120" show-overflow-tooltip />
-        <el-table-column fixed="right" label="鎿嶄綔" min-width="200" align="center">
+        <el-table-column fixed="right" label="鎿嶄綔" min-width="100" align="center">
           <template #default="scope">
             <el-button link type="primary" size="small" @click="openForm('edit', scope.row)">缂栬緫</el-button>
 <!--            <el-button link type="primary" size="small" @click="openForm('view', scope.row)">璇︽儏</el-button>-->
             <el-button link type="primary" size="small" @click="downLoadFile(scope.row)">闄勪欢</el-button>
-            <el-button link type="primary" size="small" @click="openDeliveryForm(scope.row)">鍙戣揣</el-button>
+<!--            <el-button link type="primary" size="small" @click="openDeliveryForm(scope.row)">鍙戣揣</el-button>-->
           </template>
         </el-table-column>
       </el-table>
@@ -442,6 +481,15 @@
 						</el-form-item>
 					</el-col>
 				</el-row>
+        <el-row :gutter="30">
+          <el-col :span="24">
+            <el-form-item label="瀹℃壒浜猴細" prop="approverId">
+              <el-select v-model="deliveryForm.approverId" placeholder="璇烽�夋嫨瀹℃壒浜�" clearable :disabled="operationType === 'view'">
+                <el-option v-for="item in userList" :key="item.userId" :label="item.nickName" :value="item.userId" />
+              </el-select>
+            </el-form-item>
+          </el-col>
+        </el-row>
 			</el-form>
 			<template #footer>
 				<div class="dialog-footer">
@@ -601,6 +649,11 @@
     shippingCarNumber: [
       { required: true, message: "璇疯緭鍏ュ彂璐ц溅鐗屽彿", trigger: "blur" }
     ],
+    approverId:[
+      {
+        required: true,message: "",
+      }
+    ]
   },
 });
 const { deliveryForm, deliveryRules } = toRefs(deliveryFormData);
@@ -628,7 +681,9 @@
   page.size = obj.limit;
   getList();
 };
-const getList = () => {
+const getList =async () => {
+  let userLists = await userListNoPage();
+  userList.value = userLists.data;
   tableLoading.value = true;
   const { entryDate, ...rest } = searchForm;
   ledgerListPage({ ...rest, ...page })
@@ -709,23 +764,31 @@
   productSelectedRows.value = selectedRows;
 };
 const expandedRowKeys = ref([]);
-// 灞曞紑琛�
-const expandChange = (row, expandedRows) => {
-  if (expandedRows.length > 0) {
+// 灞曞紑琛岋紙濮嬬粓鍙睍寮�涓�琛岋級
+const expandChange = (row) => {
+  const rowKey = row.id;
+  const isExpanded = expandedRowKeys.value.includes(rowKey);
+
+  if (isExpanded) {
+    // 褰撳墠琛屽凡灞曞紑 -> 鏀惰捣
     expandedRowKeys.value = [];
-    try {
-      productList({ salesLedgerId: row.id, type: 1 }).then((res) => {
-        const index = tableData.value.findIndex((item) => item.id === row.id);
-        if (index > -1) {
-          tableData.value[index].children = res.data;
-        }
-        expandedRowKeys.value.push(row.id);
-      });
-    } catch (error) {
-      console.log(error);
-    }
-  } else {
-    expandedRowKeys.value = [];
+    return;
+  }
+
+  // 灞曞紑褰撳墠琛屽墠锛屽厛鏀惰捣鍏跺畠琛�
+  expandedRowKeys.value = [];
+
+  try {
+    productList({ salesLedgerId: row.id, type: 1 }).then((res) => {
+      const index = tableData.value.findIndex((item) => item.id === row.id);
+      if (index > -1) {
+        tableData.value[index].children = res.data;
+      }
+      // 鍙繚鐣欏綋鍓嶈繖涓�琛屽浜庡睍寮�鐘舵��
+      expandedRowKeys.value = [rowKey];
+    });
+  } catch (error) {
+    console.log(error);
   }
 };
 // 涓昏〃鍚堣鏂规硶
@@ -749,8 +812,6 @@
   operationType.value = type;
   form.value = {};
   productData.value = [];
-  let userLists = await userListNoPage();
-  userList.value = userLists.data;
   customerList().then((res) => {
     customerOption.value = res;
   });
@@ -1524,16 +1585,12 @@
 
 // 鎵撳紑鍙戣揣寮规
 const openDeliveryForm = (row) => {
-  getProductInventory({ salesLedgerId: row.id, type:1 }).then((res) => {
-    currentDeliveryRow.value = row;
-    deliveryForm.value = {
-      shippingDate: getCurrentDate(),
-      shippingCarNumber: "",
-    };
-    deliveryFormVisible.value = true;
-  }).catch(err => {
-    ElMessage.error(err.msg);
-  });
+  currentDeliveryRow.value = row;
+  deliveryForm.value = {
+    shippingDate: "", // 绉婚櫎榛樿鍊艰缃�
+    shippingCarNumber: "",
+  };
+  deliveryFormVisible.value = true;
 };
 
 // 鎻愪氦鍙戣揣琛ㄥ崟
@@ -1541,7 +1598,9 @@
   proxy.$refs["deliveryFormRef"].validate((valid) => {
     if (valid) {
       addShippingInfo({
-        salesLedgerId: currentDeliveryRow.value.id,
+        approverId:deliveryForm.value.approverId,
+        salesLedgerId: currentDeliveryRow.value.salesLedgerId,
+        salesLedgerProductId: currentDeliveryRow.value.id,
         shippingDate: deliveryForm.value.shippingDate,
         shippingCarNumber: deliveryForm.value.shippingCarNumber,
       })
@@ -1549,6 +1608,7 @@
           proxy.$modal.msgSuccess("鍙戣揣鎴愬姛");
           closeDeliveryDia();
           getList();
+          expandedRowKeys.value = [];
         })
         .catch(() => {
           proxy.$modal.msgError("鍙戣揣澶辫触锛岃閲嶈瘯");

--
Gitblit v1.9.3