From 265820c7f0df74a1c69308dcc2b1b61812ccd892 Mon Sep 17 00:00:00 2001
From: spring <2396852758@qq.com>
Date: 星期三, 17 九月 2025 15:35:11 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/dev' into dev

---
 src/views/procurementManagement/procurementReport/index.vue       |  847 +++++++++++
 src/store/modules/user.js                                         |    1 
 src/views/reportAnalysis/dataDashboard/index.vue                  |   19 
 src/views/procurementManagement/arrivalManagement/index.vue       |  149 +
 src/views/inspectionManagement/components/formDia.vue             |  174 ++
 src/views/inspectionManagement/components/viewFiles.vue           |  246 +++
 src/views/salesManagement/paymentShipping/index.vue               |    8 
 src/api/procurementManagement/advancedPriceManagement.js          |  302 ++++
 src/views/inspectionManagement/components/qrCodeDia.vue           |  132 +
 src/api/procurementManagement/returnManagement.js                 |   35 
 src/api/procurementManagement/arrivalManagement.js                |   43 
 src/views/procurementManagement/procurementPlan/index.vue         |  821 ++++++++++
 src/api/procurementManagement/procurementPlan.js                  |  127 +
 src/assets/BI/biaoti.png                                          |    0 
 src/views/inspectionManagement/index.vue                          |  391 +++++
 src/views/procurementManagement/advancedPriceManagement/index.vue |  874 +++++++++++
 src/views/inspectionManagement/components/viewQrCodeFiles.vue     |  169 ++
 src/views/procurementManagement/returnManagement/index.vue        |  144 +
 18 files changed, 4,375 insertions(+), 107 deletions(-)

diff --git a/src/api/procurementManagement/advancedPriceManagement.js b/src/api/procurementManagement/advancedPriceManagement.js
new file mode 100644
index 0000000..c1dd47c
--- /dev/null
+++ b/src/api/procurementManagement/advancedPriceManagement.js
@@ -0,0 +1,302 @@
+// 楂樼骇閲囪喘浠锋牸绠$悊API鎺ュ彛
+import request from "@/utils/request";
+
+// 鍒嗛〉鏌ヨ浠锋牸鍒楄〃
+export function getPriceList(query) {
+  return request({
+    url: "/procurement/price/list",
+    method: "get",
+    params: query,
+  });
+}
+
+// 鑾峰彇浠锋牸璇︽儏
+export function getPriceDetail(id) {
+  return request({
+    url: `/procurement/price/detail/${id}`,
+    method: "get",
+  });
+}
+
+// 鏂板浠锋牸
+export function addPrice(data) {
+  return request({
+    url: "/procurement/price/add",
+    method: "post",
+    data: data,
+  });
+}
+
+// 鏇存柊浠锋牸
+export function updatePrice(data) {
+  return request({
+    url: "/procurement/price/update",
+    method: "put",
+    data: data,
+  });
+}
+
+// 鍒犻櫎浠锋牸
+export function deletePrice(id) {
+  return request({
+    url: `/procurement/price/delete/${id}`,
+    method: "delete",
+  });
+}
+
+// 鎵归噺鍒犻櫎浠锋牸
+export function batchDeletePrice(ids) {
+  return request({
+    url: "/procurement/price/batchDelete",
+    method: "delete",
+    data: { ids },
+  });
+}
+
+// 澶嶅埗浠锋牸
+export function copyPrice(id) {
+  return request({
+    url: `/procurement/price/copy/${id}`,
+    method: "post",
+  });
+}
+
+// 搴旂敤浠锋牸锛堝皢寰呯敓鏁堢姸鎬佹敼涓烘湁鏁堬級
+export function applyPrice(id) {
+  return request({
+    url: `/procurement/price/apply/${id}`,
+    method: "put",
+  });
+}
+
+// 鏆傚仠浠锋牸
+export function suspendPrice(id) {
+  return request({
+    url: `/procurement/price/suspend/${id}`,
+    method: "put",
+  });
+}
+
+// 鎵归噺璁剧疆鎶樻墸
+export function batchSetDiscount(data) {
+  return request({
+    url: "/procurement/price/batchDiscount",
+    method: "post",
+    data: data,
+  });
+}
+
+// 鑾峰彇鎶樻墸閰嶇疆
+export function getDiscountConfig(id) {
+  return request({
+    url: `/procurement/price/discount/${id}`,
+    method: "get",
+  });
+}
+
+// 璁剧疆鍗曚釜鍟嗗搧鎶樻墸
+export function setDiscount(data) {
+  return request({
+    url: "/procurement/price/setDiscount",
+    method: "post",
+    data: data,
+  });
+}
+
+// 鑾峰彇闃舵鎶樻墸閰嶇疆
+export function getTieredDiscount(id) {
+  return request({
+    url: `/procurement/price/tieredDiscount/${id}`,
+    method: "get",
+  });
+}
+
+// 璁剧疆闃舵鎶樻墸
+export function setTieredDiscount(data) {
+  return request({
+    url: "/procurement/price/setTieredDiscount",
+    method: "post",
+    data: data,
+  });
+}
+
+// 鑾峰彇浠锋牸鎺у埗璁剧疆
+export function getPriceControlConfig() {
+  return request({
+    url: "/procurement/price/controlConfig",
+    method: "get",
+  });
+}
+
+// 鏇存柊浠锋牸鎺у埗璁剧疆
+export function updatePriceControlConfig(data) {
+  return request({
+    url: "/procurement/price/controlConfig",
+    method: "put",
+    data: data,
+  });
+}
+
+// 鑾峰彇浠锋牸棰勮鍒楄〃
+export function getPriceWarnings(query) {
+  return request({
+    url: "/procurement/price/warnings",
+    method: "get",
+    params: query,
+  });
+}
+
+// 澶勭悊浠锋牸棰勮
+export function handlePriceWarning(id, action) {
+  return request({
+    url: `/procurement/price/warning/${id}`,
+    method: "put",
+    data: { action },
+  });
+}
+
+// 鑾峰彇浠锋牸鍘嗗彶璁板綍
+export function getPriceHistory(id, query) {
+  return request({
+    url: `/procurement/price/history/${id}`,
+    method: "get",
+    params: query,
+  });
+}
+
+// 鑾峰彇浠锋牸缁熻鏁版嵁
+export function getPriceStatistics(query) {
+  return request({
+    url: "/procurement/price/statistics",
+    method: "get",
+    params: query,
+  });
+}
+
+// 瀵煎嚭浠锋牸鏁版嵁
+export function exportPriceData(query) {
+  return request({
+    url: "/procurement/price/export",
+    method: "get",
+    params: query,
+    responseType: 'blob',
+  });
+}
+
+// 瀵煎叆浠锋牸鏁版嵁
+export function importPriceData(file) {
+  const formData = new FormData();
+  formData.append('file', file);
+  return request({
+    url: "/procurement/price/import",
+    method: "post",
+    data: formData,
+    headers: {
+      'Content-Type': 'multipart/form-data',
+    },
+  });
+}
+
+// 鑾峰彇浠锋牸妯℃澘
+export function downloadPriceTemplate() {
+  return request({
+    url: "/procurement/price/template",
+    method: "get",
+    responseType: 'blob',
+  });
+}
+
+// 浠锋牸瀹℃壒
+export function approvePrice(id, data) {
+  return request({
+    url: `/procurement/price/approve/${id}`,
+    method: "put",
+    data: data,
+  });
+}
+
+// 浠锋牸椹冲洖
+export function rejectPrice(id, data) {
+  return request({
+    url: `/procurement/price/reject/${id}`,
+    method: "put",
+    data: data,
+  });
+}
+
+// 鑾峰彇渚涘簲鍟嗗垪琛紙鐢ㄤ簬涓嬫媺閫夋嫨锛�
+export function getSupplierOptions() {
+  return request({
+    url: "/procurement/price/suppliers",
+    method: "get",
+  });
+}
+
+// 鑾峰彇鍟嗗搧鍒楄〃锛堢敤浜庝笅鎷夐�夋嫨锛�
+export function getProductOptions(query) {
+  return request({
+    url: "/procurement/price/products",
+    method: "get",
+    params: query,
+  });
+}
+
+// 鑾峰彇鍟嗗搧璇︾粏淇℃伅
+export function getProductInfo(productId) {
+  return request({
+    url: `/procurement/price/productInfo/${productId}`,
+    method: "get",
+  });
+}
+
+// 浠锋牸姣旇緝鍒嗘瀽
+export function comparePrices(data) {
+  return request({
+    url: "/procurement/price/compare",
+    method: "post",
+    data: data,
+  });
+}
+
+// 鑾峰彇浠锋牸瓒嬪娍鏁版嵁
+export function getPriceTrend(id, period) {
+  return request({
+    url: `/procurement/price/trend/${id}`,
+    method: "get",
+    params: { period },
+  });
+}
+
+// 浠锋牸棰勬祴
+export function predictPrice(id, data) {
+  return request({
+    url: `/procurement/price/predict/${id}`,
+    method: "post",
+    data: data,
+  });
+}
+
+// 鑾峰彇甯傚満浠锋牸鍙傝��
+export function getMarketPriceReference(productCode) {
+  return request({
+    url: `/procurement/price/marketRef/${productCode}`,
+    method: "get",
+  });
+}
+
+// 浠锋牸鍙樺姩閫氱煡璁剧疆
+export function updateNotificationSettings(data) {
+  return request({
+    url: "/procurement/price/notifications",
+    method: "put",
+    data: data,
+  });
+}
+
+// 鑾峰彇浠锋牸鍙樺姩閫氱煡璁剧疆
+export function getNotificationSettings() {
+  return request({
+    url: "/procurement/price/notifications",
+    method: "get",
+  });
+}
diff --git a/src/api/procurementManagement/arrivalManagement.js b/src/api/procurementManagement/arrivalManagement.js
new file mode 100644
index 0000000..107fc3c
--- /dev/null
+++ b/src/api/procurementManagement/arrivalManagement.js
@@ -0,0 +1,43 @@
+// 閿�鍞彴璐﹂〉闈㈡帴鍙�
+import request from "@/utils/request";
+
+// 鍒嗛〉鏌ヨ
+export function listPage(query) {
+    return request({
+        url: "/inboundManagement/listPage",
+        method: "get",
+        params: query,
+    });
+}
+
+export function listPageCopy(query) {
+    return request({
+        url: "/inboundManagement/listPage",
+        method: "get",
+        params: query,
+    });
+}
+// 鏂板
+export function add(data) {
+    return request({
+        url: "/inboundManagement/add",
+        method: "post",
+        data
+    });
+}
+// 淇敼
+export function update(data) {
+    return request({
+        url: "/inboundManagement/update",
+        method: "post",
+        data
+    });
+}
+// 鍒犻櫎閿�鍞彴璐�
+export function del(data) {
+    return request({
+        url: "/inboundManagement/del",
+        method: "delete",
+        data
+    });
+}
\ No newline at end of file
diff --git a/src/api/procurementManagement/procurementPlan.js b/src/api/procurementManagement/procurementPlan.js
new file mode 100644
index 0000000..04c58b3
--- /dev/null
+++ b/src/api/procurementManagement/procurementPlan.js
@@ -0,0 +1,127 @@
+import request from "@/utils/request";
+
+// 鍒嗛〉鏌ヨ閲囪喘璁″垝鍒楄〃
+export function getProcurementPlanList(query) {
+  return request({
+    url: "/procurement/plan/list",
+    method: "get",
+    params: query,
+  });
+}
+
+// 鏂板閲囪喘璁″垝
+export function addProcurementPlan(data) {
+  return request({
+    url: "/procurement/plan/add",
+    method: "post",
+    data: data,
+  });
+}
+
+// 淇敼閲囪喘璁″垝
+export function updateProcurementPlan(data) {
+  return request({
+    url: "/procurement/plan/update",
+    method: "put",
+    data: data,
+  });
+}
+
+// 鍒犻櫎閲囪喘璁″垝
+export function deleteProcurementPlan(ids) {
+  return request({
+    url: "/procurement/plan/delete",
+    method: "delete",
+    data: ids,
+  });
+}
+
+// 鏍规嵁ID鑾峰彇閲囪喘璁″垝璇︽儏
+export function getProcurementPlanById(id) {
+  return request({
+    url: `/procurement/plan/${id}`,
+    method: "get",
+  });
+}
+
+// 鎵ц閲囪喘璁″垝璁$畻
+export function calculateProcurementPlan(data) {
+  return request({
+    url: "/procurement/plan/calculate",
+    method: "post",
+    data: data,
+  });
+}
+
+
+// 鑾峰彇浜у搧鐜版湁搴撳瓨淇℃伅
+export function getProductExistingStock(productIds) {
+  return request({
+    url: "/inventory/existingStock/productInfo",
+    method: "post",
+    data: productIds,
+  });
+}
+
+// 鑾峰彇浜у搧瀹夊叏搴撳瓨淇℃伅
+export function getProductSafetyStock(productIds) {
+  return request({
+    url: "/inventory/safetyStock/productInfo",
+    method: "post",
+    data: productIds,
+  });
+}
+
+// 鑾峰彇浜у搧棰勮鍑哄簱淇℃伅
+export function getProductExpectedOutbound(productIds) {
+  return request({
+    url: "/inventory/expectedOutbound/productInfo",
+    method: "post",
+    data: productIds,
+  });
+}
+
+// 鑾峰彇浜у搧棰勮鍏ュ簱淇℃伅
+export function getProductExpectedInbound(productIds) {
+  return request({
+    url: "/inventory/expectedInbound/productInfo",
+    method: "post",
+    data: productIds,
+  });
+}
+
+// 瀵煎嚭閲囪喘璁″垝
+export function exportProcurementPlan(query) {
+  return request({
+    url: "/procurement/plan/export",
+    method: "get",
+    params: query,
+    responseType: "blob",
+  });
+}
+
+// 鐢熸垚閲囪喘璁㈠崟
+export function generatePurchaseOrder(data) {
+  return request({
+    url: "/procurement/plan/generateOrder",
+    method: "post",
+    data: data,
+  });
+}
+
+// 楠岃瘉璁$畻鍏紡
+export function validateFormula(formula) {
+  return request({
+    url: "/procurement/plan/validateFormula",
+    method: "post",
+    data: { formula },
+  });
+}
+
+// 鑾峰彇璁$畻鍏紡妯℃澘
+export function getFormulaTemplates() {
+  return request({
+    url: "/procurement/plan/formulaTemplates",
+    method: "get",
+  });
+}
diff --git a/src/api/procurementManagement/returnManagement.js b/src/api/procurementManagement/returnManagement.js
new file mode 100644
index 0000000..e765701
--- /dev/null
+++ b/src/api/procurementManagement/returnManagement.js
@@ -0,0 +1,35 @@
+// 閿�鍞彴璐﹂〉闈㈡帴鍙�
+import request from "@/utils/request";
+
+// 鍒嗛〉鏌ヨ
+export function listPage(query) {
+    return request({
+        url: "/returnManagement/listPage",
+        method: "get",
+        params: query,
+    });
+}
+// 鏂板
+export function add(data) {
+    return request({
+        url: "/returnManagement/add",
+        method: "post",
+        data
+    });
+}
+// 淇敼
+export function update(data) {
+    return request({
+        url: "/returnManagement/update",
+        method: "post",
+        data
+    });
+}
+// 鍒犻櫎閿�鍞彴璐�
+export function del(data) {
+    return request({
+        url: "/returnManagement/del",
+        method: "delete",
+        data
+    });
+}
\ No newline at end of file
diff --git a/src/assets/BI/biaoti.png b/src/assets/BI/biaoti.png
index f905f1c..3c5ccb9 100644
--- a/src/assets/BI/biaoti.png
+++ b/src/assets/BI/biaoti.png
Binary files differ
diff --git a/src/store/modules/user.js b/src/store/modules/user.js
index d52efa6..057af50 100644
--- a/src/store/modules/user.js
+++ b/src/store/modules/user.js
@@ -2,6 +2,7 @@
 import { getToken, setToken, removeToken } from '@/utils/auth'
 import { isHttp, isEmpty } from "@/utils/validate"
 import defAva from '@/assets/images/profile.jpg'
+import { defineStore } from 'pinia'
 
 const useUserStore = defineStore(
   'user',
diff --git a/src/views/inspectionManagement/components/formDia.vue b/src/views/inspectionManagement/components/formDia.vue
new file mode 100644
index 0000000..9d9a9fd
--- /dev/null
+++ b/src/views/inspectionManagement/components/formDia.vue
@@ -0,0 +1,174 @@
+<template>
+  <div>
+    <el-dialog :title="operationType === 'add' ? '鏂板宸℃浠诲姟' : '缂栬緫宸℃浠诲姟'"
+               v-model="dialogVisitable" width="800px" @close="cancel">
+      <el-form :model="form" :rules="rules" ref="formRef" label-width="120px">
+        <el-row>
+          <el-col :span="12">
+            <el-form-item label="浠诲姟鍚嶇О" prop="taskName">
+              <el-input v-model="form.taskName" placeholder="璇疯緭鍏ヤ换鍔″悕绉�" maxlength="30" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="鍦扮偣" prop="inspectionLocation">
+              <el-input v-model="form.inspectionLocation" placeholder="璇疯緭鍏ュ湴鐐�" maxlength="30" />
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row>
+          <el-col :span="12">
+            <el-form-item label="宸℃浜�" prop="inspector">
+              <el-select v-model="form.inspector" placeholder="璇烽�夋嫨" multiple clearable>
+                <el-option v-for="item in userList" :label="item.nickName" :value="item.userId" :key="item.userId"/>
+              </el-select>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="澶囨敞" prop="remarks">
+              <el-input v-model="form.remarks" placeholder="璇疯緭鍏ュ娉�" type="textarea" />
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row>
+          <el-col :span="12">
+            <el-form-item label="浠诲姟棰戠巼" prop="frequencyType">
+              <el-select v-model="form.frequencyType" placeholder="璇烽�夋嫨" clearable>
+                <el-option label="姣忔棩" value="DAILY"/>
+                <el-option label="姣忓懆" value="WEEKLY"/>
+                <el-option label="姣忔湀" value="MONTHLY"/>
+                <el-option label="瀛e害" value="QUARTERLY"/>
+              </el-select>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12" v-if="form.frequencyType === 'DAILY' && form.frequencyType">
+            <el-form-item label="鏃ユ湡" prop="frequencyDetail">
+              <el-time-picker v-model="form.frequencyDetail" placeholder="閫夋嫨鏃堕棿" format="HH:mm"
+                              value-format="HH:mm" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12" v-if="form.frequencyType === 'WEEKLY' && form.frequencyType">
+            <el-form-item label="鏃ユ湡" prop="frequencyDetail">
+              <el-select v-model="form.week" placeholder="璇烽�夋嫨" clearable style="width: 50%">
+                <el-option label="鍛ㄤ竴" value="MON"/>
+                <el-option label="鍛ㄤ簩" value="TUE"/>
+                <el-option label="鍛ㄤ笁" value="WED"/>
+                <el-option label="鍛ㄥ洓" value="THU"/>
+                <el-option label="鍛ㄤ簲" value="FRI"/>
+                <el-option label="鍛ㄥ叚" value="SAT"/>
+                <el-option label="鍛ㄦ棩" value="SUN"/>
+              </el-select>
+              <el-time-picker v-model="form.time" placeholder="閫夋嫨鏃堕棿" format="HH:mm"
+                              value-format="HH:mm"  style="width: 50%"/>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12" v-if="form.frequencyType === 'MONTHLY' && form.frequencyType">
+            <el-form-item label="鏃ユ湡" prop="frequencyDetail">
+              <el-date-picker
+                  v-model="form.frequencyDetail"
+                  type="datetime"
+                  clearable
+                  placeholder="閫夋嫨寮�濮嬫棩鏈�"
+                  format="DD,HH:mm"
+                  value-format="DD,HH:mm"
+              />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12" v-if="form.frequencyType === 'QUARTERLY' && form.frequencyType">
+            <el-form-item label="鏃ユ湡" prop="frequencyDetail">
+              <el-date-picker
+                  v-model="form.frequencyDetail"
+                  type="datetime"
+                  clearable
+                  placeholder="閫夋嫨寮�濮嬫棩鏈�"
+                  format="MM,DD,HH:mm"
+                  value-format="MM,DD,HH:mm"
+              />
+            </el-form-item>
+          </el-col>
+        </el-row>
+      </el-form>
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button @click="cancel">鍙栨秷</el-button>
+          <el-button type="primary" @click="submitForm">淇濆瓨</el-button>
+        </div>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+
+<script setup>
+import {reactive, ref} from "vue";
+import useUserStore from '@/store/modules/user'
+import {addOrEditTimingTask} from "@/api/inspectionManagement/index.js";
+import {userListAll} from "@/api/publicApi/index.js";
+
+const { proxy } = getCurrentInstance()
+const emit = defineEmits()
+const userStore = useUserStore()
+const dialogVisitable = ref(false);
+const operationType = ref('add');
+const data = reactive({
+  form: {
+    taskName: '',
+    inspectionLocation: '',
+    inspector: '',
+    inspectorIds: '',
+    remarks: '',
+    frequencyType: '',
+    frequencyDetail: '',
+  },
+  rules: {
+    taskName: [{ required: true, message: "璇疯緭鍏ヤ换鍔″悕绉�", trigger: "blur" },],
+    inspectionLocation: [{ required: true, message: "璇疯緭鍏ュ湴鐐�", trigger: "blur" },],
+    inspector: [{ required: true, message: "璇疯緭鍏ュ贰妫�浜�", trigger: "blur" },],
+  }
+})
+const { form, rules } = toRefs(data)
+const userList = ref([])
+
+// 鎵撳紑寮规
+const openDialog = async (type, row) => {
+  dialogVisitable.value = true
+  userListAll().then(res => {
+    userList.value = res.data
+  })
+  if (type === 'edit') {
+    form.value = {...row}
+    form.value.inspector = form.value.inspectorIds.split(',').map(Number)
+  }
+}
+
+// 鍏抽棴鍚堝苟琛ㄥ崟
+const cancel = () => {
+  proxy.resetForm("formRef")
+  dialogVisitable.value = false
+  emit('closeDia')
+}
+
+// 鎻愪氦鍚堝苟琛ㄥ崟
+const submitForm = () => {
+  proxy.$refs["formRef"].validate(async valid => {
+    if (valid) {
+      form.value.inspectorIds = form.value.inspector.join(',')
+			delete form.value.inspector
+      if (form.value.frequencyType === 'WEEKLY') {
+        let frequencyDetail = ''
+        frequencyDetail = form.value.week + ',' + form.value.time
+        form.value.frequencyDetail = frequencyDetail
+      }
+      let res = await userStore.getInfo()
+      form.value.registrantId = res.user.userId
+      addOrEditTimingTask(form.value).then(() => {
+        cancel()
+        proxy.$modal.msgSuccess('鎻愪氦鎴愬姛')
+      })
+    }
+  })
+}
+defineExpose({ openDialog })
+</script>
+
+<style scoped>
+
+</style>
\ No newline at end of file
diff --git a/src/views/inspectionManagement/components/qrCodeDia.vue b/src/views/inspectionManagement/components/qrCodeDia.vue
new file mode 100644
index 0000000..136c18c
--- /dev/null
+++ b/src/views/inspectionManagement/components/qrCodeDia.vue
@@ -0,0 +1,132 @@
+<template>
+  <div>
+    <el-dialog :title="operationType === 'add' ? '鏂板浜岀淮鐮�' : '缂栬緫浜岀淮鐮�'"
+               v-model="dialogVisitable" width="500px" @close="cancel">
+      <el-form :model="form" :rules="rules" ref="formRef" label-width="120px">
+        <el-row>
+          <el-col :span="24">
+            <el-form-item label="璁惧鍚嶇О" prop="deviceName">
+              <el-input v-model="form.deviceName" placeholder="璇疯緭鍏ヨ澶囧悕绉�" maxlength="30" />
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row>
+          <el-col :span="24">
+            <el-form-item label="鎵�鍦ㄤ綅缃弿杩�" prop="location">
+              <el-input v-model="form.location" placeholder="璇疯緭鍏ユ墍鍦ㄤ綅缃弿杩�" maxlength="30"/>
+            </el-form-item>
+          </el-col>
+        </el-row>
+      </el-form>
+      <div>
+        <el-button type="primary" @click="submitForm">鐢熸垚骞舵墦鍗颁簩缁寸爜</el-button>
+      </div>
+      <div v-if="isShowQrCode" class="print-section" ref="qrCodeContainer" id="qrCodeContainer">
+        <vue-qrcode :value="qrCodeValue" :width="qrCodeSize"></vue-qrcode>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script setup>
+import useUserStore from "@/store/modules/user.js";
+import {reactive, ref} from "vue";
+import printJS from 'print-js';
+import {addOrEditQrCode} from "@/api/inspectionUpload/index.js";
+
+const { proxy } = getCurrentInstance()
+const emit = defineEmits()
+const userStore = useUserStore()
+const dialogVisitable = ref(false);
+const isShowQrCode = ref(false);
+const operationType = ref('add');
+
+const qrCodeValue = ref('');
+const qrCodeSize = ref(100);
+const data = reactive({
+  form: {
+    deviceName: '',
+    location: '',
+    qrCodeId: '',
+    id: ''
+  },
+  rules: {
+    deviceName: [{ required: true, message: '璇疯緭鍏ヨ澶囧悕绉�', trigger: 'blur' }],
+    location: [{ required: true, message: '璇疯緭鍏ュ湴鐐�', trigger: 'blur' }]
+  }
+})
+const { form, rules } = toRefs(data)
+
+
+// 鎵撳紑寮规
+const openDialog = async (type, row) => {
+  dialogVisitable.value = true
+  qrCodeValue.value = ''
+  isShowQrCode.value = false;
+  if (type === 'edit') {
+    form.value.id = row.id
+    form.value.qrCodeId = row.id
+    form.value.deviceName = row.deviceName
+    form.value.location = row.location
+    // 灏嗚〃鍗曟暟鎹浆涓� JSON 瀛楃涓蹭綔涓轰簩缁寸爜鍐呭
+    qrCodeValue.value = JSON.stringify(form.value);
+    isShowQrCode.value = true;
+  }
+}
+// 鎻愪氦鍚堝苟琛ㄥ崟
+const submitForm = () => {
+  proxy.$refs["formRef"].validate(valid => {
+    if (valid) {
+      addOrEditQrCode(form.value).then((res) => {
+        form.value.qrCodeId = res.data
+      })
+      // 灏嗚〃鍗曟暟鎹浆涓� JSON 瀛楃涓蹭綔涓轰簩缁寸爜鍐呭
+      qrCodeValue.value = JSON.stringify(form.value);
+      isShowQrCode.value = true;
+      showQrCode()
+    }
+  })
+}
+const showQrCode = () => {
+  // 寤惰繜鎵ц鎵撳嵃锛岄伩鍏� DOM 鏇存柊鍓嶅氨璋冪敤鎵撳嵃
+  setTimeout(() => {
+    printJS({
+      printable: 'qrCodeContainer',//椤甸潰
+      type: "html",//鏂囨。绫诲瀷
+      maxWidth: 360,
+      style: `@page {
+                margin:0;
+                size: 400px 75px collapse;
+                margin-top:3px;
+                &:first-of-type{
+                  margin-top:0 !important;
+                }
+              }
+              html{
+                zoom:100%;
+              }
+              @media print{
+                width: 400px;
+                height: 75px;
+                margin:0;
+              }`,
+      targetStyles: ["*"], // 浣跨敤dom鐨勬墍鏈夋牱寮忥紝寰堥噸瑕�
+      font_size: '0.20cm',
+    });
+  }, 300);
+}
+// 鍏抽棴鍚堝苟琛ㄥ崟
+const cancel = () => {
+  proxy.resetForm("formRef")
+  dialogVisitable.value = false
+  emit('closeDia')
+}
+defineExpose({ openDialog })
+</script>
+
+<style scoped>
+.print-section {
+  text-align: center;
+  margin-top: 30px;
+}
+</style>
\ No newline at end of file
diff --git a/src/views/inspectionManagement/components/viewFiles.vue b/src/views/inspectionManagement/components/viewFiles.vue
new file mode 100644
index 0000000..d1c9d8d
--- /dev/null
+++ b/src/views/inspectionManagement/components/viewFiles.vue
@@ -0,0 +1,246 @@
+<template>
+  <div>
+    <el-dialog title="鏌ョ湅闄勪欢"
+               v-model="dialogVisitable" width="800px" @close="cancel">
+      <div class="upload-container">
+        <!-- 鐢熶骇鍓� -->
+        <div class="form-container">
+          <div class="title">鐢熶骇鍓�</div>
+          
+          <!-- 鍥剧墖鍒楄〃 -->
+          <div style="display: flex; flex-wrap: wrap;">
+            <img v-for="(item, index) in beforeProductionImgs" :key="index"
+                 @click="showMedia(beforeProductionImgs, index, 'image')"
+                 :src="item" style="max-width: 100px; height: 100px; margin: 5px;" alt="">
+          </div>
+          
+          <!-- 瑙嗛鍒楄〃 -->
+          <div style="display: flex; flex-wrap: wrap;">
+            <div
+                v-for="(videoUrl, index) in beforeProductionVideos"
+                :key="index"
+                @click="showMedia(beforeProductionVideos, index, 'video')"
+                style="position: relative; margin: 10px; cursor: pointer;"
+            >
+              <div style="width: 160px; height: 90px; background-color: #333; display: flex; align-items: center; justify-content: center;">
+                <img src="@/assets/images/video.png" alt="鎾斁" style="width: 30px; height: 30px; opacity: 0.8;" />
+              </div>
+              <div style="text-align: center; font-size: 12px; color: #666;">鐐瑰嚮鎾斁</div>
+            </div>
+          </div>
+        </div>
+        
+        <!-- 鐢熶骇鍚� -->
+        <div class="form-container">
+          <div class="title">鐢熶骇鍚�</div>
+          
+          <!-- 鍥剧墖鍒楄〃 -->
+          <div style="display: flex; flex-wrap: wrap;">
+            <img v-for="(item, index) in afterProductionImgs" :key="index"
+                 @click="showMedia(afterProductionImgs, index, 'image')"
+                 :src="item" style="max-width: 100px; height: 100px; margin: 5px;" alt="">
+          </div>
+          
+          <!-- 瑙嗛鍒楄〃 -->
+          <div style="display: flex; flex-wrap: wrap;">
+            <div
+                v-for="(videoUrl, index) in afterProductionVideos"
+                :key="index"
+                @click="showMedia(afterProductionVideos, index, 'video')"
+                style="position: relative; margin: 10px; cursor: pointer;"
+            >
+              <div style="width: 160px; height: 90px; background-color: #333; display: flex; align-items: center; justify-content: center;">
+                <img src="@/assets/images/video.png" alt="鎾斁" style="width: 30px; height: 30px; opacity: 0.8;" />
+              </div>
+              <div style="text-align: center; font-size: 12px; color: #666;">鐐瑰嚮鎾斁</div>
+            </div>
+          </div>
+        </div>
+        
+        <!-- 鐢熶骇闂 -->
+        <div class="form-container">
+          <div class="title">鐢熶骇闂</div>
+          
+          <!-- 鍥剧墖鍒楄〃 -->
+          <div style="display: flex; flex-wrap: wrap;">
+            <img v-for="(item, index) in productionIssuesImgs" :key="index"
+                 @click="showMedia(productionIssuesImgs, index, 'image')"
+                 :src="item" style="max-width: 100px; height: 100px; margin: 5px;" alt="">
+          </div>
+          
+          <!-- 瑙嗛鍒楄〃 -->
+          <div style="display: flex; flex-wrap: wrap;">
+            <div
+                v-for="(videoUrl, index) in productionIssuesVideos"
+                :key="index"
+                @click="showMedia(productionIssuesVideos, index, 'video')"
+                style="position: relative; margin: 10px; cursor: pointer;"
+            >
+              <div style="width: 160px; height: 90px; background-color: #333; display: flex; align-items: center; justify-content: center;">
+                <img src="@/assets/images/video.png" alt="鎾斁" style="width: 30px; height: 30px; opacity: 0.8;" />
+              </div>
+              <div style="text-align: center; font-size: 12px; color: #666;">鐐瑰嚮鎾斁</div>
+            </div>
+          </div>
+        </div>
+      </div>
+    </el-dialog>
+    
+    <!-- 缁熶竴濯掍綋鏌ョ湅鍣� -->
+    <div v-if="isMediaViewerVisible" class="media-viewer-overlay" @click.self="closeMediaViewer">
+      <div class="media-viewer-content" @click.stop>
+        <!-- 鍥剧墖 -->
+        <vue-easy-lightbox
+            v-if="mediaType === 'image'"
+            :visible="isMediaViewerVisible"
+            :imgs="mediaList"
+            :index="currentMediaIndex"
+            @hide="closeMediaViewer"
+        ></vue-easy-lightbox>
+        
+        <!-- 瑙嗛 -->
+        <div v-else-if="mediaType === 'video'" style="position: relative;">
+          <Video
+              :src="mediaList[currentMediaIndex]"
+              autoplay
+              controls
+              style="max-width: 90vw; max-height: 80vh;"
+          />
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+<script setup>
+import { ref } from 'vue';
+import VueEasyLightbox from 'vue-easy-lightbox';
+
+// 鎺у埗寮圭獥鏄剧ず
+const dialogVisitable = ref(false);
+
+// 鍥剧墖鏁扮粍
+const beforeProductionImgs = ref([]);
+const afterProductionImgs = ref([]);
+const productionIssuesImgs = ref([]);
+
+// 瑙嗛鏁扮粍
+const beforeProductionVideos = ref([]);
+const afterProductionVideos = ref([]);
+const productionIssuesVideos = ref([]);
+
+// 濯掍綋鏌ョ湅鍣ㄧ姸鎬�
+const isMediaViewerVisible = ref(false);
+const currentMediaIndex = ref(0);
+const mediaList = ref([]); // 瀛樺偍褰撳墠瑕佹煡鐪嬬殑濯掍綋鍒楄〃锛堝惈鍥剧墖鍜岃棰戝璞★級
+const mediaType = ref('image'); // image | video
+
+// 澶勭悊姣忎竴绫绘暟鎹細鍒嗙鍥剧墖鍜岃棰�
+function processItems(items) {
+  const images = [];
+  const videos = [];
+  items.forEach(item => {
+    if (item.contentType?.startsWith('image/')) {
+      images.push(item.url);
+    } else if (item.contentType?.startsWith('video/')) {
+      videos.push(item.url);
+    }
+  });
+  return { images, videos };
+}
+
+// 鎵撳紑寮圭獥骞跺姞杞芥暟鎹�
+const openDialog = async (row) => {
+  const { images: beforeImgs, videos: beforeVids } = processItems(row.beforeProduction);
+  const { images: afterImgs, videos: afterVids } = processItems(row.afterProduction);
+  const { images: issueImgs, videos: issueVids } = processItems(row.productionIssues);
+  
+  beforeProductionImgs.value = beforeImgs;
+  beforeProductionVideos.value = beforeVids;
+  
+  afterProductionImgs.value = afterImgs;
+  afterProductionVideos.value = afterVids;
+  
+  productionIssuesImgs.value = issueImgs;
+  productionIssuesVideos.value = issueVids;
+  
+  dialogVisitable.value = true;
+};
+
+// 鏄剧ず濯掍綋锛堝浘鐗� or 瑙嗛锛�
+function showMedia(mediaArray, index, type) {
+  mediaList.value = mediaArray;
+  currentMediaIndex.value = index;
+  mediaType.value = type;
+  isMediaViewerVisible.value = true;
+}
+
+// 鍏抽棴濯掍綋鏌ョ湅鍣�
+function closeMediaViewer() {
+  isMediaViewerVisible.value = false;
+  mediaList.value = [];
+  mediaType.value = 'image';
+}
+
+// 琛ㄥ崟鍏抽棴鏂规硶
+const cancel = () => {
+  dialogVisitable.value = false;
+};
+
+defineExpose({ openDialog });
+</script>
+<style scoped lang="scss">
+.upload-container {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  padding: 20px;
+  border: 1px solid #dcdfe6;
+  box-sizing: border-box;
+  
+  .form-container {
+    flex: 1;
+    width: 100%;
+    margin-bottom: 20px;
+  }
+}
+
+.title {
+  font-size: 14px;
+  color: #165dff;
+  line-height: 20px;
+  font-weight: 600;
+  padding-left: 10px;
+  position: relative;
+  margin: 6px 0;
+  
+  &::before {
+    content: "";
+    position: absolute;
+    left: 0;
+    top: 3px;
+    width: 4px;
+    height: 14px;
+    background-color: #165dff;
+  }
+}
+
+.media-viewer-overlay {
+  position: fixed;
+  top: 0;
+  left: 0;
+  right: 0;
+  bottom: 0;
+  background-color: rgba(0, 0, 0, 0.8);
+  z-index: 9999;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+}
+
+.media-viewer-content {
+  position: relative;
+  max-width: 90vw;
+  max-height: 90vh;
+  overflow: hidden;
+}
+</style>
\ No newline at end of file
diff --git a/src/views/inspectionManagement/components/viewQrCodeFiles.vue b/src/views/inspectionManagement/components/viewQrCodeFiles.vue
new file mode 100644
index 0000000..f8e923a
--- /dev/null
+++ b/src/views/inspectionManagement/components/viewQrCodeFiles.vue
@@ -0,0 +1,169 @@
+<template>
+  <div>
+    <el-dialog title="鏌ョ湅闄勪欢"
+               v-model="dialogVisitable" width="800px" @close="cancel">
+      <div class="upload-container">
+        <div class="form-container">
+          <div class="title">宸℃闄勪欢</div>
+          <!-- 鍥剧墖鍒楄〃 -->
+          <div style="display: flex; flex-wrap: wrap;">
+            <img v-for="(item, index) in beforeProductionImgs" :key="index"
+                 @click="showMedia(beforeProductionImgs, index, 'image')"
+                 :src="item" style="max-width: 100px; height: 100px; margin: 5px;" alt="">
+          </div>
+          
+          <!-- 瑙嗛鍒楄〃 -->
+          <div style="display: flex; flex-wrap: wrap;">
+            <div
+                v-for="(videoUrl, index) in beforeProductionVideos"
+                :key="index"
+                @click="showMedia(beforeProductionVideos, index, 'video')"
+                style="position: relative; margin: 10px; cursor: pointer;"
+            >
+              <div style="width: 160px; height: 90px; background-color: #333; display: flex; align-items: center; justify-content: center;">
+                <img src="@/assets/images/video.png" alt="鎾斁" style="width: 30px; height: 30px; opacity: 0.8;" />
+              </div>
+              <div style="text-align: center; font-size: 12px; color: #666;">鐐瑰嚮鎾斁</div>
+            </div>
+          </div>
+        </div>
+      </div>
+    </el-dialog>
+    <!-- 缁熶竴濯掍綋鏌ョ湅鍣� -->
+    <div v-if="isMediaViewerVisible" class="media-viewer-overlay" @click.self="closeMediaViewer">
+      <div class="media-viewer-content" @click.stop>
+        <!-- 鍥剧墖 -->
+        <vue-easy-lightbox
+            v-if="mediaType === 'image'"
+            :visible="isMediaViewerVisible"
+            :imgs="mediaList"
+            :index="currentMediaIndex"
+            @hide="closeMediaViewer"
+        ></vue-easy-lightbox>
+        
+        <!-- 瑙嗛 -->
+        <div v-else-if="mediaType === 'video'" style="position: relative;">
+          <Video
+              :src="mediaList[currentMediaIndex]"
+              autoplay
+              controls
+              style="max-width: 90vw; max-height: 80vh;"
+          />
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+// 鎺у埗寮圭獥鏄剧ず
+import VueEasyLightbox from "vue-easy-lightbox";
+
+const dialogVisitable = ref(false);
+// 鍥剧墖鏁扮粍
+const beforeProductionImgs = ref([]);
+// 瑙嗛鏁扮粍
+const beforeProductionVideos = ref([]);
+// 濯掍綋鏌ョ湅鍣ㄧ姸鎬�
+const isMediaViewerVisible = ref(false);
+const currentMediaIndex = ref(0);
+const mediaList = ref([]); // 瀛樺偍褰撳墠瑕佹煡鐪嬬殑濯掍綋鍒楄〃锛堝惈鍥剧墖鍜岃棰戝璞★級
+const mediaType = ref('image'); // image | video
+
+// 鎵撳紑寮圭獥骞跺姞杞芥暟鎹�
+const openDialog = async (row) => {
+  const { images: beforeImgs, videos: beforeVids } = processItems(row.storageBlobDTO);
+  
+  beforeProductionImgs.value = beforeImgs;
+  beforeProductionVideos.value = beforeVids;
+  dialogVisitable.value = true;
+};
+// 鏄剧ず濯掍綋锛堝浘鐗� or 瑙嗛锛�
+function showMedia(mediaArray, index, type) {
+  mediaList.value = mediaArray;
+  currentMediaIndex.value = index;
+  mediaType.value = type;
+  isMediaViewerVisible.value = true;
+}
+// 鍏抽棴濯掍綋鏌ョ湅鍣�
+function closeMediaViewer() {
+  isMediaViewerVisible.value = false;
+  mediaList.value = [];
+  mediaType.value = 'image';
+}
+// 琛ㄥ崟鍏抽棴鏂规硶
+const cancel = () => {
+  dialogVisitable.value = false;
+};
+// 澶勭悊姣忎竴绫绘暟鎹細鍒嗙鍥剧墖鍜岃棰�
+function processItems(items) {
+  const images = [];
+  const videos = [];
+  items.forEach(item => {
+    if (item.contentType?.startsWith('image/')) {
+      images.push(item.url);
+    } else if (item.contentType?.startsWith('video/')) {
+      videos.push(item.url);
+    }
+  });
+  return { images, videos };
+}
+defineExpose({ openDialog });
+</script>
+
+<style scoped lang="scss">
+.upload-container {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  padding: 20px;
+  border: 1px solid #dcdfe6;
+  box-sizing: border-box;
+  
+  .form-container {
+    flex: 1;
+    width: 100%;
+    margin-bottom: 20px;
+  }
+}
+
+.title {
+  font-size: 14px;
+  color: #165dff;
+  line-height: 20px;
+  font-weight: 600;
+  padding-left: 10px;
+  position: relative;
+  margin: 6px 0;
+  
+  &::before {
+    content: "";
+    position: absolute;
+    left: 0;
+    top: 3px;
+    width: 4px;
+    height: 14px;
+    background-color: #165dff;
+  }
+}
+
+.media-viewer-overlay {
+  position: fixed;
+  top: 0;
+  left: 0;
+  right: 0;
+  bottom: 0;
+  background-color: rgba(0, 0, 0, 0.8);
+  z-index: 9999;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+}
+
+.media-viewer-content {
+  position: relative;
+  max-width: 90vw;
+  max-height: 90vh;
+  overflow: hidden;
+}
+</style>
\ No newline at end of file
diff --git a/src/views/inspectionManagement/index.vue b/src/views/inspectionManagement/index.vue
new file mode 100644
index 0000000..7e5edc0
--- /dev/null
+++ b/src/views/inspectionManagement/index.vue
@@ -0,0 +1,391 @@
+<template>
+  <div class="app-container">
+    <el-form :inline="true" :model="queryParams" class="search-form">
+      <el-form-item label="鎼滅储">
+        <el-input
+            v-model="queryParams.searchAll"
+            placeholder="璇疯緭鍏ュ叧閿瓧"
+            clearable
+            :style="{ width: '100%' }"
+        />
+      </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-tabs
+          v-model="activeTab"
+          class="info-tabs"
+          @tab-click="handleTabClick"
+      >
+        <el-tab-pane
+            v-for="tab in tabs"
+            :key="tab.name"
+            :label="tab.label"
+            :name="tab.name"
+        />
+      </el-tabs>
+      <div style="display: flex;flex-direction: row;justify-content: space-between;" v-if="tabName === 'task'">
+        <el-radio-group v-model="activeRadio" @change="radioChange">
+          <el-radio-button v-for="tab in radios"
+                           :key="tab.name"
+                           :label="tab.label"
+                           :value="tab.name"/>
+        </el-radio-group>
+        <!-- 鎿嶄綔鎸夐挳鍖� -->
+        <el-space v-if="activeRadio !== 'task'">
+          <el-button type="primary" :icon="Plus" @click="handleAdd(undefined)">鏂板缓</el-button>
+          <el-button type="danger" :icon="Delete" @click="handleDelete">鍒犻櫎</el-button>
+          <!-- <el-button type="info" plain :icon="Download">瀵煎嚭</el-button> -->
+        </el-space>
+      </div>
+      <div>
+        <div>
+          <ETable :loading="tableLoading"
+                  :table-data="tableData"
+                  :columns="tableColumns"
+                  @selection-change="handleSelectionChange"
+                  :show-selection="true"
+                  :border="true"
+                  style="width: 100%;height: calc(100vh - 30em)"
+                  operationsWidth="130"
+                  :operations="operationsArr"
+                  @edit="handleAdd"
+                  @viewFile="viewFile"
+                  v-if="tabName === 'task'"
+          >
+          <template #inspector="{ row }">
+            <div class="person-tags">
+              <!-- 璋冭瘯淇℃伅锛屼笂绾挎椂鍒犻櫎 -->
+              <!-- {{ console.log('inspector data:', row.inspector) }} -->
+              <template v-if="row.inspector && row.inspector.length > 0">
+                <el-tag
+                  v-for="(person, index) in row.inspector"
+                  :key="index"
+                  size="small"
+                  type="primary"
+                  class="person-tag"
+                >
+                  {{ person }}
+                </el-tag>
+              </template>
+              <span v-else class="no-data">--</span>
+            </div>
+          </template>
+          </ETable>
+          <el-table ref="table" :data="tableData" height="480" v-loading="tableLoading" border v-else style="width: 100%;height: calc(100vh - 25em)">
+            <el-table-column label="搴忓彿" type="index" width="60" align="center" />
+            <el-table-column prop="deviceName" label="璁惧鍚嶇О" :show-overflow-tooltip="true">
+              <template #default="scope">
+                {{scope.row.qrCode.deviceName}}
+              </template>
+            </el-table-column>
+            <el-table-column prop="location" label="鎵�鍦ㄤ綅缃弿杩�" :show-overflow-tooltip="true">
+              <template #default="scope">
+                {{scope.row.qrCode.location}}
+              </template>
+            </el-table-column>
+            <el-table-column prop="scanner" label="宸℃浜�"></el-table-column>
+            <el-table-column prop="scanTime" label="宸℃鏃堕棿"></el-table-column>
+            <el-table-column fixed="right" label="鎿嶄綔">
+              <template #default="scope">
+                <el-button link type="primary" @click="handleAdd(scope.row)">鏌ョ湅闄勪欢</el-button>
+              </template>
+            </el-table-column>
+          </el-table>
+        </div>
+        <pagination
+            v-if="total>0"
+            :page="pageNum"
+            :limit="pageSize"
+            :total="total"
+            @pagination="handlePagination"
+            :layout="'total, prev, pager, next, jumper'"
+        />
+      </div>
+    </el-card>
+    <form-dia ref="formDia" @closeDia="handleQuery"></form-dia>
+    <qr-code-dia ref="qrCodeDia" @closeDia="handleQuery"></qr-code-dia>
+    <view-files ref="viewFiles"></view-files>
+    <view-qr-code-files ref="viewQrCodeFiles"></view-qr-code-files>
+  </div>
+</template>
+
+<script setup>
+import { Delete, Plus } from "@element-plus/icons-vue";
+import { onMounted, ref, reactive, getCurrentInstance, nextTick } from "vue";
+
+// 缁勪欢寮曞叆
+import Pagination from "@/components/Pagination/index.vue";
+import ETable from "@/components/Table/ETable.vue";
+import FormDia from "@/views/inspectionManagement/components/formDia.vue";
+import QrCodeDia from "@/views/inspectionManagement/components/qrCodeDia.vue";
+import ViewFiles from "@/views/inspectionManagement/components/viewFiles.vue";
+import ViewQrCodeFiles from "@/views/inspectionManagement/components/viewQrCodeFiles.vue";
+
+// 鎺ュ彛寮曞叆
+import {
+  delTimingTask,
+  inspectionTaskList,
+  timingTaskList
+} from "@/api/inspectionManagement/index.js";
+import {
+  delQrCode,
+  qrCodeList,
+  qrCodeScanRecordList
+} from "@/api/inspectionUpload/index.js";
+
+// 鍏ㄥ眬鍙橀噺
+const { proxy } = getCurrentInstance();
+const formDia = ref();
+const qrCodeDia = ref();
+const viewFiles = ref();
+const viewQrCodeFiles = ref();
+
+// 鏌ヨ鍙傛暟
+const queryParams = reactive({
+  searchAll: "",
+});
+
+// 鏍囩椤甸厤缃�
+const activeTab = ref("task");
+const tabName = ref("task");
+const tabs = reactive([
+  { name: "task", label: "鐢熶骇宸℃" },
+  { name: "qrCodeScanRecord", label: "鐜板満宸℃璁板綍" },
+]);
+
+// 鍗曢�夋閰嶇疆
+const activeRadio = ref("taskManage");
+const radios = reactive([
+  { name: "taskManage", label: "瀹氭椂浠诲姟绠$悊" },
+  { name: "task", label: "瀹氭椂浠诲姟璁板綍" },
+  { name: "qrCode", label: "浜岀淮鐮佺鐞�" },
+]);
+
+// 琛ㄦ牸鏁版嵁
+const selectedRows = ref([]);
+const tableData = ref([]);
+const operationsArr = ref([]);
+const tableColumns = ref([]);
+const tableLoading = ref(false);
+const total = ref(0);
+const pageNum = ref(1);
+const pageSize = ref(10);
+
+// 鍒楅厤缃�
+const columns = ref([
+  { prop: "taskName", label: "宸℃浠诲姟鍚嶇О", minWidth: 160 },
+  { prop: "inspectionLocation", label: "鍦扮偣", minWidth: 120 },
+  { prop: "remarks", label: "澶囨敞", minWidth: 150 },
+  { prop: "inspector", label: "鎵ц宸℃浜�", minWidth: 150, slot: "inspector" },
+  {
+    prop: "frequencyType",
+    label: "棰戞",
+    minWidth: 150,
+    formatter: (_, __, val) => ({
+      DAILY: "姣忔棩",
+      WEEKLY: "姣忓懆",
+      MONTHLY: "姣忔湀",
+      QUARTERLY: "瀛e害"
+    }[val] || "")
+  },
+  {
+    prop: "frequencyDetail",
+    label: "寮�濮嬫棩鏈熶笌鏃堕棿",
+    minWidth: 150,
+    formatter: (row, column, cellValue) => {
+      // 鍏堝垽鏂槸鍚︽槸瀛楃涓�
+      if (typeof cellValue !== 'string') return '';
+      let val = cellValue;
+      const replacements = {
+        MON: '鍛ㄤ竴',
+        TUE: '鍛ㄤ簩',
+        WED: '鍛ㄤ笁',
+        THU: '鍛ㄥ洓',
+        FRI: '鍛ㄤ簲',
+        SAT: '鍛ㄥ叚',
+        SUN: '鍛ㄦ棩'
+      };
+      // 浣跨敤姝e垯涓�娆℃�ф浛鎹㈡墍鏈夊尮閰嶉」
+      return val.replace(/MON|TUE|WED|THU|FRI|SAT|SUN/g, match => replacements[match]);
+    }
+  },
+  { prop: "registrant", label: "鐧昏浜�", minWidth: 100 },
+  { prop: "createTime", label: "鐧昏鏃ユ湡", minWidth: 100 },
+]);
+
+const columns1 = ref([
+  { prop: "deviceName", label: "璁惧鍚嶇О", minWidth: 160 },
+  { prop: "location", label: "鎵�鍦ㄤ綅缃弿杩�", minWidth: 120 },
+  { prop: "createBy", label: "鍒涘缓鑰�", minWidth: 100 },
+  { prop: "createTime", label: "鍒涘缓鏃堕棿", minWidth: 100 },
+]);
+
+onMounted(() => {
+  radioChange('taskManage');
+});
+
+// 鏍囩椤电偣鍑讳簨浠�
+const handleTabClick = (tab) => {
+  tabName.value = tab.props.name;
+  tableData.value = [];
+  getList();
+};
+
+// 鍗曢�夊彉鍖�
+const radioChange = (value) => {
+  if (value === "taskManage") {
+    tableColumns.value = columns.value;
+    operationsArr.value = ['edit'];
+  } else if (value === "task") {
+    tableColumns.value = columns.value;
+    operationsArr.value = ['viewFile'];
+  } else {
+    tableColumns.value = columns1.value;
+    operationsArr.value = ['edit'];
+  }
+  pageNum.value = 1;
+  pageSize.value = 10;
+  getList();
+};
+
+// 鏌ヨ鎿嶄綔
+const handleQuery = () => {
+  pageNum.value = 1;
+  pageSize.value = 10;
+  getList();
+};
+// 鍒嗛〉澶勭悊
+const handlePagination = (val) => {
+	pageNum.value = val.page;
+	pageSize.value = val.limit;
+	getList();
+};
+// 鑾峰彇鍒楄〃鏁版嵁
+const getList = () => {
+  tableLoading.value = true;
+  
+  const params = { ...queryParams, size: pageSize.value, current: pageNum.value };
+  
+  let apiCall;
+  if (tabName.value === 'task') {
+    switch (activeRadio.value) {
+      case "task":
+        apiCall = inspectionTaskList(params);
+        break;
+      case "qrCode":
+        apiCall = qrCodeList(params);
+        break;
+      default:
+        apiCall = timingTaskList(params);
+    }
+  } else {
+    apiCall = qrCodeScanRecordList(params);
+  }
+  
+  apiCall.then(res => {
+    const rawData = res.data.records || [];
+    // 澶勭悊 inspector 瀛楁锛屽皢瀛楃涓茶浆鎹负鏁扮粍锛堥�傜敤浜庢墍鏈夋儏鍐碉級
+    tableData.value = rawData.map(item => {
+      const processedItem = { ...item };
+      
+      // 澶勭悊 inspector 瀛楁
+      if (processedItem.inspector) {
+        if (typeof processedItem.inspector === 'string') {
+          // 瀛楃涓叉寜閫楀彿鍒嗗壊
+          processedItem.inspector = processedItem.inspector.split(',').map(s => s.trim()).filter(s => s);
+        } else if (!Array.isArray(processedItem.inspector)) {
+          // 闈炴暟缁勮浆涓烘暟缁�
+          processedItem.inspector = [processedItem.inspector];
+        }
+      } else {
+        // 绌哄�艰涓虹┖鏁扮粍
+        processedItem.inspector = [];
+      }
+      
+      return processedItem;
+    });
+    total.value = res.data.total || 0;
+  }).finally(() => {
+    tableLoading.value = false;
+  });
+};
+
+// 閲嶇疆鏌ヨ
+const resetQuery = () => {
+  for (const key in queryParams) {
+    if (!["pageNum", "pageSize"].includes(key)) {
+      queryParams[key] = "";
+    }
+  }
+  handleQuery();
+};
+
+// 鏂板 / 缂栬緫
+const handleAdd = (row) => {
+  const type = row ? 'edit' : 'add';
+  nextTick(() => {
+    if (tabName.value === 'task') {
+      if (activeRadio.value === "taskManage") {
+        formDia.value?.openDialog(type, row);
+      } else if (activeRadio.value === "qrCode") {
+        qrCodeDia.value?.openDialog(type, row);
+      }
+    } else {
+      viewQrCodeFiles.value?.openDialog(row);
+    }
+  });
+};
+
+// 鏌ョ湅闄勪欢
+const viewFile = (row) => {
+  nextTick(() => {
+    viewFiles.value?.openDialog(row);
+  });
+};
+
+// 鍒犻櫎鎿嶄綔
+const handleDelete = () => {
+  if (!selectedRows.value.length) {
+    proxy.$modal.msgWarning("璇烽�夋嫨瑕佸垹闄ょ殑鏁版嵁");
+    return;
+  }
+  
+  const deleteIds = selectedRows.value.map(item => item.id);
+  const api = activeRadio.value === "taskManage" ? delTimingTask : delQrCode;
+  
+  proxy.$modal.confirm('鏄惁纭鍒犻櫎鎵�閫夋暟鎹」锛�').then(() => {
+    return api(deleteIds);
+  }).then(() => {
+    proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+    handleQuery();
+  }).catch(() => {});
+};
+
+// 澶氶�夊彉鏇�
+const handleSelectionChange = (selection) => {
+  selectedRows.value = selection;
+};
+</script>
+
+<style scoped>
+.person-tags {
+  display: flex;
+  flex-wrap: wrap;
+  gap: 4px;
+}
+
+.person-tag {
+  margin-right: 4px;
+  margin-bottom: 2px;
+}
+
+.no-data {
+  color: #909399;
+  font-size: 14px;
+}
+</style>
\ No newline at end of file
diff --git a/src/views/procurementManagement/advancedPriceManagement/index.vue b/src/views/procurementManagement/advancedPriceManagement/index.vue
new file mode 100644
index 0000000..89fbc4b
--- /dev/null
+++ b/src/views/procurementManagement/advancedPriceManagement/index.vue
@@ -0,0 +1,874 @@
+<template>
+  <div class="app-container">
+    <!-- 鎼滅储鍖哄煙 -->
+    <el-card class="search-card" shadow="never">
+      <el-form :model="searchForm" :inline="true" label-width="100px">
+        <el-form-item label="鍟嗗搧鍚嶇О锛�">
+          <el-input v-model="searchForm.productName" placeholder="璇疯緭鍏ュ晢鍝佸悕绉�" clearable style="width: 200px" />
+        </el-form-item>
+        <el-form-item label="渚涘簲鍟嗭細">
+          <el-select v-model="searchForm.supplierId" placeholder="璇烽�夋嫨渚涘簲鍟�" clearable style="width: 200px">
+            <el-option v-for="supplier in supplierList" :key="supplier.id" :label="supplier.name" :value="supplier.id" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="浠锋牸鐘舵�侊細">
+          <el-select v-model="searchForm.priceStatus" placeholder="璇烽�夋嫨鐘舵��" clearable style="width: 150px">
+            <el-option label="鏈夋晥" value="active" />
+            <el-option label="寰呯敓鏁�" value="pending" />
+            <el-option label="宸茶繃鏈�" value="expired" />
+            <el-option label="宸叉殏鍋�" value="suspended" />
+          </el-select>
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" @click="handleSearch" :loading="loading">
+            <el-icon><Search /></el-icon>
+            鎼滅储
+          </el-button>
+          <el-button @click="resetSearch">
+            <el-icon><Refresh /></el-icon>
+            閲嶇疆
+          </el-button>
+        </el-form-item>
+      </el-form>
+    </el-card>
+
+    <!-- 鍔熻兘鎸夐挳鍖哄煙 -->
+    <el-card class="action-card" shadow="never">
+      <div class="action-buttons">
+        <el-button type="primary" @click="openDialog('add')">
+          <el-icon><Plus /></el-icon>
+          鏂板浠锋牸
+        </el-button>
+        <el-button type="success" @click="openBatchDiscountDialog">
+          <el-icon><Discount /></el-icon>
+          鎵归噺鎶樻墸
+        </el-button>
+        <el-button type="warning" @click="openPriceControlDialog">
+          <el-icon><Setting /></el-icon>
+          浠锋牸鎺у埗
+        </el-button>
+        <el-button type="info" @click="exportData">
+          <el-icon><Download /></el-icon>
+          瀵煎嚭鏁版嵁
+        </el-button>
+        <el-button type="danger" @click="handleBatchDelete" :disabled="selectedRows.length === 0">
+          <el-icon><Delete /></el-icon>
+          鎵归噺鍒犻櫎
+        </el-button>
+      </div>
+    </el-card>
+
+
+    <!-- 涓昏〃鏍� -->
+    <el-card class="table-card" shadow="never">
+      <el-table 
+        :data="tableData" 
+        border 
+        v-loading="loading" 
+        @selection-change="handleSelectionChange"
+        :default-sort="{ prop: 'updateTime', order: 'descending' }"
+      >
+        <el-table-column type="selection" width="55" align="center" />
+        <el-table-column label="鍟嗗搧淇℃伅" min-width="200">
+          <template #default="{ row }">
+            <div class="product-info">
+              <div class="product-name">{{ row.productName }}</div>
+              <div class="product-spec">{{ row.specification }}</div>
+              <div class="product-code">缂栫爜: {{ row.productCode }}</div>
+            </div>
+          </template>
+        </el-table-column>
+        <el-table-column label="渚涘簲鍟�" prop="supplierName" width="150" />
+        <el-table-column label="鍩虹浠锋牸" width="120" align="right">
+          <template #default="{ row }">
+            <span class="price-text">楼{{ row.basePrice.toFixed(2) }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column label="鎶樻墸淇℃伅" width="150">
+          <template #default="{ row }">
+            <div v-if="row.discountType">
+              <el-tag :type="getDiscountTagType(row.discountType)" size="small">
+                {{ getDiscountText(row.discountType) }}
+              </el-tag>
+              <div class="discount-value">{{ row.discountValue }}{{ row.discountType === 'percentage' ? '%' : '鍏�' }}</div>
+            </div>
+            <span v-else class="no-discount">鏃犳姌鎵�</span>
+          </template>
+        </el-table-column>
+        <el-table-column label="瀹為檯浠锋牸" width="120" align="right">
+          <template #default="{ row }">
+            <span class="final-price">楼{{ calculateFinalPrice(row).toFixed(2) }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column label="浠锋牸鎺у埗" width="120">
+          <template #default="{ row }">
+            <div class="price-control">
+              <div v-if="row.priceControl?.minPrice" class="control-item">
+                鏈�浣�: 楼{{ row.priceControl.minPrice.toFixed(2) }}
+              </div>
+              <div v-if="row.priceControl?.maxPrice" class="control-item">
+                鏈�楂�: 楼{{ row.priceControl.maxPrice.toFixed(2) }}
+              </div>
+            </div>
+          </template>
+        </el-table-column>
+        <el-table-column label="鐘舵��" width="100" align="center">
+          <template #default="{ row }">
+            <el-tag :type="getStatusType(row.status)">{{ getStatusText(row.status) }}</el-tag>
+            <div v-if="isPriceWarning(row)" class="warning-indicator">
+              <el-icon color="#F56C6C"><Warning /></el-icon>
+            </div>
+          </template>
+        </el-table-column>
+        <el-table-column label="鐢熸晥鏃堕棿" prop="effectiveTime" width="180" />
+        <el-table-column label="鏇存柊鏃堕棿" prop="updateTime" width="180" sortable />
+        <el-table-column label="鎿嶄綔" width="250" align="center" fixed="right">
+          <template #default="{ row }">
+            <el-button type="primary" link @click="openDialog('edit', row)">
+              <el-icon><Edit /></el-icon>
+              缂栬緫
+            </el-button>
+            <el-button type="success" link @click="openDiscountDialog(row)">
+              <el-icon><Discount /></el-icon>
+              鎶樻墸
+            </el-button>
+            <el-button type="danger" link @click="handleDelete(row)">
+              <el-icon><Delete /></el-icon>
+              鍒犻櫎
+            </el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+
+      <!-- 鍒嗛〉 -->
+      <div class="pagination-wrapper">
+        <el-pagination
+          v-model:current-page="pagination.currentPage"
+          v-model:page-size="pagination.pageSize"
+          :page-sizes="[10, 20, 50, 100]"
+          :total="pagination.total"
+          layout="total, sizes, prev, pager, next, jumper"
+          @size-change="handleSizeChange"
+          @current-change="handleCurrentChange"
+        />
+      </div>
+    </el-card>
+
+    <!-- 鏂板/缂栬緫瀵硅瘽妗� -->
+    <el-dialog v-model="dialogVisible" :title="dialogType === 'add' ? '鏂板浠锋牸' : '缂栬緫浠锋牸'" width="800px">
+      <el-form :model="formData" :rules="formRules" ref="formRef" label-width="120px">
+        <el-row :gutter="20">
+          <el-col :span="12">
+            <el-form-item label="鍟嗗搧鍚嶇О" prop="productName">
+              <el-select v-model="formData.productName" placeholder="璇烽�夋嫨鍟嗗搧" style="width: 100%" filterable>
+                <el-option v-for="product in productList" :key="product.id" :label="product.name" :value="product.name" />
+              </el-select>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="鍟嗗搧缂栫爜" prop="productCode">
+              <el-input v-model="formData.productCode" placeholder="璇疯緭鍏ュ晢鍝佺紪鐮�" />
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row :gutter="20">
+          <el-col :span="12">
+            <el-form-item label="瑙勬牸鍨嬪彿" prop="specification">
+              <el-input v-model="formData.specification" placeholder="璇疯緭鍏ヨ鏍煎瀷鍙�" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="渚涘簲鍟�" prop="supplierName">
+              <el-select v-model="formData.supplierName" placeholder="璇烽�夋嫨渚涘簲鍟�" style="width: 100%">
+                <el-option v-for="supplier in supplierList" :key="supplier.id" :label="supplier.name" :value="supplier.name" />
+              </el-select>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row :gutter="20">
+          <el-col :span="12">
+            <el-form-item label="鍩虹浠锋牸" prop="basePrice">
+              <el-input-number v-model="formData.basePrice" :min="0" :precision="2" placeholder="璇疯緭鍏ュ熀纭�浠锋牸" style="width: 100%" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="鍗曚綅">
+              <el-input v-model="formData.unit" placeholder="璇疯緭鍏ュ崟浣�" />
+            </el-form-item>
+          </el-col>
+        </el-row>
+        
+        <!-- 鎶樻墸璁剧疆 -->
+        <el-divider content-position="left">鎶樻墸璁剧疆</el-divider>
+        <el-row :gutter="20">
+          <el-col :span="8">
+            <el-form-item label="鎶樻墸绫诲瀷">
+              <el-select v-model="formData.discountType" placeholder="璇烽�夋嫨鎶樻墸绫诲瀷" style="width: 100%">
+                <el-option label="鏃犳姌鎵�" value="" />
+                <el-option label="鐧惧垎姣旀姌鎵�" value="percentage" />
+                <el-option label="鍥哄畾閲戦" value="fixed" />
+                <el-option label="闃舵鎶樻墸" value="tiered" />
+              </el-select>
+            </el-form-item>
+          </el-col>
+          <el-col :span="8">
+            <el-form-item label="鎶樻墸鍊�" v-if="formData.discountType && formData.discountType !== 'tiered'">
+              <el-input-number 
+                v-model="formData.discountValue" 
+                :min="0" 
+                :max="formData.discountType === 'percentage' ? 100 : undefined"
+                :precision="2" 
+                placeholder="璇疯緭鍏ユ姌鎵e��" 
+                style="width: 100%" 
+              />
+            </el-form-item>
+          </el-col>
+          <el-col :span="8">
+            <el-form-item label="鎶樻墸鏈夋晥鏈�">
+              <el-date-picker 
+                v-model="formData.discountEndTime" 
+                type="datetime" 
+                placeholder="閫夋嫨缁撴潫鏃堕棿" 
+                style="width: 100%" 
+              />
+            </el-form-item>
+          </el-col>
+        </el-row>
+
+        <!-- 闃舵鎶樻墸璁剧疆 -->
+        <div v-if="formData.discountType === 'tiered'">
+          <el-form-item label="闃舵鎶樻墸">
+            <el-table :data="formData.tieredDiscount" border size="small">
+              <el-table-column label="鏈�灏忔暟閲�" width="120">
+                <template #default="{ row, $index }">
+                  <el-input-number v-model="row.minQty" :min="0" size="small" />
+                </template>
+              </el-table-column>
+              <el-table-column label="鏈�澶ф暟閲�" width="120">
+                <template #default="{ row, $index }">
+                  <el-input-number v-model="row.maxQty" :min="0" size="small" />
+                </template>
+              </el-table-column>
+              <el-table-column label="鎶樻墸鐜�(%)" width="120">
+                <template #default="{ row, $index }">
+                  <el-input-number v-model="row.discount" :min="0" :max="100" :precision="2" size="small" />
+                </template>
+              </el-table-column>
+              <el-table-column label="鎿嶄綔" width="80">
+                <template #default="{ row, $index }">
+                  <el-button type="danger" link @click="removeTieredRow($index)">鍒犻櫎</el-button>
+                </template>
+              </el-table-column>
+            </el-table>
+            <el-button type="primary" link @click="addTieredRow" class="mt-2">娣诲姞闃舵</el-button>
+          </el-form-item>
+        </div>
+
+        <!-- 浠锋牸鎺у埗 -->
+        <el-divider content-position="left">浠锋牸鎺у埗</el-divider>
+        <el-row :gutter="20">
+          <el-col :span="8">
+            <el-form-item label="鏈�浣庝环鏍�">
+              <el-input-number v-model="formData.minPrice" :min="0" :precision="2" placeholder="鏈�浣庝环鏍�" style="width: 100%" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="8">
+            <el-form-item label="鏈�楂樹环鏍�">
+              <el-input-number v-model="formData.maxPrice" :min="0" :precision="2" placeholder="鏈�楂樹环鏍�" style="width: 100%" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="8">
+            <el-form-item label="棰勮闃堝��(%)">
+              <el-input-number v-model="formData.warningThreshold" :min="0" :max="100" :precision="1" placeholder="棰勮闃堝��" style="width: 100%" />
+            </el-form-item>
+          </el-col>
+        </el-row>
+
+        <el-row :gutter="20">
+          <el-col :span="12">
+            <el-form-item label="鐢熸晥鏃堕棿" prop="effectiveTime">
+              <el-date-picker v-model="formData.effectiveTime" type="datetime" placeholder="閫夋嫨鐢熸晥鏃堕棿" style="width: 100%" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="澶辨晥鏃堕棿">
+              <el-date-picker v-model="formData.expireTime" type="datetime" placeholder="閫夋嫨澶辨晥鏃堕棿" style="width: 100%" />
+            </el-form-item>
+          </el-col>
+        </el-row>
+
+        <el-form-item label="璋冧环鍘熷洜" prop="reason">
+          <el-select v-model="formData.reason" placeholder="璇烽�夋嫨璋冧环鍘熷洜" style="width: 100%">
+            <el-option label="甯傚満浠锋牸鍙樺姩" value="market" />
+            <el-option label="鎴愭湰鍙樺寲" value="cost" />
+            <el-option label="渚涘簲鍟嗚皟鏁�" value="supplier" />
+            <el-option label="瀛h妭鎬ц皟鏁�" value="seasonal" />
+            <el-option label="淇冮攢娲诲姩" value="promotion" />
+            <el-option label="鍏朵粬鍘熷洜" value="other" />
+          </el-select>
+        </el-form-item>
+
+        <el-form-item label="澶囨敞">
+          <el-input v-model="formData.remark" type="textarea" :rows="3" placeholder="璇疯緭鍏ュ娉ㄤ俊鎭�" />
+        </el-form-item>
+      </el-form>
+      <template #footer>
+        <el-button @click="dialogVisible = false">鍙栨秷</el-button>
+        <el-button type="primary" @click="handleSubmit" :loading="submitLoading">纭畾</el-button>
+      </template>
+    </el-dialog>
+
+    <!-- 鎵归噺鎶樻墸瀵硅瘽妗� -->
+    <el-dialog v-model="batchDiscountVisible" title="鎵归噺璁剧疆鎶樻墸" width="600px">
+      <el-form :model="batchDiscountForm" label-width="120px">
+        <el-form-item label="鎶樻墸绫诲瀷">
+          <el-select v-model="batchDiscountForm.discountType" placeholder="璇烽�夋嫨鎶樻墸绫诲瀷" style="width: 100%">
+            <el-option label="鐧惧垎姣旀姌鎵�" value="percentage" />
+            <el-option label="鍥哄畾閲戦" value="fixed" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="鎶樻墸鍊�">
+          <el-input-number 
+            v-model="batchDiscountForm.discountValue" 
+            :min="0" 
+            :max="batchDiscountForm.discountType === 'percentage' ? 100 : undefined"
+            :precision="2" 
+            placeholder="璇疯緭鍏ユ姌鎵e��" 
+            style="width: 100%" 
+          />
+        </el-form-item>
+        <el-form-item label="鐢熸晥鏃堕棿">
+          <el-date-picker v-model="batchDiscountForm.effectiveTime" type="datetime" placeholder="閫夋嫨鐢熸晥鏃堕棿" style="width: 100%" />
+        </el-form-item>
+        <el-form-item label="澶辨晥鏃堕棿">
+          <el-date-picker v-model="batchDiscountForm.expireTime" type="datetime" placeholder="閫夋嫨澶辨晥鏃堕棿" style="width: 100%" />
+        </el-form-item>
+        <el-form-item label="閫傜敤鍟嗗搧">
+          <div class="selected-items">
+            宸查�夋嫨 {{ selectedRows.length }} 涓晢鍝�
+          </div>
+        </el-form-item>
+      </el-form>
+      <template #footer>
+        <el-button @click="batchDiscountVisible = false">鍙栨秷</el-button>
+        <el-button type="primary" @click="handleBatchDiscount">纭畾</el-button>
+      </template>
+    </el-dialog>
+
+    <!-- 浠锋牸鎺у埗瀵硅瘽妗� -->
+    <el-dialog v-model="priceControlVisible" title="浠锋牸鎺у埗璁剧疆" width="700px">
+      <el-form :model="priceControlForm" label-width="120px">
+        <el-form-item label="榛樿鏈�浣庝环鏍�">
+          <el-input-number v-model="priceControlForm.defaultMinPrice" :min="0" :precision="2" style="width: 200px" />
+        </el-form-item>
+        <el-form-item label="榛樿鏈�楂樹环鏍�">
+          <el-input-number v-model="priceControlForm.defaultMaxPrice" :min="0" :precision="2" style="width: 200px" />
+        </el-form-item>
+        <el-form-item label="浠锋牸鍙樺姩闃堝��">
+          <el-input-number v-model="priceControlForm.changeThreshold" :min="0" :max="100" :precision="1" style="width: 200px" />
+        </el-form-item>
+      </el-form>
+      <template #footer>
+        <el-button @click="priceControlVisible = false">鍙栨秷</el-button>
+        <el-button type="primary" @click="handlePriceControl">淇濆瓨璁剧疆</el-button>
+      </template>
+    </el-dialog>
+
+  </div>
+</template>
+
+<script setup>
+import { ref, reactive, computed, onMounted } from 'vue'
+import { ElMessage, ElMessageBox } from 'element-plus'
+import {
+  Search, Refresh, Plus, Discount, Setting, Download, Delete, Edit, 
+  Warning
+} from '@element-plus/icons-vue'
+
+// 鍝嶅簲寮忔暟鎹�
+const loading = ref(false)
+const submitLoading = ref(false)
+const dialogVisible = ref(false)
+const batchDiscountVisible = ref(false)
+const priceControlVisible = ref(false)
+const dialogType = ref('add')
+const selectedRows = ref([])
+const formRef = ref()
+
+// 鎼滅储琛ㄥ崟
+const searchForm = reactive({
+  productName: '',
+  supplierId: '',
+  priceStatus: ''
+})
+
+// 鍒嗛〉
+const pagination = reactive({
+  currentPage: 1,
+  pageSize: 20,
+  total: 0
+})
+
+
+// 琛ㄥ崟鏁版嵁
+const formData = reactive({
+  productName: '',
+  productCode: '',
+  specification: '',
+  supplierName: '',
+  basePrice: 0,
+  unit: '',
+  discountType: '',
+  discountValue: 0,
+  discountEndTime: '',
+  tieredDiscount: [],
+  minPrice: null,
+  maxPrice: null,
+  warningThreshold: 10,
+  effectiveTime: '',
+  expireTime: '',
+  reason: '',
+  remark: ''
+})
+
+// 鎵归噺鎶樻墸琛ㄥ崟
+const batchDiscountForm = reactive({
+  discountType: 'percentage',
+  discountValue: 0,
+  effectiveTime: '',
+  expireTime: ''
+})
+
+// 浠锋牸鎺у埗琛ㄥ崟
+const priceControlForm = reactive({
+  defaultMinPrice: 0,
+  defaultMaxPrice: 0,
+  changeThreshold: 10,
+})
+
+// 琛ㄥ崟楠岃瘉瑙勫垯
+const formRules = {
+  productName: [{ required: true, message: '璇烽�夋嫨鍟嗗搧鍚嶇О', trigger: 'change' }],
+  productCode: [{ required: true, message: '璇疯緭鍏ュ晢鍝佺紪鐮�', trigger: 'blur' }],
+  supplierName: [{ required: true, message: '璇烽�夋嫨渚涘簲鍟�', trigger: 'change' }],
+  basePrice: [{ required: true, message: '璇疯緭鍏ュ熀纭�浠锋牸', trigger: 'blur' }],
+  effectiveTime: [{ required: true, message: '璇烽�夋嫨鐢熸晥鏃堕棿', trigger: 'change' }],
+  reason: [{ required: true, message: '璇烽�夋嫨璋冧环鍘熷洜', trigger: 'change' }]
+}
+
+// 妯℃嫙鏁版嵁
+const tableData = ref([
+  {
+    id: 1,
+    productName: '楂樺己搴﹁灪鏍�',
+    productCode: 'HQ001',
+    specification: 'M12脳80',
+    supplierName: '浼樿川浜旈噾渚涘簲鍟�',
+    basePrice: 2.50,
+    discountType: 'percentage',
+    discountValue: 10,
+    priceControl: { minPrice: 2.00, maxPrice: 3.00 },
+    status: 'active',
+    effectiveTime: '2025-01-01 00:00:00',
+    updateTime: '2025-09-17 10:30:00',
+    unit: '涓�',
+    reason: 'market',
+    remark: '甯傚満浠锋牸璋冩暣'
+  },
+  {
+    id: 2,
+    productName: '涓嶉攬閽㈢',
+    productCode: 'BXG002',
+    specification: '桅25脳2.0',
+    supplierName: '閽㈡潗璐告槗鍏徃',
+    basePrice: 45.80,
+    discountType: 'fixed',
+    discountValue: 5,
+    priceControl: { minPrice: 40.00, maxPrice: 50.00 },
+    status: 'pending',
+    effectiveTime: '2025-10-01 00:00:00',
+    updateTime: '2025-09-16 14:20:00',
+    unit: '绫�',
+    reason: 'cost',
+    remark: '鍘熸潗鏂欐垚鏈笂娑�'
+  }
+])
+
+const supplierList = ref([
+  { id: 1, name: '浼樿川浜旈噾渚涘簲鍟�' },
+  { id: 2, name: '閽㈡潗璐告槗鍏徃' },
+  { id: 3, name: '寤烘潗鎵瑰彂鍟�' }
+])
+
+const productList = ref([
+  { id: 1, name: '楂樺己搴﹁灪鏍�' },
+  { id: 2, name: '涓嶉攬閽㈢' },
+  { id: 3, name: '閾濆悎閲戝瀷鏉�' }
+])
+
+
+// 璁$畻灞炴��
+const finalTableData = computed(() => {
+  return tableData.value.filter(item => {
+    if (searchForm.productName && !item.productName.includes(searchForm.productName)) return false
+    if (searchForm.supplierId && item.supplierId !== searchForm.supplierId) return false
+    if (searchForm.priceStatus && item.status !== searchForm.priceStatus) return false
+    
+    return true
+  })
+})
+
+// 鏂规硶
+const calculateFinalPrice = (row) => {
+  let finalPrice = row.basePrice
+  if (row.discountType === 'percentage') {
+    finalPrice = row.basePrice * (1 - row.discountValue / 100)
+  } else if (row.discountType === 'fixed') {
+    finalPrice = row.basePrice - row.discountValue
+  }
+  return Math.max(finalPrice, 0)
+}
+
+const getDiscountTagType = (discountType) => {
+  const typeMap = {
+    percentage: 'success',
+    fixed: 'warning',
+    tiered: 'info'
+  }
+  return typeMap[discountType] || 'info'
+}
+
+const getDiscountText = (discountType) => {
+  const textMap = {
+    percentage: '鐧惧垎姣�',
+    fixed: '鍥哄畾閲戦',
+    tiered: '闃舵鎶樻墸'
+  }
+  return textMap[discountType] || '鏈煡'
+}
+
+const getStatusType = (status) => {
+  const statusMap = {
+    active: 'success',
+    pending: 'warning',
+    expired: 'info',
+    suspended: 'danger'
+  }
+  return statusMap[status] || 'info'
+}
+
+const getStatusText = (status) => {
+  const statusMap = {
+    active: '鏈夋晥',
+    pending: '寰呯敓鏁�',
+    expired: '宸茶繃鏈�',
+    suspended: '宸叉殏鍋�'
+  }
+  return statusMap[status] || '鏈煡'
+}
+
+const isPriceWarning = (row) => {
+  if (!row.priceControl) return false
+  const finalPrice = calculateFinalPrice(row)
+  return finalPrice < row.priceControl.minPrice || finalPrice > row.priceControl.maxPrice
+}
+
+
+const handleSearch = () => {
+  loading.value = true
+  // 妯℃嫙API璋冪敤
+  setTimeout(() => {
+    loading.value = false
+  }, 500)
+}
+
+const resetSearch = () => {
+  Object.assign(searchForm, {
+    productName: '',
+    supplierId: '',
+    priceStatus: ''
+  })
+  handleSearch()
+}
+
+
+const openDialog = (type, row = {}) => {
+  dialogType.value = type
+  if (type === 'edit' && row.id) {
+    Object.assign(formData, {
+      ...row,
+      minPrice: row.priceControl?.minPrice,
+      maxPrice: row.priceControl?.maxPrice,
+      tieredDiscount: row.tieredDiscount || []
+    })
+  } else {
+    resetFormData()
+  }
+  dialogVisible.value = true
+}
+
+const resetFormData = () => {
+  Object.assign(formData, {
+    productName: '',
+    productCode: '',
+    specification: '',
+    supplierName: '',
+    basePrice: 0,
+    unit: '',
+    discountType: '',
+    discountValue: 0,
+    discountEndTime: '',
+    tieredDiscount: [],
+    minPrice: null,
+    maxPrice: null,
+    warningThreshold: 10,
+    effectiveTime: '',
+    expireTime: '',
+    reason: '',
+    remark: ''
+  })
+}
+
+const addTieredRow = () => {
+  formData.tieredDiscount.push({
+    minQty: 0,
+    maxQty: 0,
+    discount: 0
+  })
+}
+
+const removeTieredRow = (index) => {
+  formData.tieredDiscount.splice(index, 1)
+}
+
+const handleSubmit = async () => {
+  if (!formRef.value) return
+  
+  try {
+    await formRef.value.validate()
+    submitLoading.value = true
+    
+    // 妯℃嫙API璋冪敤
+    setTimeout(() => {
+      if (dialogType.value === 'add') {
+        const newItem = {
+          id: Date.now(),
+          ...formData,
+          priceControl: {
+            minPrice: formData.minPrice,
+            maxPrice: formData.maxPrice
+          },
+          status: 'pending',
+          updateTime: new Date().toLocaleString()
+        }
+        tableData.value.unshift(newItem)
+        ElMessage.success('鏂板鎴愬姛')
+      } else {
+        // 缂栬緫閫昏緫
+        ElMessage.success('缂栬緫鎴愬姛')
+      }
+      
+      dialogVisible.value = false
+      submitLoading.value = false
+    }, 1000)
+  } catch (error) {
+    console.error('琛ㄥ崟楠岃瘉澶辫触:', error)
+  }
+}
+
+const openBatchDiscountDialog = () => {
+  if (selectedRows.value.length === 0) {
+    ElMessage.warning('璇峰厛閫夋嫨瑕佽缃姌鎵g殑鍟嗗搧')
+    return
+  }
+  batchDiscountVisible.value = true
+}
+
+const handleBatchDiscount = () => {
+  // 鎵归噺璁剧疆鎶樻墸閫昏緫
+  selectedRows.value.forEach(row => {
+    row.discountType = batchDiscountForm.discountType
+    row.discountValue = batchDiscountForm.discountValue
+  })
+  
+  ElMessage.success(`宸蹭负 ${selectedRows.value.length} 涓晢鍝佽缃姌鎵)
+  batchDiscountVisible.value = false
+}
+
+const openPriceControlDialog = () => {
+  priceControlVisible.value = true
+}
+
+const handlePriceControl = () => {
+  ElMessage.success('浠锋牸鎺у埗璁剧疆宸蹭繚瀛�')
+  priceControlVisible.value = false
+}
+
+const openDiscountDialog = (row) => {
+  // 鍗曚釜鍟嗗搧鎶樻墸璁剧疆
+  openDialog('edit', row)
+}
+
+
+const handleDelete = (row) => {
+  ElMessageBox.confirm('纭畾瑕佸垹闄よ繖鏉¤褰曞悧锛�', '鎻愮ず', {
+    confirmButtonText: '纭畾',
+    cancelButtonText: '鍙栨秷',
+    type: 'warning'
+  }).then(() => {
+    const index = tableData.value.findIndex(item => item.id === row.id)
+    if (index !== -1) {
+      tableData.value.splice(index, 1)
+      ElMessage.success('鍒犻櫎鎴愬姛')
+    }
+  })
+}
+
+const handleBatchDelete = () => {
+  if (selectedRows.value.length === 0) {
+    ElMessage.warning('璇峰厛閫夋嫨瑕佸垹闄ょ殑璁板綍')
+    return
+  }
+  
+  ElMessageBox.confirm(`纭畾瑕佸垹闄ら�変腑鐨� ${selectedRows.value.length} 鏉¤褰曞悧锛焋, '鎻愮ず', {
+    confirmButtonText: '纭畾',
+    cancelButtonText: '鍙栨秷',
+    type: 'warning'
+  }).then(() => {
+    selectedRows.value.forEach(row => {
+      const index = tableData.value.findIndex(item => item.id === row.id)
+      if (index !== -1) {
+        tableData.value.splice(index, 1)
+      }
+    })
+    ElMessage.success('鎵归噺鍒犻櫎鎴愬姛')
+    selectedRows.value = []
+  })
+}
+
+const handleSelectionChange = (rows) => {
+  selectedRows.value = rows
+}
+
+const handleSizeChange = (size) => {
+  pagination.pageSize = size
+  handleSearch()
+}
+
+const handleCurrentChange = (page) => {
+  pagination.currentPage = page
+  handleSearch()
+}
+
+const exportData = () => {
+  ElMessage.success('鏁版嵁瀵煎嚭鍔熻兘寮�鍙戜腑...')
+}
+
+// 鐢熷懡鍛ㄦ湡
+onMounted(() => {
+  handleSearch()
+})
+</script>
+
+<style scoped>
+.app-container {
+  padding: 20px;
+}
+
+.search-card, .action-card, .table-card {
+  margin-bottom: 20px;
+}
+
+.action-buttons {
+  display: flex;
+  gap: 10px;
+  flex-wrap: wrap;
+}
+
+
+.product-info {
+  line-height: 1.4;
+}
+
+.product-name {
+  font-weight: bold;
+  color: #303133;
+}
+
+.product-spec, .product-code {
+  font-size: 12px;
+  color: #909399;
+}
+
+.price-text {
+  font-weight: bold;
+  color: #409EFF;
+}
+
+.final-price {
+  font-weight: bold;
+  color: #67C23A;
+  font-size: 16px;
+}
+
+.discount-value {
+  font-size: 12px;
+  color: #E6A23C;
+  margin-top: 2px;
+}
+
+.no-discount {
+  color: #C0C4CC;
+  font-size: 12px;
+}
+
+.price-control {
+  font-size: 12px;
+  line-height: 1.3;
+}
+
+.control-item {
+  color: #909399;
+}
+
+.warning-indicator {
+  margin-top: 2px;
+}
+
+.pagination-wrapper {
+  display: flex;
+  justify-content: end;
+  margin-top: 20px;
+}
+
+.selected-items {
+  color: #409EFF;
+  font-weight: bold;
+}
+
+
+.mt-2 {
+  margin-top: 8px;
+}
+
+.ml-2 {
+  margin-left: 8px;
+}
+
+:deep(.el-table) {
+  font-size: 13px;
+}
+
+:deep(.el-table th) {
+  background-color: #fafafa;
+}
+
+:deep(.el-card__body) {
+  padding: 15px;
+}
+
+:deep(.el-divider__text) {
+  font-weight: bold;
+  color: #409EFF;
+}
+</style>
diff --git a/src/views/procurementManagement/arrivalManagement/index.vue b/src/views/procurementManagement/arrivalManagement/index.vue
index d2c89b1..060d2f1 100644
--- a/src/views/procurementManagement/arrivalManagement/index.vue
+++ b/src/views/procurementManagement/arrivalManagement/index.vue
@@ -18,7 +18,6 @@
     <el-card class="table-card" shadow="never">
       <div class="table-header">
         <el-button type="primary" @click="openDialog('add')">鏂板鍒拌揣</el-button>
-        <el-button type="success" @click="handleBatchReceive">鎵归噺鏀惰揣</el-button>
         <el-button type="danger" @click="handleBatchDelete">鎵归噺鍒犻櫎</el-button>
       </div>
 
@@ -37,23 +36,34 @@
         <el-table-column label="鎿嶄綔" width="200" align="center">
           <template #default="{ row }">
             <el-button type="primary" link @click="openDialog('edit', row)">缂栬緫</el-button>
-            <el-button type="success" link @click="handleReceive(row)">鏀惰揣</el-button>
+            <el-button type="success" v-if="row.status === 'pending'" link @click="handleReceive(row)">鏀惰揣</el-button>
             <el-button type="danger" link @click="handleDelete(row)">鍒犻櫎</el-button>
           </template>
         </el-table-column>
       </el-table>
+      <!-- 鍒嗛〉 -->
+      <pagination
+          :total="total"
+          layout="total, sizes, prev, pager, next, jumper"
+          :page="pagination.current"
+          :limit="pagination.size"
+          @pagination="handleCurrentChange"
+      />
     </el-card>
 
     <el-dialog v-model="dialogVisible" :title="dialogType === 'add' ? '鏂板鍒拌揣' : '缂栬緫鍒拌揣'" width="600px">
       <el-form :model="formData" label-width="120px">
+        <el-form-item label="鍒拌揣鍗曞彿">
+          <el-input v-model="formData.arrivalNo" placeholder="鍒拌揣鍗曞彿" />
+        </el-form-item>
         <el-form-item label="閲囪喘璁㈠崟鍙�">
-          <el-select v-model="formData.orderNo" placeholder="璇烽�夋嫨閲囪喘璁㈠崟" style="width: 100%">
-            <el-option label="PO20241201001" value="PO20241201001" />
-            <el-option label="PO20241201002" value="PO20241201002" />
-          </el-select>
+          <el-input v-model="formData.orderNo" placeholder="閲囪喘璁㈠崟鍙�" />
         </el-form-item>
         <el-form-item label="渚涘簲鍟嗗悕绉�">
           <el-input v-model="formData.supplierName" placeholder="渚涘簲鍟嗗悕绉�" />
+        </el-form-item>
+        <el-form-item label="鍒拌揣鏁伴噺">
+          <el-input-number  :min="0" v-model="formData.arrivalQuantity" placeholder="鍒拌揣鏁伴噺" />
         </el-form-item>
         <el-form-item label="澶囨敞">
           <el-input v-model="formData.remark" type="textarea" :rows="3" placeholder="璇疯緭鍏ュ娉ㄤ俊鎭�" />
@@ -68,8 +78,40 @@
 </template>
 
 <script setup>
-import { ref, reactive } from 'vue'
+import { ref, reactive,onMounted } from 'vue'
 import { ElMessage, ElMessageBox } from 'element-plus'
+import {listPage,add,update,del} from "@/api/procurementManagement/arrivalManagement.js"
+import Pagination from '@/components/PIMTable/Pagination.vue'
+
+onMounted(() => {
+    getList()
+})
+
+const tableData = ref([])
+
+const getList = () => {
+  loading.value = true
+  listPage({...searchForm,...pagination}).then(res =>{
+    if(res.code === 200){
+      tableData.value = res.data.records
+      total.value = res.data.total
+      loading.value = false
+    }
+  })
+}
+
+const pagination = reactive({
+  current: 1,
+  size: 10
+})
+
+const total = ref(0)
+
+const handleCurrentChange = (val) => {
+  pagination.current = val.page
+  pagination.size = val.limit
+  getList()
+}
 
 const loading = ref(false)
 const dialogVisible = ref(false)
@@ -82,25 +124,13 @@
 })
 
 const formData = reactive({
+  arrivalNo: '',
+  arrivalQuantity: 0,
   orderNo: '',
   supplierName: '',
-  remark: ''
+  remark: '',
+  status: 'pending'
 })
-
-const mockData = [
-  {
-    id: 1,
-    arrivalNo: 'AR20241201001',
-    orderNo: 'PO20241201001',
-    supplierName: '渚涘簲鍟咥',
-    status: 'received',
-    arrivalQuantity: 250,
-    arrivalTime: '2025-12-01 15:30:00',
-    remark: '姝e父鍒拌揣'
-  }
-]
-
-const tableData = ref([...mockData])
 
 const getStatusType = (status) => {
   const statusMap = { pending: 'warning', received: 'success', stored: 'info' }
@@ -114,7 +144,7 @@
 
 const handleSearch = () => {
   loading.value = true
-  setTimeout(() => { loading.value = false }, 500)
+  getList()
 }
 
 const resetSearch = () => {
@@ -124,34 +154,45 @@
 const openDialog = (type, row = {}) => {
   dialogType.value = type
   if (type === 'edit' && row.id) {
-    Object.assign(formData, { orderNo: row.orderNo, supplierName: row.supplierName, remark: row.remark })
+    obj.id = row.id
+    Object.assign(formData, { orderNo: row.orderNo, supplierName: row.supplierName, remark: row.remark, arrivalQuantity: row.arrivalQuantity,arrivalNo: row.arrivalNo })
   } else {
-    Object.assign(formData, { orderNo: '', supplierName: '', remark: '' })
+    Object.assign(formData, { orderNo: '', supplierName: '', remark: '',arrivalQuantity: 0,arrivalNo: '' })
   }
   dialogVisible.value = true
 }
 
+const obj = reactive({
+  id:''
+})
+
 const handleSubmit = () => {
   if (dialogType.value === 'add') {
-    const newArrival = {
-      id: Date.now(),
-      arrivalNo: `AR${Date.now()}`,
-      orderNo: formData.orderNo,
-      supplierName: formData.supplierName,
-      status: 'pending',
-      arrivalQuantity: 0,
-      arrivalTime: new Date().toLocaleString(),
-      remark: formData.remark
-    }
-    tableData.value.unshift(newArrival)
-    ElMessage.success('鏂板鎴愬姛')
+    add(formData).then(res => {
+      if(res.code === 200){
+        ElMessage.success('鏂板鎴愬姛')
+        getList()
+      }
+    })
+  }else{
+    update({...formData, ...obj}).then(res => {
+      if(res.code === 200){
+        ElMessage.success('缂栬緫鎴愬姛')
+        getList()
+      }
+    })
   }
   dialogVisible.value = false
 }
 
 const handleReceive = (row) => {
   row.status = 'received'
-  ElMessage.success('鏀惰揣鎴愬姛')
+  update(row).then(res => {
+    if(res.code === 200){
+      ElMessage.success('鏀惰揣鎴愬姛')
+      getList()
+    }
+  })
 }
 
 const handleDelete = (row) => {
@@ -160,20 +201,30 @@
     cancelButtonText: '鍙栨秷',
     type: 'warning'
   }).then(() => {
-    const index = tableData.value.findIndex(item => item.id === row.id)
-    if (index !== -1) {
-      tableData.value.splice(index, 1)
-      ElMessage.success('鍒犻櫎鎴愬姛')
-    }
+    let ids = [row.id]
+    del(ids).then(res => {
+      if(res.code === 200){
+        ElMessage.success('鍒犻櫎鎴愬姛')
+        getList()
+      }
+    })
   })
 }
 
-const handleBatchReceive = () => {
-  ElMessage.success('鎵归噺鏀惰揣鎴愬姛')
-}
-
 const handleBatchDelete = () => {
-  ElMessage.success('鎵归噺鍒犻櫎鎴愬姛')
+  ElMessageBox.confirm('纭畾瑕佸垹闄ら�変腑鐨勮褰曞悧锛�', '鎻愮ず', {
+    confirmButtonText: '纭畾',
+    cancelButtonText: '鍙栨秷',
+    type: 'warning'
+  }).then(() => {
+    let ids = selectedRows.value.map(item => item.id)
+    del(ids).then(res => {
+      if(res.code === 200){
+        ElMessage.success('鍒犻櫎鎴愬姛')
+        getList()
+      }
+    })
+  })
 }
 
 const handleSelectionChange = (rows) => {
diff --git a/src/views/procurementManagement/procurementPlan/index.vue b/src/views/procurementManagement/procurementPlan/index.vue
new file mode 100644
index 0000000..fec52ed
--- /dev/null
+++ b/src/views/procurementManagement/procurementPlan/index.vue
@@ -0,0 +1,821 @@
+<template>
+  <div class="app-container">
+    <!-- 鎼滅储鍖哄煙 -->
+    <el-card class="search-card" shadow="never">
+      <el-form :model="searchForm" :inline="true" class="search-form">
+        <el-form-item label="璁″垝鍚嶇О">
+          <el-input v-model="searchForm.planName" placeholder="璇疯緭鍏ヨ鍒掑悕绉�" clearable />
+        </el-form-item>
+        <el-form-item label="鐘舵��">
+          <el-select v-model="searchForm.status" placeholder="璇烽�夋嫨鐘舵��" clearable style="width: 150px">
+            <el-option label="鍚敤" value="active" />
+            <el-option label="绂佺敤" value="inactive" />
+          </el-select>
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" @click="handleSearch">
+            <el-icon><Search /></el-icon>
+            鎼滅储
+          </el-button>
+          <el-button @click="handleReset">
+            <el-icon><Refresh /></el-icon>
+            閲嶇疆
+          </el-button>
+        </el-form-item>
+      </el-form>
+    </el-card>
+
+    <!-- 鎿嶄綔鎸夐挳 -->
+    <el-card class="table-card" shadow="never">
+      <div class="table-header">
+        <div class="table-title">閲囪喘璁″垝鍒楄〃</div>
+        <div class="table-actions">
+          <el-button type="primary" @click="handleAdd">
+            <el-icon><Plus /></el-icon>
+            鏂板璁″垝
+          </el-button>
+          <el-button type="info" @click="handleExport">
+            <el-icon><Download /></el-icon>
+            瀵煎嚭
+          </el-button>
+        </div>
+      </div>
+
+      <!-- 鏁版嵁琛ㄦ牸 -->
+      <el-table
+        v-loading="loading"
+        :data="tableData"
+        stripe
+        border
+        style="width: 100%"
+      >
+        <el-table-column prop="planName" label="璁″垝鍚嶇О" min-width="150" />
+        <el-table-column prop="description" label="鎻忚堪" min-width="200" show-overflow-tooltip />
+        <el-table-column prop="formula" label="璁$畻鍏紡" min-width="200" show-overflow-tooltip>
+          <template #default="{ row }">
+            <el-tag type="info" size="small">{{ row.formula }}</el-tag>
+          </template>
+        </el-table-column>
+        <el-table-column prop="status" label="鐘舵��" width="80" align="center">
+          <template #default="{ row }">
+            <el-tag :type="row.status === 'active' ? 'success' : 'info'" size="small">
+              {{ row.status === 'active' ? '鍚敤' : '绂佺敤' }}
+            </el-tag>
+          </template>
+        </el-table-column>
+        <el-table-column prop="lastCalculateTime" label="鏈�鍚庤绠楁椂闂�" width="160" />
+        <el-table-column label="鎿嶄綔" width="200" fixed="right" align="center">
+          <template #default="{ row }">
+            <el-button type="primary" link @click="handleEdit(row)">缂栬緫</el-button>
+            <el-button type="success" link @click="handleCalculate(row)">璁$畻</el-button>
+            <el-button type="danger" link @click="handleDelete(row)">鍒犻櫎</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+
+      <!-- 鍒嗛〉 -->
+      <div class="pagination-container">
+        <el-pagination
+          v-model:current-page="pagination.current"
+          v-model:page-size="pagination.size"
+          :page-sizes="[10, 20, 50, 100]"
+          :total="pagination.total"
+          layout="total, sizes, prev, pager, next, jumper"
+          @size-change="handleSizeChange"
+          @current-change="handleCurrentChange"
+        />
+      </div>
+    </el-card>
+
+    <!-- 鏂板/缂栬緫瀵硅瘽妗� -->
+    <el-dialog
+      v-model="dialogVisible"
+      :title="dialogType === 'add' ? '鏂板閲囪喘璁″垝' : '缂栬緫閲囪喘璁″垝'"
+      width="1000px"
+      :close-on-click-modal="false"
+    >
+      <div class="form-container">
+        <!-- 鍩烘湰淇℃伅 -->
+        <div class="form-section">
+          <div class="section-title">鍩烘湰淇℃伅</div>
+          <el-form
+            ref="formRef"
+            :model="formData"
+            :rules="formRules"
+            label-width="120px"
+          >
+            <el-row :gutter="20">
+              <el-col :span="12">
+                <el-form-item label="缂栫爜" prop="code">
+                  <el-input v-model="formData.code" placeholder="绯荤粺鑷姩鐢熸垚" disabled />
+                </el-form-item>
+              </el-col>
+              <el-col :span="12">
+                <el-form-item label="鍚嶇О" prop="planName" required>
+                  <el-input v-model="formData.planName" placeholder="璇疯緭鍏ヨ鍒掑悕绉�" />
+                </el-form-item>
+              </el-col>
+            </el-row>
+
+            <el-form-item label="鎻忚堪" prop="description">
+              <el-input
+                v-model="formData.description"
+                type="textarea"
+                :rows="3"
+                placeholder="璇疯緭鍏ヨ鍒掓弿杩�"
+              />
+            </el-form-item>
+
+            <el-row :gutter="20">
+              <el-col :span="12">
+                <el-form-item label="鏁版嵁鐘舵��" prop="dataStatus">
+                  <el-select v-model="formData.dataStatus" placeholder="璇烽�夋嫨鐘舵��" style="width: 100%">
+                    <el-option label="鑽夌" value="draft" />
+                    <el-option label="宸插鏍�" value="approved" />
+                    <el-option label="宸茬鐢�" value="disabled" />
+                  </el-select>
+                </el-form-item>
+              </el-col>
+              <el-col :span="12">
+                <el-form-item label="鏄惁绯荤粺棰勭疆">
+                  <el-checkbox v-model="formData.isSystemPreset">鏄�</el-checkbox>
+                </el-form-item>
+              </el-col>
+            </el-row>
+          </el-form>
+        </div>
+
+        <!-- 璁$畻鍙傛暟 -->
+        <div class="form-section">
+          <div class="section-title">璁$畻鍙傛暟</div>
+          <el-tabs v-model="activeTab" class="param-tabs">
+            <el-tab-pane label="闇�姹傚弬鏁�" name="demand">
+              <div class="checkbox-group">
+                <el-checkbox v-model="formData.considerExistingStock">鑰冭檻鐜版湁搴撳瓨</el-checkbox>
+                <el-checkbox v-model="formData.warehouseMRPControl">浠撳簱杩愯MRP鐨勬帶鍒�</el-checkbox>
+                <el-checkbox v-model="formData.calculateTotalDemand">璁$畻鎬婚渶姹�</el-checkbox>
+                <el-checkbox v-model="formData.considerSafetyStock">鑰冭檻瀹夊叏搴撳瓨</el-checkbox>
+                <el-checkbox v-model="formData.considerLockedStock">鑰冭檻閿佸簱</el-checkbox>
+                <el-checkbox v-model="formData.notConsiderMaterialAux">涓嶈�冭檻鐗╂枡杈呭姪灞炴��</el-checkbox>
+                <el-checkbox v-model="formData.negativeStockAsDemand">璐熷簱瀛樹綔涓洪渶姹�</el-checkbox>
+              </div>
+            </el-tab-pane>
+            <el-tab-pane label="璁$畻鍙傛暟" name="calculation">
+              <div class="checkbox-group">
+                <el-checkbox v-model="formData.considerExistingStock">鑰冭檻鐜版湁搴撳瓨</el-checkbox>
+                <el-checkbox v-model="formData.warehouseMRPControl">浠撳簱杩愯MRP鐨勬帶鍒�</el-checkbox>
+                <el-checkbox v-model="formData.calculateTotalDemand">璁$畻鎬婚渶姹�</el-checkbox>
+                <el-checkbox v-model="formData.considerSafetyStock">鑰冭檻瀹夊叏搴撳瓨</el-checkbox>
+                <el-checkbox v-model="formData.considerLockedStock">鑰冭檻閿佸簱</el-checkbox>
+                <el-checkbox v-model="formData.notConsiderMaterialAux">涓嶈�冭檻鐗╂枡杈呭姪灞炴��</el-checkbox>
+                <el-checkbox v-model="formData.negativeStockAsDemand">璐熷簱瀛樹綔涓洪渶姹�</el-checkbox>
+              </div>
+            </el-tab-pane>
+          </el-tabs>
+        </div>
+
+        <!-- 姹囨�诲悎骞堕�夐」 -->
+        <div class="form-section">
+          <div class="section-title">姹囨�诲悎骞堕�夐」</div>
+          <div class="checkbox-group">
+            <el-checkbox v-model="formData.summaryMaterial">鐗╂枡</el-checkbox>
+            <el-checkbox v-model="formData.summaryAuxAttributes">杈呭姪灞炴��</el-checkbox>
+            <el-checkbox v-model="formData.summaryDemandDate">闇�姹傛棩鏈�</el-checkbox>
+          </div>
+        </div>
+
+        <!-- 璁$畻鍏紡 -->
+        <div class="form-section">
+          <div class="section-title">璁$畻鍏紡</div>
+          <div class="formula-input-section">
+            <el-form-item label="璁$畻鍏紡" prop="formula" required>
+              <el-input
+                v-model="formData.formula"
+                placeholder="渚嬪: 棰勮鍑哄簱鏁伴噺 - 鐜版湁搴撳瓨 + 瀹夊叏搴撳瓨 - 棰勮鍏ュ簱鏁伴噺"
+                @input="validateFormula"
+              />
+            </el-form-item>
+            <div class="formula-help">
+              <el-text type="info" size="small">
+                鏀寔鍙橀噺锛氶璁″嚭搴撴暟閲忋�佺幇鏈夊簱瀛樸�佸畨鍏ㄥ簱瀛樸�侀璁″叆搴撴暟閲�
+              </el-text>
+            </div>
+          </div>
+        </div>
+      </div>
+
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button @click="dialogVisible = false">鍙栨秷</el-button>
+          <el-button type="primary" @click="handleSubmit" :loading="submitLoading">纭畾</el-button>
+        </div>
+      </template>
+    </el-dialog>
+
+    <!-- 浜у搧閫夋嫨瀵硅瘽妗� -->
+    <el-dialog
+      v-model="productSelectDialogVisible"
+      title="閫夋嫨浜у搧"
+      width="800px"
+      :close-on-click-modal="false"
+    >
+      <div class="product-select">
+        <el-alert
+          title="璇烽�夋嫨瑕佽绠楃殑浜у搧"
+          type="info"
+          :closable="false"
+          show-icon
+        >
+          <template #default>
+            <p>閫夋嫨浜у搧鍚庯紝绯荤粺灏嗘牴鎹綋鍓嶈绠楀叕寮忓拰浜у搧搴撳瓨鎯呭喌杩涜璁$畻銆�</p>
+          </template>
+        </el-alert>
+
+        <el-table
+          v-loading="productLoading"
+          :data="productList"
+          @selection-change="handleProductSelectionChange"
+          stripe
+          border
+          style="width: 100%; margin-top: 20px;"
+        >
+          <el-table-column type="selection" width="55" />
+          <el-table-column prop="productName" label="浜у搧鍚嶇О" min-width="150" />
+          <el-table-column prop="productCode" label="浜у搧缂栫爜" width="120" />
+          <el-table-column prop="existingStock" label="鐜版湁搴撳瓨" width="100" align="right" />
+          <el-table-column prop="safetyStock" label="瀹夊叏搴撳瓨" width="100" align="right" />
+          <el-table-column prop="expectedOutbound" label="棰勮鍑哄簱" width="100" align="right" />
+          <el-table-column prop="expectedInbound" label="棰勮鍏ュ簱" width="100" align="right" />
+        </el-table>
+      </div>
+
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button @click="productSelectDialogVisible = false">鍙栨秷</el-button>
+          <el-button type="primary" @click="handleConfirmProductSelection" :disabled="selectedProducts.length === 0">
+            纭璁$畻
+          </el-button>
+        </div>
+      </template>
+    </el-dialog>
+
+    <!-- 璁$畻缁撴灉瀵硅瘽妗� -->
+    <el-dialog
+      v-model="calculateDialogVisible"
+      title="閲囪喘璁$畻缁撴灉"
+      width="1000px"
+      :close-on-click-modal="false"
+    >
+      <div class="calculate-result">
+        <el-alert
+          title="璁$畻缁撴灉"
+          type="success"
+          :closable="false"
+          show-icon
+        >
+          <template #default>
+            <p>鍩轰簬褰撳墠閰嶇疆鐨勮绠楀叕寮忓拰搴撳瓨鎯呭喌锛岀郴缁熷凡璁$畻鍑哄悇浜у搧鐨勯噰璐渶姹傘��</p>
+          </template>
+        </el-alert>
+
+        <el-table :data="calculateResult" stripe border style="width: 100%; margin-top: 20px;">
+          <el-table-column prop="productName" label="浜у搧鍚嶇О" min-width="150" />
+          <el-table-column prop="productCode" label="浜у搧缂栫爜" width="120" />
+          <el-table-column prop="existingStock" label="鐜版湁搴撳瓨" width="100" align="right" />
+          <el-table-column prop="safetyStock" label="瀹夊叏搴撳瓨" width="100" align="right" />
+          <el-table-column prop="expectedOutbound" label="棰勮鍑哄簱鏁伴噺" width="120" align="right" />
+          <el-table-column prop="expectedInbound" label="棰勮鍏ュ簱鏁伴噺" width="120" align="right" />
+          <el-table-column prop="weeklyNetDemand" label="鎸夊懆鍑�闇�姹�" width="120" align="right">
+            <template #default="{ row }">
+              <el-tag :type="row.weeklyNetDemand > 0 ? 'warning' : 'success'" size="small">
+                {{ row.weeklyNetDemand }}
+              </el-tag>
+            </template>
+          </el-table-column>
+          <el-table-column prop="suggestedPurchase" label="寤鸿閲囪喘" width="100" align="right">
+            <template #default="{ row }">
+              <el-tag :type="row.suggestedPurchase > 0 ? 'danger' : 'success'" size="small">
+                {{ row.suggestedPurchase }}
+              </el-tag>
+            </template>
+          </el-table-column>
+        </el-table>
+      </div>
+
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button @click="calculateDialogVisible = false">鍏抽棴</el-button>
+          <el-button type="primary" @click="handleCreatePurchaseOrder">鐢熸垚閲囪喘璁㈠崟</el-button>
+        </div>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+
+<script setup>
+import { ref, reactive, onMounted } from 'vue'
+import { ElMessage, ElMessageBox } from 'element-plus'
+import { Search, Refresh, Plus, Download } from '@element-plus/icons-vue'
+
+// 鍝嶅簲寮忔暟鎹�
+const loading = ref(false)
+const submitLoading = ref(false)
+const dialogVisible = ref(false)
+const productSelectDialogVisible = ref(false)
+const calculateDialogVisible = ref(false)
+const dialogType = ref('add')
+const productLoading = ref(false)
+const selectedProducts = ref([])
+const currentPlan = ref(null)
+
+// 鎼滅储琛ㄥ崟
+const searchForm = reactive({
+  planName: '',
+  status: ''
+})
+
+// 鍒嗛〉鏁版嵁
+const pagination = reactive({
+  current: 1,
+  size: 20,
+  total: 0
+})
+
+// 琛ㄥ崟鏁版嵁
+const formData = reactive({
+  code: '',
+  planName: '',
+  description: '',
+  dataStatus: '',
+  isSystemPreset: false,
+  formula: '',
+  // 璁$畻鍙傛暟
+  considerExistingStock: false,
+  warehouseMRPControl: false,
+  calculateTotalDemand: false,
+  considerSafetyStock: false,
+  considerLockedStock: false,
+  notConsiderMaterialAux: false,
+  negativeStockAsDemand: false,
+  // 姹囨�诲悎骞堕�夐」
+  summaryMaterial: false,
+  summaryAuxAttributes: false,
+  summaryDemandDate: false
+})
+
+// 褰撳墠婵�娲荤殑鏍囩椤�
+const activeTab = ref('demand')
+
+// 琛ㄥ崟楠岃瘉瑙勫垯
+const formRules = {
+  planName: [
+    { required: true, message: '璇疯緭鍏ヨ鍒掑悕绉�', trigger: 'blur' }
+  ],
+  dataStatus: [
+    { required: true, message: '璇烽�夋嫨鏁版嵁鐘舵��', trigger: 'change' }
+  ],
+  formula: [
+    { required: true, message: '璇疯緭鍏ヨ绠楀叕寮�', trigger: 'blur' }
+  ]
+}
+
+// 琛ㄦ牸鏁版嵁
+const tableData = ref([
+  {
+    id: 1,
+    planName: '甯歌浜у搧閲囪喘璁″垝',
+    description: '鍩轰簬鍘嗗彶閿�鍞暟鎹殑甯歌浜у搧閲囪喘璁″垝',
+    formula: '棰勮鍑哄簱鏁伴噺 - 鐜版湁搴撳瓨 + 瀹夊叏搴撳瓨 - 棰勮鍏ュ簱鏁伴噺',
+    status: 'active',
+    lastCalculateTime: '2024-12-01 10:30:00',
+    remark: '閫傜敤浜庡父瑙勪骇鍝�'
+  },
+  {
+    id: 2,
+    planName: '瀛h妭鎬т骇鍝侀噰璐鍒�',
+    description: '鑰冭檻瀛h妭鍥犵礌鐨勫鑺傛�т骇鍝侀噰璐鍒�',
+    formula: '棰勮鍑哄簱鏁伴噺 - 鐜版湁搴撳瓨 + 瀹夊叏搴撳瓨 * 1.2 - 棰勮鍏ュ簱鏁伴噺',
+    status: 'active',
+    lastCalculateTime: '2024-11-28 15:20:00',
+    remark: '閫傜敤浜庡鑺傛�т骇鍝�'
+  }
+])
+
+// 浜у搧鍒楄〃鏁版嵁
+const productList = ref([
+  {
+    id: 1,
+    productName: '浜у搧A',
+    productCode: 'PA001',
+    existingStock: 100,
+    safetyStock: 50,
+    expectedOutbound: 200,
+    expectedInbound: 30
+  },
+  {
+    id: 2,
+    productName: '浜у搧B',
+    productCode: 'PB002',
+    existingStock: 80,
+    safetyStock: 30,
+    expectedOutbound: 150,
+    expectedInbound: 20
+  },
+  {
+    id: 3,
+    productName: '浜у搧C',
+    productCode: 'PC003',
+    existingStock: 120,
+    safetyStock: 60,
+    expectedOutbound: 180,
+    expectedInbound: 25
+  },
+  {
+    id: 4,
+    productName: '浜у搧D',
+    productCode: 'PD004',
+    existingStock: 90,
+    safetyStock: 40,
+    expectedOutbound: 160,
+    expectedInbound: 35
+  }
+])
+
+// 璁$畻缁撴灉鏁版嵁
+const calculateResult = ref([
+  {
+    productName: '浜у搧A',
+    existingStock: 100,
+    safetyStock: 50,
+    expectedOutbound: 200,
+    expectedInbound: 30,
+    weeklyNetDemand: 120,
+    suggestedPurchase: 150
+  },
+  {
+    productName: '浜у搧B',
+    existingStock: 80,
+    safetyStock: 30,
+    expectedOutbound: 150,
+    expectedInbound: 20,
+    weeklyNetDemand: 100,
+    suggestedPurchase: 120
+  }
+])
+
+// 鏂规硶
+const handleSearch = () => {
+  pagination.current = 1
+  loadData()
+}
+
+const handleReset = () => {
+  Object.assign(searchForm, {
+    planName: '',
+    status: ''
+  })
+  handleSearch()
+}
+
+const loadData = () => {
+  loading.value = true
+  // 妯℃嫙API璋冪敤
+  setTimeout(() => {
+    pagination.total = tableData.value.length
+    loading.value = false
+  }, 500)
+}
+
+const handleAdd = () => {
+  dialogType.value = 'add'
+  resetForm()
+  // 鑷姩鐢熸垚缂栫爜
+  formData.code = 'CGJH' + String(Date.now()).slice(-4)
+  dialogVisible.value = true
+}
+
+const handleEdit = (row) => {
+  dialogType.value = 'edit'
+  Object.assign(formData, row)
+  dialogVisible.value = true
+}
+
+const handleDelete = async (row) => {
+  try {
+    await ElMessageBox.confirm('纭畾瑕佸垹闄よ繖涓噰璐鍒掑悧锛�', '鎻愮ず', {
+      confirmButtonText: '纭畾',
+      cancelButtonText: '鍙栨秷',
+      type: 'warning'
+    })
+    
+    const index = tableData.value.findIndex(item => item.id === row.id)
+    if (index > -1) {
+      tableData.value.splice(index, 1)
+      ElMessage.success('鍒犻櫎鎴愬姛')
+      loadData()
+    }
+  } catch {
+    // 鐢ㄦ埛鍙栨秷鍒犻櫎
+  }
+}
+
+const handleSubmit = async () => {
+  try {
+    // 琛ㄥ崟楠岃瘉
+    if (!formData.planName || !formData.formula) {
+      ElMessage.error('璇峰~鍐欏繀濉」')
+      return
+    }
+
+    submitLoading.value = true
+
+    if (dialogType.value === 'add') {
+      // 鏂板
+      const newItem = {
+        ...formData,
+        id: Date.now(),
+        lastCalculateTime: '-'
+      }
+      tableData.value.unshift(newItem)
+      ElMessage.success('鏂板鎴愬姛')
+    } else {
+      // 缂栬緫
+      const index = tableData.value.findIndex(item => item.id === formData.id)
+      if (index > -1) {
+        tableData.value[index] = { ...formData }
+        ElMessage.success('缂栬緫鎴愬姛')
+      }
+    }
+
+    dialogVisible.value = false
+    loadData()
+  } catch (error) {
+    ElMessage.error('鎿嶄綔澶辫触')
+  } finally {
+    submitLoading.value = false
+  }
+}
+
+const resetForm = () => {
+  Object.assign(formData, {
+    code: '',
+    planName: '',
+    description: '',
+    dataStatus: '',
+    isSystemPreset: false,
+    formula: '',
+    // 璁$畻鍙傛暟
+    considerExistingStock: false,
+    warehouseMRPControl: false,
+    calculateTotalDemand: false,
+    considerSafetyStock: false,
+    considerLockedStock: false,
+    notConsiderMaterialAux: false,
+    negativeStockAsDemand: false,
+    // 姹囨�诲悎骞堕�夐」
+    summaryMaterial: false,
+    summaryAuxAttributes: false,
+    summaryDemandDate: false
+  })
+  activeTab.value = 'demand'
+}
+
+const validateFormula = () => {
+  // 绠�鍗曠殑鍏紡楠岃瘉
+  const formula = formData.formula
+  if (formula && !/^[a-zA-Z\u4e00-\u9fa5\s\*\+\-\/\(\)\d\.]+$/.test(formula)) {
+    ElMessage.warning('鍏紡鏍煎紡鍙兘涓嶆纭紝璇锋鏌�')
+  }
+}
+
+const handleCalculate = (row) => {
+  currentPlan.value = row
+  productSelectDialogVisible.value = true
+  loadProductList()
+}
+
+const loadProductList = () => {
+  productLoading.value = true
+  // 妯℃嫙鍔犺浇浜у搧鏁版嵁
+  setTimeout(() => {
+    productLoading.value = false
+  }, 500)
+}
+
+const handleProductSelectionChange = (selection) => {
+  selectedProducts.value = selection
+}
+
+const handleConfirmProductSelection = () => {
+  if (selectedProducts.value.length === 0) {
+    ElMessage.warning('璇烽�夋嫨瑕佽绠楃殑浜у搧')
+    return
+  }
+  
+  ElMessage.success(`姝e湪璁$畻 ${currentPlan.value.planName} 鐨勯噰璐渶姹�...`)
+  productSelectDialogVisible.value = false
+  
+  // 鏍规嵁閫夋嫨鐨勪骇鍝佸拰璁$畻鍏紡杩涜璁$畻
+  calculateWithSelectedProducts()
+}
+
+const calculateWithSelectedProducts = () => {
+  // 妯℃嫙璁$畻杩囩▼
+  setTimeout(() => {
+    // 鏍规嵁閫夋嫨鐨勪骇鍝佹洿鏂拌绠楃粨鏋�
+    const result = selectedProducts.value.map(product => {
+      // 杩欓噷搴旇鏍规嵁瀹為檯鐨勮绠楀叕寮忚繘琛岃绠�
+      // 绀轰緥锛氶璁″嚭搴撴暟閲� - 鐜版湁搴撳瓨 + 瀹夊叏搴撳瓨 - 棰勮鍏ュ簱鏁伴噺
+      const weeklyNetDemand = product.expectedOutbound - product.existingStock + product.safetyStock - product.expectedInbound
+      const suggestedPurchase = Math.max(0, weeklyNetDemand)
+      
+      return {
+        productName: product.productName,
+        productCode: product.productCode,
+        existingStock: product.existingStock,
+        safetyStock: product.safetyStock,
+        expectedOutbound: product.expectedOutbound,
+        expectedInbound: product.expectedInbound,
+        weeklyNetDemand: weeklyNetDemand,
+        suggestedPurchase: suggestedPurchase
+      }
+    })
+    
+    calculateResult.value = result
+    calculateDialogVisible.value = true
+  }, 1000)
+}
+
+
+const handleCreatePurchaseOrder = () => {
+  ElMessage.success('姝e湪鐢熸垚閲囪喘璁㈠崟...')
+  calculateDialogVisible.value = false
+}
+
+const handleExport = () => {
+  ElMessage.success('姝e湪瀵煎嚭鏁版嵁...')
+}
+
+
+const handleSizeChange = (size) => {
+  pagination.size = size
+  loadData()
+}
+
+const handleCurrentChange = (current) => {
+  pagination.current = current
+  loadData()
+}
+
+// 鐢熷懡鍛ㄦ湡
+onMounted(() => {
+  loadData()
+})
+</script>
+
+<style scoped>
+.app-container {
+  padding: 20px;
+}
+
+.page-header {
+  margin-bottom: 20px;
+}
+
+.page-header h2 {
+  margin: 0 0 8px 0;
+  color: #303133;
+  font-size: 24px;
+  font-weight: 600;
+}
+
+.page-header p {
+  margin: 0;
+  color: #909399;
+  font-size: 14px;
+}
+
+.search-card {
+  margin-bottom: 20px;
+}
+
+.search-form {
+  margin-bottom: 0;
+}
+
+.table-card {
+  margin-bottom: 20px;
+}
+
+.table-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  margin-bottom: 20px;
+}
+
+.table-title {
+  font-size: 16px;
+  font-weight: 600;
+  color: #303133;
+}
+
+.table-actions {
+  display: flex;
+  gap: 10px;
+}
+
+.pagination-container {
+  margin-top: 20px;
+  display: flex;
+  justify-content: end;
+}
+
+.form-container {
+  padding: 0 20px;
+}
+
+.formula-help {
+  margin-top: 5px;
+}
+
+.calculate-result {
+  padding: 20px 0;
+}
+
+.dialog-footer {
+  text-align: right;
+}
+
+:deep(.el-card__body) {
+  padding: 20px;
+}
+
+:deep(.el-table) {
+  font-size: 14px;
+}
+
+:deep(.el-form-item__label) {
+  font-weight: 500;
+}
+
+.form-container {
+  padding: 0;
+}
+
+.form-section {
+  margin-bottom: 24px;
+  border: 1px solid #e4e7ed;
+  border-radius: 6px;
+  overflow: hidden;
+}
+
+.section-title {
+  background-color: #f5f7fa;
+  padding: 12px 16px;
+  font-weight: 600;
+  color: #303133;
+  border-bottom: 1px solid #e4e7ed;
+}
+
+.form-section .el-form {
+  padding: 20px;
+}
+
+.param-tabs {
+  padding: 20px;
+}
+
+.param-tabs :deep(.el-tabs__header) {
+  margin-bottom: 20px;
+}
+
+.param-tabs :deep(.el-tabs__item.is-active) {
+  color: #f56c6c;
+  border-bottom-color: #f56c6c;
+}
+
+.checkbox-group {
+  display: flex;
+  flex-wrap: wrap;
+  gap: 16px;
+}
+
+.checkbox-group .el-checkbox {
+  margin-right: 0;
+  margin-bottom: 8px;
+}
+
+.formula-input-section {
+  padding: 20px;
+}
+
+.formula-input-section .el-form-item {
+  margin-bottom: 12px;
+}
+
+.formula-help {
+  text-align: center;
+  margin-top: 8px;
+}
+</style>
diff --git a/src/views/procurementManagement/procurementReport/index.vue b/src/views/procurementManagement/procurementReport/index.vue
new file mode 100644
index 0000000..a12b4ba
--- /dev/null
+++ b/src/views/procurementManagement/procurementReport/index.vue
@@ -0,0 +1,847 @@
+<template>
+  <div class="app-container">
+    <!-- 鎶ヨ〃閫夋嫨鍣� -->
+    <el-card class="report-selector" shadow="never">
+      <el-tabs v-model="activeReport" @tab-change="handleReportChange">
+        <el-tab-pane label="閲囪喘璁㈠崟鎵ц姹囨�昏〃" name="orderSummary">
+          <template #label>
+            <span class="tab-label">
+              <el-icon><Document /></el-icon>
+              閲囪喘璁㈠崟鎵ц姹囨�昏〃
+            </span>
+          </template>
+        </el-tab-pane>
+        <el-tab-pane label="閲囪喘璁㈠崟鎵ц鏄庣粏琛�" name="orderDetail">
+          <template #label>
+            <span class="tab-label">
+              <el-icon><List /></el-icon>
+              閲囪喘璁㈠崟鎵ц鏄庣粏琛�
+            </span>
+          </template>
+        </el-tab-pane>
+        <el-tab-pane label="閲囪喘涓氬姟姹囨�昏〃" name="businessSummary">
+          <template #label>
+            <span class="tab-label">
+              <el-icon><TrendCharts /></el-icon>
+              閲囪喘涓氬姟姹囨�昏〃
+            </span>
+          </template>
+        </el-tab-pane>
+        <el-tab-pane label="渚涘簲鍟嗕緵璐ф眹鎬昏〃" name="supplierSummary">
+          <template #label>
+            <span class="tab-label">
+              <el-icon><Shop /></el-icon>
+              渚涘簲鍟嗕緵璐ф眹鎬昏〃
+            </span>
+          </template>
+        </el-tab-pane>
+      </el-tabs>
+    </el-card>
+
+    <!-- 鏌ヨ鏉′欢 -->
+    <el-card class="search-card" shadow="never">
+      <el-form :model="searchForm" :inline="true" class="search-form">
+        <el-form-item label="鏃堕棿鑼冨洿锛�">
+          <el-date-picker
+            v-model="searchForm.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 label="渚涘簲鍟嗭細" v-if="activeReport === 'supplierSummary'">
+          <el-select v-model="searchForm.supplierId" placeholder="璇烽�夋嫨渚涘簲鍟�" clearable style="width: 200px">
+            <el-option
+              v-for="supplier in supplierList"
+              :key="supplier.id"
+              :label="supplier.name"
+              :value="supplier.id"
+            />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="鍟嗗搧绫诲埆锛�" v-if="activeReport === 'businessSummary'">
+          <el-select v-model="searchForm.categoryId" placeholder="璇烽�夋嫨鍟嗗搧绫诲埆" clearable style="width: 200px">
+            <el-option
+              v-for="category in categoryList"
+              :key="category.id"
+              :label="category.name"
+              :value="category.id"
+            />
+          </el-select>
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" @click="handleSearch" :loading="loading">
+            <el-icon><Search /></el-icon>
+            鏌ヨ
+          </el-button>
+          <el-button @click="resetSearch">
+            <el-icon><Refresh /></el-icon>
+            閲嶇疆
+          </el-button>
+          <el-button type="success" @click="exportReport">
+            <el-icon><Download /></el-icon>
+            瀵煎嚭
+          </el-button>
+        </el-form-item>
+      </el-form>
+    </el-card>
+
+    <!-- 鎶ヨ〃鍐呭 -->
+    <el-card class="report-content" shadow="never">
+      <!-- 閲囪喘璁㈠崟鎵ц姹囨�昏〃 -->
+      <div v-if="activeReport === 'orderSummary'" class="report-section">
+        <div class="section-header">
+          <h3>閲囪喘璁㈠崟鎵ц姹囨�昏〃</h3>
+          <div class="summary-stats">
+            <div class="stat-item">
+              <span class="stat-label">鎬昏鍗曟暟锛�</span>
+              <span class="stat-value">{{ orderSummaryStats.totalOrders }}</span>
+            </div>
+            <div class="stat-item">
+              <span class="stat-label">鎬婚噾棰濓細</span>
+              <span class="stat-value">楼{{ orderSummaryStats.totalAmount.toLocaleString() }}</span>
+            </div>
+            <div class="stat-item">
+              <span class="stat-label">瀹屾垚鐜囷細</span>
+              <span class="stat-value">{{ orderSummaryStats.completionRate }}%</span>
+            </div>
+          </div>
+        </div>
+        
+        <el-table :data="orderSummaryData" border v-loading="loading" stripe>
+          <el-table-column label="璁㈠崟缂栧彿" prop="orderNo" width="180" fixed="left" />
+          <el-table-column label="渚涘簲鍟嗗悕绉�" prop="supplierName" width="150" />
+          <el-table-column label="璁㈠崟鏃ユ湡" prop="orderDate" width="120" />
+          <el-table-column label="璁″垝浜ゆ湡" prop="plannedDelivery" width="120" />
+          <el-table-column label="瀹為檯浜ゆ湡" prop="actualDelivery" width="120" />
+          <el-table-column label="璁㈠崟閲戦" prop="orderAmount" width="120">
+            <template #default="{ row }">楼{{ row.orderAmount.toLocaleString() }}</template>
+          </el-table-column>
+          <el-table-column label="宸蹭粯閲戦" prop="paidAmount" width="120">
+            <template #default="{ row }">楼{{ row.paidAmount.toLocaleString() }}</template>
+          </el-table-column>
+          <el-table-column label="瀹屾垚鐘舵��" prop="status" width="100">
+            <template #default="{ row }">
+              <el-tag :type="getStatusType(row.status)">{{ getStatusText(row.status) }}</el-tag>
+            </template>
+          </el-table-column>
+          <el-table-column label="瀹屾垚鐜�" prop="completionRate" width="100">
+            <template #default="{ row }">{{ row.completionRate }}%</template>
+          </el-table-column>
+          <el-table-column label="寤惰繜澶╂暟" prop="delayDays" width="100">
+            <template #default="{ row }">
+              <span :class="{ 'delay-text': row.delayDays > 0 }">{{ row.delayDays }}</span>
+            </template>
+          </el-table-column>
+        </el-table>
+      </div>
+
+      <!-- 閲囪喘璁㈠崟鎵ц鏄庣粏琛� -->
+      <div v-if="activeReport === 'orderDetail'" class="report-section">
+        <div class="section-header">
+          <h3>閲囪喘璁㈠崟鎵ц鏄庣粏琛�</h3>
+          <div class="summary-stats">
+            <div class="stat-item">
+              <span class="stat-label">鏄庣粏鏉℃暟锛�</span>
+              <span class="stat-value">{{ orderDetailStats.totalItems }}</span>
+            </div>
+            <div class="stat-item">
+              <span class="stat-label">宸叉敹璐э細</span>
+              <span class="stat-value">{{ orderDetailStats.receivedItems }}</span>
+            </div>
+            <div class="stat-item">
+              <span class="stat-label">寰呮敹璐э細</span>
+              <span class="stat-value">{{ orderDetailStats.pendingItems }}</span>
+            </div>
+          </div>
+        </div>
+        
+        <el-table :data="orderDetailData" border v-loading="loading" stripe>
+          <el-table-column label="璁㈠崟缂栧彿" prop="orderNo" width="150" fixed="left" />
+          <el-table-column label="鍟嗗搧缂栫爜" prop="productCode" width="120" />
+          <el-table-column label="鍟嗗搧鍚嶇О" prop="productName" width="200" />
+          <el-table-column label="瑙勬牸鍨嬪彿" prop="specification" width="150" />
+          <el-table-column label="鍗曚綅" prop="unit" width="80" />
+          <el-table-column label="璁″垝鏁伴噺" prop="plannedQuantity" width="100" />
+          <el-table-column label="宸叉敹璐ф暟閲�" prop="receivedQuantity" width="120" />
+          <el-table-column label="寰呮敹璐ф暟閲�" prop="pendingQuantity" width="120" />
+          <el-table-column label="鍗曚环" prop="unitPrice" width="100">
+            <template #default="{ row }">楼{{ row.unitPrice.toFixed(2) }}</template>
+          </el-table-column>
+          <el-table-column label="灏忚" prop="subtotal" width="120">
+            <template #default="{ row }">楼{{ row.subtotal.toLocaleString() }}</template>
+          </el-table-column>
+          <el-table-column label="鏀惰揣鐘舵��" prop="status" width="100">
+            <template #default="{ row }">
+              <el-tag :type="getReceiptStatusType(row.status)">{{ getReceiptStatusText(row.status) }}</el-tag>
+            </template>
+          </el-table-column>
+          <el-table-column label="鏈�鍚庢敹璐ф棩鏈�" prop="lastReceiptDate" width="120" />
+        </el-table>
+      </div>
+
+      <!-- 閲囪喘涓氬姟姹囨�昏〃 -->
+      <div v-if="activeReport === 'businessSummary'" class="report-section">
+        <div class="section-header">
+          <h3>閲囪喘涓氬姟姹囨�昏〃</h3>
+          <div class="summary-stats">
+            <div class="stat-item">
+              <span class="stat-label">閲囪喘鎬婚锛�</span>
+              <span class="stat-value">楼{{ businessSummaryStats.totalAmount.toLocaleString() }}</span>
+            </div>
+            <div class="stat-item">
+              <span class="stat-label">鍟嗗搧绉嶇被锛�</span>
+              <span class="stat-value">{{ businessSummaryStats.productTypes }}</span>
+            </div>
+            <div class="stat-item">
+              <span class="stat-label">渚涘簲鍟嗘暟锛�</span>
+              <span class="stat-value">{{ businessSummaryStats.supplierCount }}</span>
+            </div>
+          </div>
+        </div>
+        
+        <el-table :data="businessSummaryData" border v-loading="loading" stripe>
+          <el-table-column label="鍟嗗搧绫诲埆" prop="category" width="150" fixed="left" />
+          <el-table-column label="鍟嗗搧缂栫爜" prop="productCode" width="120" />
+          <el-table-column label="鍟嗗搧鍚嶇О" prop="productName" width="200" />
+          <el-table-column label="瑙勬牸鍨嬪彿" prop="specification" width="150" />
+          <el-table-column label="閲囪喘鏁伴噺" prop="purchaseQuantity" width="120" />
+          <el-table-column label="閲囪喘閲戦" prop="purchaseAmount" width="120">
+            <template #default="{ row }">楼{{ row.purchaseAmount.toLocaleString() }}</template>
+          </el-table-column>
+          <el-table-column label="骞冲潎鍗曚环" prop="avgPrice" width="100">
+            <template #default="{ row }">楼{{ row.avgPrice.toFixed(2) }}</template>
+          </el-table-column>
+          <el-table-column label="閲囪喘娆℃暟" prop="purchaseCount" width="100" />
+          <el-table-column label="涓昏渚涘簲鍟�" prop="mainSupplier" width="150" />
+          <el-table-column label="鏈�鍚庨噰璐棩鏈�" prop="lastPurchaseDate" width="120" />
+        </el-table>
+      </div>
+
+      <!-- 渚涘簲鍟嗕緵璐ф眹鎬昏〃 -->
+      <div v-if="activeReport === 'supplierSummary'" class="report-section">
+        <div class="section-header">
+          <h3>渚涘簲鍟嗕緵璐ф眹鎬昏〃</h3>
+          <div class="summary-stats">
+            <div class="stat-item">
+              <span class="stat-label">渚涘簲鍟嗘�绘暟锛�</span>
+              <span class="stat-value">{{ supplierSummaryStats.totalSuppliers }}</span>
+            </div>
+            <div class="stat-item">
+              <span class="stat-label">渚涜揣鎬婚锛�</span>
+              <span class="stat-value">楼{{ supplierSummaryStats.totalAmount.toLocaleString() }}</span>
+            </div>
+            <div class="stat-item">
+              <span class="stat-label">骞冲潎璇勫垎锛�</span>
+              <span class="stat-value">{{ supplierSummaryStats.avgRating.toFixed(1) }}</span>
+            </div>
+          </div>
+        </div>
+        
+        <el-table :data="supplierSummaryData" border v-loading="loading" stripe>
+          <el-table-column label="渚涘簲鍟嗙紪鐮�" prop="supplierCode" width="120" fixed="left" />
+          <el-table-column label="渚涘簲鍟嗗悕绉�" prop="supplierName" width="200" />
+          <el-table-column label="鑱旂郴浜�" prop="contactPerson" width="120" />
+          <el-table-column label="鑱旂郴鐢佃瘽" prop="phone" width="130" />
+          <el-table-column label="渚涜揣璁㈠崟鏁�" prop="orderCount" width="120" />
+          <el-table-column label="渚涜揣閲戦" prop="supplyAmount" width="120">
+            <template #default="{ row }">楼{{ row.supplyAmount.toLocaleString() }}</template>
+          </el-table-column>
+          <el-table-column label="宸蹭粯閲戦" prop="paidAmount" width="120">
+            <template #default="{ row }">楼{{ row.paidAmount.toLocaleString() }}</template>
+          </el-table-column>
+          <el-table-column label="鏈粯閲戦" prop="unpaidAmount" width="120">
+            <template #default="{ row }">楼{{ row.unpaidAmount.toLocaleString() }}</template>
+          </el-table-column>
+          <el-table-column label="鎸夋椂浜よ揣鐜�" prop="onTimeRate" width="120">
+            <template #default="{ row }">{{ row.onTimeRate }}%</template>
+          </el-table-column>
+          <el-table-column label="璐ㄩ噺璇勫垎" prop="qualityRating" width="100">
+            <template #default="{ row }">
+              <el-rate v-model="row.qualityRating" disabled show-score text-color="#ff9900" />
+            </template>
+          </el-table-column>
+          <el-table-column label="鍚堜綔鐘舵��" prop="status" width="100">
+            <template #default="{ row }">
+              <el-tag :type="getSupplierStatusType(row.status)">{{ getSupplierStatusText(row.status) }}</el-tag>
+            </template>
+          </el-table-column>
+        </el-table>
+      </div>
+    </el-card>
+  </div>
+</template>
+
+<script setup>
+import { ref, reactive, onMounted } from 'vue'
+import { ElMessage } from 'element-plus'
+import { Document, List, TrendCharts, Shop, Search, Refresh, Download } from '@element-plus/icons-vue'
+
+// 鍝嶅簲寮忔暟鎹�
+const loading = ref(false)
+const activeReport = ref('orderSummary')
+
+// 鎼滅储琛ㄥ崟
+const searchForm = reactive({
+  dateRange: [],
+  supplierId: '',
+  categoryId: ''
+})
+
+// 渚涘簲鍟嗗垪琛�
+const supplierList = ref([
+  { id: 1, name: '姹熻嫃鍗庤仈鐢靛瓙绉戞妧鏈夐檺鍏徃' },
+  { id: 2, name: '涓婃捣绮惧瘑鏈烘鍒堕�犳湁闄愬叕鍙�' },
+  { id: 3, name: '娣卞湷鏅鸿兘璁惧鏈夐檺鍏徃' },
+  { id: 4, name: '鍖椾含鏂版潗鏂欑鎶�鏈夐檺鍏徃' },
+  { id: 5, name: '骞垮窞鐢靛瓙鍏冨櫒浠舵湁闄愬叕鍙�' }
+])
+
+// 鍟嗗搧绫诲埆鍒楄〃
+const categoryList = ref([
+  { id: 1, name: '鐢靛瓙鍏冨櫒浠�' },
+  { id: 2, name: '鏈烘璁惧' },
+  { id: 3, name: '鍘熸潗鏂�' },
+  { id: 4, name: '鍔炲叕鐢ㄥ搧' },
+  { id: 5, name: '鍖呰鏉愭枡' }
+])
+
+// 缁熻鏁版嵁
+const orderSummaryStats = ref({
+  totalOrders: 156,
+  totalAmount: 2580000,
+  completionRate: 87.5
+})
+
+const orderDetailStats = ref({
+  totalItems: 1248,
+  receivedItems: 1089,
+  pendingItems: 159
+})
+
+const businessSummaryStats = ref({
+  totalAmount: 2580000,
+  productTypes: 89,
+  supplierCount: 25
+})
+
+const supplierSummaryStats = ref({
+  totalSuppliers: 25,
+  totalAmount: 2580000,
+  avgRating: 4.2
+})
+
+// 閲囪喘璁㈠崟鎵ц姹囨�昏〃鏁版嵁
+const orderSummaryData = ref([
+  {
+    orderNo: 'PO20241201001',
+    supplierName: '姹熻嫃鍗庤仈鐢靛瓙绉戞妧鏈夐檺鍏徃',
+    orderDate: '2024-12-01',
+    plannedDelivery: '2024-12-15',
+    actualDelivery: '2024-12-14',
+    orderAmount: 125000,
+    paidAmount: 100000,
+    status: 'completed',
+    completionRate: 100,
+    delayDays: -1
+  },
+  {
+    orderNo: 'PO20241201002',
+    supplierName: '涓婃捣绮惧瘑鏈烘鍒堕�犳湁闄愬叕鍙�',
+    orderDate: '2024-12-02',
+    plannedDelivery: '2024-12-20',
+    actualDelivery: '2024-12-22',
+    orderAmount: 280000,
+    paidAmount: 140000,
+    status: 'partial',
+    completionRate: 75,
+    delayDays: 2
+  },
+  {
+    orderNo: 'PO20241201003',
+    supplierName: '娣卞湷鏅鸿兘璁惧鏈夐檺鍏徃',
+    orderDate: '2024-12-03',
+    plannedDelivery: '2024-12-25',
+    actualDelivery: '',
+    orderAmount: 180000,
+    paidAmount: 0,
+    status: 'pending',
+    completionRate: 0,
+    delayDays: 0
+  },
+  {
+    orderNo: 'PO20241201004',
+    supplierName: '鍖椾含鏂版潗鏂欑鎶�鏈夐檺鍏徃',
+    orderDate: '2024-12-04',
+    plannedDelivery: '2024-12-18',
+    actualDelivery: '2024-12-18',
+    orderAmount: 95000,
+    paidAmount: 95000,
+    status: 'completed',
+    completionRate: 100,
+    delayDays: 0
+  },
+  {
+    orderNo: 'PO20241201005',
+    supplierName: '骞垮窞鐢靛瓙鍏冨櫒浠舵湁闄愬叕鍙�',
+    orderDate: '2024-12-05',
+    plannedDelivery: '2024-12-28',
+    actualDelivery: '',
+    orderAmount: 220000,
+    paidAmount: 0,
+    status: 'pending',
+    completionRate: 0,
+    delayDays: 0
+  }
+])
+
+// 閲囪喘璁㈠崟鎵ц鏄庣粏琛ㄦ暟鎹�
+const orderDetailData = ref([
+  {
+    orderNo: 'PO20241201001',
+    productCode: 'EL001',
+    productName: '鐢甸樆鍣� 1K惟 卤5%',
+    specification: '1/4W 纰宠啘鐢甸樆',
+    unit: '涓�',
+    plannedQuantity: 1000,
+    receivedQuantity: 1000,
+    pendingQuantity: 0,
+    unitPrice: 0.15,
+    subtotal: 150,
+    status: 'completed',
+    lastReceiptDate: '2024-12-14'
+  },
+  {
+    orderNo: 'PO20241201001',
+    productCode: 'EL002',
+    productName: '鐢靛鍣� 100渭F',
+    specification: '25V 閾濈數瑙g數瀹�',
+    unit: '涓�',
+    plannedQuantity: 500,
+    receivedQuantity: 500,
+    pendingQuantity: 0,
+    unitPrice: 0.85,
+    subtotal: 425,
+    status: 'completed',
+    lastReceiptDate: '2024-12-14'
+  },
+  {
+    orderNo: 'PO20241201002',
+    productCode: 'ME001',
+    productName: '绮惧瘑杞存壙',
+    specification: '6205-2RS 娣辨矡鐞冭酱鎵�',
+    unit: '涓�',
+    plannedQuantity: 200,
+    receivedQuantity: 150,
+    pendingQuantity: 50,
+    unitPrice: 25.5,
+    subtotal: 5100,
+    status: 'partial',
+    lastReceiptDate: '2024-12-20'
+  },
+  {
+    orderNo: 'PO20241201002',
+    productCode: 'ME002',
+    productName: '涓嶉攬閽㈣灪涓�',
+    specification: 'M8脳20 304涓嶉攬閽�',
+    unit: '涓�',
+    plannedQuantity: 1000,
+    receivedQuantity: 1000,
+    pendingQuantity: 0,
+    unitPrice: 0.8,
+    subtotal: 800,
+    status: 'completed',
+    lastReceiptDate: '2024-12-20'
+  },
+  {
+    orderNo: 'PO20241201003',
+    productCode: 'SM001',
+    productName: '鏅鸿兘浼犳劅鍣�',
+    specification: '娓╁害浼犳劅鍣� DS18B20',
+    unit: '涓�',
+    plannedQuantity: 300,
+    receivedQuantity: 0,
+    pendingQuantity: 300,
+    unitPrice: 12.5,
+    subtotal: 3750,
+    status: 'pending',
+    lastReceiptDate: ''
+  }
+])
+
+// 閲囪喘涓氬姟姹囨�昏〃鏁版嵁
+const businessSummaryData = ref([
+  {
+    category: '鐢靛瓙鍏冨櫒浠�',
+    productCode: 'EL001',
+    productName: '鐢甸樆鍣� 1K惟 卤5%',
+    specification: '1/4W 纰宠啘鐢甸樆',
+    purchaseQuantity: 5000,
+    purchaseAmount: 750,
+    avgPrice: 0.15,
+    purchaseCount: 8,
+    mainSupplier: '姹熻嫃鍗庤仈鐢靛瓙绉戞妧鏈夐檺鍏徃',
+    lastPurchaseDate: '2024-12-01'
+  },
+  {
+    category: '鐢靛瓙鍏冨櫒浠�',
+    productCode: 'EL002',
+    productName: '鐢靛鍣� 100渭F',
+    specification: '25V 閾濈數瑙g數瀹�',
+    purchaseQuantity: 2500,
+    purchaseAmount: 2125,
+    avgPrice: 0.85,
+    purchaseCount: 6,
+    mainSupplier: '姹熻嫃鍗庤仈鐢靛瓙绉戞妧鏈夐檺鍏徃',
+    lastPurchaseDate: '2024-12-01'
+  },
+  {
+    category: '鏈烘璁惧',
+    productCode: 'ME001',
+    productName: '绮惧瘑杞存壙',
+    specification: '6205-2RS 娣辨矡鐞冭酱鎵�',
+    purchaseQuantity: 800,
+    purchaseAmount: 20400,
+    avgPrice: 25.5,
+    purchaseCount: 4,
+    mainSupplier: '涓婃捣绮惧瘑鏈烘鍒堕�犳湁闄愬叕鍙�',
+    lastPurchaseDate: '2024-12-02'
+  },
+  {
+    category: '鏈烘璁惧',
+    productCode: 'ME002',
+    productName: '涓嶉攬閽㈣灪涓�',
+    specification: 'M8脳20 304涓嶉攬閽�',
+    purchaseQuantity: 5000,
+    purchaseAmount: 4000,
+    avgPrice: 0.8,
+    purchaseCount: 12,
+    mainSupplier: '涓婃捣绮惧瘑鏈烘鍒堕�犳湁闄愬叕鍙�',
+    lastPurchaseDate: '2024-12-02'
+  },
+  {
+    category: '鏅鸿兘璁惧',
+    productCode: 'SM001',
+    productName: '鏅鸿兘浼犳劅鍣�',
+    specification: '娓╁害浼犳劅鍣� DS18B20',
+    purchaseQuantity: 1200,
+    purchaseAmount: 15000,
+    avgPrice: 12.5,
+    purchaseCount: 5,
+    mainSupplier: '娣卞湷鏅鸿兘璁惧鏈夐檺鍏徃',
+    lastPurchaseDate: '2024-12-03'
+  }
+])
+
+// 渚涘簲鍟嗕緵璐ф眹鎬昏〃鏁版嵁
+const supplierSummaryData = ref([
+  {
+    supplierCode: 'SUP001',
+    supplierName: '姹熻嫃鍗庤仈鐢靛瓙绉戞妧鏈夐檺鍏徃',
+    contactPerson: '寮犵粡鐞�',
+    phone: '0512-88888888',
+    orderCount: 45,
+    supplyAmount: 850000,
+    paidAmount: 680000,
+    unpaidAmount: 170000,
+    onTimeRate: 95,
+    qualityRating: 4.5,
+    status: 'active'
+  },
+  {
+    supplierCode: 'SUP002',
+    supplierName: '涓婃捣绮惧瘑鏈烘鍒堕�犳湁闄愬叕鍙�',
+    contactPerson: '鏉庢��',
+    phone: '021-66666666',
+    orderCount: 32,
+    supplyAmount: 1200000,
+    paidAmount: 900000,
+    unpaidAmount: 300000,
+    onTimeRate: 88,
+    qualityRating: 4.2,
+    status: 'active'
+  },
+  {
+    supplierCode: 'SUP003',
+    supplierName: '娣卞湷鏅鸿兘璁惧鏈夐檺鍏徃',
+    contactPerson: '鐜嬪伐绋嬪笀',
+    phone: '0755-77777777',
+    orderCount: 28,
+    supplyAmount: 680000,
+    paidAmount: 400000,
+    unpaidAmount: 280000,
+    onTimeRate: 92,
+    qualityRating: 4.3,
+    status: 'active'
+  },
+  {
+    supplierCode: 'SUP004',
+    supplierName: '鍖椾含鏂版潗鏂欑鎶�鏈夐檺鍏徃',
+    contactPerson: '闄堝崥澹�',
+    phone: '010-55555555',
+    orderCount: 18,
+    supplyAmount: 320000,
+    paidAmount: 250000,
+    unpaidAmount: 70000,
+    onTimeRate: 85,
+    qualityRating: 4.0,
+    status: 'active'
+  },
+  {
+    supplierCode: 'SUP005',
+    supplierName: '骞垮窞鐢靛瓙鍏冨櫒浠舵湁闄愬叕鍙�',
+    contactPerson: '鍒樼粡鐞�',
+    phone: '020-44444444',
+    orderCount: 22,
+    supplyAmount: 480000,
+    paidAmount: 200000,
+    unpaidAmount: 280000,
+    onTimeRate: 78,
+    qualityRating: 3.8,
+    status: 'warning'
+  }
+])
+
+// 鏂规硶
+const handleReportChange = (tabName) => {
+  activeReport.value = tabName
+  handleSearch()
+}
+
+const handleSearch = () => {
+  loading.value = true
+  // 妯℃嫙API璋冪敤
+  setTimeout(() => {
+    loading.value = false
+    ElMessage.success('鏌ヨ瀹屾垚')
+  }, 1000)
+}
+
+const resetSearch = () => {
+  Object.assign(searchForm, {
+    dateRange: [],
+    supplierId: '',
+    categoryId: ''
+  })
+  handleSearch()
+}
+
+const exportReport = () => {
+  ElMessage.success('瀵煎嚭鍔熻兘寮�鍙戜腑...')
+}
+
+// 鐘舵�佺浉鍏虫柟娉�
+const getStatusType = (status) => {
+  const statusMap = {
+    completed: 'success',
+    partial: 'warning',
+    pending: 'info'
+  }
+  return statusMap[status] || 'info'
+}
+
+const getStatusText = (status) => {
+  const statusMap = {
+    completed: '宸插畬鎴�',
+    partial: '閮ㄥ垎瀹屾垚',
+    pending: '寰呮墽琛�'
+  }
+  return statusMap[status] || '鏈煡'
+}
+
+const getReceiptStatusType = (status) => {
+  const statusMap = {
+    completed: 'success',
+    partial: 'warning',
+    pending: 'info'
+  }
+  return statusMap[status] || 'info'
+}
+
+const getReceiptStatusText = (status) => {
+  const statusMap = {
+    completed: '宸叉敹璐�',
+    partial: '閮ㄥ垎鏀惰揣',
+    pending: '寰呮敹璐�'
+  }
+  return statusMap[status] || '鏈煡'
+}
+
+const getSupplierStatusType = (status) => {
+  const statusMap = {
+    active: 'success',
+    warning: 'warning',
+    inactive: 'info'
+  }
+  return statusMap[status] || 'info'
+}
+
+const getSupplierStatusText = (status) => {
+  const statusMap = {
+    active: '姝e父鍚堜綔',
+    warning: '闇�鍏虫敞',
+    inactive: '鏆傚仠鍚堜綔'
+  }
+  return statusMap[status] || '鏈煡'
+}
+
+onMounted(() => {
+  // 璁剧疆榛樿鏃堕棿鑼冨洿涓烘渶杩�30澶�
+  const endDate = new Date()
+  const startDate = new Date()
+  startDate.setDate(startDate.getDate() - 30)
+  
+  searchForm.dateRange = [
+    startDate.toISOString().split('T')[0],
+    endDate.toISOString().split('T')[0]
+  ]
+})
+</script>
+
+<style scoped>
+.app-container {
+  padding: 20px;
+  background-color: #f5f7fa;
+  min-height: 100vh;
+}
+
+.page-header {
+  text-align: center;
+  margin-bottom: 20px;
+  padding: 20px;
+  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+  border-radius: 10px;
+  color: white;
+}
+
+.page-header h2 {
+  margin: 0 0 10px 0;
+  font-size: 28px;
+  font-weight: 600;
+}
+
+.page-header p {
+  margin: 0;
+  font-size: 16px;
+  opacity: 0.9;
+}
+
+.report-selector {
+  margin-bottom: 20px;
+  border-radius: 8px;
+}
+
+.tab-label {
+  display: flex;
+  align-items: center;
+  gap: 8px;
+}
+
+.search-card {
+  margin-bottom: 20px;
+  border-radius: 8px;
+}
+
+.search-form {
+  margin-bottom: 0;
+}
+
+.report-content {
+  border-radius: 8px;
+}
+
+.report-section {
+  min-height: 400px;
+}
+
+.section-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  margin-bottom: 20px;
+  padding-bottom: 15px;
+  border-bottom: 2px solid #e4e7ed;
+}
+
+.section-header h3 {
+  margin: 0;
+  font-size: 20px;
+  font-weight: 600;
+  color: #303133;
+}
+
+.summary-stats {
+  display: flex;
+  gap: 30px;
+}
+
+.stat-item {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+}
+
+.stat-label {
+  font-size: 14px;
+  color: #606266;
+  margin-bottom: 5px;
+}
+
+.stat-value {
+  font-size: 18px;
+  font-weight: 600;
+  color: #409EFF;
+}
+
+.delay-text {
+  color: #F56C6C;
+  font-weight: 600;
+}
+
+:deep(.el-table) {
+  border-radius: 8px;
+  overflow: hidden;
+}
+
+:deep(.el-table th) {
+  background-color: #f8f9fa;
+  color: #606266;
+  font-weight: 600;
+}
+
+:deep(.el-table--striped .el-table__body tr.el-table__row--striped td) {
+  background-color: #fafafa;
+}
+
+:deep(.el-tabs__header) {
+  margin-bottom: 0;
+}
+
+:deep(.el-tabs__nav-wrap) {
+  padding: 0 20px;
+}
+
+:deep(.el-tabs__item) {
+  font-size: 16px;
+  font-weight: 500;
+}
+
+:deep(.el-tabs__item.is-active) {
+  color: #409EFF;
+}
+
+:deep(.el-rate) {
+  display: flex;
+  align-items: center;
+}
+
+:deep(.el-rate__text) {
+  margin-left: 8px;
+  font-size: 14px;
+  color: #606266;
+}
+</style>
diff --git a/src/views/procurementManagement/returnManagement/index.vue b/src/views/procurementManagement/returnManagement/index.vue
index d86e524..2a54083 100644
--- a/src/views/procurementManagement/returnManagement/index.vue
+++ b/src/views/procurementManagement/returnManagement/index.vue
@@ -21,7 +21,6 @@
     <el-card class="table-card" shadow="never">
       <div class="table-header">
         <el-button type="primary" @click="openDialog('add')">鏂板閫�璐у崟</el-button>
-        <el-button type="success" @click="handleBatchApprove">鎵归噺瀹℃牳</el-button>
         <el-button type="danger" @click="handleBatchDelete">鎵归噺鍒犻櫎</el-button>
       </div>
 
@@ -42,9 +41,6 @@
             <el-tag :type="getStatusType(row.status)">{{ getStatusText(row.status) }}</el-tag>
           </template>
         </el-table-column>
-        <el-table-column label="閫�璐ч噾棰�" prop="returnAmount" width="120">
-          <template #default="{ row }">楼{{ row.returnAmount.toFixed(2) }}</template>
-        </el-table-column>
         <el-table-column label="鍒涘缓鏃堕棿" prop="createTime" width="180" />
         <el-table-column label="鎿嶄綔" width="200" align="center">
           <template #default="{ row }">
@@ -54,6 +50,14 @@
           </template>
         </el-table-column>
       </el-table>
+      <!-- 鍒嗛〉 -->
+      <pagination
+          :total="total"
+          layout="total, sizes, prev, pager, next, jumper"
+          :page="pagination.current"
+          :limit="pagination.size"
+          @pagination="handleCurrentChange"
+      />
     </el-card>
 
     <el-dialog v-model="dialogVisible" :title="dialogType === 'add' ? '鏂板閫�璐у崟' : '缂栬緫閫�璐у崟'" width="600px">
@@ -65,7 +69,9 @@
           </el-select>
         </el-form-item>
         <el-form-item label="鍏宠仈鍗曞彿">
-          <el-input v-model="formData.relatedNo" placeholder="璇疯緭鍏ュ叧鑱斿崟鍙�" />
+          <el-select v-model="formData.relatedNo" placeholder="璇烽�夋嫨鍏宠仈鍗曞彿" style="width: 100%">
+            <el-option v-for="item in onList" :key="item.arrivalNo" :label="item.arrivalNo" :value="item.arrivalNo" />
+          </el-select>
         </el-form-item>
         <el-form-item label="渚涘簲鍟嗗悕绉�">
           <el-input v-model="formData.supplierName" placeholder="璇疯緭鍏ヤ緵搴斿晢鍚嶇О" />
@@ -90,13 +96,49 @@
 </template>
 
 <script setup>
-import { ref, reactive } from 'vue'
+import { ref, reactive,onMounted } from 'vue'
 import { ElMessage, ElMessageBox } from 'element-plus'
+import Pagination from '@/components/PIMTable/Pagination.vue'
+import {listPage,add,update,del} from "@/api/procurementManagement/returnManagement.js"
+import {listPageCopy} from "@/api/procurementManagement/arrivalManagement.js"
+
+onMounted(() => {
+  getList()
+  list()
+})
+const onList = ref([])
+const list = () =>{
+  listPageCopy({current:-1}).then(res=>{
+    if(res.code === 200){
+      onList.value = res.data.records
+    }
+  })
+}
+const tableData = ref([])
+const getList = () => {
+  loading.value = true
+  listPage({...searchForm,...pagination}).then(res =>{
+    if(res.code === 200){
+      tableData.value = res.data.records
+      console.log(tableData.value)
+      total.value = res.data.total
+      loading.value = false
+    }
+  })
+}
 
 const loading = ref(false)
 const dialogVisible = ref(false)
 const dialogType = ref('add')
 const selectedRows = ref([])
+
+
+const pagination = reactive({
+  current: 1,
+  size: 10
+})
+
+const total = ref(0)
 
 const searchForm = reactive({
   returnNo: '',
@@ -108,25 +150,9 @@
   relatedNo: '',
   supplierName: '',
   returnReason: '',
-  remark: ''
+  remark: '',
+  status: ''
 })
-
-const mockData = [
-  {
-    id: 1,
-    returnNo: 'RT20241201001',
-    relatedNo: 'PO20241201001',
-    returnType: 'purchase',
-    supplierName: '渚涘簲鍟咥',
-    status: 'approved',
-    returnAmount: 500.00,
-    createTime: '2025-12-01 17:30:00',
-    returnReason: '璐ㄩ噺闂',
-    remark: '鍟嗗搧瀛樺湪璐ㄩ噺闂'
-  }
-]
-
-const tableData = ref([...mockData])
 
 const getReturnTypeText = (type) => {
   const typeMap = { purchase: '閲囪喘閫�璐�', quality: '璐ㄦ閫�璐�' }
@@ -145,7 +171,7 @@
 
 const handleSearch = () => {
   loading.value = true
-  setTimeout(() => { loading.value = false }, 500)
+  getList()
 }
 
 const resetSearch = () => {
@@ -154,13 +180,15 @@
 
 const openDialog = (type, row = {}) => {
   dialogType.value = type
+  obj.id = row.id
   if (type === 'edit' && row.id) {
     Object.assign(formData, {
       returnType: row.returnType,
       relatedNo: row.relatedNo,
       supplierName: row.supplierName,
       returnReason: row.returnReason,
-      remark: row.remark
+      remark: row.remark,
+      status: row.status
     })
   } else {
     Object.assign(formData, {
@@ -168,35 +196,43 @@
       relatedNo: '',
       supplierName: '',
       returnReason: '',
-      remark: ''
+      remark: '',
+      status: 'pending'
     })
   }
   dialogVisible.value = true
 }
-
+const obj = reactive({
+  id: ''
+})
 const handleSubmit = () => {
   if (dialogType.value === 'add') {
-    const newReturn = {
-      id: Date.now(),
-      returnNo: `RT${Date.now()}`,
-      relatedNo: formData.relatedNo,
-      returnType: formData.returnType,
-      supplierName: formData.supplierName,
-      status: 'pending',
-      returnAmount: 0,
-      createTime: new Date().toLocaleString(),
-      returnReason: formData.returnReason,
-      remark: formData.remark
+    formData.status = 'pending'
+   add(formData).then(res => {
+    if(res.code === 200){
+      ElMessage.success('鏂板鎴愬姛')
+      getList()
     }
-    tableData.value.unshift(newReturn)
-    ElMessage.success('鏂板鎴愬姛')
+  })
+  }else{
+    update({...formData,...obj}).then(res => {
+      if(res.code === 200){
+        ElMessage.success('淇敼鎴愬姛')
+        getList()
+      }
+    })
   }
   dialogVisible.value = false
 }
 
 const handleApprove = (row) => {
   row.status = 'approved'
-  ElMessage.success('瀹℃牳閫氳繃')
+  update(row).then(res => {
+    if(res.code === 200){
+      ElMessage.success('瀹℃牳鎴愬姛')
+      getList()
+    }
+  })
 }
 
 const handleDelete = (row) => {
@@ -205,20 +241,24 @@
     cancelButtonText: '鍙栨秷',
     type: 'warning'
   }).then(() => {
-    const index = tableData.value.findIndex(item => item.id === row.id)
-    if (index !== -1) {
-      tableData.value.splice(index, 1)
-      ElMessage.success('鍒犻櫎鎴愬姛')
-    }
+    let ids = [row.id]
+    del(ids).then(res => {
+      if(res.code === 200){
+        ElMessage.success('鍒犻櫎鎴愬姛')
+        getList()
+      }
+    })
   })
 }
 
-const handleBatchApprove = () => {
-  ElMessage.success('鎵归噺瀹℃牳鎴愬姛')
-}
-
 const handleBatchDelete = () => {
-  ElMessage.success('鎵归噺鍒犻櫎鎴愬姛')
+  let ids = selectedRows.value.map(item => item.id)
+  del(ids).then(res => {
+    if(res.code === 200){
+      ElMessage.success('鎵归噺鍒犻櫎鎴愬姛')
+      getList()
+    }
+  })
 }
 
 const handleSelectionChange = (rows) => {
diff --git a/src/views/reportAnalysis/dataDashboard/index.vue b/src/views/reportAnalysis/dataDashboard/index.vue
index 6fe840b..9848898 100644
--- a/src/views/reportAnalysis/dataDashboard/index.vue
+++ b/src/views/reportAnalysis/dataDashboard/index.vue
@@ -12,6 +12,7 @@
 
       <!-- 椤堕儴鏍囬鏍� -->
       <div class="dashboard-header">
+        <div class="factory-name">{{ userStore.currentFactoryName }}</div>
       </div>
 
       <!-- 涓昏鍐呭鍖哄煙 -->
@@ -241,6 +242,7 @@
 import { ref, onMounted, onBeforeUnmount, nextTick } from 'vue'
 import autofit from 'autofit.js'
 import Echarts from "@/components/Echarts/echarts.vue";
+import useUserStore from '@/store/modules/user'
 import {
 	analysisCustomerContractAmounts, getAmountHalfYear,
 	homeTodos,
@@ -258,6 +260,9 @@
 
 // 鍏ㄥ睆鐩稿叧鐘舵��
 const isFullscreen = ref(false);
+
+// 鐢ㄦ埛store
+const userStore = useUserStore()
 
 // 鍝嶅簲寮忔暟鎹�
 const currentTime = ref('')
@@ -915,7 +920,7 @@
   // 浣跨敤nextTick纭繚DOM瀹屽叏娓叉煋鍚庡啀鍒濆鍖栧浘琛�
   nextTick(() => {
     // 鍒濆鍖朼utofit鑷�傚簲
-    autofit.init({ dh: 1440, dw: 2560, el: '.data-dashboard', resize: true }, false)
+    autofit.init({ dh: 1080, dw: 1920, el: '.data-dashboard', resize: true }, false)
     
     // 娣诲姞鑷姩婊氬姩鍔ㄧ敾鏁堟灉 - 瀹㈡埛淇℃伅鍒楄〃
     const contractList = refContractList.value
@@ -1044,7 +1049,6 @@
   position: relative;
   width: 100%;
 	height: 100%;
-  overflow: hidden;
 	background-image: url("@/assets/BI/backImage@2x.png");
 	background-size: cover;
 	background-position: center;
@@ -1090,6 +1094,17 @@
 	background-size: cover;
 	background-position: center;
 	background-repeat: no-repeat;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+}
+
+.factory-name {
+  font-weight: 600;
+font-size: 52px;
+color: #FFFFFF;
+top: 32px;
+position: absolute;
 }
 
 .fullscreen-btn {
diff --git a/src/views/salesManagement/paymentShipping/index.vue b/src/views/salesManagement/paymentShipping/index.vue
index ae59d08..0bcfd87 100644
--- a/src/views/salesManagement/paymentShipping/index.vue
+++ b/src/views/salesManagement/paymentShipping/index.vue
@@ -91,8 +91,8 @@
       <pagination
         :total="total"
         layout="total, sizes, prev, pager, next, jumper"
-        :page="pagination.currentPage"
-        :limit="pagination.pageSize"
+        :page="pagination.current"
+        :limit="pagination.size"
         @pagination="handleCurrentChange"
       />
     </el-card>
@@ -496,8 +496,8 @@
 }
 
 const handleCurrentChange = (val) => {
-  pagination.currentPage = val.page
-  pagination.pageSize = val.limit
+  pagination.current = val.page
+  pagination.size = val.limit
 }
 </script>
 

--
Gitblit v1.9.3