From bc278f02a34cdce5be02e42b26fe9e1bc6a0d6e6 Mon Sep 17 00:00:00 2001
From: maven <2163098428@qq.com>
Date: 星期四, 18 九月 2025 13:39:39 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/dev' into dev

---
 src/views/collaborativeApproval/notificationManagement/summary/index.vue         |  403 ++++
 multiple/config.json                                                             |   10 
 src/api/publicApi/index.js                                                       |   42 
 src/views/collaborativeApproval/notificationManagement/meetSetting/index.vue     |  306 +++
 src/views/procurementManagement/index.vue                                        |   42 
 src/views/salesManagement/salesLedger/index.vue                                  |  646 ++++++
 multiple/assets/favicon/CMNYico.ico                                              |    0 
 src/views/collaborativeApproval/notificationManagement/meetApplication/index.vue |  398 +++
 src/api/inspectionManagement/index.js                                            |   61 
 src/views/inventoryManagement/dispatchLog/index.vue                              | 1047 +++++-----
 multiple/assets/logo/CMNYLogo.png                                                |    0 
 src/api/salesManagement/salesQuotation.js                                        |  112 +
 src/views/collaborativeApproval/notificationManagement/meetExamine/index.vue     |  418 ++++
 src/views/procurementManagement/procurementReport/index.vue                      |   31 
 src/views/collaborativeApproval/meetingBoard/index.vue                           |  228 -
 src/api/inspectionUpload/index.js                                                |   43 
 src/views/salesManagement/salesQuotation/index.vue                               |  604 ++++++
 src/api/collaborativeApproval/meeting.js                                         |  118 +
 src/router/index.js                                                              |  198 -
 src/views/collaborativeApproval/notificationManagement/meetIndex/index.vue       |  371 +++
 src/assets/images/video.png                                                      |    0 
 src/views/collaborativeApproval/notificationManagement/meetPublish/index.vue     |  416 ++++
 package.json                                                                     |    2 
 src/views/collaborativeApproval/notificationManagement/meetDraft/index.vue       |  495 ++++
 src/views/inspectionManagement/index.vue                                         |    6 
 25 files changed, 5,164 insertions(+), 833 deletions(-)

diff --git a/multiple/assets/favicon/CMNYico.ico b/multiple/assets/favicon/CMNYico.ico
new file mode 100644
index 0000000..4536de7
--- /dev/null
+++ b/multiple/assets/favicon/CMNYico.ico
Binary files differ
diff --git a/multiple/assets/logo/CMNYLogo.png b/multiple/assets/logo/CMNYLogo.png
new file mode 100644
index 0000000..202664a
--- /dev/null
+++ b/multiple/assets/logo/CMNYLogo.png
Binary files differ
diff --git a/multiple/config.json b/multiple/config.json
index 738b52e..a1f5164 100644
--- a/multiple/config.json
+++ b/multiple/config.json
@@ -167,6 +167,16 @@
     "logo": "logo/JSYNYLogo.png",
     "favicon": "favicon/JSYNYico.ico"
   },
+  "CMNY": {
+    "env": {
+      "VITE_APP_TITLE": "鍒涢摥鑳芥簮淇℃伅绠$悊绯荤粺",
+      "VITE_BASE_API": "http://114.132.189.42:9088",
+      "VITE_JAVA_API": "http://114.132.189.42:9087"
+    },
+    "screen": "screen/DHDCView.png",
+    "logo": "logo/CMNYLogo.png",
+    "favicon": "favicon/CMNYico.ico"
+  },
   "screen": "/src/assets/images/login-background.png",
   "logo": "/src/assets/logo/logo.png",
   "favicon": "/public/favicon.ico"
diff --git a/package.json b/package.json
index b57034d..e80e1e7 100644
--- a/package.json
+++ b/package.json
@@ -34,11 +34,13 @@
     "jsencrypt": "3.3.2",
     "nprogress": "0.2.0",
     "pinia": "2.1.7",
+    "print-js": "^1.6.0",
     "qrcode": "^1.5.4",
     "sortablejs": "^1.15.6",
     "splitpanes": "3.1.5",
     "vue": "3.4.31",
     "vue-cropper": "1.1.1",
+    "vue-easy-lightbox": "^1.19.0",
     "vue-esign": "^1.1.4",
     "vue-router": "4.4.0",
     "vuedraggable": "4.1.0"
diff --git a/src/api/collaborativeApproval/meeting.js b/src/api/collaborativeApproval/meeting.js
new file mode 100644
index 0000000..20df8b1
--- /dev/null
+++ b/src/api/collaborativeApproval/meeting.js
@@ -0,0 +1,118 @@
+import request from "@/utils/request";
+
+export function getMeetingRoomList(data) {
+    return request({
+        url: "/meeting/roomList",
+        method: "post",
+        data: data,
+    });
+}
+
+export function saveRoom(data) {
+    return request({
+        url: "/meeting/saveRoom",
+        method: "post",
+        data: data,
+    });
+}
+
+export function delRoom(id) {
+    return request({
+        url: "/meeting/delRoom/"+id,
+        method: "delete",
+    });
+}
+
+export function getRoomEnum() {
+    return request({
+        url: "/meeting/roomEnum",
+        method: "get",
+    });
+}
+
+export function getDraftList(data){
+    return request({
+        url: "/meeting/draftList",
+        method: "post",
+        data: data,
+    });
+}
+
+export function saveDraft(data) {
+    return request({
+        url: "/meeting/saveDraft",
+        method: "post",
+        data: data,
+    });
+}
+
+export function delDraft(id) {
+    return request({
+        url: "/meeting/delDraft/"+id,
+        method: "delete",
+    });
+}
+
+export function saveMeetingApplication(data){
+    return request({
+        url: "/meeting/saveMeetingApplication",
+        method: "post",
+        data: data,
+    });
+}
+
+export function getExamineList(data) {
+    return request({
+        url: "/meeting/applicationList",
+        method: "post",
+        data: data,
+    });
+}
+
+
+export function getMeetingUseList(data){
+    return request({
+        url: "/meeting/meetingUseList",
+        method: "post",
+        data: data,
+    });
+}
+
+export function getMeetingPublish(data){
+    return request({
+        url: "/meeting/meetingPublishList",
+        method: "post",
+        data: data
+    });
+}
+
+
+export function getMeetingMinutesByMeetingId(id){
+    return request({
+        url: "/meeting/getMeetingMinutesByMeetingId/"+id,
+        method: "get",
+    });
+}
+
+export function saveMeetingMinutes(data){
+    return request({
+        url: "/meeting/saveMeetingMinutes",
+        method: "post",
+        data: data,
+    });
+}
+
+
+export function getMeetSummary(){
+    return request({
+        url: "/meeting/getMeetSummary",
+        method: "get",
+    });
+}
+
+export function getMeetSummaryItems(){
+    return request({
+        url: "/meeting/getMeetSummaryItems",
+        method: "get",
+    });
+}
diff --git a/src/api/inspectionManagement/index.js b/src/api/inspectionManagement/index.js
new file mode 100644
index 0000000..d0c444a
--- /dev/null
+++ b/src/api/inspectionManagement/index.js
@@ -0,0 +1,61 @@
+// 宸℃绠$悊
+import request from '@/utils/request'
+
+// 宸℃浠诲姟琛ㄨ〃鏌ヨ
+export function inspectionTaskList(query) {
+    return request({
+        url: '/inspectionTask/list',
+        method: 'get',
+        params: query
+    })
+}
+// 宸℃浠诲姟琛ㄦ柊澧炰慨鏀�
+export function addOrEditInspectionTask(query) {
+    return request({
+        url: '/inspectionTask/addOrEditInspectionTask',
+        method: 'post',
+        data: query
+    })
+}
+// 宸℃浠诲姟琛ㄥ垹闄�
+export function delInspectionTask(query) {
+    return request({
+        url: '/inspectionTask/delInspectionTask',
+        method: 'delete',
+        data: query
+    })
+}
+// 瀹氭椂宸℃浠诲姟琛ㄥ垹闄�
+export function delTimingTask(query) {
+    return request({
+        url: '/timingTask/delTimingTask',
+        method: 'delete',
+        data: query
+    })
+}
+
+// /inspectionTask/addOrEditInspectionTask
+// 宸℃涓婁紶
+export function uploadInspectionTask(query) {
+    return request({
+        url: '/inspectionTask/addOrEditInspectionTask',
+        method: 'post',
+        data: query
+    })
+}
+// 瀹氭椂宸℃浠诲姟琛ㄦ煡璇�
+export function timingTaskList(query) {
+    return request({
+        url: '/timingTask/list',
+        method: 'get',
+        params: query
+    })
+}
+// 瀹氭椂宸℃浠诲姟琛ㄦ柊澧炰慨鏀�
+export function addOrEditTimingTask(query) {
+    return request({
+        url: '/timingTask/addOrEditTimingTask',
+        method: 'post',
+        data: query
+    })
+}
\ No newline at end of file
diff --git a/src/api/inspectionUpload/index.js b/src/api/inspectionUpload/index.js
new file mode 100644
index 0000000..0d954e2
--- /dev/null
+++ b/src/api/inspectionUpload/index.js
@@ -0,0 +1,43 @@
+// 宸℃涓婁紶
+import request from '@/utils/request'
+
+// 浜岀淮鐮佺鐞嗚〃鏌ヨ
+export function qrCodeList(query) {
+    return request({
+        url: '/qrCode/list',
+        method: 'get',
+        params: query
+    })
+}
+// 浜岀淮鐮佹壂鐮佽褰曡〃鏌ヨ
+export function qrCodeScanRecordList(query) {
+    return request({
+        url: '/qrCodeScanRecord/list',
+        method: 'get',
+        params: query
+    })
+}
+// 浜岀淮鐮佺鐞嗚〃鏂板淇敼
+export function addOrEditQrCode(query) {
+    return request({
+        url: '/qrCode/addOrEditQrCode',
+        method: 'post',
+        data: query
+    })
+}
+// 浜岀淮鐮佹壂鐮佽褰曡〃鏂板淇敼
+export function addOrEditQrCodeRecord(query) {
+    return request({
+        url: '/qrCodeScanRecord/addOrEditQrCodeRecord',
+        method: 'post',
+        data: query
+    })
+}
+// 浜岀淮鐮佹壂鐮佽褰曡〃鏂板淇敼
+export function delQrCode(query) {
+    return request({
+        url: '/qrCode/delQrCode',
+        method: 'delete',
+        data: query
+    })
+}
\ No newline at end of file
diff --git a/src/api/publicApi/index.js b/src/api/publicApi/index.js
new file mode 100644
index 0000000..8022592
--- /dev/null
+++ b/src/api/publicApi/index.js
@@ -0,0 +1,42 @@
+// 鏂囨。绠$悊
+import request from '@/utils/request'
+
+
+// /system/user/listAll
+// 鏌ヨ鎵�鏈夌敤鎴峰垪琛�
+export function userListAll() {
+  return request({
+    url: '/system/user/listAll',
+    method: 'get'
+  })
+}
+
+// /equipmentManagement/equipmentList
+// 鏌ヨ璁惧鍒楄〃
+export function getEquipmentList(query) {
+  return request({
+    url: '/equipmentManagement/equipmentList',
+    method: 'get',
+    params: query
+  })
+}
+
+// /coalInfo/coalInfoList
+// 鏌ヨ鐓ょ鍒楄〃
+export function getCoalInfoList(query) {
+    return request({
+        url: '/coalInfo/coalInfoList',
+        method: 'get',
+        params: query
+    })
+}
+
+// /coalField/coalFieldList
+// 鏌ヨ鐓よ川瀛楁鍒楄〃
+export function getCoalFieldList(query) {
+    return request({
+        url: '/coalField/coalFieldList',
+        method: 'get',
+        params: query
+    })
+}
\ No newline at end of file
diff --git a/src/api/salesManagement/salesQuotation.js b/src/api/salesManagement/salesQuotation.js
new file mode 100644
index 0000000..aae54cb
--- /dev/null
+++ b/src/api/salesManagement/salesQuotation.js
@@ -0,0 +1,112 @@
+// 閿�鍞姤浠烽〉闈㈡帴鍙�
+import request from "@/utils/request";
+
+// 鍒嗛〉鏌ヨ鎶ヤ环鍗曞垪琛�
+export function quotationList(query) {
+  return request({
+    url: "/sales/quotation/list",
+    method: "get",
+    params: query,
+  });
+}
+
+// 鏌ヨ鎶ヤ环鍗曡鎯�
+export function getQuotationDetail(query) {
+  return request({
+    url: "/sales/quotation/detail",
+    method: "get",
+    params: query,
+  });
+}
+
+// 鏂板鎶ヤ环鍗�
+export function addQuotation(data) {
+  return request({
+    url: "/sales/quotation/add",
+    method: "post",
+    data: data,
+  });
+}
+
+// 淇敼鎶ヤ环鍗�
+export function updateQuotation(data) {
+  return request({
+    url: "/sales/quotation/update",
+    method: "put",
+    data: data,
+  });
+}
+
+// 鍒犻櫎鎶ヤ环鍗�
+export function deleteQuotation(query) {
+  return request({
+    url: "/sales/quotation/delete",
+    method: "delete",
+    data: query,
+  });
+}
+
+// 鍙戦�佹姤浠峰崟
+export function sendQuotation(data) {
+  return request({
+    url: "/sales/quotation/send",
+    method: "post",
+    data: data,
+  });
+}
+
+// 鎶ヤ环鍗曡浆璁㈠崟
+export function convertToOrder(data) {
+  return request({
+    url: "/sales/quotation/convertToOrder",
+    method: "post",
+    data: data,
+  });
+}
+
+// 鏌ヨ瀹㈡埛鍒楄〃
+export function getCustomerList(query) {
+  return request({
+    url: "/basic/customer/list",
+    method: "get",
+    params: query,
+  });
+}
+
+// 鏌ヨ浜у搧鍒楄〃
+export function getProductList(query) {
+  return request({
+    url: "/basic/product/list",
+    method: "get",
+    params: query,
+  });
+}
+
+// 鏌ヨ涓氬姟鍛樺垪琛�
+export function getSalespersonList(query) {
+  return request({
+    url: "/system/user/salespersonList",
+    method: "get",
+    params: query,
+  });
+}
+
+// 瀵煎嚭鎶ヤ环鍗�
+export function exportQuotation(query) {
+  return request({
+    url: "/sales/quotation/export",
+    method: "get",
+    params: query,
+    responseType: "blob",
+  });
+}
+
+// 鎵撳嵃鎶ヤ环鍗�
+export function printQuotation(query) {
+  return request({
+    url: "/sales/quotation/print",
+    method: "get",
+    params: query,
+    responseType: "blob",
+  });
+}
diff --git a/src/assets/images/video.png b/src/assets/images/video.png
new file mode 100644
index 0000000..7a90175
--- /dev/null
+++ b/src/assets/images/video.png
Binary files differ
diff --git a/src/router/index.js b/src/router/index.js
index 437e523..9c5a968 100644
--- a/src/router/index.js
+++ b/src/router/index.js
@@ -1,6 +1,6 @@
-import { createWebHistory, createRouter } from 'vue-router'
+import { createWebHistory, createRouter } from "vue-router";
 /* Layout */
-import Layout from '@/layout'
+import Layout from "@/layout";
 
 /**
  * Note: 璺敱閰嶇疆椤�
@@ -16,85 +16,80 @@
  * roles: ['admin', 'common']       // 璁块棶璺敱鐨勮鑹叉潈闄�
  * permissions: ['a:a:a', 'b:b:b']  // 璁块棶璺敱鐨勮彍鍗曟潈闄�
  * meta : {
-    noCache: true                   // 濡傛灉璁剧疆涓簍rue锛屽垯涓嶄細琚� <keep-alive> 缂撳瓨(榛樿 false)
-    title: 'title'                  // 璁剧疆璇ヨ矾鐢卞湪渚ц竟鏍忓拰闈㈠寘灞戜腑灞曠ず鐨勫悕瀛�
-    icon: 'svg-name'                // 璁剧疆璇ヨ矾鐢辩殑鍥炬爣锛屽搴旇矾寰剆rc/assets/icons/svg
-    breadcrumb: false               // 濡傛灉璁剧疆涓篺alse锛屽垯涓嶄細鍦╞readcrumb闈㈠寘灞戜腑鏄剧ず
-    activeMenu: '/system/user'      // 褰撹矾鐢辫缃簡璇ュ睘鎬э紝鍒欎細楂樹寒鐩稿搴旂殑渚ц竟鏍忋��
-  }
+ noCache: true                   // 濡傛灉璁剧疆涓簍rue锛屽垯涓嶄細琚� <keep-alive> 缂撳瓨(榛樿 false)
+ title: 'title'                  // 璁剧疆璇ヨ矾鐢卞湪渚ц竟鏍忓拰闈㈠寘灞戜腑灞曠ず鐨勫悕瀛�
+ icon: 'svg-name'                // 璁剧疆璇ヨ矾鐢辩殑鍥炬爣锛屽搴旇矾寰剆rc/assets/icons/svg
+ breadcrumb: false               // 濡傛灉璁剧疆涓篺alse锛屽垯涓嶄細鍦╞readcrumb闈㈠寘灞戜腑鏄剧ず
+ activeMenu: '/system/user'      // 褰撹矾鐢辫缃簡璇ュ睘鎬э紝鍒欎細楂樹寒鐩稿搴旂殑渚ц竟鏍忋��
+ }
  */
 
 // 鍏叡璺敱
 export const constantRoutes = [
   {
-    path: '/redirect',
+    path: "/redirect",
     component: Layout,
     hidden: true,
     children: [
       {
-        path: '/redirect/:path(.*)',
-        component: () => import('@/views/redirect/index.vue')
-      }
-    ]
+        path: "/redirect/:path(.*)",
+        component: () => import("@/views/redirect/index.vue"),
+      },
+    ],
   },
   {
-    path: '/login',
-    component: () => import('@/views/login'),
-    hidden: true
-  },
-  {
-    path: "/callbacklccpn",
-    component: () => import("@/views/tideLogin.vue"),
+    path: "/login",
+    component: () => import("@/views/login"),
     hidden: true,
   },
   {
-    path: '/register',
-    component: () => import('@/views/register'),
-    hidden: true
+    path: "/register",
+    component: () => import("@/views/register"),
+    hidden: true,
   },
   {
     path: "/:pathMatch(.*)*",
-    component: () => import('@/views/error/404'),
-    hidden: true
+    component: () => import("@/views/error/404"),
+    hidden: true,
   },
   {
-    path: '/401',
-    component: () => import('@/views/error/401'),
-    hidden: true
+    path: "/401",
+    component: () => import("@/views/error/401"),
+    hidden: true,
   },
 
   {
-    path: '',
+    path: "",
     component: Layout,
-    redirect: '/index',
+    redirect: "/index",
     children: [
       {
-        path: '/index',
-        component: () => import('@/views/index'),
-        name: 'Index',
-        meta: { title: '棣栭〉', icon: 'dashboard', affix: true }
-      }
-    ]
+        path: "/index",
+        component: () => import("@/views/index"),
+        name: "Index",
+        meta: { title: "棣栭〉", icon: "dashboard", affix: true },
+      },
+    ],
   },
-  // {
-  //   path: '/main/MobileChat',
-  //   component: Layout,
-  //   redirect: '',
-  //   hidden: true,
-  //   children: [
-  //     {
-  //       path: '',
-  //       component: () => import('@/views/chatHome/chatHomeIndex/MobileChat'),
-  //       name: 'MobileChat',
-  //       meta: { title: 'AI瀵硅瘽', icon: 'dashboard', affix: true}
-  //     }
-  //   ]
-  // },
   {
-    path: '/user',
+    path: "/main/MobileChat",
+    component: Layout,
+    redirect: "",
+    hidden: true,
+    children: [
+      {
+        path: "",
+        component: () => import("@/views/chatHome/chatHomeIndex/MobileChat"),
+        name: "MobileChat",
+        meta: { title: "AI瀵硅瘽", icon: "dashboard", affix: true },
+      },
+    ],
+  },
+  {
+    path: "/user",
     component: Layout,
     hidden: true,
-    redirect: 'noredirect',
+    redirect: "noredirect",
     children: [
       {
         path: "profile",
@@ -111,98 +106,91 @@
     name: "DeviceInfo",
     meta: { title: "璁惧淇℃伅", icon: "monitor" },
   },
-  {
-    path: "/data-dashboard",
-    component: () => import("@/views/reportAnalysis/dataDashboard/index.vue"),
-    hidden: true,
-    name: "DataDashboard",
-    meta: { title: "鏁版嵁澶у睆", icon: "dashboard" },
-  },
 ];
 
 // 鍔ㄦ�佽矾鐢憋紝鍩轰簬鐢ㄦ埛鏉冮檺鍔ㄦ�佸幓鍔犺浇
 export const dynamicRoutes = [
   {
-    path: '/system/user-auth',
+    path: "/system/user-auth",
     component: Layout,
     hidden: true,
-    permissions: ['system:user:edit'],
+    permissions: ["system:user:edit"],
     children: [
       {
-        path: 'role/:userId(\\d+)',
-        component: () => import('@/views/system/user/authRole'),
-        name: 'AuthRole',
-        meta: { title: '鍒嗛厤瑙掕壊', activeMenu: '/system/user' }
-      }
-    ]
+        path: "role/:userId(\\d+)",
+        component: () => import("@/views/system/user/authRole"),
+        name: "AuthRole",
+        meta: { title: "鍒嗛厤瑙掕壊", activeMenu: "/system/user" },
+      },
+    ],
   },
   {
-    path: '/system/role-auth',
+    path: "/system/role-auth",
     component: Layout,
     hidden: true,
-    permissions: ['system:role:edit'],
+    permissions: ["system:role:edit"],
     children: [
       {
-        path: 'user/:roleId(\\d+)',
-        component: () => import('@/views/system/role/authUser'),
-        name: 'AuthUser',
-        meta: { title: '鍒嗛厤鐢ㄦ埛', activeMenu: '/system/role' }
-      }
-    ]
+        path: "user/:roleId(\\d+)",
+        component: () => import("@/views/system/role/authUser"),
+        name: "AuthUser",
+        meta: { title: "鍒嗛厤鐢ㄦ埛", activeMenu: "/system/role" },
+      },
+    ],
   },
   {
-    path: '/system/dict-data',
+    path: "/system/dict-data",
     component: Layout,
     hidden: true,
-    permissions: ['system:dict:list'],
+    permissions: ["system:dict:list"],
     children: [
       {
-        path: 'index/:dictId(\\d+)',
-        component: () => import('@/views/system/dict/data'),
-        name: 'Data',
-        meta: { title: '瀛楀吀鏁版嵁', activeMenu: '/system/dict' }
-      }
-    ]
+        path: "index/:dictId(\\d+)",
+        component: () => import("@/views/system/dict/data"),
+        name: "Data",
+        meta: { title: "瀛楀吀鏁版嵁", activeMenu: "/system/dict" },
+      },
+    ],
   },
   {
-    path: '/monitor/job-log',
+    path: "/monitor/job-log",
     component: Layout,
     hidden: true,
-    permissions: ['monitor:job:list'],
+    permissions: ["monitor:job:list"],
     children: [
       {
-        path: 'index/:jobId(\\d+)',
-        component: () => import('@/views/monitor/job/log'),
-        name: 'JobLog',
-        meta: { title: '璋冨害鏃ュ織', activeMenu: '/monitor/job' }
-      }
-    ]
+        path: "index/:jobId(\\d+)",
+        component: () => import("@/views/monitor/job/log"),
+        name: "JobLog",
+        meta: { title: "璋冨害鏃ュ織", activeMenu: "/monitor/job" },
+      },
+    ],
   },
   {
-    path: '/tool/gen-edit',
+    path: "/tool/gen-edit",
     component: Layout,
     hidden: true,
-    permissions: ['tool:gen:edit'],
+    permissions: ["tool:gen:edit"],
     children: [
       {
-        path: 'index/:tableId(\\d+)',
-        component: () => import('@/views/tool/gen/editTable'),
-        name: 'GenEdit',
-        meta: { title: '淇敼鐢熸垚閰嶇疆', activeMenu: '/tool/gen' }
-      }
-    ]
-  }
-]
+        path: "index/:tableId(\\d+)",
+        component: () => import("@/views/tool/gen/editTable"),
+        name: "GenEdit",
+        meta: { title: "淇敼鐢熸垚閰嶇疆", activeMenu: "/tool/gen" },
+      },
+    ],
+  },
+];
 
 const router = createRouter({
   history: createWebHistory(),
   routes: constantRoutes,
   scrollBehavior(to, from, savedPosition) {
     if (savedPosition) {
-      return savedPosition
+      return savedPosition;
     }
-    return { top: 0 }
+    return { top: 0 };
   },
-})
+});
 
-export default router
+export default router;
diff --git a/src/views/collaborativeApproval/meetingBoard/index.vue b/src/views/collaborativeApproval/meetingBoard/index.vue
index b6b803b..dfbb922 100644
--- a/src/views/collaborativeApproval/meetingBoard/index.vue
+++ b/src/views/collaborativeApproval/meetingBoard/index.vue
@@ -16,7 +16,7 @@
       </el-card>
       <el-card class="stat-card">
         <div class="stat-content">
-          <div class="stat-number">{{ stats.ongoing }}</div>
+          <div class="stat-number">{{ stats.underWay }}</div>
           <div class="stat-label">杩涜涓�</div>
         </div>
       </el-card>
@@ -28,7 +28,7 @@
       </el-card>
       <el-card class="stat-card">
         <div class="stat-content">
-          <div class="stat-number">{{ stats.upcoming }}</div>
+          <div class="stat-number">{{ stats.toStart }}</div>
           <div class="stat-label">鍗冲皢寮�濮�</div>
         </div>
       </el-card>
@@ -45,11 +45,11 @@
             </el-tag>
           </div>
           <div class="meeting-time">
-            <el-icon><Clock /></el-icon>
-            {{ formatTime(meeting.startTime) }} - {{ formatTime(meeting.endTime) }}
+             {{dayjs(meeting.startTime).format("YYYY-MM-DD")}}<el-icon><Clock /></el-icon>
+           {{ formatTime(meeting.startTime) }} - {{ formatTime(meeting.endTime) }}
           </div>
         </div>
-        
+
         <div class="meeting-info">
           <div class="info-item">
             <el-icon><Location /></el-icon>
@@ -66,79 +66,18 @@
         </div>
 
         <div class="meeting-agenda">
-          <h4>璁▼瀹夋帓</h4>
+          <h4>浼氳绾</h4>
           <div class="agenda-list">
-            <div 
-              v-for="(agenda, index) in meeting.agenda" 
-              :key="index"
-              class="agenda-item"
-              :class="{ 'active': agenda.status === 'active', 'completed': agenda.status === 'completed' }"
-            >
-              <span class="agenda-time">{{ agenda.time }}</span>
-              <span class="agenda-content">{{ agenda.content }}</span>
-              <el-tag 
-                :type="getAgendaStatusType(agenda.status)" 
-                size="small"
-              >
-                {{ getAgendaStatusText(agenda.status) }}
-              </el-tag>
+            <div class="editor-container">
+              <div
+                  v-html="meeting.content"
+              />
             </div>
           </div>
         </div>
-
-<!--        <div class="meeting-actions">-->
-<!--          <el-button type="primary" size="small" @click="joinMeeting(meeting)">-->
-<!--            鍔犲叆浼氳-->
-<!--          </el-button>-->
-<!--          <el-button type="info" size="small" @click="viewDetails(meeting)">-->
-<!--            鏌ョ湅璇︽儏-->
-<!--          </el-button>-->
-<!--          <el-button type="warning" size="small" @click="editMeeting(meeting)">-->
-<!--            缂栬緫-->
-<!--          </el-button>-->
-<!--        </div>-->
       </el-card>
     </div>
 
-    <!-- 鍒涘缓浼氳瀵硅瘽妗� -->
-    <el-dialog v-model="dialogVisible" title="鍒涘缓浼氳" width="600px">
-      <el-form :model="meetingForm" label-width="100px">
-        <el-form-item label="浼氳鏍囬">
-          <el-input v-model="meetingForm.title" placeholder="璇疯緭鍏ヤ細璁爣棰�" />
-        </el-form-item>
-        <el-form-item label="浼氳鏃堕棿">
-          <el-date-picker
-            v-model="meetingForm.timeRange"
-            type="datetimerange"
-            range-separator="鑷�"
-            start-placeholder="寮�濮嬫椂闂�"
-            end-placeholder="缁撴潫鏃堕棿"
-            format="YYYY-MM-DD HH:mm"
-            value-format="YYYY-MM-DD HH:mm:ss"
-          />
-        </el-form-item>
-        <el-form-item label="浼氳鍦扮偣">
-          <el-input v-model="meetingForm.location" placeholder="璇疯緭鍏ヤ細璁湴鐐�" />
-        </el-form-item>
-        <el-form-item label="涓绘寔浜�">
-          <el-input v-model="meetingForm.host" placeholder="璇疯緭鍏ヤ富鎸佷汉濮撳悕" />
-        </el-form-item>
-        <el-form-item label="浼氳鎻忚堪">
-          <el-input
-            v-model="meetingForm.description"
-            type="textarea"
-            :rows="3"
-            placeholder="璇疯緭鍏ヤ細璁弿杩�"
-          />
-        </el-form-item>
-      </el-form>
-      <template #footer>
-        <span class="dialog-footer">
-          <el-button @click="dialogVisible = false">鍙栨秷</el-button>
-          <el-button type="primary" @click="submitMeeting">纭畾</el-button>
-        </span>
-      </template>
-    </el-dialog>
   </div>
 </template>
 
@@ -146,63 +85,21 @@
 import { ref, reactive, onMounted } from 'vue'
 import { ElMessage } from 'element-plus'
 import { Clock, Location, User, UserFilled } from '@element-plus/icons-vue'
+import Editor from "@/components/Editor/index.vue";
+import {getMeetSummaryItems,getMeetSummary} from '@/api/collaborativeApproval/meeting.js'
+import dayjs from "dayjs";
 
 // 缁熻鏁版嵁
-const stats = reactive({
-  total: 12,
-  ongoing: 3,
-  completed: 7,
-  upcoming: 2
+const stats = ref({
+  total: 0,
+  underWay: 0,
+  completed: 0,
+  toStart: 0
 })
 
 // 浼氳鏁版嵁
 const meetings = ref([
-  {
-    id: 1,
-    title: '浜у搧寮�鍙戝懆浼�',
-    status: 'ongoing',
-    startTime: '2025-01-15 09:00:00',
-    endTime: '2025-01-15 10:30:00',
-    location: '浼氳瀹',
-    host: '闄堝織寮�',
-    participants: ['闄堝織寮�', '鍒橀泤濠�', '鐜嬪缓鍥�', '璧典附鍗�'],
-    agenda: [
-      { time: '09:00-09:15', content: '涓婂懆宸ヤ綔鎬荤粨', status: 'completed' },
-      { time: '09:15-09:45', content: '鏈懆寮�鍙戣鍒�', status: 'active' },
-      { time: '09:45-10:00', content: '鎶�鏈毦鐐硅璁�', status: 'pending' },
-      { time: '10:00-10:30', content: '闂鍙嶉涓庤В鍐�', status: 'pending' }
-    ]
-  },
-  {
-    id: 2,
-    title: '瀹㈡埛闇�姹傝瘎瀹′細',
-    status: 'upcoming',
-    startTime: '2025-01-15 14:00:00',
-    endTime: '2025-01-15 15:00:00',
-    location: '绾夸笂浼氳',
-    host: '闄堝織寮�',
-    participants: ['闄堝織寮�', '鍒橀泤濠�', '瀛欐槑鍗�', '瀹㈡埛浠h〃'],
-    agenda: [
-      { time: '14:00-14:20', content: '闇�姹傝儗鏅粙缁�', status: 'pending' },
-      { time: '14:20-14:40', content: '鍔熻兘闇�姹傚垎鏋�', status: 'pending' },
-      { time: '14:40-15:00', content: '鎶�鏈彲琛屾�ц瘎浼�', status: 'pending' }
-    ]
-  },
-  {
-    id: 3,
-    title: '鍥㈤槦寤鸿娲诲姩',
-    status: 'completed',
-    startTime: '2025-01-14 16:00:00',
-    endTime: '2025-01-14 18:00:00',
-    location: '鍏徃澶у巺',
-    host: '浜轰簨閮�',
-    participants: ['鍏ㄤ綋鍛樺伐'],
-    agenda: [
-      { time: '16:00-16:30', content: '鍥㈤槦娓告垙', status: 'completed' },
-      { time: '16:30-17:00', content: '缁忛獙鍒嗕韩', status: 'completed' },
-      { time: '17:00-18:00', content: '鑷敱浜ゆ祦', status: 'completed' }
-    ]
-  }
+
 ])
 
 // 瀵硅瘽妗嗙浉鍏�
@@ -218,9 +115,9 @@
 // 鑾峰彇鐘舵�佺被鍨�
 const getStatusType = (status) => {
   const statusMap = {
-    'ongoing': 'success',
-    'upcoming': 'warning',
-    'completed': 'info'
+    '2': 'success',
+    '1': 'warning',
+    '0': 'info'
   }
   return statusMap[status] || 'info'
 }
@@ -228,9 +125,9 @@
 // 鑾峰彇鐘舵�佹枃鏈�
 const getStatusText = (status) => {
   const statusMap = {
-    'ongoing': '杩涜涓�',
-    'upcoming': '鍗冲皢寮�濮�',
-    'completed': '宸插畬鎴�'
+    '2': '杩涜涓�',
+    '1': '鍗冲皢寮�濮�',
+    '0': '宸插畬鎴�'
   }
   return statusMap[status] || '鏈煡'
 }
@@ -261,65 +158,16 @@
   return date.toLocaleTimeString('zh-CN', { hour: '2-digit', minute: '2-digit' })
 }
 
-// 鍒涘缓浼氳
-const createMeeting = () => {
-  dialogVisible.value = true
-  // 閲嶇疆琛ㄥ崟
-  Object.assign(meetingForm, {
-    title: '',
-    timeRange: [],
-    location: '',
-    host: '',
-    description: ''
+
+onMounted( async () => {
+  let [resp1,resp2] = await Promise.all([getMeetSummary(),getMeetSummaryItems()])
+  stats.value = resp1.data
+  meetings.value = resp2.data.map(item => {
+    return {
+      ...item,
+      participants: JSON.parse(item.participants)
+    }
   })
-}
-
-// 鎻愪氦浼氳
-const submitMeeting = () => {
-  if (!meetingForm.title || !meetingForm.timeRange.length || !meetingForm.location || !meetingForm.host) {
-    ElMessage.warning('璇峰~鍐欏畬鏁寸殑浼氳淇℃伅')
-    return
-  }
-  
-  // 鍒涘缓鏂颁細璁�
-  const newMeeting = {
-    id: Date.now(),
-    title: meetingForm.title,
-    status: 'upcoming',
-    startTime: meetingForm.timeRange[0],
-    endTime: meetingForm.timeRange[1],
-    location: meetingForm.location,
-    host: meetingForm.host,
-    participants: [meetingForm.host],
-    agenda: [
-      { time: '寰呭畾', content: '璁▼寰呭畾', status: 'pending' }
-    ]
-  }
-  
-  meetings.value.unshift(newMeeting)
-  stats.total++
-  stats.upcoming++
-  
-  ElMessage.success('浼氳鍒涘缓鎴愬姛')
-  dialogVisible.value = false
-}
-
-// 鍔犲叆浼氳
-const joinMeeting = (meeting) => {
-  ElMessage.success(`宸插姞鍏ヤ細璁細${meeting.title}`)
-}
-
-// 鏌ョ湅璇︽儏
-const viewDetails = (meeting) => {
-  ElMessage.info(`鏌ョ湅浼氳璇︽儏锛�${meeting.title}`)
-}
-
-// 缂栬緫浼氳
-const editMeeting = (meeting) => {
-  ElMessage.info(`缂栬緫浼氳锛�${meeting.title}`)
-}
-
-onMounted(() => {
   console.log('浼氳鐪嬫澘椤甸潰鍔犺浇瀹屾垚')
 })
 </script>
@@ -480,19 +328,19 @@
   .stats-cards {
     grid-template-columns: repeat(2, 1fr);
   }
-  
+
   .meeting-header {
     flex-direction: column;
     gap: 10px;
   }
-  
+
   .meeting-info {
     flex-direction: column;
     gap: 10px;
   }
-  
+
   .meeting-actions {
     flex-direction: column;
   }
 }
-</style>
\ No newline at end of file
+</style>
diff --git a/src/views/collaborativeApproval/notificationManagement/meetApplication/index.vue b/src/views/collaborativeApproval/notificationManagement/meetApplication/index.vue
new file mode 100644
index 0000000..1a2859a
--- /dev/null
+++ b/src/views/collaborativeApproval/notificationManagement/meetApplication/index.vue
@@ -0,0 +1,398 @@
+<template>
+  <div class="app-container">
+    <!-- 椤甸潰鏍囬 -->
+    <div class="page-header">
+      <h2>浼氳鐢宠</h2>
+    </div>
+
+    <!-- 鐢宠绫诲瀷閫夋嫨 -->
+    <el-card class="type-card">
+      <div class="type-selector">
+        <div
+            v-for="type in applicationTypes"
+            :key="type.value"
+            class="type-item"
+            :class="{ active: currentType === type.value }"
+            @click="changeType(type.value)"
+        >
+          <div class="type-icon">
+            <el-icon :size="24"><component :is="type.icon"/></el-icon>
+          </div>
+          <div class="type-info">
+            <div class="type-name">{{ type.name }}</div>
+            <div class="type-desc">{{ type.desc }}</div>
+          </div>
+        </div>
+      </div>
+    </el-card>
+
+    <!-- 浼氳鐢宠琛ㄥ崟 -->
+    <el-card>
+      <div class="form-header">
+        <h3>{{ getCurrentTypeName() }}鐢宠</h3>
+      </div>
+
+      <el-form
+          ref="meetingFormRef"
+          :model="meetingForm"
+          :rules="rules"
+          label-width="100px"
+      >
+        <el-row :gutter="20">
+          <el-col :span="12">
+            <el-form-item label="浼氳涓婚" prop="title">
+              <el-input v-model="meetingForm.title" placeholder="璇疯緭鍏ヤ細璁富棰�"/>
+            </el-form-item>
+          </el-col>
+        </el-row>
+
+        <el-row :gutter="20">
+          <el-col :span="12">
+            <el-form-item label="浼氳瀹�" prop="roomId">
+              <el-select v-model="meetingForm.roomId" placeholder="璇烽�夋嫨浼氳瀹�" style="width: 100%">
+                <el-option
+                    v-for="room in meetingRooms"
+                    :key="room.id"
+                    :label="`${room.name} (${room.location})`"
+                    :value="room.id"
+                />
+              </el-select>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="涓绘寔浜�" prop="host">
+              <el-input v-model="meetingForm.host" placeholder="璇疯緭鍏ヤ富鎸佷汉濮撳悕"/>
+            </el-form-item>
+          </el-col>
+        </el-row>
+
+        <el-row :gutter="20">
+          <el-col :span="12">
+            <el-form-item label="浼氳鏃ユ湡" prop="meetingDate">
+              <el-date-picker
+                  v-model="meetingForm.meetingDate"
+                  type="date"
+                  placeholder="璇烽�夋嫨浼氳鏃ユ湡"
+                  value-format="YYYY-MM-DD"
+                  format="YYYY-MM-DD"
+                  :disabled-date="disabledDate"
+                  style="width: 100%"
+              />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <!-- 绌哄垪锛屼繚鎸佸竷灞� -->
+          </el-col>
+        </el-row>
+
+        <el-row :gutter="20">
+          <el-col :span="12">
+            <el-form-item label="寮�濮嬫椂闂�" prop="startTime">
+              <el-select
+                  v-model="meetingForm.startTime"
+                  placeholder="璇烽�夋嫨寮�濮嬫椂闂�"
+                  style="width: 100%"
+              >
+                <el-option
+                    v-for="time in timeOptions"
+                    :key="time.value"
+                    :label="time.label"
+                    :value="time.value"
+                />
+              </el-select>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="缁撴潫鏃堕棿" prop="endTime">
+              <el-select
+                  v-model="meetingForm.endTime"
+                  placeholder="璇烽�夋嫨缁撴潫鏃堕棿"
+                  style="width: 100%"
+              >
+                <el-option
+                    v-for="time in timeOptions"
+                    :key="time.value"
+                    :label="time.label"
+                    :value="time.value"
+                />
+              </el-select>
+            </el-form-item>
+          </el-col>
+        </el-row>
+
+        <el-form-item label="鍙備細浜哄憳" prop="participants">
+          <el-select
+              v-model="meetingForm.participants"
+              multiple
+              filterable
+              placeholder="璇烽�夋嫨鍙備細浜哄憳"
+              style="width: 100%"
+          >
+            <el-option
+                v-for="person in employees"
+                :key="person.id"
+                :label="`${person.staffName} (${person.postJob})`"
+                :value="person.id"
+            />
+          </el-select>
+        </el-form-item>
+
+        <el-form-item label="浼氳璇存槑" prop="description">
+          <el-input
+              v-model="meetingForm.description"
+              type="textarea"
+              :rows="4"
+              placeholder="璇疯緭鍏ヤ細璁鏄�"
+          />
+        </el-form-item>
+      </el-form>
+
+      <div class="form-footer">
+        <el-button @click="resetForm">閲嶇疆</el-button>
+        <el-button type="primary" @click="submitForm">鎻愪氦</el-button>
+      </div>
+    </el-card>
+  </div>
+</template>
+
+<script setup>
+import {ref, reactive, onMounted} from 'vue'
+import {ElMessage} from 'element-plus'
+import {Plus, Document, Promotion, Bell} from '@element-plus/icons-vue'
+import {getRoomEnum, saveMeetingApplication} from '@/api/collaborativeApproval/meeting.js'
+import {getStaffOnJob} from "@/api/personnelManagement/onboarding.js";
+
+// 褰撳墠鐢宠绫诲瀷
+const currentType = ref('department') // approval: 瀹℃壒娴佺▼, department: 閮ㄩ棬绾�, notification: 閫氱煡鍙戝竷
+
+// 鐢宠绫诲瀷閫夐」
+const applicationTypes = ref([
+  {
+    value: 'approval',
+    name: '瀹℃壒娴佺▼浼氳',
+    desc: '闇�瑕佺粡杩囧绾у鎵圭殑浼氳鐢宠',
+    icon: Document
+  },
+  {
+    value: 'department',
+    name: '閮ㄩ棬绾т細璁�',
+    desc: '閮ㄩ棬鍐呴儴浼氳鐢宠娴佺▼',
+    icon: Promotion
+  },
+  {
+    value: 'notification',
+    name: '浼氳閫氱煡',
+    desc: '鏃犻渶瀹℃壒鐩存帴鍙戝竷鐨勪細璁�氱煡',
+    icon: Bell
+  }
+])
+
+// 琛ㄥ崟鏁版嵁
+const meetingForm = reactive({
+  title: '',
+  type: '',
+  roomId: '',
+  host: '',
+  meetingDate: '',
+  startTime: '',
+  endTime: '',
+  participants: [],
+  description: ''
+})
+
+// 琛ㄥ崟鏍¢獙瑙勫垯
+const rules = {
+  title: [{required: true, message: '璇疯緭鍏ヤ細璁富棰�', trigger: 'blur'}],
+  roomId: [{required: true, message: '璇烽�夋嫨浼氳瀹�', trigger: 'change'}],
+  host: [{required: true, message: '璇疯緭鍏ヤ富鎸佷汉', trigger: 'blur'}],
+  meetingDate: [{required: true, message: '璇烽�夋嫨浼氳鏃ユ湡', trigger: 'change'}],
+  startTime: [{required: true, message: '璇烽�夋嫨寮�濮嬫椂闂�', trigger: 'change'}],
+  endTime: [{required: true, message: '璇烽�夋嫨缁撴潫鏃堕棿', trigger: 'change'}],
+  participants: [{required: true, message: '璇烽�夋嫨鍙備細浜哄憳', trigger: 'change'}]
+}
+
+// 琛ㄥ崟寮曠敤
+const meetingFormRef = ref(null)
+
+// 浼氳瀹ゅ垪琛�
+const meetingRooms = ref([])
+
+// 鍛樺伐鍒楄〃
+const employees = ref([])
+
+// 鏃堕棿閫夐」锛堜互鍗婂皬鏃朵负闂撮殧锛�
+const timeOptions = ref([])
+
+// 鍒濆鍖栨椂闂撮�夐」
+const initTimeOptions = () => {
+  const options = []
+  for (let hour = 8; hour <= 18; hour++) {
+    // 姣忎釜灏忔椂娣诲姞涓や釜閫夐」锛氭暣鐐瑰拰鍗婄偣
+    options.push({
+      value: `${hour.toString().padStart(2, '0')}:00`,
+      label: `${hour.toString().padStart(2, '0')}:00`
+    })
+
+    if (hour < 18) { // 18:00涔嬪悗娌℃湁鍗婄偣閫夐」
+      options.push({
+        value: `${hour.toString().padStart(2, '0')}:30`,
+        label: `${hour.toString().padStart(2, '0')}:30`
+      })
+    }
+  }
+  timeOptions.value = options
+}
+
+// 绂佺敤鏃ユ湡锛堢鐢ㄤ粖澶╀箣鍓嶇殑鏃ユ湡锛�
+const disabledDate = (time) => {
+  // 绂佺敤浠婂ぉ涔嬪墠鐨勬棩鏈�
+  return time.getTime() < Date.now() - 86400000
+}
+
+// 鍒囨崲鐢宠绫诲瀷
+const changeType = (type) => {
+  currentType.value = type
+}
+
+// 鑾峰彇褰撳墠绫诲瀷鍚嶇О
+const getCurrentTypeName = () => {
+  const type = applicationTypes.value.find(t => t.value === currentType.value)
+  return type ? type.name : ''
+}
+
+// 閲嶇疆琛ㄥ崟
+const resetForm = () => {
+  meetingFormRef.value?.resetFields()
+}
+
+// 鎻愪氦琛ㄥ崟
+const submitForm = () => {
+  meetingFormRef.value?.validate((valid) => {
+    if (valid) {
+
+      let formData = {...meetingForm}
+      formData.applicationType = currentType.value
+      formData.startTime = `${meetingForm.meetingDate} ${meetingForm.startTime}:00`
+      formData.endTime = `${meetingForm.meetingDate} ${meetingForm.endTime}:00`
+      formData.participants = JSON.stringify(formData.participants)
+      console.log(formData)
+      saveMeetingApplication(formData).then(() => {
+
+        // 妯℃嫙鎻愪氦鎿嶄綔
+        ElMessage.success(`${getCurrentTypeName()}鎻愪氦鎴愬姛`)
+
+        // 鏍规嵁涓嶅悓绫诲瀷鎵ц涓嶅悓鎿嶄綔
+        switch (currentType.value) {
+          case 'approval':
+            ElMessage.info('浼氳宸叉彁浜ゅ鎵规祦绋�')
+            break
+          case 'department':
+            ElMessage.info('閮ㄩ棬绾т細璁敵璇峰凡鎻愪氦')
+            break
+          case 'notification':
+            ElMessage.info('浼氳閫氱煡宸插彂甯�')
+            break
+        }
+        resetForm()
+      })
+
+    }
+  })
+}
+
+// 椤甸潰鍔犺浇鏃跺垵濮嬪寲
+onMounted(() => {
+  initTimeOptions()
+  getRoomEnum().then(res => {
+    meetingRooms.value = res.data
+  })
+  getStaffOnJob().then(res => {
+    employees.value = res.data.sort((a, b) => a.postJob.localeCompare(b.postJob))
+  })
+})
+</script>
+
+<style scoped>
+.app-container {
+  padding: 20px;
+}
+
+.page-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  margin-bottom: 20px;
+}
+
+.page-header h2 {
+  margin: 0;
+  color: #303133;
+}
+
+.type-card {
+  margin-bottom: 20px;
+}
+
+.type-selector {
+  display: flex;
+  gap: 20px;
+}
+
+.type-item {
+  flex: 1;
+  display: flex;
+  align-items: center;
+  padding: 20px;
+  border: 1px solid #ebeef5;
+  border-radius: 8px;
+  cursor: pointer;
+  transition: all 0.3s;
+}
+
+.type-item:hover {
+  border-color: #409eff;
+  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
+}
+
+.type-item.active {
+  border-color: #409eff;
+  background-color: #ecf5ff;
+}
+
+.type-icon {
+  margin-right: 15px;
+  color: #409eff;
+}
+
+.type-name {
+  font-size: 16px;
+  font-weight: 500;
+  color: #303133;
+  margin-bottom: 5px;
+}
+
+.type-desc {
+  font-size: 14px;
+  color: #909399;
+}
+
+.form-header {
+  margin-bottom: 20px;
+  padding-bottom: 15px;
+  border-bottom: 1px solid #ebeef5;
+}
+
+.form-header h3 {
+  margin: 0;
+  color: #303133;
+}
+
+.form-footer {
+  display: flex;
+  justify-content: flex-end;
+  gap: 10px;
+  margin-top: 30px;
+  padding-top: 20px;
+  border-top: 1px solid #ebeef5;
+}
+</style>
diff --git a/src/views/collaborativeApproval/notificationManagement/meetDraft/index.vue b/src/views/collaborativeApproval/notificationManagement/meetDraft/index.vue
new file mode 100644
index 0000000..0c62b8b
--- /dev/null
+++ b/src/views/collaborativeApproval/notificationManagement/meetDraft/index.vue
@@ -0,0 +1,495 @@
+<template>
+  <div class="app-container">
+    <!-- 椤甸潰鏍囬 -->
+    <div class="page-header">
+      <h2>浼氳鑽夌</h2>
+      <el-button type="primary" @click="handleAdd">
+        <el-icon><Plus /></el-icon>
+        鏂板缓鑽夌
+      </el-button>
+    </div>
+
+    <!-- 鎼滅储鍖哄煙 -->
+    <el-card class="search-card">
+      <el-form :model="searchForm" label-width="100px" inline>
+        <el-form-item label="浼氳涓婚">
+          <el-input v-model="searchForm.title" placeholder="璇疯緭鍏ヤ細璁富棰�" clearable />
+        </el-form-item>
+        <el-form-item label="浼氳鏃ユ湡">
+          <el-date-picker
+            v-model="searchForm.meetingDate"
+            type="date"
+            placeholder="璇烽�夋嫨浼氳鏃ユ湡"
+            value-format="YYYY-MM-DD"
+            format="YYYY-MM-DD"
+            style="width: 100%"
+          />
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" @click="handleSearch">鎼滅储</el-button>
+          <el-button @click="resetSearch">閲嶇疆</el-button>
+        </el-form-item>
+      </el-form>
+    </el-card>
+
+    <!-- 鑽夌鍒楄〃 -->
+    <el-card>
+      <el-table v-loading="loading" :data="draftList" border>
+        <el-table-column prop="title" label="浼氳涓婚" align="center" min-width="200" show-overflow-tooltip />
+        <el-table-column prop="room" label="浼氳瀹�" align="center" width="120" />
+        <el-table-column prop="host" label="涓绘寔浜�" align="center" width="120" />
+        <el-table-column prop="meetingTime" label="浼氳鏃堕棿" align="center" width="180">
+          <template #default="scope">
+            {{ formatDateTime(scope.row.meetingTime) }}
+          </template>
+        </el-table-column>
+        <el-table-column prop="participants" label="鍙備細浜烘暟" align="center" width="100">
+          <template #default="scope">
+            {{ scope.row.participants }}浜�
+          </template>
+        </el-table-column>
+        <el-table-column prop="createTime" label="鍒涘缓鏃堕棿" align="center" width="180" />
+        <el-table-column label="鎿嶄綔" align="center" width="200" fixed="right">
+          <template #default="scope">
+            <el-button type="primary" link @click="viewDraft(scope.row)">鏌ョ湅</el-button>
+            <el-button type="primary" link @click="editDraft(scope.row)">缂栬緫</el-button>
+            <el-button type="danger" link @click="deleteDraft(scope.row)">鍒犻櫎</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+
+      <!-- 鍒嗛〉 -->
+      <pagination
+        v-show="total > 0"
+        :total="total"
+        v-model:page="queryParams.current"
+        v-model:limit="queryParams.size"
+        @pagination="getList"
+      />
+    </el-card>
+
+    <!-- 浼氳鑽夌璇︽儏瀵硅瘽妗� -->
+    <el-dialog
+      title="浼氳鑽夌璇︽儏"
+      v-model="detailDialogVisible"
+      width="800px"
+    >
+      <div v-if="currentDraft">
+        <el-descriptions :column="2" border>
+          <el-descriptions-item label="浼氳涓婚">{{ currentDraft.title }}</el-descriptions-item>
+          <el-descriptions-item label="浼氳缂栧彿">{{ currentDraft.meetingId }}</el-descriptions-item>
+          <el-descriptions-item label="浼氳瀹�">{{ currentDraft.room }}</el-descriptions-item>
+          <el-descriptions-item label="涓绘寔浜�">{{ currentDraft.host }}</el-descriptions-item>
+          <el-descriptions-item label="浼氳鏃堕棿" :span="2">
+            {{ formatDateTime(currentDraft.meetingTime) }}
+          </el-descriptions-item>
+          <el-descriptions-item label="鍒涘缓鏃堕棿">{{ currentDraft.createTime }}</el-descriptions-item>
+        </el-descriptions>
+
+        <div class="content-section mt-20">
+          <h4>鍙備細浜哄憳</h4>
+          <div class="participants-list">
+            {{ currentDraft.participantList }}
+          </div>
+        </div>
+
+        <div class="content-section mt-20">
+          <h4>浼氳璇存槑</h4>
+          <div class="meeting-description">{{ currentDraft.description }}</div>
+        </div>
+      </div>
+
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button @click="detailDialogVisible = false">鍏� 闂�</el-button>
+        </div>
+      </template>
+    </el-dialog>
+
+    <!-- 鏂板缓/缂栬緫鑽夌瀵硅瘽妗� -->
+    <el-dialog
+      :title="dialogTitle"
+      v-model="editDialogVisible"
+      width="700px"
+    >
+      <el-form :model="meetingForm" :rules="rules" ref="meetingFormRef" label-width="100px">
+        <el-form-item label="浼氳涓婚" prop="title">
+          <el-input v-model="meetingForm.title" placeholder="璇疯緭鍏ヤ細璁富棰�" />
+        </el-form-item>
+        <el-form-item label="浼氳瀹�" prop="room">
+          <el-select v-model="meetingForm.roomId" placeholder="璇烽�夋嫨浼氳瀹�" style="width: 100%">
+            <el-option v-for="(v,k) in roomList" :label="v.name" :value="v.id" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="涓绘寔浜�" prop="host">
+          <el-input v-model="meetingForm.host" placeholder="璇疯緭鍏ヤ富鎸佷汉" />
+        </el-form-item>
+        <el-row :gutter="20">
+          <el-col :span="12">
+            <el-form-item label="浼氳鏃ユ湡" prop="meetingDate">
+              <el-date-picker
+                v-model="meetingForm.meetingDate"
+                type="date"
+                placeholder="璇烽�夋嫨浼氳鏃ユ湡"
+                value-format="YYYY-MM-DD"
+                format="YYYY-MM-DD"
+                :disabled-date="disabledDate"
+                style="width: 100%"
+              />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <!-- 绌哄垪锛屼繚鎸佸竷灞� -->
+          </el-col>
+        </el-row>
+        <el-row :gutter="20">
+          <el-col :span="12">
+            <el-form-item label="寮�濮嬫椂闂�" prop="startTime">
+              <el-select
+                v-model="meetingForm.startTime"
+                placeholder="璇烽�夋嫨寮�濮嬫椂闂�"
+                style="width: 100%"
+              >
+                <el-option
+                  v-for="time in timeOptions"
+                  :key="time.value"
+                  :label="time.label"
+                  :value="time.value"
+                />
+              </el-select>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="缁撴潫鏃堕棿" prop="endTime">
+              <el-select
+                v-model="meetingForm.endTime"
+                placeholder="璇烽�夋嫨缁撴潫鏃堕棿"
+                style="width: 100%"
+              >
+                <el-option
+                  v-for="time in timeOptions"
+                  :key="time.value"
+                  :label="time.label"
+                  :value="time.value"
+                />
+              </el-select>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-form-item label="鍙備細浜烘暟" prop="participants">
+          <el-input
+              v-model="meetingForm.participants"
+              type="number"
+              placeholder="璇疯緭鍏ュ弬浼氫汉鏁�"
+          />
+        </el-form-item>
+        <el-form-item label="鍙備細浜哄憳" prop="participants">
+          <el-input
+            v-model="meetingForm.participantList"
+            type="textarea"
+            :rows="3"
+            placeholder="璇疯緭鍏ュ弬浼氫汉鍛橈紝鐢ㄩ�楀彿鍒嗛殧"
+          />
+        </el-form-item>
+        <el-form-item label="浼氳璇存槑">
+          <el-input
+            v-model="meetingForm.description"
+            type="textarea"
+            :rows="4"
+            placeholder="璇疯緭鍏ヤ細璁鏄�"
+          />
+        </el-form-item>
+      </el-form>
+
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button @click="editDialogVisible = false">鍙� 娑�</el-button>
+          <el-button type="primary" @click="submitForm">淇� 瀛�</el-button>
+        </div>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+
+<script setup>
+import { ref, reactive, onMounted } from 'vue'
+import { ElMessage, ElMessageBox } from 'element-plus'
+import { Plus } from '@element-plus/icons-vue'
+import Pagination from '@/components/Pagination/index.vue'
+import {getRoomEnum,getDraftList,saveDraft,delDraft} from '@/api/collaborativeApproval/meeting.js'
+import dayjs from "dayjs";
+// 鏁版嵁鍒楄〃鍔犺浇鐘舵��
+const loading = ref(false)
+
+// 鎬绘潯鏁�
+const total = ref(0)
+
+// 鑽夌鍒楄〃鏁版嵁
+const draftList = ref([])
+
+// 鏌ヨ鍙傛暟
+const queryParams = reactive({
+  current: 1,
+  size: 10
+})
+
+// 鎼滅储琛ㄥ崟
+const searchForm = reactive({
+  title: '',
+  meetingDate: ''
+})
+
+// 鏄惁鏄剧ず瀵硅瘽妗�
+const detailDialogVisible = ref(false)
+const editDialogVisible = ref(false)
+
+const roomList = ref([])
+
+// 瀵硅瘽妗嗘爣棰�
+const dialogTitle = ref('')
+
+// 褰撳墠鏌ョ湅鐨勮崏绋�
+const currentDraft = ref(null)
+
+// 琛ㄥ崟寮曠敤
+const meetingFormRef = ref(null)
+
+// 鏃堕棿閫夐」锛堜互鍗婂皬鏃朵负闂撮殧锛屽伐浣滄椂闂�8:00-18:00锛�
+const timeOptions = ref([])
+
+// 琛ㄥ崟鏁版嵁
+const meetingForm = reactive({
+  id: '',
+  meetingId: '',
+  title: '',
+  roomId: '',
+  host: '',
+  meetingDate: '',
+  startTime: '',
+  endTime: '',
+  participants: 0,
+  participantList: '',
+  description: '',
+  createTime: ''
+})
+
+// 琛ㄥ崟鏍¢獙瑙勫垯
+const rules = {
+  title: [{ required: true, message: '璇疯緭鍏ヤ細璁富棰�', trigger: 'blur' }],
+  roomId: [{ required: true, message: '璇烽�夋嫨浼氳瀹�', trigger: 'change' }],
+  host: [{ required: true, message: '璇疯緭鍏ヤ富鎸佷汉', trigger: 'blur' }],
+  meetingDate: [{ required: true, message: '璇烽�夋嫨浼氳鏃ユ湡', trigger: 'change' }],
+  startTime: [{ required: true, message: '璇烽�夋嫨寮�濮嬫椂闂�', trigger: 'change' }],
+  endTime: [{ required: true, message: '璇烽�夋嫨缁撴潫鏃堕棿', trigger: 'change' }]
+}
+
+// 鍒濆鍖栨椂闂撮�夐」锛堜互鍗婂皬鏃朵负闂撮殧锛屽伐浣滄椂闂�8:00-18:00锛�
+const initTimeOptions = () => {
+  const options = []
+  for (let hour = 8; hour <= 18; hour++) {
+    // 姣忎釜灏忔椂娣诲姞涓や釜閫夐」锛氭暣鐐瑰拰鍗婄偣
+    options.push({
+      value: `${hour.toString().padStart(2, '0')}:00`,
+      label: `${hour.toString().padStart(2, '0')}:00`
+    })
+
+    if (hour < 18) { // 18:00涔嬪悗娌℃湁鍗婄偣閫夐」
+      options.push({
+        value: `${hour.toString().padStart(2, '0')}:30`,
+        label: `${hour.toString().padStart(2, '0')}:30`
+      })
+    }
+  }
+  timeOptions.value = options
+}
+
+// 绂佺敤鏃ユ湡锛堢鐢ㄤ粖澶╀箣鍓嶇殑鏃ユ湡锛�
+const disabledDate = (time) => {
+  // 绂佺敤浠婂ぉ涔嬪墠鐨勬棩鏈�
+  return time.getTime() < Date.now() - 86400000
+}
+
+// 鏌ヨ鏁版嵁
+const getList = async () => {
+  loading.value = true
+
+  let resp = await getDraftList({...queryParams,...searchForm})
+  queryParams.current = resp.data.current
+  draftList.value = resp.data.records.map(it=>{
+    it.room = roomList.value.find(room=>it.roomId===room.id).name ?? ""
+    it.meetingTime = `${it.meetingDate} ${dayjs(it.startTime).format("HH:mm")} ~ ${dayjs(it.endTime).format("HH:mm")}`
+    return it
+  })
+
+  loading.value = false
+
+}
+
+// 鎼滅储鎸夐挳鎿嶄綔
+const handleSearch = () => {
+  queryParams.pageNum = 1
+  getList()
+}
+
+// 閲嶇疆鎼滅储琛ㄥ崟
+const resetSearch = () => {
+  Object.assign(searchForm, {
+    title: '',
+    createTime: []
+  })
+  handleSearch()
+}
+
+// 娣诲姞鎸夐挳鎿嶄綔
+const handleAdd = () => {
+  dialogTitle.value = '鏂板缓鑽夌'
+  resetForm()
+  editDialogVisible.value = true
+}
+
+// 鏌ョ湅鑽夌璇︽儏
+const viewDraft = (row) => {
+  currentDraft.value = row
+  detailDialogVisible.value = true
+}
+
+// 缂栬緫鑽夌
+const editDraft = (row) => {
+  dialogTitle.value = '缂栬緫鑽夌'
+  Object.assign(meetingForm, {
+    id: row.id,
+    meetingId: row.meetingId,
+    title: row.title,
+    room: row.room,
+    roomId: row.id,
+    host: row.host,
+    meetingDate: row.meetingTime.split(' ')[0],
+    startTime: row.meetingTime.split(' ')[1],
+    endTime: row.meetingTime.split(' ')[3],
+    participants: row.participants,
+    participantList: row.participantList,
+    description: row.description,
+    createTime: row.createTime
+  })
+  editDialogVisible.value = true
+}
+
+// 鍒犻櫎鑽夌
+const deleteDraft = (row) => {
+  ElMessageBox.confirm(
+    `纭鍒犻櫎浼氳鑽夌 "${row.title}"?`,
+    '鍒犻櫎鑽夌',
+    {
+      confirmButtonText: '纭畾',
+      cancelButtonText: '鍙栨秷',
+      type: 'warning'
+    }
+  ).then(() => {
+    delDraft(row.id).then(resp=>{
+      ElMessage.success('鑽夌鍒犻櫎鎴愬姛')
+      getList()
+    })
+
+  }).catch(() => {})
+}
+
+// 閲嶇疆琛ㄥ崟
+const resetForm = () => {
+  Object.assign(meetingForm, {
+    id: '',
+    meetingId: '',
+    title: '',
+    room: '',
+    host: '',
+    meetingDate: '',
+    startTime: '',
+    endTime: '',
+    participants: 0,
+    participantList: '',
+    description: '',
+    createTime: ''
+  })
+}
+
+// 鎻愪氦琛ㄥ崟
+const submitForm = () => {
+  meetingFormRef.value.validate((valid) => {
+    if (valid) {
+      let formData = {...meetingForm}
+      formData.startTime = dayjs(meetingForm.meetingDate + ' ' + meetingForm.startTime).format("YYYY-MM-DD HH:mm:ss")
+      formData.endTime = dayjs(meetingForm.meetingDate + ' ' + meetingForm.endTime).format("YYYY-MM-DD HH:mm:ss")
+      saveDraft(formData).then(()=>{
+        ElMessage.success('淇濆瓨鎴愬姛')
+        editDialogVisible.value = false
+        getList()
+      })
+    }
+  })
+}
+
+// 鏍煎紡鍖栨棩鏈熸椂闂�
+const formatDateTime = (dateTime) => {
+  if (!dateTime) return ''
+  return dateTime.replace(' ', '\n')
+}
+
+// 椤甸潰鍔犺浇鏃惰幏鍙栨暟鎹�
+onMounted(() => {
+  initTimeOptions()
+  getList()
+  getRoomEnum().then((res) => {
+    roomList.value = res.data
+  })
+})
+</script>
+
+<style scoped>
+.app-container {
+  padding: 20px;
+}
+
+.page-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  margin-bottom: 20px;
+}
+
+.page-header h2 {
+  margin: 0;
+  color: #303133;
+}
+
+.search-card {
+  margin-bottom: 20px;
+}
+
+.dialog-footer {
+  display: flex;
+  justify-content: flex-end;
+  gap: 10px;
+}
+
+.content-section h4 {
+  margin: 0 0 15px 0;
+  color: #303133;
+}
+
+.mt-20 {
+  margin-top: 20px;
+}
+
+.participants-list {
+  min-height: 40px;
+  padding: 15px;
+  border-radius: 4px;
+  line-height: 1.6;
+}
+
+.meeting-description {
+  padding: 15px;
+  border-radius: 4px;
+  line-height: 1.6;
+  white-space: pre-wrap;
+}
+</style>
diff --git a/src/views/collaborativeApproval/notificationManagement/meetExamine/index.vue b/src/views/collaborativeApproval/notificationManagement/meetExamine/index.vue
new file mode 100644
index 0000000..0883ec3
--- /dev/null
+++ b/src/views/collaborativeApproval/notificationManagement/meetExamine/index.vue
@@ -0,0 +1,418 @@
+<template>
+  <div class="app-container">
+    <!-- 椤甸潰鏍囬 -->
+    <div class="page-header">
+      <h2>浼氳瀹℃壒</h2>
+    </div>
+
+    <!-- 鎼滅储鍖哄煙 -->
+    <el-card class="search-card">
+      <el-form :model="searchForm" inline>
+        <el-form-item label="浼氳涓婚">
+          <el-input v-model="searchForm.title" placeholder="璇疯緭鍏ヤ細璁富棰�" clearable/>
+        </el-form-item>
+        <el-form-item label="鐢宠浜�">
+          <el-input v-model="searchForm.applicant" placeholder="璇疯緭鍏ョ敵璇蜂汉" clearable/>
+        </el-form-item>
+        <el-form-item label="瀹℃壒鐘舵��">
+          <el-select style="width: 100px" v-model="searchForm.status" placeholder="璇烽�夋嫨瀹℃壒鐘舵��" clearable>
+            <el-option label="寰呭鎵�" value="0"/>
+            <el-option label="宸查�氳繃" value="1"/>
+            <el-option label="鏈鎵�" value="2"/>
+            <el-option label="宸插彇娑�" value="3"/>
+          </el-select>
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" @click="handleSearch">鎼滅储</el-button>
+          <el-button @click="resetSearch">閲嶇疆</el-button>
+        </el-form-item>
+      </el-form>
+    </el-card>
+
+    <!-- 浼氳瀹℃壒鍒楄〃 -->
+    <el-card>
+      <el-table v-loading="loading" :data="approvalList" border>
+        <el-table-column prop="title" label="浼氳涓婚" align="center" min-width="200" show-overflow-tooltip/>
+        <el-table-column prop="applicant" label="鐢宠浜�" align="center" width="120"/>
+        <el-table-column prop="host" label="涓荤悊浜�" align="center" width="120"/>
+        <el-table-column prop="meetingTime" label="浼氳鏃堕棿" align="center" width="180">
+          <template #default="scope">
+            {{ formatDateTime(scope.row.meetingTime) }}
+          </template>
+        </el-table-column>
+        <el-table-column prop="location" label="浼氳鍦扮偣" align="center" width="150"/>
+        <el-table-column prop="participants" label="鍙備細浜烘暟" align="center" width="100">
+          <template #default="scope">
+            {{ scope.row.participants.length }}浜�
+          </template>
+        </el-table-column>
+        <el-table-column prop="status" label="瀹℃壒鐘舵��" align="center" width="120">
+          <template #default="scope">
+            <el-tag :type="getStatusType(scope.row.status)">
+              {{ getStatusText(scope.row.status) }}
+            </el-tag>
+          </template>
+        </el-table-column>
+        <el-table-column label="鎿嶄綔" align="center" width="200" fixed="right">
+          <template #default="scope">
+            <el-button type="primary" link @click="viewDetail(scope.row)">鏌ョ湅</el-button>
+            <el-button
+                v-if="scope.row.status == '0'"
+                type="primary"
+                link
+                @click="handleApproval(scope.row)"
+            >
+              瀹℃壒
+            </el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+
+      <!-- 鍒嗛〉 -->
+      <pagination
+          v-show="total > 0"
+          :total="total"
+          v-model:page="queryParams.current"
+          v-model:limit="queryParams.size"
+          @pagination="getList"
+      />
+    </el-card>
+
+    <!-- 浼氳璇︽儏瀵硅瘽妗� -->
+    <el-dialog
+        title="浼氳璇︽儏"
+        v-model="detailDialogVisible"
+        width="800px"
+    >
+      <div v-if="currentMeeting">
+         <el-descriptions label-width="100px" class="meeting-desc" :column="2" border>
+          <el-descriptions-item label="浼氳涓婚" label-class-name="nowrap-label">{{
+              currentMeeting.title
+            }}</el-descriptions-item>
+          <el-descriptions-item label="鐢宠浜�" label-class-name="nowrap-label">{{
+              currentMeeting.applicant
+            }}</el-descriptions-item>
+          <el-descriptions-item label="涓荤悊浜�" label-class-name="nowrap-label">{{
+              currentMeeting.host
+            }}</el-descriptions-item>
+          <el-descriptions-item label="浼氳鏃堕棿" :span="2" label-class-name="nowrap-label">
+            {{ formatDateTime(currentMeeting.meetingTime) }}
+          </el-descriptions-item>
+          <el-descriptions-item label="浼氳鍦扮偣" label-class-name="nowrap-label">{{
+              currentMeeting.location
+            }}</el-descriptions-item>
+          <el-descriptions-item label="鍙備細浜烘暟" label-class-name="nowrap-label">{{
+              currentMeeting.participants.length
+            }}浜�</el-descriptions-item>
+          <el-descriptions-item label="瀹℃壒鐘舵��" label-class-name="nowrap-label">
+            <el-tag :type="getStatusType(currentMeeting.status)">
+              {{ getStatusText(currentMeeting.status) }}
+            </el-tag>
+          </el-descriptions-item>
+          <el-descriptions-item label="鐢宠鏃堕棿" label-class-name="nowrap-label">{{
+              currentMeeting.createTime
+            }}</el-descriptions-item>
+          <el-descriptions-item style="max-height: 400px" label="浼氳璇存槑" :span="2"
+                                label-class-name="nowrap-label">{{ currentMeeting.description }}</el-descriptions-item>
+        </el-descriptions>
+
+
+        <div class="content-section mt-20">
+          <h4>鍙備細浜哄憳</h4>
+          <div class="participants-list">
+            <el-tag
+                v-for="participant in currentMeeting.participants"
+                :key="participant.id"
+                style="margin-right: 10px; margin-bottom: 10px;"
+            >
+              {{ participant.name }}
+            </el-tag>
+          </div>
+        </div>
+      </div>
+
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button @click="detailDialogVisible = false">鍏� 闂�</el-button>
+        </div>
+      </template>
+    </el-dialog>
+
+    <!-- 浼氳瀹℃壒瀵硅瘽妗� -->
+    <el-dialog
+        title="浼氳瀹℃壒"
+        v-model="approvalDialogVisible"
+    >
+      <div v-if="currentMeeting">
+        <el-descriptions :column="2" border>
+          <el-descriptions-item label="浼氳涓婚">{{ currentMeeting.title }}</el-descriptions-item>
+          <el-descriptions-item label="鐢宠浜�">{{ currentMeeting.applicant }}</el-descriptions-item>
+          <el-descriptions-item label="涓荤悊浜�">{{ currentMeeting.host }}</el-descriptions-item>
+          <el-descriptions-item label="浼氳鏃堕棿" :span="2">
+            {{ formatDateTime(currentMeeting.meetingTime) }}
+          </el-descriptions-item>
+          <el-descriptions-item label="浼氳鍦扮偣">{{ currentMeeting.location }}</el-descriptions-item>
+          <el-descriptions-item label="鍙備細浜烘暟">{{ currentMeeting.participants.length }}浜�</el-descriptions-item>
+        </el-descriptions>
+
+        <div class="content-section mt-20">
+          <h4>鍙備細浜哄憳</h4>
+          <div class="participants-list">
+            <el-tag
+                v-for="participant in currentMeeting.participants"
+                :key="participant.id"
+                style="margin-right: 10px; margin-bottom: 10px;"
+            >
+              {{ participant.name }}
+            </el-tag>
+          </div>
+        </div>
+
+        <div v-show="false" class="approval-opinion mt-20">
+          <h4>瀹℃壒鎰忚</h4>
+          <el-input
+              v-model="approvalOpinion"
+              type="textarea"
+              placeholder="璇疯緭鍏ュ鎵规剰瑙�"
+              :rows="4"
+          />
+        </div>
+      </div>
+
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button @click="approvalDialogVisible = false">鍙� 娑�</el-button>
+          <el-button type="danger" @click="submitApproval('2')">涓嶉�氳繃</el-button>
+          <el-button type="primary" @click="submitApproval('1')">閫� 杩�</el-button>
+        </div>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+
+<script setup>
+import {ref, reactive, onMounted} from 'vue'
+import {ElMessage, ElMessageBox} from 'element-plus'
+import Pagination from '@/components/Pagination/index.vue'
+import {getRoomEnum, getExamineList,saveMeetingApplication} from '@/api/collaborativeApproval/meeting.js'
+import {getStaffOnJob} from "@/api/personnelManagement/onboarding.js";
+import dayjs from "dayjs";
+
+// 鏁版嵁鍒楄〃鍔犺浇鐘舵��
+const loading = ref(false)
+
+// 鎬绘潯鏁�
+const total = ref(0)
+const roomEnum = ref([])
+const staffList = ref([])
+// 瀹℃壒鍒楄〃鏁版嵁
+const approvalList = ref([])
+
+// 鏌ヨ鍙傛暟
+const queryParams = reactive({
+  current: 1,
+  size: 10
+})
+
+// 鎼滅储琛ㄥ崟
+const searchForm = reactive({
+  title: '',
+  applicant: '',
+  status: ''
+})
+
+// 鏄惁鏄剧ず瀵硅瘽妗�
+const detailDialogVisible = ref(false)
+const approvalDialogVisible = ref(false)
+
+// 褰撳墠鏌ョ湅鐨勪細璁�
+const currentMeeting = ref(null)
+
+// 瀹℃壒鎰忚
+const approvalOpinion = ref('')
+
+// 鏌ヨ鏁版嵁
+const getList = async () => {
+  loading.value = true
+  let resp = await getExamineList({...searchForm, ...queryParams})
+  approvalList.value = resp.data.records.map(it => {
+    let room = roomEnum.value.find(room => it.roomId === room.id)
+    it.location = `${room.name}(${room.location})`
+    let staffs = JSON.parse(it.participants)
+    it.staffCount = staffs.size
+    it.meetingTime = `${it.meetingDate} ${dayjs(it.startTime).format('HH:mm:ss')} ~ ${dayjs(it.endTime).format('HH:mm:ss')}`
+    it.participants = staffList.value.filter(staff => staffs.some(id=>id === staff.id)).map(staff => {
+      return {
+        id: staff.id,
+        name: `${staff.staffName}(${staff.postJob})`
+      }
+    })
+
+
+    return it
+  })
+  total.value = resp.data.total
+  loading.value = false
+}
+
+// 鎼滅储鎸夐挳鎿嶄綔
+const handleSearch = () => {
+  queryParams.pageNum = 1
+  getList()
+}
+
+// 閲嶇疆鎼滅储琛ㄥ崟
+const resetSearch = () => {
+  Object.assign(searchForm, {
+    title: '',
+    applicant: '',
+    status: ''
+  })
+  handleSearch()
+}
+
+// 鏌ョ湅璇︽儏
+const viewDetail = (row) => {
+  currentMeeting.value = row
+  detailDialogVisible.value = true
+}
+
+// 澶勭悊瀹℃壒
+const handleApproval = (row) => {
+  currentMeeting.value = row
+  approvalOpinion.value = ''
+  approvalDialogVisible.value = true
+}
+
+// 鑾峰彇鐘舵�佺被鍨�
+const getStatusType = (status) => {
+  const statusMap = {
+    '0': 'info',     // 寰呭鎵�
+    '1': 'success',  // 宸查�氳繃
+    '2': 'warning',  // 鏈�氳繃
+    '3': 'danger'   // 鍙栨秷
+  }
+  return statusMap[status] || 'info'
+}
+
+// 鑾峰彇鐘舵�佹枃鏈�
+const getStatusText = (status) => {
+  const statusMap = {
+    '0': '寰呭鎵�',
+    '1': '宸查�氳繃',
+    '2': '鏈�氳繃',
+    '3': '宸插彇娑�'
+  }
+  return statusMap[status] || '鏈煡'
+}
+
+// 鏍煎紡鍖栨棩鏈熸椂闂�
+const formatDateTime = (dateTime) => {
+  if (!dateTime) return ''
+  return dateTime.replace(' ', '\n')
+}
+
+// 鎻愪氦瀹℃壒
+const submitApproval = (status) => {
+  // if (status === 'approved' && !approvalOpinion.value.trim()) {
+  //   ElMessage.warning('璇峰~鍐欏鎵规剰瑙�')
+  //   return
+  // }
+
+  ElMessageBox.confirm(
+      `纭${status === '1' ? '閫氳繃' : '涓嶉�氳繃'}璇ヤ細璁敵璇凤紵`,
+      '瀹℃壒纭',
+      {
+        confirmButtonText: '纭畾',
+        cancelButtonText: '鍙栨秷',
+        type: 'warning'
+      }
+  ).then(() => {
+    saveMeetingApplication({
+      id: currentMeeting.value.id,
+      status: status
+    }).then(resp=>{
+      // 鏇存柊浼氳鐘舵��
+      currentMeeting.value.status = status
+
+      ElMessage.success('瀹℃壒鎻愪氦鎴愬姛')
+      approvalDialogVisible.value = false
+      getList()
+    })
+
+  }).catch(() => {
+  })
+}
+
+// 椤甸潰鍔犺浇鏃惰幏鍙栨暟鎹�
+onMounted(async () => {
+  const [resp1, resp2]= await Promise.all([getRoomEnum(), getStaffOnJob()])
+  roomEnum.value = resp1.data
+  staffList.value = resp2.data
+
+  await getList()
+})
+</script>
+
+<style scoped>
+.app-container {
+  padding: 20px;
+}
+
+.page-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  margin-bottom: 20px;
+}
+
+.page-header h2 {
+  margin: 0;
+  color: #303133;
+}
+
+.search-card {
+  margin-bottom: 20px;
+}
+
+.dialog-footer {
+  display: flex;
+  justify-content: flex-end;
+  gap: 10px;
+}
+
+.content-section h4 {
+  margin: 0 0 15px 0;
+  color: #303133;
+}
+
+.mt-20 {
+  margin-top: 20px;
+}
+
+.participants-list {
+  min-height: 40px;
+  padding: 15px;
+  border-radius: 4px;
+  line-height: 1.6;
+}
+
+.approval-opinion h4 {
+  margin: 0 0 15px 0;
+  color: #303133;
+}
+
+.nowrap-label {
+  white-space: nowrap !important;
+}
+
+.description-content {
+  white-space: pre-wrap;
+  word-wrap: break-word;
+  line-height: 1.6;
+  padding: 10px;
+  background-color: #f5f7fa;
+  border-radius: 4px;
+  min-height: 60px;
+}
+</style>
diff --git a/src/views/collaborativeApproval/notificationManagement/meetIndex/index.vue b/src/views/collaborativeApproval/notificationManagement/meetIndex/index.vue
new file mode 100644
index 0000000..2e9d9a9
--- /dev/null
+++ b/src/views/collaborativeApproval/notificationManagement/meetIndex/index.vue
@@ -0,0 +1,371 @@
+<template>
+  <div class="app-container">
+    <!-- 椤甸潰鏍囬 -->
+    <div class="page-header">
+      <h2>浼氳瀹や娇鐢ㄦ煡璇�</h2>
+    </div>
+
+    <!-- 鏌ヨ鏉′欢 -->
+    <el-card class="search-card">
+      <el-form :model="queryForm" label-width="80px" inline>
+        <el-form-item label="鏌ヨ鏃ユ湡">
+          <el-date-picker
+              v-model="queryForm.meetingDate"
+              type="date"
+              placeholder="璇烽�夋嫨鏃ユ湡"
+              value-format="YYYY-MM-DD"
+              format="YYYY-MM-DD"
+              :clearable="false"
+          />
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" @click="handleSearch">鏌ヨ</el-button>
+          <el-button @click="resetSearch">閲嶇疆</el-button>
+        </el-form-item>
+      </el-form>
+    </el-card>
+
+    <!-- 浼氳瀹や娇鐢ㄦ儏鍐� -->
+    <el-card class="table-container" :loading="loading">
+      <div class="time-table">
+        <!-- 琛ㄥご -->
+        <div class="table-header">
+          <div class="header-cell room-header">浼氳瀹�</div>
+          <div
+              v-for="timeSlot in timeSlots"
+              :key="timeSlot.value"
+              class="header-cell time-header"
+          >
+            {{ timeSlot.label }}
+          </div>
+        </div>
+
+        <!-- 琛ㄦ牸鍐呭 -->
+        <div class="table-body">
+          <div
+              v-for="room in roomUsage"
+              :key="room.id"
+              class="table-row"
+          >
+            <div class="cell room-cell">{{ room.name }}</div>
+            <div class="cells-container">
+              <template v-for="(cell, index) in generateMeetingCells(room)" :key="index">
+                <div
+                    class="cell content-cell"
+                    :class="[cell.type, `status-${cell.meeting?.status || '0'}`]"
+                    :style="{ flex: cell.span-0.2 }"
+                    @click="viewMeetingDetails(cell)"
+                >
+                  <div v-if="cell.type === 'meeting'" class="meeting-content">
+                    <div class="meeting-title">{{ cell.meeting.title }}</div>
+                    <div class="meeting-time">{{ cell.startTime }}-{{ cell.endTime }}</div>
+                  </div>
+                  <div v-else class="free-content">
+                    绌洪棽
+                  </div>
+                </div>
+              </template>
+            </div>
+          </div>
+        </div>
+      </div>
+    </el-card>
+
+    <!-- 浼氳璇︽儏瀵硅瘽妗� -->
+    <el-dialog
+        title="浼氳璇︽儏"
+        v-model="detailDialogVisible"
+        width="800px"
+    >
+      <div v-if="currentMeeting">
+        <el-descriptions :column="1" border>
+          <el-descriptions-item label="浼氳涓婚">{{ currentMeeting.title }}</el-descriptions-item>
+          <el-descriptions-item label="浼氳瀹�">{{ currentMeeting.room }}</el-descriptions-item>
+          <el-descriptions-item label="浼氳鏃堕棿">{{ currentMeeting.time }}</el-descriptions-item>
+          <el-descriptions-item label="涓绘寔浜�">{{ currentMeeting.host }}</el-descriptions-item>
+          <el-descriptions-item label="鍙備細浜烘暟">{{ currentMeeting.participants }}浜�</el-descriptions-item>
+          <el-descriptions-item label="浼氳璇存槑">{{ currentMeeting.description }}</el-descriptions-item>
+        </el-descriptions>
+      </div>
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button @click="detailDialogVisible = false">鍏� 闂�</el-button>
+        </div>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+
+<script setup>
+import {ref, reactive, onMounted} from 'vue'
+import {ElMessage} from 'element-plus'
+import {getMeetingUseList} from "@/api/collaborativeApproval/meeting.js"
+import dayjs from "dayjs";
+
+// 鏌ヨ琛ㄥ崟
+const queryForm = reactive({
+  meetingDate: dayjs().format('YYYY-MM-DD')
+})
+let loading = ref(false)
+// 鏃堕棿娈碉紙浠ュ崐灏忔椂涓洪棿闅旓級
+const timeSlots = ref([])
+
+// 浼氳瀹や娇鐢ㄦ儏鍐�
+const roomUsage = ref([])
+
+// 褰撳墠鏌ョ湅鐨勪細璁�
+const currentMeeting = ref(null)
+
+// 鏄惁鏄剧ず璇︽儏瀵硅瘽妗�
+const detailDialogVisible = ref(false)
+
+// 鍒濆鍖栨椂闂存Ы锛堜互鍗婂皬鏃朵负闂撮殧锛屼粠8:00鍒�18:00锛�
+const initTimeSlots = () => {
+  const slots = []
+  for (let hour = 8; hour < 18; hour++) {
+    // 姣忎釜灏忔椂娣诲姞涓や釜鏃堕棿娈碉細鏁寸偣鍜屽崐鐐�
+    slots.push({
+      label: `${hour.toString().padStart(2, '0')}:00`,
+      value: `${hour.toString().padStart(2, '0')}:00`
+    })
+
+    if (hour < 18) { // 鍒�17:30涓烘
+      slots.push({
+        label: `${hour.toString().padStart(2, '0')}:30`,
+        value: `${hour.toString().padStart(2, '0')}:30`
+      })
+    }
+  }
+  timeSlots.value = slots
+}
+
+// 鐢熸垚浼氳瀹ょ殑鏃堕棿鍗曞厓鏍�
+const generateMeetingCells = (room) => {
+  const cells = []
+  const meetings = room.meetings || []
+  const occupiedSlots = new Set()
+
+  // 澶勭悊姣忎釜浼氳
+  for (const meeting of meetings) {
+
+    const startIdx = timeSlots.value.findIndex(slot => slot.value === meeting.startTime)
+    let endIdx = timeSlots.value.findIndex(slot => slot.value === meeting.endTime)
+    if (endIdx === -1) {
+      endIdx = timeSlots.value.length
+    }
+    console.log('endIdx111', endIdx)
+    if (startIdx !== -1 && endIdx !== -1) {
+      // 鏍囪琚崰鐢ㄧ殑鏃堕棿娈�
+      for (let i = startIdx; i < endIdx; i++) {
+        occupiedSlots.add(timeSlots.value[i].value)
+      }
+
+      // 鍒涘缓浼氳鍗曞厓鏍�
+      cells.push({
+        type: 'meeting',
+        meeting: meeting,
+        span: endIdx - startIdx,
+        startTime: meeting.startTime,
+        endTime: meeting.endTime
+      })
+    }
+  }
+
+  // 澶勭悊绌洪棽鏃堕棿娈�
+  for (let i = 0; i < timeSlots.value.length; i++) {
+    const slot = timeSlots.value[i]
+    if (!occupiedSlots.has(slot.value)) {
+      // 鏌ユ壘杩炵画鐨勭┖闂叉椂闂存
+      let span = 1
+      while (i + span < timeSlots.value.length &&
+      !occupiedSlots.has(timeSlots.value[i + span].value)) {
+        occupiedSlots.add(timeSlots.value[i + span].value)
+        span++
+      }
+
+      cells.push({
+        type: 'free',
+        span: span,
+        time: slot.value
+      })
+    }
+  }
+
+  // 鎸夋椂闂存帓搴�
+  cells.sort((a, b) => {
+    const timeA = a.startTime || a.time
+    const timeB = b.startTime || b.time
+    return timeSlots.value.findIndex(s => s.value === timeA) -
+        timeSlots.value.findIndex(s => s.value === timeB)
+  })
+  console.log('cells', cells)
+  return cells
+}
+
+// 鏌ョ湅浼氳璇︽儏
+const viewMeetingDetails = (cell) => {
+  if (cell && cell.type === 'meeting') {
+    currentMeeting.value = cell.meeting
+    detailDialogVisible.value = true
+  } else {
+    ElMessage.info('璇ユ椂闂存浼氳瀹ょ┖闂�')
+  }
+}
+
+// 鏌ヨ鎸夐挳鎿嶄綔
+const handleSearch = async () => {
+  loading.value = true
+  let resp = await getMeetingUseList({...queryForm})
+  roomUsage.value = resp.data
+  loading.value = false
+}
+
+// 閲嶇疆鎼滅储琛ㄥ崟
+const resetSearch = () => {
+  queryForm.date = dayjs().format('YYYY-MM-DD')
+}
+
+// 椤甸潰鍔犺浇鏃惰幏鍙栨暟鎹�
+onMounted(() => {
+  // 鍒濆鍖栨椂闂存Ы
+  initTimeSlots()
+
+  // 榛樿鏌ヨ浠婂ぉ鐨勬暟鎹�
+  const today = new Date()
+  queryForm.date = today.toISOString().split('T')[0]
+  handleSearch()
+})
+</script>
+
+<style scoped>
+.app-container {
+  padding: 20px;
+}
+
+.page-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  margin-bottom: 20px;
+}
+
+.page-header h2 {
+  margin: 0;
+  color: #303133;
+}
+
+.search-card {
+  margin-bottom: 20px;
+}
+
+.table-container {
+  padding: 0;
+}
+
+.time-table {
+  width: 100%;
+  border-collapse: collapse;
+}
+
+.table-header {
+  display: flex;
+  border: 1px solid;
+}
+
+.table-row {
+  display: flex;
+  border: 1px solid #ebeef5;
+  border-top: none;
+}
+
+.header-cell {
+  padding: 12px 5px;
+  text-align: center;
+  font-weight: bold;
+  border-right: 1px solid;
+  min-height: 20px;
+}
+
+.room-header {
+  width: 120px;
+}
+
+.time-header {
+  flex: 1;
+}
+
+.cell {
+  padding: 15px 5px;
+  text-align: center;
+  border-right: 1px solid;
+  min-height: 20px;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  word-break: break-word;
+  line-height: 1.2;
+}
+
+.room-cell {
+  width: 120px;
+  font-weight: bold;
+}
+
+.cells-container {
+  flex: 1;
+  display: flex;
+}
+
+.content-cell {
+  min-height: 60px;
+  cursor: pointer;
+  transition: all 0.3s;
+}
+
+.content-cell:hover {
+  opacity: 0.8;
+}
+
+.free {
+  color: #f56c6c;
+}
+
+.meeting {
+  display: flex;
+  flex-direction: column;
+  justify-content: center;
+}
+
+.status-1 {
+  background-color: #fef0f0;
+  color: #d14646;
+}
+
+.status-0 {
+  background-color: #c7ddc8;
+  color: rgba(230, 162, 60, 0.29);
+}
+
+.meeting-content {
+  width: 100%;
+}
+
+.meeting-title {
+  font-weight: bold;
+  margin-bottom: 5px;
+}
+
+.meeting-time {
+  font-size: 12px;
+}
+
+.free-content {
+  color: #909399;
+}
+
+.dialog-footer {
+  display: flex;
+  justify-content: flex-end;
+  gap: 10px;
+}
+</style>
diff --git a/src/views/collaborativeApproval/notificationManagement/meetPublish/index.vue b/src/views/collaborativeApproval/notificationManagement/meetPublish/index.vue
new file mode 100644
index 0000000..3f0fc69
--- /dev/null
+++ b/src/views/collaborativeApproval/notificationManagement/meetPublish/index.vue
@@ -0,0 +1,416 @@
+<template>
+  <div class="app-container">
+    <!-- 椤甸潰鏍囬 -->
+    <div class="page-header">
+      <h2>浼氳鍙戝竷</h2>
+    </div>
+
+    <!-- 鎼滅储鍖哄煙 -->
+    <el-card class="search-card">
+      <el-form :model="searchForm" inline>
+        <el-form-item label="浼氳涓婚">
+          <el-input v-model="searchForm.title" placeholder="璇疯緭鍏ヤ細璁富棰�" clearable/>
+        </el-form-item>
+        <el-form-item label="鐢宠浜�">
+          <el-input v-model="searchForm.applicant" placeholder="璇疯緭鍏ョ敵璇蜂汉" clearable/>
+        </el-form-item>
+        <el-form-item label="鍙戝竷鐘舵��">
+          <el-select style="width: 100px" v-model="searchForm.status" placeholder="璇烽�夋嫨鍙戝竷鐘舵��" clearable>
+            <el-option label="寰呭彂甯�" value="0"/>
+            <el-option label="宸插彂甯�" value="1"/>
+          </el-select>
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" @click="handleSearch">鎼滅储</el-button>
+          <el-button @click="resetSearch">閲嶇疆</el-button>
+        </el-form-item>
+      </el-form>
+    </el-card>
+
+    <!-- 浼氳鍙戝竷鍒楄〃 -->
+    <el-card>
+      <el-table v-loading="loading" :data="approvalList" border>
+        <el-table-column prop="title" label="浼氳涓婚" align="center" min-width="200" show-overflow-tooltip/>
+        <el-table-column prop="applicant" label="鐢宠浜�" align="center" width="120"/>
+        <el-table-column prop="host" label="涓荤悊浜�" align="center" width="120"/>
+        <el-table-column prop="meetingTime" label="浼氳鏃堕棿" align="center" width="180">
+          <template #default="scope">
+            {{ formatDateTime(scope.row.meetingTime) }}
+          </template>
+        </el-table-column>
+        <el-table-column prop="location" label="浼氳鍦扮偣" align="center" width="150"/>
+        <el-table-column prop="participants" label="鍙備細浜烘暟" align="center" width="100">
+          <template #default="scope">
+            {{ scope.row.participants.length }}浜�
+          </template>
+        </el-table-column>
+        <el-table-column prop="status" label="鍙戝竷鐘舵��" align="center" width="120">
+          <template #default="scope">
+            <el-tag :type="getStatusType(scope.row.status)">
+              {{ getStatusText(scope.row.status) }}
+            </el-tag>
+          </template>
+        </el-table-column>
+        <el-table-column label="鎿嶄綔" align="center" width="200" fixed="right">
+          <template #default="scope">
+            <el-button type="primary" link @click="viewDetail(scope.row)">鏌ョ湅</el-button>
+            <el-button
+                v-if="scope.row.status == '0'"
+                type="primary"
+                link
+                @click="handleApproval(scope.row)"
+            >
+              鍙戝竷
+            </el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+
+      <!-- 鍒嗛〉 -->
+      <pagination
+          v-show="total > 0"
+          :total="total"
+          v-model:page="queryParams.current"
+          v-model:limit="queryParams.size"
+          @pagination="getList"
+      />
+    </el-card>
+
+    <!-- 浼氳璇︽儏瀵硅瘽妗� -->
+    <el-dialog
+        title="浼氳璇︽儏"
+        v-model="detailDialogVisible"
+        width="800px"
+    >
+      <div v-if="currentMeeting">
+         <el-descriptions label-width="100px" class="meeting-desc" :column="2" border>
+          <el-descriptions-item label="浼氳涓婚" label-class-name="nowrap-label">{{
+              currentMeeting.title
+            }}</el-descriptions-item>
+          <el-descriptions-item label="鐢宠浜�" label-class-name="nowrap-label">{{
+              currentMeeting.applicant
+            }}</el-descriptions-item>
+          <el-descriptions-item label="涓荤悊浜�" label-class-name="nowrap-label">{{
+              currentMeeting.host
+            }}</el-descriptions-item>
+          <el-descriptions-item label="浼氳鏃堕棿" :span="2" label-class-name="nowrap-label">
+            {{ formatDateTime(currentMeeting.meetingTime) }}
+          </el-descriptions-item>
+          <el-descriptions-item label="浼氳鍦扮偣" label-class-name="nowrap-label">{{
+              currentMeeting.location
+            }}</el-descriptions-item>
+          <el-descriptions-item label="鍙備細浜烘暟" label-class-name="nowrap-label">{{
+              currentMeeting.participants.length
+            }}浜�</el-descriptions-item>
+          <el-descriptions-item label="鍙戝竷鐘舵��" label-class-name="nowrap-label">
+            <el-tag :type="getStatusType(currentMeeting.status)">
+              {{ getStatusText(currentMeeting.status) }}
+            </el-tag>
+          </el-descriptions-item>
+          <el-descriptions-item label="鐢宠鏃堕棿" label-class-name="nowrap-label">{{
+              currentMeeting.createTime
+            }}</el-descriptions-item>
+          <el-descriptions-item style="max-height: 400px" label="浼氳璇存槑" :span="2"
+                                label-class-name="nowrap-label">{{ currentMeeting.description }}</el-descriptions-item>
+        </el-descriptions>
+
+
+        <div class="content-section mt-20">
+          <h4>鍙備細浜哄憳</h4>
+          <div class="participants-list">
+            <el-tag
+                v-for="participant in currentMeeting.participants"
+                :key="participant.id"
+                style="margin-right: 10px; margin-bottom: 10px;"
+            >
+              {{ participant.name }}
+            </el-tag>
+          </div>
+        </div>
+      </div>
+
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button @click="detailDialogVisible = false">鍏� 闂�</el-button>
+        </div>
+      </template>
+    </el-dialog>
+
+    <!-- 浼氳鍙戝竷瀵硅瘽妗� -->
+    <el-dialog
+        title="浼氳鍙戝竷"
+        v-model="approvalDialogVisible"
+    >
+      <div v-if="currentMeeting">
+        <el-descriptions :column="2" border>
+          <el-descriptions-item label="浼氳涓婚">{{ currentMeeting.title }}</el-descriptions-item>
+          <el-descriptions-item label="鐢宠浜�">{{ currentMeeting.applicant }}</el-descriptions-item>
+          <el-descriptions-item label="涓荤悊浜�">{{ currentMeeting.host }}</el-descriptions-item>
+          <el-descriptions-item label="浼氳鏃堕棿" :span="2">
+            {{ formatDateTime(currentMeeting.meetingTime) }}
+          </el-descriptions-item>
+          <el-descriptions-item label="浼氳鍦扮偣">{{ currentMeeting.location }}</el-descriptions-item>
+          <el-descriptions-item label="鍙備細浜烘暟">{{ currentMeeting.participants.length }}浜�</el-descriptions-item>
+        </el-descriptions>
+
+        <div class="content-section mt-20">
+          <h4>鍙備細浜哄憳</h4>
+          <div class="participants-list">
+            <el-tag
+                v-for="participant in currentMeeting.participants"
+                :key="participant.id"
+                style="margin-right: 10px; margin-bottom: 10px;"
+            >
+              {{ participant.name }}
+            </el-tag>
+          </div>
+        </div>
+
+        <div class="approval-opinion mt-20">
+          <h4>鍙戝竷鎰忚</h4>
+          <el-input
+              v-model="publishComment"
+              type="textarea"
+              placeholder="璇疯緭鍏ュ彂甯冩剰瑙�"
+              :rows="4"
+          />
+        </div>
+      </div>
+
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button @click="approvalDialogVisible = false">鍙� 娑�</el-button>
+<!--          <el-button type="danger" @click="submitApproval('2')">涓嶉�氳繃</el-button>-->
+          <el-button type="primary" @click="submitApproval('1')">鍙� 甯�</el-button>
+        </div>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+
+<script setup>
+import {ref, reactive, onMounted} from 'vue'
+import {ElMessage, ElMessageBox} from 'element-plus'
+import Pagination from '@/components/Pagination/index.vue'
+import {getRoomEnum, getMeetingPublish,saveMeetingApplication} from '@/api/collaborativeApproval/meeting.js'
+import {getStaffOnJob} from "@/api/personnelManagement/onboarding.js";
+import dayjs from "dayjs";
+
+// 鏁版嵁鍒楄〃鍔犺浇鐘舵��
+const loading = ref(false)
+
+// 鎬绘潯鏁�
+const total = ref(0)
+const roomEnum = ref([])
+const staffList = ref([])
+// 鍙戝竷鍒楄〃鏁版嵁
+const approvalList = ref([])
+
+// 鏌ヨ鍙傛暟
+const queryParams = reactive({
+  current: 1,
+  size: 10
+})
+
+// 鎼滅储琛ㄥ崟
+const searchForm = reactive({
+  title: '',
+  applicant: '',
+  status: ''
+})
+
+// 鏄惁鏄剧ず瀵硅瘽妗�
+const detailDialogVisible = ref(false)
+const approvalDialogVisible = ref(false)
+
+// 褰撳墠鏌ョ湅鐨勪細璁�
+const currentMeeting = ref(null)
+
+// 鍙戝竷鎰忚
+const publishComment = ref('')
+
+// 鏌ヨ鏁版嵁
+const getList = async () => {
+  loading.value = true
+  let resp = await getMeetingPublish({...searchForm, ...queryParams})
+  approvalList.value = resp.data.records.map(it => {
+    let room = roomEnum.value.find(room => it.roomId === room.id)
+    it.location = `${room.name}(${room.location})`
+    let staffs = JSON.parse(it.participants)
+    it.staffCount = staffs.size
+    it.status = it.publishStatus
+    it.meetingTime = `${it.meetingDate} ${dayjs(it.startTime).format('HH:mm:ss')} ~ ${dayjs(it.endTime).format('HH:mm:ss')}`
+    it.participants = staffList.value.filter(staff => staffs.some(id=>id === staff.id)).map(staff => {
+      return {
+        id: staff.id,
+        name: `${staff.staffName}(${staff.postJob})`
+      }
+    })
+
+
+    return it
+  })
+  total.value = resp.data.total
+  loading.value = false
+}
+
+// 鎼滅储鎸夐挳鎿嶄綔
+const handleSearch = () => {
+  queryParams.pageNum = 1
+  getList()
+}
+
+// 閲嶇疆鎼滅储琛ㄥ崟
+const resetSearch = () => {
+  Object.assign(searchForm, {
+    title: '',
+    applicant: '',
+    status: ''
+  })
+  handleSearch()
+}
+
+// 鏌ョ湅璇︽儏
+const viewDetail = (row) => {
+  currentMeeting.value = row
+  detailDialogVisible.value = true
+}
+
+// 澶勭悊鍙戝竷
+const handleApproval = (row) => {
+  currentMeeting.value = row
+  publishComment.value = ''
+  approvalDialogVisible.value = true
+}
+
+// 鑾峰彇鐘舵�佺被鍨�
+const getStatusType = (status) => {
+  const statusMap = {
+    '0': 'info',     // 寰呭彂甯�
+    '1': 'success',  // 宸查�氳繃
+    '2': 'danger',  // 鏈�氳繃
+  }
+  return statusMap[status] || 'info'
+}
+
+// 鑾峰彇鐘舵�佹枃鏈�
+const getStatusText = (status) => {
+  const statusMap = {
+    '0': '寰呭彂甯�',
+    '1': '宸插彂甯�',
+    '2': '宸插彇娑�',
+  }
+  return statusMap[status] || '鏈煡'
+}
+
+// 鏍煎紡鍖栨棩鏈熸椂闂�
+const formatDateTime = (dateTime) => {
+  if (!dateTime) return ''
+  return dateTime.replace(' ', '\n')
+}
+
+// 鎻愪氦鍙戝竷
+const submitApproval = (status) => {
+  // if (status === 'approved' && !publishComment.value.trim()) {
+  //   ElMessage.warning('璇峰~鍐欏彂甯冩剰瑙�')
+  //   return
+  // }
+
+  ElMessageBox.confirm(
+      `纭${status === '1' ? '鍙戝竷' : '鍙栨秷'}璇ヤ細璁紵`,
+      '鍙戝竷纭',
+      {
+        confirmButtonText: '纭畾',
+        cancelButtonText: '鍙栨秷',
+        type: 'warning'
+      }
+  ).then(() => {
+    saveMeetingApplication({
+      id: currentMeeting.value.id,
+      publishStatus: status,
+      publishComment: publishComment.value
+    }).then(resp=>{
+      // 鏇存柊浼氳鐘舵��
+      currentMeeting.value.status = status
+
+      ElMessage.success('鍙戝竷鎻愪氦鎴愬姛')
+      approvalDialogVisible.value = false
+      getList()
+    })
+
+  }).catch(() => {
+  })
+}
+
+// 椤甸潰鍔犺浇鏃惰幏鍙栨暟鎹�
+onMounted(async () => {
+  const [resp1, resp2]= await Promise.all([getRoomEnum(), getStaffOnJob()])
+  roomEnum.value = resp1.data
+  staffList.value = resp2.data
+
+  await getList()
+})
+</script>
+
+<style scoped>
+.app-container {
+  padding: 20px;
+}
+
+.page-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  margin-bottom: 20px;
+}
+
+.page-header h2 {
+  margin: 0;
+  color: #303133;
+}
+
+.search-card {
+  margin-bottom: 20px;
+}
+
+.dialog-footer {
+  display: flex;
+  justify-content: flex-end;
+  gap: 10px;
+}
+
+.content-section h4 {
+  margin: 0 0 15px 0;
+  color: #303133;
+}
+
+.mt-20 {
+  margin-top: 20px;
+}
+
+.participants-list {
+  min-height: 40px;
+  padding: 15px;
+  border-radius: 4px;
+  line-height: 1.6;
+}
+
+.approval-opinion h4 {
+  margin: 0 0 15px 0;
+  color: #303133;
+}
+
+.nowrap-label {
+  white-space: nowrap !important;
+}
+
+.description-content {
+  white-space: pre-wrap;
+  word-wrap: break-word;
+  line-height: 1.6;
+  padding: 10px;
+  background-color: #f5f7fa;
+  border-radius: 4px;
+  min-height: 60px;
+}
+</style>
diff --git a/src/views/collaborativeApproval/notificationManagement/meetSetting/index.vue b/src/views/collaborativeApproval/notificationManagement/meetSetting/index.vue
new file mode 100644
index 0000000..c290be4
--- /dev/null
+++ b/src/views/collaborativeApproval/notificationManagement/meetSetting/index.vue
@@ -0,0 +1,306 @@
+<template>
+  <div class="app-container">
+    <!-- 椤甸潰鏍囬 -->
+    <div class="page-header">
+      <h2>浼氳瀹よ缃�</h2>
+      <el-button type="primary" @click="handleAdd">
+        <el-icon><Plus /></el-icon>
+        鏂板浼氳瀹�
+      </el-button>
+    </div>
+
+    <!-- 鎼滅储鍖哄煙 -->
+    <el-card class="search-card">
+      <el-form :model="searchForm" label-width="100px" inline>
+        <el-form-item label="浼氳瀹ゅ悕绉�">
+          <el-input v-model="searchForm.name" placeholder="璇疯緭鍏ヤ細璁鍚嶇О" clearable />
+        </el-form-item>
+        <el-form-item label="浣嶇疆">
+          <el-input v-model="searchForm.location" placeholder="璇疯緭鍏ヤ綅缃�" clearable />
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" @click="handleSearch">鎼滅储</el-button>
+          <el-button @click="resetSearch">閲嶇疆</el-button>
+        </el-form-item>
+      </el-form>
+    </el-card>
+
+    <!-- 浼氳瀹ゅ垪琛� -->
+    <el-card>
+      <el-table v-loading="loading" :data="meetingRoomList" border>
+        <el-table-column prop="name" label="浼氳瀹ゅ悕绉�" align="center" />
+        <el-table-column prop="location" label="浣嶇疆" align="center" />
+        <el-table-column prop="capacity" label="瀹圭撼浜烘暟" align="center" />
+        <el-table-column prop="equipment" label="璁惧閰嶇疆" align="center">
+          <template #default="scope">
+            <el-tag v-for="item in scope.row.equipment" :key="item" style="margin-right: 5px; margin-bottom: 5px;">
+              {{ item }}
+            </el-tag>
+          </template>
+        </el-table-column>
+        <el-table-column prop="status" label="鐘舵��" align="center" width="100">
+          <template #default="scope">
+            <el-tag :type="scope.row.status === 1 ? 'success' : 'danger'">
+              {{ scope.row.status === 1 ? '鍚敤' : '绂佺敤' }}
+            </el-tag>
+          </template>
+        </el-table-column>
+        <el-table-column label="鎿嶄綔" align="center" width="200">
+          <template #default="scope">
+            <el-button type="primary" link @click="handleEdit(scope.row)">缂栬緫</el-button>
+            <el-button type="danger" link @click="handleDelete(scope.row)">鍒犻櫎</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+
+      <!-- 鍒嗛〉 -->
+      <pagination
+        v-show="total > 0"
+        :total="total"
+        v-model:page="queryParams.current"
+        v-model:limit="queryParams.size"
+        @pagination="getList"
+      />
+    </el-card>
+
+    <!-- 娣诲姞/缂栬緫瀵硅瘽妗� -->
+    <el-dialog :title="dialogTitle" v-model="dialogVisible" width="600px" @close="cancel">
+      <el-form ref="meetingRoomFormRef" :model="meetingRoomForm" :rules="rules" label-width="100px">
+        <el-form-item label="浼氳瀹ゅ悕绉�" prop="name">
+          <el-input v-model="meetingRoomForm.name" placeholder="璇疯緭鍏ヤ細璁鍚嶇О" />
+        </el-form-item>
+        <el-form-item label="浣嶇疆" prop="location">
+          <el-input v-model="meetingRoomForm.location" placeholder="璇疯緭鍏ヤ細璁浣嶇疆" />
+        </el-form-item>
+        <el-form-item label="瀹圭撼浜烘暟" prop="capacity">
+          <el-input-number v-model="meetingRoomForm.capacity" :min="1" placeholder="璇疯緭鍏ュ绾充汉鏁�" />
+        </el-form-item>
+        <el-form-item label="璁惧閰嶇疆" prop="equipment">
+          <el-select v-model="meetingRoomForm.equipment" multiple placeholder="璇烽�夋嫨璁惧閰嶇疆" style="width: 100%">
+            <el-option
+              v-for="item in equipmentOptions"
+              :key="item.value"
+              :label="item.label"
+              :value="item.value"
+            />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="鐘舵��" prop="status">
+          <el-radio-group v-model="meetingRoomForm.status">
+            <el-radio :label="1">鍚敤</el-radio>
+            <el-radio :label="0">绂佺敤</el-radio>
+          </el-radio-group>
+        </el-form-item>
+        <el-form-item label="澶囨敞" prop="remark">
+          <el-input v-model="meetingRoomForm.remark" type="textarea" placeholder="璇疯緭鍏ュ娉�" />
+        </el-form-item>
+      </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 { ref, reactive, onMounted } from 'vue'
+import { ElMessage, ElMessageBox } from 'element-plus'
+import { Plus } from '@element-plus/icons-vue'
+import Pagination from '@/components/Pagination/index.vue'
+import {getMeetingRoomList,saveRoom,delRoom} from '@/api/collaborativeApproval/meeting.js'
+
+// 鏁版嵁鍒楄〃鍔犺浇鐘舵��
+const loading = ref(false)
+
+// 鎬绘潯鏁�
+const total = ref(0)
+
+// 浼氳瀹ゅ垪琛ㄦ暟鎹�
+const meetingRoomList = ref([])
+
+// 鏌ヨ鍙傛暟
+const queryParams = reactive({
+  current: 1,
+  size: 10
+})
+
+// 鎼滅储琛ㄥ崟
+const searchForm = reactive({
+  name: '',
+  location: ''
+})
+
+// 瀵硅瘽妗嗘爣棰�
+const dialogTitle = ref('')
+
+// 鏄惁鏄剧ず瀵硅瘽妗�
+const dialogVisible = ref(false)
+
+// 璁惧閰嶇疆閫夐」
+const equipmentOptions = ref([
+  { value: '鎶曞奖浠�', label: '鎶曞奖浠�' },
+  { value: '鐢佃', label: '鐢佃' },
+  { value: '闊冲搷', label: '闊冲搷' },
+  { value: '鐢佃瘽', label: '鐢佃瘽' },
+  { value: '瑙嗛浼氳绯荤粺', label: '瑙嗛浼氳绯荤粺' },
+  { value: '鐧芥澘', label: '鐧芥澘' },
+  { value: '鍐欏瓧鏉�', label: '鍐欏瓧鏉�' },
+  { value: '鏃犵嚎缃戠粶', label: '鏃犵嚎缃戠粶' }
+])
+
+// 琛ㄥ崟鏁版嵁
+const meetingRoomForm = reactive({
+  id: undefined,
+  name: '',
+  location: '',
+  capacity: 10,
+  equipment: [],
+  status: 1,
+  remark: ''
+})
+
+// 琛ㄥ崟鏍¢獙瑙勫垯
+const rules = {
+  name: [{ required: true, message: '浼氳瀹ゅ悕绉颁笉鑳戒负绌�', trigger: 'blur' }],
+  location: [{ required: true, message: '浣嶇疆涓嶈兘涓虹┖', trigger: 'blur' }],
+  capacity: [{ required: true, message: '瀹圭撼浜烘暟涓嶈兘涓虹┖', trigger: 'blur' }]
+}
+
+// 琛ㄥ崟寮曠敤
+const meetingRoomFormRef = ref(null)
+
+// 鏌ヨ鏁版嵁
+const getList = async () => {
+  loading.value = true
+
+  let resp = await getMeetingRoomList({...searchForm,...queryParams})
+  meetingRoomList.value = resp.data.records.map(it=>{
+    it.equipment = it.equipment.split(',')
+    return it;
+  })
+  total.value = resp.data.total
+  loading.value = false
+
+}
+
+// 鎼滅储鎸夐挳鎿嶄綔
+const handleSearch = () => {
+  queryParams.current = 1
+  getList()
+}
+
+// 閲嶇疆鎼滅储琛ㄥ崟
+const resetSearch = () => {
+  Object.assign(searchForm, {
+    name: '',
+    location: ''
+  })
+  handleSearch()
+}
+
+// 娣诲姞鎸夐挳鎿嶄綔
+const handleAdd = () => {
+  dialogTitle.value = '娣诲姞浼氳瀹�'
+  dialogVisible.value = true
+}
+
+// 淇敼鎸夐挳鎿嶄綔
+const handleEdit = (row) => {
+  dialogTitle.value = '淇敼浼氳瀹�'
+  Object.assign(meetingRoomForm, row)
+  dialogVisible.value = true
+}
+
+// 鍒犻櫎鎸夐挳鎿嶄綔
+const handleDelete = (row) => {
+  ElMessageBox.confirm(
+    `鏄惁纭鍒犻櫎浼氳瀹� "${row.name}"?`,
+    '璀﹀憡',
+    {
+      confirmButtonText: '纭畾',
+      cancelButtonText: '鍙栨秷',
+      type: 'warning'
+    }
+  ).then(() => {
+    // 妯℃嫙鍒犻櫎鎿嶄綔
+    delRoom(row.id).then(resp=>{
+      ElMessage.success('鍒犻櫎鎴愬姛')
+      getList()
+    })
+
+  }).catch(() => {})
+}
+
+// 鍙栨秷鎸夐挳
+const cancel = () => {
+  dialogVisible.value = false
+  reset()
+}
+
+// 琛ㄥ崟閲嶇疆
+const reset = () => {
+  Object.assign(meetingRoomForm, {
+    id: undefined,
+    name: '',
+    location: '',
+    capacity: 10,
+    equipment: [],
+    status: 1,
+    remark: ''
+  })
+  meetingRoomFormRef.value?.resetFields()
+}
+
+// 鎻愪氦琛ㄥ崟
+const submitForm = () => {
+  meetingRoomFormRef.value?.validate((valid) => {
+    if (valid) {
+      // 妯℃嫙鎻愪氦鎿嶄綔
+
+      let formData = {...  meetingRoomForm}
+      formData.equipment = formData.equipment.join(',')
+      saveRoom(formData).then(resp=>{
+        ElMessage.success('淇濆瓨鎴愬姛')
+        dialogVisible.value = false
+        getList()
+      })
+    }
+  })
+}
+
+// 椤甸潰鍔犺浇鏃惰幏鍙栨暟鎹�
+onMounted(() => {
+  getList()
+})
+</script>
+
+<style scoped>
+.app-container {
+  padding: 20px;
+}
+
+.page-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  margin-bottom: 20px;
+}
+
+.page-header h2 {
+  margin: 0;
+  color: #303133;
+}
+
+.search-card {
+  margin-bottom: 20px;
+}
+
+.dialog-footer {
+  display: flex;
+  justify-content: flex-end;
+  gap: 10px;
+}
+</style>
diff --git a/src/views/collaborativeApproval/notificationManagement/summary/index.vue b/src/views/collaborativeApproval/notificationManagement/summary/index.vue
new file mode 100644
index 0000000..04eaa4a
--- /dev/null
+++ b/src/views/collaborativeApproval/notificationManagement/summary/index.vue
@@ -0,0 +1,403 @@
+<template>
+  <div class="app-container">
+    <!-- 椤甸潰鏍囬 -->
+    <div class="page-header">
+      <h2>浼氳绾</h2>
+    </div>
+
+    <!-- 鎼滅储鍖哄煙 -->
+    <el-card class="search-card">
+      <el-form :model="searchForm" inline>
+        <el-form-item label="浼氳涓婚">
+          <el-input v-model="searchForm.title" placeholder="璇疯緭鍏ヤ細璁富棰�" clearable />
+        </el-form-item>
+        <el-form-item label="鐢宠浜�">
+          <el-input v-model="searchForm.applicant" placeholder="璇疯緭鍏ョ敵璇蜂汉" clearable />
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" @click="handleSearch">鎼滅储</el-button>
+          <el-button @click="resetSearch">閲嶇疆</el-button>
+        </el-form-item>
+      </el-form>
+    </el-card>
+
+    <!-- 浼氳鍒楄〃 -->
+    <el-card>
+      <el-table v-loading="loading" :data="meetingList" border>
+        <el-table-column prop="title" label="浼氳涓婚" align="center" min-width="200" show-overflow-tooltip />
+        <el-table-column prop="applicant" label="鐢宠浜�" align="center" width="120" />
+        <el-table-column prop="host" label="涓绘寔浜�" align="center" width="120" />
+        <el-table-column prop="meetingTime" label="浼氳鏃堕棿" align="center" width="180">
+          <template #default="scope">
+            {{ formatDateTime(scope.row.meetingTime) }}
+          </template>
+        </el-table-column>
+        <el-table-column prop="location" label="浼氳鍦扮偣" align="center" width="150" />
+        <el-table-column prop="participants" label="鍙備細浜烘暟" align="center" width="100">
+          <template #default="scope">
+            {{ scope.row.participants.length }}浜�
+          </template>
+        </el-table-column>
+        <el-table-column label="鎿嶄綔" align="center" width="200" fixed="right">
+          <template #default="scope">
+            <el-button type="primary" link @click="viewDetail(scope.row)">鏌ョ湅</el-button>
+            <el-button
+              type="primary"
+              link
+              @click="addMinutes(scope.row)"
+            >
+              娣诲姞绾
+            </el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+
+      <!-- 鍒嗛〉 -->
+      <pagination
+        v-show="total > 0"
+        :total="total"
+        v-model:page="queryParams.current"
+        v-model:limit="queryParams.size"
+        @pagination="getList"
+      />
+    </el-card>
+
+    <!-- 浼氳璇︽儏瀵硅瘽妗� -->
+    <el-dialog
+      title="浼氳璇︽儏"
+      v-model="detailDialogVisible"
+      width="800px"
+    >
+      <div v-if="currentMeeting">
+        <el-descriptions label-width="100px" class="meeting-desc" :column="2" border>
+          <el-descriptions-item label="浼氳涓婚" label-class-name="nowrap-label">{{
+            currentMeeting.title
+          }}</el-descriptions-item>
+          <el-descriptions-item label="鐢宠浜�" label-class-name="nowrap-label">{{
+            currentMeeting.applicant
+          }}</el-descriptions-item>
+          <el-descriptions-item label="涓绘寔浜�" label-class-name="nowrap-label">{{
+            currentMeeting.host
+          }}</el-descriptions-item>
+          <el-descriptions-item label="浼氳鏃堕棿" :span="2" label-class-name="nowrap-label">
+            {{ formatDateTime(currentMeeting.meetingTime) }}
+          </el-descriptions-item>
+          <el-descriptions-item label="浼氳鍦扮偣" label-class-name="nowrap-label">{{
+            currentMeeting.location
+          }}</el-descriptions-item>
+          <el-descriptions-item label="鍙備細浜烘暟" label-class-name="nowrap-label">{{
+            currentMeeting.participants.length
+          }}浜�</el-descriptions-item>
+          <el-descriptions-item label="瀹℃壒鐘舵��" label-class-name="nowrap-label">
+            <el-tag :type="getStatusType(currentMeeting.status)">
+              {{ getStatusText(currentMeeting.status) }}
+            </el-tag>
+          </el-descriptions-item>
+          <el-descriptions-item label="鐢宠鏃堕棿" label-class-name="nowrap-label">{{
+            currentMeeting.createTime
+          }}</el-descriptions-item>
+          <el-descriptions-item style="max-height: 400px" label="浼氳璇存槑" :span="2"
+            label-class-name="nowrap-label">{{ currentMeeting.description }}</el-descriptions-item>
+        </el-descriptions>
+
+        <div class="content-section mt-20">
+          <h4>鍙備細浜哄憳</h4>
+          <div class="participants-list">
+            <el-tag
+              v-for="participant in currentMeeting.participants"
+              :key="participant.id"
+              style="margin-right: 10px; margin-bottom: 10px;"
+            >
+              {{ participant.name }}
+            </el-tag>
+          </div>
+        </div>
+      </div>
+
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button @click="detailDialogVisible = false">鍏� 闂�</el-button>
+        </div>
+      </template>
+    </el-dialog>
+
+    <!-- 娣诲姞浼氳绾瀵硅瘽妗� -->
+    <el-dialog
+      title="娣诲姞浼氳绾"
+      v-model="minutesDialogVisible"
+      width="80%"
+      @close="handleCloseMinutesDialog"
+    >
+      <div v-if="currentMeeting">
+        <el-descriptions :column="2" border>
+          <el-descriptions-item label="浼氳涓婚">{{ currentMeeting.title }}</el-descriptions-item>
+          <el-descriptions-item label="鐢宠浜�">{{ currentMeeting.applicant }}</el-descriptions-item>
+          <el-descriptions-item label="涓绘寔浜�">{{ currentMeeting.host }}</el-descriptions-item>
+          <el-descriptions-item label="浼氳鏃堕棿" :span="2">
+            {{ formatDateTime(currentMeeting.meetingTime) }}
+          </el-descriptions-item>
+          <el-descriptions-item label="浼氳鍦扮偣">{{ currentMeeting.location }}</el-descriptions-item>
+          <el-descriptions-item label="鍙備細浜烘暟">{{ currentMeeting.participants.length }}浜�</el-descriptions-item>
+        </el-descriptions>
+
+        <div class="content-section mt-20">
+          <h4>浼氳绾鍐呭</h4>
+          <div class="editor-container">
+            <Editor
+              v-model="minutesContent"
+              :min-height="400"
+            />
+          </div>
+        </div>
+      </div>
+
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button @click="minutesDialogVisible = false">鍙� 娑�</el-button>
+          <el-button type="primary" @click="submitMinutes">淇� 瀛�</el-button>
+        </div>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+
+<script setup>
+import { ref, reactive, onMounted } from 'vue'
+import { ElMessage } from 'element-plus'
+import Pagination from '@/components/Pagination/index.vue'
+import Editor from '@/components/Editor/index.vue'
+import { getRoomEnum, getMeetingPublish ,getMeetingMinutesByMeetingId,saveMeetingMinutes} from '@/api/collaborativeApproval/meeting.js'
+import { getStaffOnJob } from "@/api/personnelManagement/onboarding.js"
+import dayjs from "dayjs"
+
+// 鏁版嵁鍒楄〃鍔犺浇鐘舵��
+const loading = ref(false)
+
+// 鎬绘潯鏁�
+const total = ref(0)
+const roomEnum = ref([])
+const staffList = ref([])
+
+// 浼氳鍒楄〃鏁版嵁
+const meetingList = ref([])
+
+// 鏌ヨ鍙傛暟
+const queryParams = reactive({
+  current: 1,
+  size: 10
+})
+
+// 鎼滅储琛ㄥ崟
+const searchForm = reactive({
+  title: '',
+  applicant: '',
+  // status: '1' // 榛樿鍙樉绀哄凡閫氳繃瀹℃壒鐨勪細璁�
+})
+
+// 鏄惁鏄剧ず瀵硅瘽妗�
+const detailDialogVisible = ref(false)
+const minutesDialogVisible = ref(false)
+
+// 褰撳墠鏌ョ湅鐨勪細璁�
+const currentMeeting = ref(null)
+
+// 浼氳绾鍐呭
+const minutesContent = ref('')
+const minutesContentId = ref('')
+
+// 鏌ヨ鏁版嵁
+const getList = async () => {
+  loading.value = true
+  let resp = await getMeetingPublish({ ...searchForm, ...queryParams })
+  meetingList.value = resp.data.records.map(it => {
+    let room = roomEnum.value.find(room => it.roomId === room.id)
+    it.location = `${room.name}(${room.location})`
+    let staffs = JSON.parse(it.participants)
+    it.staffCount = staffs.size
+    it.meetingTime = `${it.meetingDate} ${dayjs(it.startTime).format('HH:mm:ss')} ~ ${dayjs(it.endTime).format('HH:mm:ss')}`
+    it.participants = staffList.value.filter(staff => staffs.some(id => id === staff.id)).map(staff => {
+      return {
+        id: staff.id,
+        name: `${staff.staffName}(${staff.postJob})`
+      }
+    })
+
+    return it
+  })
+  total.value = resp.data.total
+  loading.value = false
+}
+
+// 鎼滅储鎸夐挳鎿嶄綔
+const handleSearch = () => {
+  queryParams.current = 1
+  getList()
+}
+
+// 閲嶇疆鎼滅储琛ㄥ崟
+const resetSearch = () => {
+  Object.assign(searchForm, {
+    title: '',
+    applicant: '',
+    // status: '1'
+  })
+  handleSearch()
+}
+
+// 鏌ョ湅璇︽儏
+const viewDetail = (row) => {
+  currentMeeting.value = row
+  detailDialogVisible.value = true
+}
+
+// 娣诲姞浼氳绾
+const addMinutes = async (row) => {
+  let resp = await getMeetingMinutesByMeetingId(row.id)
+  currentMeeting.value = row
+  if (resp.data){
+    minutesContent.value = resp.data.content
+    minutesContentId.value = resp.data.id
+  }else {
+    minutesContent.value = `<h2>${row.title}浼氳绾</h2>
+<p><strong>浼氳鏃堕棿锛�</strong>${row.meetingTime}</p>
+<p><strong>浼氳鍦扮偣锛�</strong>${row.location}</p>
+<p><strong>涓绘寔浜猴細</strong>${row.host}</p>
+<p><strong>鍙備細浜哄憳锛�</strong></p>
+<ol>
+  ${row.participants.map(p => `<li>${p.name}</li>`).join('')}
+</ol>
+<p><strong>浼氳鍐呭锛�</strong></p>
+<ol>
+  <li>璁涓�锛�
+    <ul>
+      <li>璁ㄨ鍐呭锛�</li>
+      <li>鍐宠浜嬮」锛�</li>
+    </ul>
+  </li>
+  <li>璁浜岋細
+    <ul>
+      <li>璁ㄨ鍐呭锛�</li>
+      <li>鍐宠浜嬮」锛�</li>
+    </ul>
+  </li>
+</ol>
+<p><strong>澶囨敞锛�</strong></p>`
+  }
+
+  minutesDialogVisible.value = true
+}
+
+// 鎻愪氦浼氳绾
+const submitMinutes = () => {
+  if (!minutesContent.value) {
+    ElMessage.warning('璇疯緭鍏ヤ細璁邯瑕佸唴瀹�')
+    return
+  }
+  saveMeetingMinutes({
+    id: minutesContentId.value,
+    content: minutesContent.value,
+    meetingId: currentMeeting.value.id,
+    title: currentMeeting.value.title
+  }).then(resp=>{
+    console.log('浼氳绾鍐呭:', minutesContent.value)
+    ElMessage.success('浼氳绾淇濆瓨鎴愬姛')
+    minutesDialogVisible.value = false
+  })
+
+}
+
+// 鍏抽棴浼氳绾瀵硅瘽妗�
+const handleCloseMinutesDialog = () => {
+  minutesContent.value = ''
+}
+
+// 鑾峰彇鐘舵�佺被鍨�
+const getStatusType = (status) => {
+  const statusMap = {
+    '0': 'info',     // 寰呭鎵�
+    '1': 'success',  // 宸查�氳繃
+    '2': 'warning',  // 鏈�氳繃
+    '3': 'danger'   // 鍙栨秷
+  }
+  return statusMap[status] || 'info'
+}
+
+// 鑾峰彇鐘舵�佹枃鏈�
+const getStatusText = (status) => {
+  const statusMap = {
+    '0': '寰呭鎵�',
+    '1': '宸查�氳繃',
+    '2': '鏈�氳繃',
+    '3': '宸插彇娑�'
+  }
+  return statusMap[status] || '鏈煡'
+}
+
+// 鏍煎紡鍖栨棩鏈熸椂闂�
+const formatDateTime = (dateTime) => {
+  if (!dateTime) return ''
+  return dateTime.replace(' ', '\n')
+}
+
+// 椤甸潰鍔犺浇鏃惰幏鍙栨暟鎹�
+onMounted(async () => {
+  const [resp1, resp2] = await Promise.all([getRoomEnum(), getStaffOnJob()])
+  roomEnum.value = resp1.data
+  staffList.value = resp2.data
+
+  await getList()
+})
+</script>
+
+<style scoped>
+.app-container {
+  padding: 20px;
+}
+
+.page-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  margin-bottom: 20px;
+}
+
+.page-header h2 {
+  margin: 0;
+  color: #303133;
+}
+
+.search-card {
+  margin-bottom: 20px;
+}
+
+.dialog-footer {
+  display: flex;
+  justify-content: flex-end;
+  gap: 10px;
+}
+
+.content-section h4 {
+  margin: 0 0 15px 0;
+  color: #303133;
+}
+
+.mt-20 {
+  margin-top: 20px;
+}
+
+.participants-list {
+  min-height: 40px;
+  padding: 15px;
+  border-radius: 4px;
+  line-height: 1.6;
+}
+
+.nowrap-label {
+  white-space: nowrap !important;
+}
+
+.editor-container {
+  border: 1px solid #dcdfe6;
+  border-radius: 4px;
+}
+</style>
diff --git a/src/views/inspectionManagement/index.vue b/src/views/inspectionManagement/index.vue
index 7e5edc0..e95b51a 100644
--- a/src/views/inspectionManagement/index.vue
+++ b/src/views/inspectionManagement/index.vue
@@ -44,7 +44,7 @@
       </div>
       <div>
         <div>
-          <ETable :loading="tableLoading"
+          <PIMTable :loading="tableLoading"
                   :table-data="tableData"
                   :columns="tableColumns"
                   @selection-change="handleSelectionChange"
@@ -75,7 +75,7 @@
               <span v-else class="no-data">--</span>
             </div>
           </template>
-          </ETable>
+          </PIMTable>
           <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">
@@ -120,7 +120,7 @@
 
 // 缁勪欢寮曞叆
 import Pagination from "@/components/Pagination/index.vue";
-import ETable from "@/components/Table/ETable.vue";
+import PIMTable from "@/components/PIMTable/PIMTable.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";
diff --git a/src/views/inventoryManagement/dispatchLog/index.vue b/src/views/inventoryManagement/dispatchLog/index.vue
index 177868d..65c90e8 100644
--- a/src/views/inventoryManagement/dispatchLog/index.vue
+++ b/src/views/inventoryManagement/dispatchLog/index.vue
@@ -1,248 +1,249 @@
 <template>
-  <div class="app-container">
-    <div class="search_form">
-      <div>
-        <span class="search_title">渚涘簲鍟嗗悕绉帮細</span>
-        <el-input
-          v-model="searchForm.supplierName"
-          style="width: 240px"
-          placeholder="璇疯緭鍏�"
-          @change="handleQuery"
-          clearable
-          prefix-icon="Search"
-        />
-        <el-button type="primary" @click="handleQuery" style="margin-left: 10px"
-          >鎼滅储</el-button
-        >
-      </div>
-      <div>
-        <!-- <el-button type="primary" @click="openForm('add')">鏂板</el-button> -->
-        <el-button @click="handleOut">瀵煎嚭</el-button>
-        <el-button type="danger" plain @click="handleDelete">鍒犻櫎</el-button>
-      </div>
-    </div>
-    <div class="table_list">
-      <el-table
-        :data="tableData"
-        border
-        v-loading="tableLoading"
-        @selection-change="handleSelectionChange"
-        :expand-row-keys="expandedRowKeys"
-        :row-key="(row) => row.id"
-        show-summary
-        style="width: 100%"
-        :summary-method="summarizeMainTable"
-        height="calc(100vh - 18.5em)"
-      >
-        <el-table-column align="center" type="selection" width="55" />
-        <el-table-column align="center" label="搴忓彿" type="index" width="60" />
-        <el-table-column
-          label="鍑哄簱鏃ユ湡"
-          prop="createTime"
-          min-width="130"
-          show-overflow-tooltip
-        />
-        <el-table-column
-          label="渚涘簲鍟嗗悕绉�"
-          prop="supplierName"
-          width="250"
-          show-overflow-tooltip
-        />
-        <el-table-column
-          label="浜у搧澶х被"
-          prop="productCategory"
-          width="100"
-          show-overflow-tooltip
-        />
-        <el-table-column
-          label="瑙勬牸鍨嬪彿"
-          prop="specificationModel"
-          width="100"
-          show-overflow-tooltip
-        />
-        <el-table-column
-          label="鍗曚綅"
-          prop="unit"
-          width="80"
-          show-overflow-tooltip
-        />
-        <el-table-column
-          label="鍑哄簱鏁伴噺"
-          prop="inboundNum"
-          width="100"
-          show-overflow-tooltip
-        />
-        <el-table-column
-          label="鍚◣鍗曚环(鍏�)"
-          prop="taxInclusiveUnitPrice"
-          width="200"
-          show-overflow-tooltip
-        />
-        <el-table-column
-          label="鍚◣鎬讳环(鍏�)"
-          prop="taxInclusiveTotalPrice"
-          width="200"
-          show-overflow-tooltip
-        />
-        <el-table-column
-          label="绋庣巼(%)"
-          prop="taxRate"
-          width="100"
-          show-overflow-tooltip
-        />
-        <el-table-column
-          label="涓嶅惈绋庢�讳环(鍏�)"
-          prop="taxExclusiveTotalPrice"
-          width="180"
-          show-overflow-tooltip
-        />
-        <el-table-column
-          label="鍑哄簱浜�"
-          prop="createBy"
-          width="80"
-          show-overflow-tooltip
-        />
-        <!-- <el-table-column
-          fixed="right"
-          label="鎿嶄綔"
-          min-width="60"
-          align="center"
-        >
-          <template #default="scope">
-            <el-button
-              link
-              type="primary"
-              size="small"
-              @click="openForm('edit', scope.row)"
-              >缂栬緫</el-button
-            >
-          </template>
-        </el-table-column> -->
-      </el-table>
-      <pagination
-        v-show="total > 0"
-        :total="total"
-        layout="total, sizes, prev, pager, next, jumper"
-        :page="page.current"
-        :limit="page.size"
-        @pagination="paginationChange"
-      />
-    </div>
-
-    <!-- 鎵撳嵃棰勮寮圭獥 -->
-    <el-dialog
-      v-model="printPreviewVisible"
-      title="鎵撳嵃棰勮"
-      width="90%"
-      :close-on-click-modal="false"
-      class="print-preview-dialog"
-    >
-      <div class="print-preview-container">
-                 <div class="print-preview-header">
-           <el-button type="primary" @click="executePrint">鎵ц鎵撳嵃</el-button>
-           <el-button @click="printPreviewVisible = false">鍏抽棴棰勮</el-button>
-         </div>
-                   <div class="print-preview-content">
-          <div v-if="printData.length === 0" style="text-align: center; padding: 50px; color: #999;">
-            鏆傛棤鎵撳嵃鏁版嵁
-          </div>
-          <div v-else style="text-align: center; padding: 10px; color: #666; font-size: 14px; background: #e8f4fd; margin-bottom: 10px;">
-            鍏� {{ printData.length }} 鏉℃暟鎹緟鎵撳嵃
-          </div>
-          <div v-for="(item, index) in printData" :key="index" class="print-page">
-            <div class="delivery-note">
-              <div class="header">
-                <div class="company-name">榧庤瘹鐟炲疄涓氭湁闄愯矗浠诲叕鍙�</div>
-                <div class="document-title">闆跺敭鍙戣揣鍗�</div>
-              </div>
-              
-              <div class="info-section">
-                <div class="info-row">
-                  <div>
-                    <span class="label">鍙戣揣鏃ユ湡锛�</span>
-                  <span class="value">{{ formatDate(item.createTime) }}</span>
-                  </div>
-                                     <div>
-                     
-                   <span class="label">瀹㈡埛鍚嶇О锛�</span>
-                   <span class="value">{{ item.supplierName || '寮犵埍鏈�' }}</span>
-                   </div>
-                </div>
-                <div class="info-row">
-                  <span class="label">鍗曞彿锛�</span>
-                  <span class="value">{{ item.code }}</span>
-                </div>
-              </div>
-
-              <div class="table-section">
-                <table class="product-table">
-                  <thead>
-                    <tr>
-                      <th>浜у搧鍚嶇О</th>
-                      <th>瑙勬牸鍨嬪彿</th>
-                      <th>鍗曚綅</th>
-                      <th>鍗曚环</th>
-                      <th>闆跺敭鏁伴噺</th>
-                      <th>闆跺敭閲戦</th>
-                    </tr>
-                  </thead>
-                  <tbody>
-                    <tr>
-                      <td>{{ item.productCategory || '鐮傜伆鐮�' }}</td>
-                      <td>{{ item.specificationModel || '鏍囧噯' }}</td>
-                      <td>{{ item.unit || '鍧�' }}</td>
-                      <td>{{ item.taxInclusiveUnitPrice || '0' }}</td>
-                      <td>{{ item.inboundNum || '2000' }}</td>
-                      <td>{{ item.taxInclusiveTotalPrice || '0' }}</td>
-                    </tr>
-                  </tbody>
-                    <tfoot>
-                     <tr>
-                       <td class="label">鍚堣</td>
-                       <td class="total-value"></td>
-                       <td class="total-value"></td>
-                       <td class="total-value"></td>
-                       <td class="total-value">{{ item.inboundNum || '2000' }}</td>
-                       <td class="total-value">{{ item.taxInclusiveTotalPrice || '0' }}</td>
-                     </tr>
-                   </tfoot>
-                </table>
-              </div>
-
-              <div class="footer-section">
-                <div class="footer-row">
-                  <div class="footer-item">
-                    <span class="label">鏀惰揣鐢佃瘽锛�</span>
-                    <span class="value"></span>
-                  </div>
-                  <div class="footer-item">
-                    <span class="label">鏀惰揣浜猴細</span>
-                    <span class="value"></span>
-                  </div>
-                                     <div class="footer-item address-item">
-                     <span class="label">鏀惰揣鍦板潃锛�</span>
-                     <span class="value address-value"></span>
-                   </div>
-                </div>
-                <div class="footer-row">
-                                     <div class="footer-item">
-                     <span class="label">鎿嶄綔鍛橈細</span>
-                     <span class="value">{{ userStore.nickname || '鎾曞紑鍓�' }}</span>
-                   </div>
-                  <div class="footer-item">
-                    <span class="label">鎵撳嵃鏃ユ湡锛�</span>
-                    <span class="value">{{ formatDateTime(new Date()) }}</span>
-                  </div>
-                </div>
-              </div>
-            </div>
-          </div>
-        </div>
-      </div>
-    </el-dialog>
-
-
-  </div>
+	<div class="app-container">
+		<div class="search_form">
+			<div>
+				<span class="search_title">渚涘簲鍟嗗悕绉帮細</span>
+				<el-input
+					v-model="searchForm.supplierName"
+					style="width: 240px"
+					placeholder="璇疯緭鍏�"
+					@change="handleQuery"
+					clearable
+					prefix-icon="Search"
+				/>
+				<el-button type="primary" @click="handleQuery" style="margin-left: 10px"
+				>鎼滅储</el-button
+				>
+			</div>
+			<div>
+				<!-- <el-button type="primary" @click="openForm('add')">鏂板</el-button> -->
+				<el-button @click="handleOut">瀵煎嚭</el-button>
+				<el-button type="danger" plain @click="handleDelete">鍒犻櫎</el-button>
+				<el-button type="primary" plain @click="handlePrint">鎵撳嵃</el-button>
+			</div>
+		</div>
+		<div class="table_list">
+			<el-table
+				:data="tableData"
+				border
+				v-loading="tableLoading"
+				@selection-change="handleSelectionChange"
+				:expand-row-keys="expandedRowKeys"
+				:row-key="(row) => row.id"
+				show-summary
+				style="width: 100%"
+				:summary-method="summarizeMainTable"
+				height="calc(100vh - 18.5em)"
+			>
+				<el-table-column align="center" type="selection" width="55" />
+				<el-table-column align="center" label="搴忓彿" type="index" width="60" />
+				<el-table-column
+					label="鍑哄簱鏃ユ湡"
+					prop="createTime"
+					min-width="250"
+					show-overflow-tooltip
+				/>
+				<el-table-column
+					label="渚涘簲鍟嗗悕绉�"
+					prop="supplierName"
+					width="250"
+					show-overflow-tooltip
+				/>
+				<el-table-column
+					label="浜у搧澶х被"
+					prop="productCategory"
+					width="100"
+					show-overflow-tooltip
+				/>
+				<el-table-column
+					label="瑙勬牸鍨嬪彿"
+					prop="specificationModel"
+					width="100"
+					show-overflow-tooltip
+				/>
+				<el-table-column
+					label="鍗曚綅"
+					prop="unit"
+					width="80"
+					show-overflow-tooltip
+				/>
+				<el-table-column
+					label="鍑哄簱鏁伴噺"
+					prop="inboundNum"
+					width="100"
+					show-overflow-tooltip
+				/>
+				<el-table-column
+					label="鍚◣鍗曚环(鍏�)"
+					prop="taxInclusiveUnitPrice"
+					width="100"
+					show-overflow-tooltip
+				/>
+				<el-table-column
+					label="鍚◣鎬讳环(鍏�)"
+					prop="taxInclusiveTotalPrice"
+					width="100"
+					show-overflow-tooltip
+				/>
+				<el-table-column
+					label="绋庣巼(%)"
+					prop="taxRate"
+					width="100"
+					show-overflow-tooltip
+				/>
+				<el-table-column
+					label="涓嶅惈绋庢�讳环(鍏�)"
+					prop="taxExclusiveTotalPrice"
+					width="180"
+					show-overflow-tooltip
+				/>
+				<el-table-column
+					label="鍑哄簱浜�"
+					prop="createBy"
+					width="80"
+					show-overflow-tooltip
+				/>
+				<!-- <el-table-column
+					fixed="right"
+					label="鎿嶄綔"
+					min-width="60"
+					align="center"
+				>
+					<template #default="scope">
+						<el-button
+							link
+							type="primary"
+							size="small"
+							@click="openForm('edit', scope.row)"
+							>缂栬緫</el-button
+						>
+					</template>
+				</el-table-column> -->
+			</el-table>
+			<pagination
+				v-show="total > 0"
+				:total="total"
+				layout="total, sizes, prev, pager, next, jumper"
+				:page="page.current"
+				:limit="page.size"
+				@pagination="paginationChange"
+			/>
+		</div>
+		
+		<!-- 鎵撳嵃棰勮寮圭獥 -->
+		<el-dialog
+			v-model="printPreviewVisible"
+			title="鎵撳嵃棰勮"
+			width="90%"
+			:close-on-click-modal="false"
+			class="print-preview-dialog"
+		>
+			<div class="print-preview-container">
+				<div class="print-preview-header">
+					<el-button type="primary" @click="executePrint">鎵ц鎵撳嵃</el-button>
+					<el-button @click="printPreviewVisible = false">鍏抽棴棰勮</el-button>
+				</div>
+				<div class="print-preview-content">
+					<div v-if="printData.length === 0" style="text-align: center; padding: 50px; color: #999;">
+						鏆傛棤鎵撳嵃鏁版嵁
+					</div>
+					<div v-else style="text-align: center; padding: 10px; color: #666; font-size: 14px; background: #e8f4fd; margin-bottom: 10px;">
+						鍏� {{ printData.length }} 鏉℃暟鎹緟鎵撳嵃
+					</div>
+					<div v-for="(item, index) in printData" :key="index" class="print-page">
+						<div class="delivery-note">
+							<div class="header">
+								<div class="company-name">榧庤瘹鐟炲疄涓氭湁闄愯矗浠诲叕鍙�</div>
+								<div class="document-title">闆跺敭鍙戣揣鍗�</div>
+							</div>
+							
+							<div class="info-section">
+								<div class="info-row">
+									<div>
+										<span class="label">鍙戣揣鏃ユ湡锛�</span>
+										<span class="value">{{ formatDate(item.createTime) }}</span>
+									</div>
+									<div>
+										
+										<span class="label">瀹㈡埛鍚嶇О锛�</span>
+										<span class="value">{{ item.supplierName || '寮犵埍鏈�' }}</span>
+									</div>
+								</div>
+								<div class="info-row">
+									<span class="label">鍗曞彿锛�</span>
+									<span class="value">{{ item.code }}</span>
+								</div>
+							</div>
+							
+							<div class="table-section">
+								<table class="product-table">
+									<thead>
+									<tr>
+										<th>浜у搧鍚嶇О</th>
+										<th>瑙勬牸鍨嬪彿</th>
+										<th>鍗曚綅</th>
+										<th>鍗曚环</th>
+										<th>闆跺敭鏁伴噺</th>
+										<th>闆跺敭閲戦</th>
+									</tr>
+									</thead>
+									<tbody>
+									<tr>
+										<td>{{ item.productCategory || '鐮傜伆鐮�' }}</td>
+										<td>{{ item.specificationModel || '鏍囧噯' }}</td>
+										<td>{{ item.unit || '鍧�' }}</td>
+										<td>{{ item.taxInclusiveUnitPrice || '0' }}</td>
+										<td>{{ item.inboundNum || '2000' }}</td>
+										<td>{{ item.taxInclusiveTotalPrice || '0' }}</td>
+									</tr>
+									</tbody>
+									<tfoot>
+									<tr>
+										<td class="label">鍚堣</td>
+										<td class="total-value"></td>
+										<td class="total-value"></td>
+										<td class="total-value"></td>
+										<td class="total-value">{{ item.inboundNum || '2000' }}</td>
+										<td class="total-value">{{ item.taxInclusiveTotalPrice || '0' }}</td>
+									</tr>
+									</tfoot>
+								</table>
+							</div>
+							
+							<div class="footer-section">
+								<div class="footer-row">
+									<div class="footer-item">
+										<span class="label">鏀惰揣鐢佃瘽锛�</span>
+										<span class="value"></span>
+									</div>
+									<div class="footer-item">
+										<span class="label">鏀惰揣浜猴細</span>
+										<span class="value"></span>
+									</div>
+									<div class="footer-item address-item">
+										<span class="label">鏀惰揣鍦板潃锛�</span>
+										<span class="value address-value"></span>
+									</div>
+								</div>
+								<div class="footer-row">
+									<div class="footer-item">
+										<span class="label">鎿嶄綔鍛橈細</span>
+										<span class="value">{{ userStore.nickName || '鎾曞紑鍓�' }}</span>
+									</div>
+									<div class="footer-item">
+										<span class="label">鎵撳嵃鏃ユ湡锛�</span>
+										<span class="value">{{ formatDateTime(new Date()) }}</span>
+									</div>
+								</div>
+							</div>
+						</div>
+					</div>
+				</div>
+			</div>
+		</el-dialog>
+	
+	
+	</div>
 </template>
 
 <script setup>
@@ -251,8 +252,8 @@
 import { ElMessageBox } from "element-plus";
 import useUserStore from "@/store/modules/user";
 import {
-  getStockOutPage,
-  delStockOut,
+	getStockOutPage,
+	delStockOut,
 } from "@/api/inventoryManagement/stockOut.js";
 
 const userStore = useUserStore();
@@ -261,8 +262,8 @@
 const selectedRows = ref([]);
 const tableLoading = ref(false);
 const page = reactive({
-  current: 1,
-  size: 100,
+	current: 1,
+	size: 100,
 });
 const total = ref(0);
 
@@ -272,136 +273,136 @@
 
 // 鐢ㄦ埛淇℃伅琛ㄥ崟寮规鏁版嵁
 const data = reactive({
-  searchForm: {
-    supplierName: "",
-  },
-  form: {
-    supplierId: null,
-    supplierName: '',
-    productId: null,
-    productName: '',
-    userId: userStore.userId,
-    nickname: '',
-    model: '',
-    productModelId: null,
-    unit: '',
-    productrecordId: null,
-    taxInclusiveUnitPrice: '',
-    taxInclusiveTotalPrice: '',
-    taxRate: '',
-    taxExclusiveTotalPrice: '',
-    inboundTime: '',
-    inboundBatch: '',
-    inboundQuantity: ''
-  },
+	searchForm: {
+		supplierName: "",
+	},
+	form: {
+		supplierId: null,
+		supplierName: '',
+		productId: null,
+		productName: '',
+		userId: userStore.userId,
+		nickName: '',
+		model: '',
+		productModelId: null,
+		unit: '',
+		productrecordId: null,
+		taxInclusiveUnitPrice: '',
+		taxInclusiveTotalPrice: '',
+		taxRate: '',
+		taxExclusiveTotalPrice: '',
+		inboundTime: '',
+		inboundBatch: '',
+		inboundQuantity: ''
+	},
 });
 const { searchForm } = toRefs(data);
 
 // 鏌ヨ鍒楄〃
 /** 鎼滅储鎸夐挳鎿嶄綔 */
 const handleQuery = () => {
-  page.current = 1;
-  getList();
+	page.current = 1;
+	getList();
 };
 const paginationChange = (obj) => {
-  page.current = obj.page;
-  page.size = obj.limit;
-  getList();
+	page.current = obj.page;
+	page.size = obj.limit;
+	getList();
 };
 const getList = () => {
-  tableLoading.value = true;
-  getStockOutPage({ ...searchForm.value, ...page })
-    .then((res) => {
-      tableLoading.value = false;
-      tableData.value = res.data.records;
-      tableData.value.map((item) => {
-        item.children = [];
-      });
-      total.value = res.data.total;
-    })
-    .catch(() => {
-      tableLoading.value = false;
-    });
+	tableLoading.value = true;
+	getStockOutPage({ ...searchForm.value, ...page })
+		.then((res) => {
+			tableLoading.value = false;
+			tableData.value = res.data.records;
+			tableData.value.map((item) => {
+				item.children = [];
+			});
+			total.value = res.data.total;
+		})
+		.catch(() => {
+			tableLoading.value = false;
+		});
 };
 
 // 琛ㄦ牸閫夋嫨鏁版嵁
 const handleSelectionChange = (selection) => {
-  // 杩囨护鎺夊瓙鏁版嵁
-  selectedRows.value = selection.filter((item) => item.id);
-  console.log("selection", selectedRows.value);
+	// 杩囨护鎺夊瓙鏁版嵁
+	selectedRows.value = selection.filter((item) => item.id);
+	console.log("selection", selectedRows.value);
 };
 const expandedRowKeys = ref([]);
 
 // 涓昏〃鍚堣鏂规硶
 const summarizeMainTable = (param) => {
-  return proxy.summarizeTable(param, [
-    "contractAmount",
-    "taxInclusiveTotalPrice",
-    "taxExclusiveTotalPrice",
-  ]);
+	return proxy.summarizeTable(param, [
+		"contractAmount",
+		"taxInclusiveTotalPrice",
+		"taxExclusiveTotalPrice",
+	]);
 };
 
 // 瀵煎嚭
 const handleOut = () => {
-  ElMessageBox.confirm("鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
-    confirmButtonText: "纭",
-    cancelButtonText: "鍙栨秷",
-    type: "warning",
-  })
-    .then(() => {
-      proxy.download("/stockmanagement/export", {}, "鍑哄簱鍙拌处.xlsx");
-    })
-    .catch(() => {
-      proxy.$modal.msg("宸插彇娑�");
-    });
+	ElMessageBox.confirm("鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
+		confirmButtonText: "纭",
+		cancelButtonText: "鍙栨秷",
+		type: "warning",
+	})
+		.then(() => {
+			proxy.download("/stockmanagement/export", {}, "鍑哄簱鍙拌处.xlsx");
+		})
+		.catch(() => {
+			proxy.$modal.msg("宸插彇娑�");
+		});
 };
 
 // 鍒犻櫎
 const handleDelete = () => {
-  let ids = [];
-  if (selectedRows.value.length > 0) {
-    ids = selectedRows.value.map((item) => item.id);
-  } else {
-    proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
-    return;
-  }
-  ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "瀵煎嚭", {
-    confirmButtonText: "纭",
-    cancelButtonText: "鍙栨秷",
-    type: "warning",
-  })
-    .then(() => {
-      delStockOut({ids:ids}).then((res) => {
-        proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
-        getList();
-      });
-    })
-    .catch(() => {
-      proxy.$modal.msg("宸插彇娑�");
-    });
+	let ids = [];
+	if (selectedRows.value.length > 0) {
+		ids = selectedRows.value.map((item) => item.id);
+	} else {
+		proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
+		return;
+	}
+	ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "瀵煎嚭", {
+		confirmButtonText: "纭",
+		cancelButtonText: "鍙栨秷",
+		type: "warning",
+	})
+		.then(() => {
+			delStockOut({ids:ids}).then((res) => {
+				proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+				getList();
+			});
+		})
+		.catch(() => {
+			proxy.$modal.msg("宸插彇娑�");
+		});
 };
 
 // 鎵撳嵃鍔熻兘
 const handlePrint = () => {
-  if (selectedRows.value.length === 0) {
-    proxy.$modal.msgWarning("璇烽�夋嫨瑕佹墦鍗扮殑鏁版嵁");
-    return;
-  }
-  printData.value = [...selectedRows.value];
-  console.log('鎵撳嵃鏁版嵁:', printData.value);
-  printPreviewVisible.value = true;
+	if (selectedRows.value.length === 0) {
+		proxy.$modal.msgWarning("璇烽�夋嫨瑕佹墦鍗扮殑鏁版嵁");
+		return;
+	}
+	printData.value = [...selectedRows.value];
+	console.log('鎵撳嵃鏁版嵁:', printData.value);
+	printPreviewVisible.value = true;
 };
 
 // 鎵ц鎵撳嵃
 const executePrint = () => {
-  console.log('寮�濮嬫墽琛屾墦鍗帮紝鏁版嵁鏉℃暟:', printData.value.length);
-  console.log('鎵撳嵃鏁版嵁:', printData.value);
-  
-  // 鍒涘缓涓�涓柊鐨勬墦鍗扮獥鍙�
-  const printWindow = window.open('', '_blank', 'width=800,height=600');
-  
-  // 鏋勫缓鎵撳嵃鍐呭
-  let printContent = `
+	console.log('寮�濮嬫墽琛屾墦鍗帮紝鏁版嵁鏉℃暟:', printData.value.length);
+	console.log('鎵撳嵃鏁版嵁:', printData.value);
+	
+	// 鍒涘缓涓�涓柊鐨勬墦鍗扮獥鍙�
+	const printWindow = window.open('', '_blank', 'width=800,height=600');
+	
+	// 鏋勫缓鎵撳嵃鍐呭
+	let printContent = `
     <!DOCTYPE html>
     <html>
     <head>
@@ -535,10 +536,10 @@
     </head>
     <body>
   `;
-  
-  // 涓烘瘡鏉℃暟鎹敓鎴愭墦鍗伴〉闈�
-  printData.value.forEach((item, index) => {
-    printContent += `
+	
+	// 涓烘瘡鏉℃暟鎹敓鎴愭墦鍗伴〉闈�
+	printData.value.forEach((item, index) => {
+		printContent += `
       <div class="print-page">
         <div class="delivery-note">
           <div class="header">
@@ -616,7 +617,7 @@
             <div class="footer-row">
               <div class="footer-item">
                 <span class="label">鎿嶄綔鍛橈細</span>
-                <span class="value">${userStore.nickname || '鎾曞紑鍓�'}</span>
+                <span class="value">${userStore.nickName || '鎾曞紑鍓�'}</span>
               </div>
               <div class="footer-item">
                 <span class="label">鎵撳嵃鏃ユ湡锛�</span>
@@ -627,227 +628,227 @@
         </div>
       </div>
     `;
-  });
-  
-  printContent += `
+	});
+	
+	printContent += `
     </body>
     </html>
   `;
-  
-  // 鍐欏叆鍐呭鍒版柊绐楀彛
-  printWindow.document.write(printContent);
-  printWindow.document.close();
-  
-  // 绛夊緟鍐呭鍔犺浇瀹屾垚鍚庢墦鍗�
-  printWindow.onload = () => {
-    setTimeout(() => {
-      printWindow.print();
-      printWindow.close();
-      printPreviewVisible.value = false;
-    }, 500);
-  };
+	
+	// 鍐欏叆鍐呭鍒版柊绐楀彛
+	printWindow.document.write(printContent);
+	printWindow.document.close();
+	
+	// 绛夊緟鍐呭鍔犺浇瀹屾垚鍚庢墦鍗�
+	printWindow.onload = () => {
+		setTimeout(() => {
+			printWindow.print();
+			printWindow.close();
+			printPreviewVisible.value = false;
+		}, 500);
+	};
 };
 
 
 
 // 鏍煎紡鍖栨棩鏈�
 const formatDate = (dateString) => {
-  if (!dateString) return getCurrentDate();
-  const date = new Date(dateString);
-  const year = date.getFullYear();
-  const month = String(date.getMonth() + 1).padStart(2, "0");
-  const day = String(date.getDate()).padStart(2, "0");
-  return `${year}/${month}/${day}`;
+	if (!dateString) return getCurrentDate();
+	const date = new Date(dateString);
+	const year = date.getFullYear();
+	const month = String(date.getMonth() + 1).padStart(2, "0");
+	const day = String(date.getDate()).padStart(2, "0");
+	return `${year}/${month}/${day}`;
 };
 
 // 鏍煎紡鍖栨棩鏈熸椂闂�
 const formatDateTime = (date) => {
-  const year = date.getFullYear();
-  const month = String(date.getMonth() + 1).padStart(2, "0");
-  const day = String(date.getDate()).padStart(2, "0");
-  const hours = String(date.getHours()).padStart(2, "0");
-  const minutes = String(date.getMinutes()).padStart(2, "0");
-  const seconds = String(date.getSeconds()).padStart(2, "0");
-  return `${year}/${month}/${day} ${hours}:${minutes}:${seconds}`;
+	const year = date.getFullYear();
+	const month = String(date.getMonth() + 1).padStart(2, "0");
+	const day = String(date.getDate()).padStart(2, "0");
+	const hours = String(date.getHours()).padStart(2, "0");
+	const minutes = String(date.getMinutes()).padStart(2, "0");
+	const seconds = String(date.getSeconds()).padStart(2, "0");
+	return `${year}/${month}/${day} ${hours}:${minutes}:${seconds}`;
 };
 // 鑾峰彇褰撳墠鏃ユ湡骞舵牸寮忓寲涓� YYYY-MM-DD
 function getCurrentDate() {
-  const today = new Date();
-  const year = today.getFullYear();
-  const month = String(today.getMonth() + 1).padStart(2, "0"); // 鏈堜唤浠�0寮�濮�
-  const day = String(today.getDate()).padStart(2, "0");
-  return `${year}-${month}-${day}`;
+	const today = new Date();
+	const year = today.getFullYear();
+	const month = String(today.getMonth() + 1).padStart(2, "0"); // 鏈堜唤浠�0寮�濮�
+	const day = String(today.getDate()).padStart(2, "0");
+	return `${year}-${month}-${day}`;
 }
 onMounted(() => {
-  getList();
+	getList();
 });
 </script>
 
 <style scoped lang="scss">
 .print-preview-dialog {
-  .el-dialog__body {
-    padding: 0;
-    max-height: 80vh;
-    overflow-y: auto;
-  }
+	.el-dialog__body {
+		padding: 0;
+		max-height: 80vh;
+		overflow-y: auto;
+	}
 }
 
 .print-preview-container {
-  .print-preview-header {
-    padding: 15px;
-    border-bottom: 1px solid #e4e7ed;
-    text-align: center;
-    
-    .el-button {
-      margin: 0 10px;
-    }
-  }
-  
-  .print-preview-content {
-  padding: 20px;
-  background-color: #f5f5f5;
-  min-height: 400px;
-}
+	.print-preview-header {
+		padding: 15px;
+		border-bottom: 1px solid #e4e7ed;
+		text-align: center;
+		
+		.el-button {
+			margin: 0 10px;
+		}
+	}
+	
+	.print-preview-content {
+		padding: 20px;
+		background-color: #f5f5f5;
+		min-height: 400px;
+	}
 }
 
 .print-page {
-  width: 220mm;
-  height: 90mm;
-  padding: 10mm;
-  margin: 0 auto;
-  background: white;
-  box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
-  margin-bottom: 10px;
-  box-sizing: border-box;
+	width: 220mm;
+	height: 90mm;
+	padding: 10mm;
+	margin: 0 auto;
+	background: white;
+	box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
+	margin-bottom: 10px;
+	box-sizing: border-box;
 }
 
 .delivery-note {
-  width: 100%;
-  height: 100%;
-  font-family: "SimSun", serif;
-  font-size: 10px;
-  line-height: 1.2;
-  display: flex;
-  flex-direction: column;
+	width: 100%;
+	height: 100%;
+	font-family: "SimSun", serif;
+	font-size: 10px;
+	line-height: 1.2;
+	display: flex;
+	flex-direction: column;
 }
 
 .header {
-  text-align: center;
-  margin-bottom: 8px;
-  
-  .company-name {
-    font-size: 18px;
-    font-weight: bold;
-    margin-bottom: 4px;
-  }
-  
-  .document-title {
-    font-size: 16px;
-    font-weight: bold;
-  }
+	text-align: center;
+	margin-bottom: 8px;
+	
+	.company-name {
+		font-size: 18px;
+		font-weight: bold;
+		margin-bottom: 4px;
+	}
+	
+	.document-title {
+		font-size: 16px;
+		font-weight: bold;
+	}
 }
 
 .info-section {
-  margin-bottom: 8px;
-  display: flex;
-  justify-content: space-between;
-  align-items: center;
-  
-  .info-row {
-    line-height: 20px;
-    
-    .label {
-      font-weight: bold;
-      width: 60px;
-      font-size: 14px;
-    }
-    
-    .value {
-      margin-right: 20px;
-      min-width: 80px;
-      font-size: 14px;
-    }
-  }
+	margin-bottom: 8px;
+	display: flex;
+	justify-content: space-between;
+	align-items: center;
+	
+	.info-row {
+		line-height: 20px;
+		
+		.label {
+			font-weight: bold;
+			width: 60px;
+			font-size: 14px;
+		}
+		
+		.value {
+			margin-right: 20px;
+			min-width: 80px;
+			font-size: 14px;
+		}
+	}
 }
 
 .table-section {
-  margin-bottom: 4px;
-  flex: 1;
-  
-  .product-table {
-    width: 100%;
-    border-collapse: collapse;
-    border: 1px solid #000;
-    
-         th, td {
-       border: 1px solid #000;
-       padding: 6px;
-       text-align: center;
-       font-size: 14px;
-       line-height: 1.4;
-     }
-    
-    th {
-      font-weight: bold;
-    }
-    
-    .total-label {
-      text-align: right;
-      font-weight: bold;
-    }
-    
-    .total-value {
-      font-weight: bold;
-    }
-  }
+	margin-bottom: 4px;
+	flex: 1;
+	
+	.product-table {
+		width: 100%;
+		border-collapse: collapse;
+		border: 1px solid #000;
+		
+		th, td {
+			border: 1px solid #000;
+			padding: 6px;
+			text-align: center;
+			font-size: 14px;
+			line-height: 1.4;
+		}
+		
+		th {
+			font-weight: bold;
+		}
+		
+		.total-label {
+			text-align: right;
+			font-weight: bold;
+		}
+		
+		.total-value {
+			font-weight: bold;
+		}
+	}
 }
 
 .footer-section {
-  .footer-row {
-    display: flex;
-    margin-bottom: 3px;
-    line-height: 20px;
-    justify-content: space-between;
-    
-         .footer-item {
-       display: flex;
-       margin-right: 20px;
-       
-       .label {
-         font-weight: bold;
-         width: 80px;
-         font-size: 14px;
-       }
-       
-       .value {
-         min-width: 80px;
-         font-size: 14px;
-       }
-       
-       &.address-item {
-         .address-value {
-           min-width: 200px;
-         }
-       }
-     }
-  }
+	.footer-row {
+		display: flex;
+		margin-bottom: 3px;
+		line-height: 20px;
+		justify-content: space-between;
+		
+		.footer-item {
+			display: flex;
+			margin-right: 20px;
+			
+			.label {
+				font-weight: bold;
+				width: 80px;
+				font-size: 14px;
+			}
+			
+			.value {
+				min-width: 80px;
+				font-size: 14px;
+			}
+			
+			&.address-item {
+				.address-value {
+					min-width: 200px;
+				}
+			}
+		}
+	}
 }
 
 @media print {
-  .app-container {
-    display: none;
-  }
-  
-           .print-page {
-      box-shadow: none;
-      margin: 0;
-      padding: 10mm;
-      padding-left: 20mm;
-      page-break-inside: avoid;
-      page-break-after: always;
-    }
-   .print-page:last-child {
-     page-break-after: avoid;
-   }
+	.app-container {
+		display: none;
+	}
+	
+	.print-page {
+		box-shadow: none;
+		margin: 0;
+		padding: 10mm;
+		padding-left: 20mm;
+		page-break-inside: avoid;
+		page-break-after: always;
+	}
+	.print-page:last-child {
+		page-break-after: avoid;
+	}
 }
 </style>
diff --git a/src/views/procurementManagement/index.vue b/src/views/procurementManagement/index.vue
index dd7c3c4..bf54384 100644
--- a/src/views/procurementManagement/index.vue
+++ b/src/views/procurementManagement/index.vue
@@ -101,6 +101,26 @@
       </el-col>
 
       <el-col :span="8">
+        <el-card class="module-card" shadow="hover" @click="navigateTo('/procurementManagement/procurementPlan')">
+          <div class="card-content">
+            <div class="card-icon">
+              <el-icon size="48" color="#9C27B0"><Calendar /></el-icon>
+            </div>
+            <div class="card-info">
+              <h3>閲囪喘璁″垝</h3>
+              <p>鏅鸿兘閲囪喘璁″垝閰嶇疆锛岃嚜鍔ㄨ绠楅噰璐渶姹傦紝鑰冭檻搴撳瓨鍜屽畨鍏ㄥ簱瀛�</p>
+              <div class="card-stats">
+                <span>娲昏穬璁″垝: {{ stats.activePlans }}</span>
+                <span>寰呰绠�: {{ stats.pendingCalculations }}</span>
+              </div>
+            </div>
+          </div>
+        </el-card>
+      </el-col>
+    </el-row>
+
+    <el-row :gutter="20" class="module-cards">
+      <el-col :span="8">
         <el-card class="module-card" shadow="hover" @click="navigateTo('/procurementManagement/procurementLedger')">
           <div class="card-content">
             <div class="card-icon">
@@ -112,6 +132,24 @@
               <div class="card-stats">
                 <span>鎬昏鍗�: {{ stats.totalOrders }}</span>
                 <span>鎬婚噾棰�: 楼{{ stats.totalAmount.toFixed(2) }}</span>
+              </div>
+            </div>
+          </div>
+        </el-card>
+      </el-col>
+
+      <el-col :span="8">
+        <el-card class="module-card" shadow="hover" @click="navigateTo('/procurementManagement/procurementReport')">
+          <div class="card-content">
+            <div class="card-icon">
+              <el-icon size="48" color="#FF6B6B"><TrendCharts /></el-icon>
+            </div>
+            <div class="card-info">
+              <h3>閲囪喘鎶ヨ〃</h3>
+              <p>閲囪喘璁㈠崟鎵ц姹囨�汇�佹槑缁嗗垎鏋愩�佷笟鍔$粺璁°�佷緵搴斿晢渚涜揣姹囨��</p>
+              <div class="card-stats">
+                <span>鎶ヨ〃绫诲瀷: 4绉�</span>
+                <span>鏁版嵁鏇存柊: 瀹炴椂</span>
               </div>
             </div>
           </div>
@@ -179,7 +217,7 @@
 <script setup>
 import { ref, onMounted } from 'vue'
 import { useRouter } from 'vue-router'
-import { Document, Box, Search, RefreshLeft, Money, List } from '@element-plus/icons-vue'
+import { Document, Box, Search, RefreshLeft, Money, List, Calendar, TrendCharts } from '@element-plus/icons-vue'
 
 const router = useRouter()
 
@@ -195,6 +233,8 @@
   approvedReturns: 3,
   activePrices: 45,
   pendingPrices: 2,
+  activePlans: 8,
+  pendingCalculations: 3,
   totalOrders: 30,
   totalAmount: 125.8,
   avgDeliveryTime: 7,
diff --git a/src/views/procurementManagement/procurementReport/index.vue b/src/views/procurementManagement/procurementReport/index.vue
index a12b4ba..33a0e91 100644
--- a/src/views/procurementManagement/procurementReport/index.vue
+++ b/src/views/procurementManagement/procurementReport/index.vue
@@ -112,9 +112,9 @@
           </div>
         </div>
         
-        <el-table :data="orderSummaryData" border v-loading="loading" stripe>
+        <el-table :data="orderSummaryData" border v-loading="loading" stripe style="width: 100%">
           <el-table-column label="璁㈠崟缂栧彿" prop="orderNo" width="180" fixed="left" />
-          <el-table-column label="渚涘簲鍟嗗悕绉�" prop="supplierName" width="150" />
+          <el-table-column label="渚涘簲鍟嗗悕绉�" prop="supplierName" min-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" />
@@ -160,11 +160,11 @@
           </div>
         </div>
         
-        <el-table :data="orderDetailData" border v-loading="loading" stripe>
+        <el-table :data="orderDetailData" border v-loading="loading" stripe style="width: 100%">
           <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="productName" min-width="200" />
+          <el-table-column label="瑙勬牸鍨嬪彿" prop="specification" min-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" />
@@ -204,11 +204,11 @@
           </div>
         </div>
         
-        <el-table :data="businessSummaryData" border v-loading="loading" stripe>
+        <el-table :data="businessSummaryData" border v-loading="loading" stripe style="width: 100%">
           <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="productName" min-width="200" />
+          <el-table-column label="瑙勬牸鍨嬪彿" prop="specification" min-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>
@@ -217,7 +217,7 @@
             <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="mainSupplier" min-width="150" />
           <el-table-column label="鏈�鍚庨噰璐棩鏈�" prop="lastPurchaseDate" width="120" />
         </el-table>
       </div>
@@ -242,9 +242,9 @@
           </div>
         </div>
         
-        <el-table :data="supplierSummaryData" border v-loading="loading" stripe>
+        <el-table :data="supplierSummaryData" border v-loading="loading" stripe style="width: 100%">
           <el-table-column label="渚涘簲鍟嗙紪鐮�" prop="supplierCode" width="120" fixed="left" />
-          <el-table-column label="渚涘簲鍟嗗悕绉�" prop="supplierName" width="200" />
+          <el-table-column label="渚涘簲鍟嗗悕绉�" prop="supplierName" min-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" />
@@ -805,6 +805,15 @@
 :deep(.el-table) {
   border-radius: 8px;
   overflow: hidden;
+  width: 100% !important;
+}
+
+:deep(.el-table__body-wrapper) {
+  width: 100% !important;
+}
+
+:deep(.el-table__header-wrapper) {
+  width: 100% !important;
 }
 
 :deep(.el-table th) {
diff --git a/src/views/salesManagement/salesLedger/index.vue b/src/views/salesManagement/salesLedger/index.vue
index afe56b5..7482d2e 100644
--- a/src/views/salesManagement/salesLedger/index.vue
+++ b/src/views/salesManagement/salesLedger/index.vue
@@ -36,6 +36,7 @@
           </el-button>
           <el-button @click="handleOut">瀵煎嚭</el-button>
           <el-button type="danger" plain @click="handleDelete">鍒犻櫎</el-button>
+          <el-button type="primary" plain @click="handlePrint">鎵撳嵃</el-button>
         </div>
       </div>
       <el-table :data="tableData" border v-loading="tableLoading" @selection-change="handleSelectionChange"
@@ -292,6 +293,120 @@
         </div>
       </template>
     </el-dialog>
+		<!-- 鎵撳嵃棰勮寮圭獥 -->
+		<el-dialog
+			v-model="printPreviewVisible"
+			title="鎵撳嵃棰勮"
+			width="90%"
+			:close-on-click-modal="false"
+			class="print-preview-dialog"
+		>
+			<div class="print-preview-container">
+				<div class="print-preview-header">
+					<el-button type="primary" @click="executePrint">鎵ц鎵撳嵃</el-button>
+					<el-button @click="printPreviewVisible = false">鍏抽棴棰勮</el-button>
+				</div>
+				<div class="print-preview-content">
+					<div v-if="printData.length === 0" style="text-align: center; padding: 50px; color: #999;">
+						鏆傛棤鎵撳嵃鏁版嵁
+					</div>
+					<div v-else style="text-align: center; padding: 10px; color: #666; font-size: 14px; background: #e8f4fd; margin-bottom: 10px;">
+						鍏� {{ printData.length }} 鏉℃暟鎹緟鎵撳嵃
+					</div>
+					<div v-for="(item, index) in printData" :key="index" class="print-page">
+						<div class="delivery-note">
+							<div class="header">
+								<div class="company-name">榧庤瘹鐟炲疄涓氭湁闄愯矗浠诲叕鍙�</div>
+								<div class="document-title">闆跺敭鍙戣揣鍗�</div>
+							</div>
+							
+							<div class="info-section">
+								<div class="info-row">
+									<div>
+										<span class="label">鍙戣揣鏃ユ湡锛�</span>
+										<span class="value">{{ formatDate(item.createTime) }}</span>
+									</div>
+									<div>
+										
+										<span class="label">瀹㈡埛鍚嶇О锛�</span>
+										<span class="value">{{ item.customerName || '寮犵埍鏈�' }}</span>
+									</div>
+								</div>
+								<div class="info-row">
+									<span class="label">鍗曞彿锛�</span>
+									<span class="value">{{ item.salesContractNo }}</span>
+								</div>
+							</div>
+							
+							<div class="table-section">
+								<table class="product-table">
+									<thead>
+									<tr>
+										<th>浜у搧鍚嶇О</th>
+										<th>瑙勬牸鍨嬪彿</th>
+										<th>鍗曚綅</th>
+										<th>鍗曚环</th>
+										<th>闆跺敭鏁伴噺</th>
+										<th>闆跺敭閲戦</th>
+									</tr>
+									</thead>
+									<tbody>
+									<tr v-for="product in item.products" :key="product.id">
+										<td>{{ product.productCategory || '' }}</td>
+										<td>{{ product.specificationModel || '' }}</td>
+										<td>{{ product.unit || '' }}</td>
+										<td>{{ product.taxInclusiveUnitPrice || '0' }}</td>
+										<td>{{ product.quantity || '0' }}</td>
+										<td>{{ product.taxInclusiveTotalPrice || '0' }}</td>
+									</tr>
+									<tr v-if="!item.products || item.products.length === 0">
+										<td colspan="6" style="text-align: center; color: #999;">鏆傛棤浜у搧鏁版嵁</td>
+									</tr>
+									</tbody>
+									<tfoot>
+									<tr>
+										<td class="label">鍚堣</td>
+										<td class="total-value"></td>
+										<td class="total-value"></td>
+										<td class="total-value"></td>
+										<td class="total-value">{{ getTotalQuantity(item.products) }}</td>
+										<td class="total-value">{{ getTotalAmount(item.products) }}</td>
+									</tr>
+									</tfoot>
+								</table>
+							</div>
+							
+							<div class="footer-section">
+								<div class="footer-row">
+									<div class="footer-item">
+										<span class="label">鏀惰揣鐢佃瘽锛�</span>
+										<span class="value"></span>
+									</div>
+									<div class="footer-item">
+										<span class="label">鏀惰揣浜猴細</span>
+										<span class="value"></span>
+									</div>
+									<div class="footer-item address-item">
+										<span class="label">鏀惰揣鍦板潃锛�</span>
+										<span class="value address-value"></span>
+									</div>
+								</div>
+								<div class="footer-row">
+									<div class="footer-item">
+										<span class="label">鎿嶄綔鍛橈細</span>
+										<span class="value">{{ userStore.nickName || '鎾曞紑鍓�' }}</span>
+									</div>
+									<div class="footer-item">
+										<span class="label">鎵撳嵃鏃ユ湡锛�</span>
+										<span class="value">{{ formatDateTime(new Date()) }}</span>
+									</div>
+								</div>
+							</div>
+						</div>
+					</div>
+				</div>
+			</div>
+		</el-dialog>
     <FileList ref="fileListRef" />
   </div>
 </template>
@@ -426,6 +541,9 @@
   // 璁剧疆涓婁紶鐨勮姹傚ご閮�
   headers: { Authorization: "Bearer " + getToken() },
 });
+// 鎵撳嵃鐩稿叧
+const printPreviewVisible = ref(false);
+const printData = ref([]);
 
 const changeDaterange = (value) => {
   if (value) {
@@ -790,6 +908,333 @@
       proxy.$modal.msg("宸插彇娑�");
     });
 };
+
+// 鎵撳嵃鍔熻兘
+const handlePrint = async () => {
+	if (selectedRows.value.length === 0) {
+		proxy.$modal.msgWarning("璇烽�夋嫨瑕佹墦鍗扮殑鏁版嵁");
+		return;
+	}
+	
+	// 鏄剧ず鍔犺浇鐘舵��
+	proxy.$modal.loading("姝e湪鑾峰彇浜у搧鏁版嵁锛岃绋嶅��...");
+	
+	try {
+		// 涓烘瘡涓�変腑鐨勯攢鍞彴璐﹁褰曟煡璇㈠搴旂殑浜у搧鏁版嵁
+		const printDataWithProducts = [];
+		
+		for (const row of selectedRows.value) {
+			try {
+				// 璋冪敤productList鎺ュ彛鏌ヨ浜у搧鏁版嵁
+				const productRes = await productList({ salesLedgerId: row.id, type: 1 });
+				
+				// 灏嗕骇鍝佹暟鎹暣鍚堝埌閿�鍞彴璐﹁褰曚腑
+				const rowWithProducts = {
+					...row,
+					products: productRes.data || []
+				};
+				
+				printDataWithProducts.push(rowWithProducts);
+			} catch (error) {
+				console.error(`鑾峰彇閿�鍞彴璐� ${row.id} 鐨勪骇鍝佹暟鎹け璐�:`, error);
+				// 鍗充娇鏌愪釜璁板綍鐨勪骇鍝佹暟鎹幏鍙栧け璐ワ紝涔熻鍖呭惈璇ヨ褰�
+				printDataWithProducts.push({
+					...row,
+					products: []
+				});
+			}
+		}
+		
+		printData.value = printDataWithProducts;
+		console.log('鎵撳嵃鏁版嵁锛堝寘鍚骇鍝侊級:', printData.value);
+		printPreviewVisible.value = true;
+		
+	} catch (error) {
+		console.error('鑾峰彇浜у搧鏁版嵁澶辫触:', error);
+		proxy.$modal.msgError("鑾峰彇浜у搧鏁版嵁澶辫触锛岃閲嶈瘯");
+	} finally {
+		proxy.$modal.closeLoading();
+	}
+};
+// 鎵ц鎵撳嵃
+const executePrint = () => {
+	console.log('寮�濮嬫墽琛屾墦鍗帮紝鏁版嵁鏉℃暟:', printData.value.length);
+	console.log('鎵撳嵃鏁版嵁:', printData.value);
+	
+	// 鍒涘缓涓�涓柊鐨勬墦鍗扮獥鍙�
+	const printWindow = window.open('', '_blank', 'width=800,height=600');
+	
+	// 鏋勫缓鎵撳嵃鍐呭
+	let printContent = `
+    <!DOCTYPE html>
+    <html>
+    <head>
+      <meta charset="UTF-8">
+      <title>鎵撳嵃棰勮</title>
+      <style>
+        body {
+          margin: 0;
+          padding: 0;
+          font-family: "SimSun", serif;
+          background: white;
+        }
+                                                     .print-page {
+            width: 200mm;
+            height: 75mm;
+            padding: 10mm;
+            padding-left: 20mm;
+            background: white;
+            box-sizing: border-box;
+            page-break-after: always;
+            page-break-inside: avoid;
+          }
+         .print-page:last-child {
+           page-break-after: avoid;
+         }
+        .delivery-note {
+          width: 100%;
+          height: 100%;
+          font-size: 12px;
+          line-height: 1.2;
+          display: flex;
+          flex-direction: column;
+          color: #000;
+        }
+        .header {
+          text-align: center;
+          margin-bottom: 8px;
+        }
+        .company-name {
+          font-size: 18px;
+          font-weight: bold;
+          margin-bottom: 4px;
+        }
+        .document-title {
+          font-size: 16px;
+          font-weight: bold;
+        }
+        .info-section {
+          margin-bottom: 8px;
+          display: flex;
+          justify-content: space-between;
+          align-items: center;
+        }
+        .info-row {
+          line-height: 20px;
+        }
+        .label {
+          font-weight: bold;
+          width: 60px;
+          font-size: 12px;
+        }
+        .value {
+          margin-right: 20px;
+          min-width: 80px;
+          font-size: 12px;
+        }
+                 .table-section {
+                 margin-bottom: 40px;
+          //  flex: 0.6;
+         }
+        .product-table {
+          width: 100%;
+          border-collapse: collapse;
+          border: 1px solid #000;
+        }
+                 .product-table th, .product-table td {
+           border: 1px solid #000;
+           padding: 6px;
+           text-align: center;
+           font-size: 12px;
+           line-height: 1.4;
+         }
+        .product-table th {
+          font-weight: bold;
+        }
+        .total-value {
+          font-weight: bold;
+        }
+        .footer-section {
+          margin-top: auto;
+        }
+        .footer-row {
+          display: flex;
+          margin-bottom: 3px;
+          line-height: 22px;
+          justify-content: space-between;
+        }
+        .footer-item {
+          display: flex;
+          margin-right: 20px;
+        }
+        .footer-item .label {
+          font-weight: bold;
+          width: 80px;
+          font-size: 12px;
+        }
+        .footer-item .value {
+          min-width: 80px;
+          font-size: 12px;
+        }
+        .address-item .address-value {
+          min-width: 200px;
+        }
+        @media print {
+          body {
+            margin: 0;
+            padding: 0;
+          }
+                     .print-page {
+             margin: 0;
+             padding: 10mm;
+             /* padding-left: 20mm; */
+             page-break-inside: avoid;
+             page-break-after: always;
+           }
+           .print-page:last-child {
+             page-break-after: avoid;
+           }
+        }
+      </style>
+    </head>
+    <body>
+  `;
+	
+	// 涓烘瘡鏉℃暟鎹敓鎴愭墦鍗伴〉闈�
+	printData.value.forEach((item, index) => {
+		printContent += `
+      <div class="print-page">
+        <div class="delivery-note">
+          <div class="header">
+            <div class="company-name">榧庤瘹鐟炲疄涓氭湁闄愯矗浠诲叕鍙�</div>
+            <div class="document-title">闆跺敭鍙戣揣鍗�</div>
+          </div>
+          
+          <div class="info-section">
+            <div class="info-row">
+              <div>
+                <span class="label">鍙戣揣鏃ユ湡锛�</span>
+                <span class="value">${formatDate(item.createTime)}</span>
+              </div>
+              <div>
+                <span class="label">瀹㈡埛鍚嶇О锛�</span>
+                <span class="value">${item.customerName || '寮犵埍鏈�'}</span>
+              </div>
+            </div>
+            <div class="info-row">
+              <span class="label">鍗曞彿锛�</span>
+              <span class="value">${item.salesContractNo || ''}</span>
+            </div>
+          </div>
+
+          <div class="table-section">
+            <table class="product-table">
+              <thead>
+                <tr>
+                  <th>浜у搧鍚嶇О</th>
+                  <th>瑙勬牸鍨嬪彿</th>
+                  <th>鍗曚綅</th>
+                  <th>鍗曚环</th>
+                  <th>闆跺敭鏁伴噺</th>
+                  <th>闆跺敭閲戦</th>
+                </tr>
+              </thead>
+              <tbody>
+                ${item.products && item.products.length > 0 ? 
+                  item.products.map(product => `
+                    <tr>
+                      <td>${product.productCategory || ''}</td>
+                      <td>${product.specificationModel || ''}</td>
+                      <td>${product.unit || ''}</td>
+                      <td>${product.taxInclusiveUnitPrice || '0'}</td>
+                      <td>${product.quantity || '0'}</td>
+                      <td>${product.taxInclusiveTotalPrice || '0'}</td>
+                    </tr>
+                  `).join('') : 
+                  '<tr><td colspan="6" style="text-align: center; color: #999;">鏆傛棤浜у搧鏁版嵁</td></tr>'
+                }
+              </tbody>
+              <tfoot>
+                <tr>
+                  <td class="label">鍚堣</td>
+                  <td class="total-value"></td>
+                  <td class="total-value"></td>
+                  <td class="total-value"></td>
+                  <td class="total-value">${getTotalQuantityForPrint(item.products)}</td>
+                  <td class="total-value">${getTotalAmountForPrint(item.products)}</td>
+                </tr>
+              </tfoot>
+            </table>
+          </div>
+
+          <div class="footer-section">
+            <div class="footer-row">
+              <div class="footer-item">
+                <span class="label">鏀惰揣鐢佃瘽锛�</span>
+                <span class="value"></span>
+              </div>
+              <div class="footer-item">
+                <span class="label">鏀惰揣浜猴細</span>
+                <span class="value"></span>
+              </div>
+              <div class="footer-item address-item">
+                <span class="label">鏀惰揣鍦板潃锛�</span>
+                <span class="value address-value"></span>
+              </div>
+            </div>
+            <div class="footer-row">
+              <div class="footer-item">
+                <span class="label">鎿嶄綔鍛橈細</span>
+                <span class="value">${userStore.nickName || '鎾曞紑鍓�'}</span>
+              </div>
+              <div class="footer-item">
+                <span class="label">鎵撳嵃鏃ユ湡锛�</span>
+                <span class="value">${formatDateTime(new Date())}</span>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+    `;
+	});
+	
+	printContent += `
+    </body>
+    </html>
+  `;
+	
+	// 鍐欏叆鍐呭鍒版柊绐楀彛
+	printWindow.document.write(printContent);
+	printWindow.document.close();
+	
+	// 绛夊緟鍐呭鍔犺浇瀹屾垚鍚庢墦鍗�
+	printWindow.onload = () => {
+		setTimeout(() => {
+			printWindow.print();
+			printWindow.close();
+			printPreviewVisible.value = false;
+		}, 500);
+	};
+};
+// 鏍煎紡鍖栨棩鏈�
+const formatDate = (dateString) => {
+	if (!dateString) return getCurrentDate();
+	const date = new Date(dateString);
+	const year = date.getFullYear();
+	const month = String(date.getMonth() + 1).padStart(2, "0");
+	const day = String(date.getDate()).padStart(2, "0");
+	return `${year}/${month}/${day}`;
+};
+// 鏍煎紡鍖栨棩鏈熸椂闂�
+const formatDateTime = (date) => {
+	const year = date.getFullYear();
+	const month = String(date.getMonth() + 1).padStart(2, "0");
+	const day = String(date.getDate()).padStart(2, "0");
+	const hours = String(date.getHours()).padStart(2, "0");
+	const minutes = String(date.getMinutes()).padStart(2, "0");
+	const seconds = String(date.getSeconds()).padStart(2, "0");
+	return `${year}/${month}/${day} ${hours}:${minutes}:${seconds}`;
+};
 // 鑾峰彇褰撳墠鏃ユ湡骞舵牸寮忓寲涓� YYYY-MM-DD
 function getCurrentDate() {
   const today = new Date();
@@ -798,6 +1243,41 @@
   const day = String(today.getDate()).padStart(2, "0");
   return `${year}-${month}-${day}`;
 }
+
+// 璁$畻浜у搧鎬绘暟閲�
+const getTotalQuantity = (products) => {
+  if (!products || products.length === 0) return '0';
+  const total = products.reduce((sum, product) => {
+    return sum + (parseFloat(product.quantity) || 0);
+  }, 0);
+  return total.toFixed(2);
+};
+
+// 璁$畻浜у搧鎬婚噾棰�
+const getTotalAmount = (products) => {
+  if (!products || products.length === 0) return '0';
+  const total = products.reduce((sum, product) => {
+    return sum + (parseFloat(product.taxInclusiveTotalPrice) || 0);
+  }, 0);
+  return total.toFixed(2);
+};
+
+// 鐢ㄤ簬鎵撳嵃鐨勮绠楀嚱鏁�
+const getTotalQuantityForPrint = (products) => {
+  if (!products || products.length === 0) return '0';
+  const total = products.reduce((sum, product) => {
+    return sum + (parseFloat(product.quantity) || 0);
+  }, 0);
+  return total.toFixed(2);
+};
+
+const getTotalAmountForPrint = (products) => {
+  if (!products || products.length === 0) return '0';
+  const total = products.reduce((sum, product) => {
+    return sum + (parseFloat(product.taxInclusiveTotalPrice) || 0);
+  }, 0);
+  return total.toFixed(2);
+};
 
 const mathNum = () => {
   console.log("productForm.value", productForm.value);
@@ -1001,4 +1481,170 @@
   justify-content: space-between;
   margin-bottom: 10px;
 }
+.print-preview-dialog {
+	.el-dialog__body {
+		padding: 0;
+		max-height: 80vh;
+		overflow-y: auto;
+	}
+}
+
+.print-preview-container {
+	.print-preview-header {
+		padding: 15px;
+		border-bottom: 1px solid #e4e7ed;
+		text-align: center;
+		
+		.el-button {
+			margin: 0 10px;
+		}
+	}
+	
+	.print-preview-content {
+		padding: 20px;
+		background-color: #f5f5f5;
+		min-height: 400px;
+	}
+}
+
+.print-page {
+	width: 220mm;
+	height: 90mm;
+	padding: 10mm;
+	margin: 0 auto;
+	background: white;
+	box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
+	margin-bottom: 10px;
+	box-sizing: border-box;
+}
+
+.delivery-note {
+	width: 100%;
+	height: 100%;
+	font-family: "SimSun", serif;
+	font-size: 10px;
+	line-height: 1.2;
+	display: flex;
+	flex-direction: column;
+}
+
+.header {
+	text-align: center;
+	margin-bottom: 8px;
+	
+	.company-name {
+		font-size: 18px;
+		font-weight: bold;
+		margin-bottom: 4px;
+	}
+	
+	.document-title {
+		font-size: 16px;
+		font-weight: bold;
+	}
+}
+
+.info-section {
+	margin-bottom: 8px;
+	display: flex;
+	justify-content: space-between;
+	align-items: center;
+	
+	.info-row {
+		line-height: 20px;
+		
+		.label {
+			font-weight: bold;
+			width: 60px;
+			font-size: 14px;
+		}
+		
+		.value {
+			margin-right: 20px;
+			min-width: 80px;
+			font-size: 14px;
+		}
+	}
+}
+
+.table-section {
+	margin-bottom: 4px;
+	flex: 1;
+	
+	.product-table {
+		width: 100%;
+		border-collapse: collapse;
+		border: 1px solid #000;
+		
+		th, td {
+			border: 1px solid #000;
+			padding: 6px;
+			text-align: center;
+			font-size: 14px;
+			line-height: 1.4;
+		}
+		
+		th {
+			font-weight: bold;
+		}
+		
+		.total-label {
+			text-align: right;
+			font-weight: bold;
+		}
+		
+		.total-value {
+			font-weight: bold;
+		}
+	}
+}
+
+.footer-section {
+	.footer-row {
+		display: flex;
+		margin-bottom: 3px;
+		line-height: 20px;
+		justify-content: space-between;
+		
+		.footer-item {
+			display: flex;
+			margin-right: 20px;
+			
+			.label {
+				font-weight: bold;
+				width: 80px;
+				font-size: 14px;
+			}
+			
+			.value {
+				min-width: 80px;
+				font-size: 14px;
+			}
+			
+			&.address-item {
+				.address-value {
+					min-width: 200px;
+				}
+			}
+		}
+	}
+}
+
+@media print {
+	.app-container {
+		display: none;
+	}
+	
+	.print-page {
+		box-shadow: none;
+		margin: 0;
+		padding: 10mm;
+		padding-left: 20mm;
+		page-break-inside: avoid;
+		page-break-after: always;
+	}
+	.print-page:last-child {
+		page-break-after: avoid;
+	}
+}
 </style>
diff --git a/src/views/salesManagement/salesQuotation/index.vue b/src/views/salesManagement/salesQuotation/index.vue
new file mode 100644
index 0000000..b89dad1
--- /dev/null
+++ b/src/views/salesManagement/salesQuotation/index.vue
@@ -0,0 +1,604 @@
+<template>
+  <div class="app-container">
+    <el-card class="box-card">
+      <!-- 鎼滅储鍖哄煙 -->
+      <el-row :gutter="20" class="search-row">
+        <el-col :span="6">
+          <el-input
+            v-model="searchForm.quotationNo"
+            placeholder="璇疯緭鍏ユ姤浠峰崟鍙�"
+            clearable
+            @keyup.enter="handleSearch"
+          >
+            <template #prefix>
+              <el-icon><Search /></el-icon>
+            </template>
+          </el-input>
+        </el-col>
+        <el-col :span="6">
+          <el-select v-model="searchForm.customer" placeholder="璇烽�夋嫨瀹㈡埛" clearable>
+            <el-option label="涓婃捣绉戞妧鏈夐檺鍏徃" value="涓婃捣绉戞妧鏈夐檺鍏徃"></el-option>
+            <el-option label="娣卞湷鐢靛瓙鏈夐檺鍏徃" value="娣卞湷鐢靛瓙鏈夐檺鍏徃"></el-option>
+            <el-option label="鍖椾含璐告槗鍏徃" value="鍖椾含璐告槗鍏徃"></el-option>
+          </el-select>
+        </el-col>
+        <el-col :span="6">
+          <el-select v-model="searchForm.status" placeholder="璇烽�夋嫨鎶ヤ环鐘舵��" clearable>
+            <el-option label="鑽夌" value="鑽夌"></el-option>
+            <el-option label="宸插彂閫�" value="宸插彂閫�"></el-option>
+            <el-option label="瀹㈡埛纭" value="瀹㈡埛纭"></el-option>
+            <el-option label="宸茶繃鏈�" value="宸茶繃鏈�"></el-option>
+          </el-select>
+        </el-col>
+        <el-col :span="6">
+          <el-button type="primary" @click="handleSearch">鎼滅储</el-button>
+          <el-button @click="resetSearch">閲嶇疆</el-button>
+          <el-button style="float: right;" type="primary" @click="handleAdd">
+            鏂板鎶ヤ环
+          </el-button>
+        </el-col>
+      </el-row>
+
+      <!-- 鎶ヤ环鍒楄〃 -->
+      <el-table
+        :data="filteredList"
+        style="width: 100%"
+        v-loading="loading"
+        border
+        stripe
+        height="calc(100vh - 22em)"
+      >
+        <el-table-column prop="id" label="ID" width="80" align="center"/>
+        <el-table-column prop="quotationNo" label="鎶ヤ环鍗曞彿" width="150" />
+        <el-table-column prop="customer" label="瀹㈡埛鍚嶇О" />
+        <el-table-column prop="salesperson" label="涓氬姟鍛�" width="100" />
+        <el-table-column prop="quotationDate" label="鎶ヤ环鏃ユ湡" width="120" />
+        <el-table-column prop="validDate" label="鏈夋晥鏈熻嚦" width="120" />
+        <el-table-column prop="totalAmount" label="鎶ヤ环閲戦" width="120">
+          <template #default="scope">
+            楼{{ scope.row.totalAmount.toFixed(2) }}
+          </template>
+        </el-table-column>
+        <el-table-column prop="status" label="鎶ヤ环鐘舵��" width="100">
+          <template #default="scope">
+            <el-tag :type="getStatusType(scope.row.status)">
+              {{ scope.row.status }}
+            </el-tag>
+          </template>
+        </el-table-column>
+        <el-table-column label="鎿嶄綔" width="250" fixed="right" align="center">
+          <template #default="scope">
+            <el-button link type="primary" @click="handleView(scope.row)">鏌ョ湅</el-button>
+            <el-button link type="primary" @click="handleEdit(scope.row)" v-if="scope.row.status === '鑽夌'">缂栬緫</el-button>
+            <el-button link type="danger" @click="handleDelete(scope.row)" v-if="scope.row.status === '鑽夌'">鍒犻櫎</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+
+      <!-- 鍒嗛〉 -->
+      <pagination
+        :total="pagination.total"
+        layout="total, sizes, prev, pager, next, jumper"
+        :page="pagination.currentPage"
+        :limit="pagination.pageSize"
+        @pagination="handleCurrentChange"
+      />
+    </el-card>
+
+    <!-- 鏂板/缂栬緫瀵硅瘽妗� -->
+    <el-dialog v-model="dialogVisible" :title="dialogTitle" width="900px" :close-on-click-modal="false">
+      <el-form :model="form" :rules="rules" ref="formRef" label-width="100px">
+        <!-- 鍩烘湰淇℃伅 -->
+        <el-card class="form-card" shadow="never">
+          <template #header>
+            <span class="card-title">鍩烘湰淇℃伅</span>
+          </template>
+          <el-row :gutter="20">
+            <el-col :span="12">
+              <el-form-item label="瀹㈡埛鍚嶇О" prop="customer">
+                <el-select v-model="form.customer" placeholder="璇烽�夋嫨瀹㈡埛" style="width: 100%" @change="handleCustomerChange">
+                  <el-option label="涓婃捣绉戞妧鏈夐檺鍏徃" value="涓婃捣绉戞妧鏈夐檺鍏徃"></el-option>
+                  <el-option label="娣卞湷鐢靛瓙鏈夐檺鍏徃" value="娣卞湷鐢靛瓙鏈夐檺鍏徃"></el-option>
+                  <el-option label="鍖椾含璐告槗鍏徃" value="鍖椾含璐告槗鍏徃"></el-option>
+                </el-select>
+              </el-form-item>
+            </el-col>
+            <el-col :span="12">
+              <el-form-item label="涓氬姟鍛�" prop="salesperson">
+                <el-select v-model="form.salesperson" placeholder="璇烽�夋嫨涓氬姟鍛�" style="width: 100%">
+                  <el-option label="闄堝織寮�" value="闄堝織寮�"></el-option>
+                  <el-option label="鍒橀泤濠�" value="鍒橀泤濠�"></el-option>
+                  <el-option label="鐜嬪缓鍥�" value="鐜嬪缓鍥�"></el-option>
+                </el-select>
+              </el-form-item>
+            </el-col>
+          </el-row>
+          <el-row :gutter="20">
+            <el-col :span="12">
+              <el-form-item label="鎶ヤ环鏃ユ湡" prop="quotationDate">
+                <el-date-picker
+                  v-model="form.quotationDate"
+                  type="date"
+                  placeholder="閫夋嫨鎶ヤ环鏃ユ湡"
+                  style="width: 100%"
+                  format="YYYY-MM-DD"
+                  value-format="YYYY-MM-DD"
+                />
+              </el-form-item>
+            </el-col>
+            <el-col :span="12">
+              <el-form-item label="鏈夋晥鏈熻嚦" prop="validDate">
+                <el-date-picker
+                  v-model="form.validDate"
+                  type="date"
+                  placeholder="閫夋嫨鏈夋晥鏈�"
+                  style="width: 100%"
+                  format="YYYY-MM-DD"
+                  value-format="YYYY-MM-DD"
+                />
+              </el-form-item>
+            </el-col>
+          </el-row>
+          <el-row :gutter="20">
+            <el-col :span="12">
+              <el-form-item label="浠樻鏂瑰紡" prop="paymentMethod">
+                <el-select v-model="form.paymentMethod" placeholder="璇烽�夋嫨浠樻鏂瑰紡" style="width: 100%">
+                  <el-option label="鍏ㄦ鍒颁粯" value="鍏ㄦ鍒颁粯"></el-option>
+                  <el-option label="鍒嗘湡浠樻" value="鍒嗘湡浠樻"></el-option>
+                  <el-option label="鏈堢粨" value="鏈堢粨"></el-option>
+                </el-select>
+              </el-form-item>
+            </el-col>
+            <el-col :span="12">
+              <el-form-item label="浜よ揣鏈�" prop="deliveryPeriod">
+                <el-input v-model="form.deliveryPeriod" placeholder="璇疯緭鍏ヤ氦璐ф湡" />
+              </el-form-item>
+            </el-col>
+          </el-row>
+        </el-card>
+
+        <!-- 浜у搧淇℃伅 -->
+        <el-card class="form-card" shadow="never">
+          <template #header>
+            <div class="card-header">
+              <span class="card-title">浜у搧淇℃伅</span>
+              <el-button type="primary" size="small" @click="addProduct">娣诲姞浜у搧</el-button>
+            </div>
+          </template>
+          <el-table :data="form.products" border style="width: 100%">
+            <el-table-column prop="productName" label="浜у搧鍚嶇О" width="200">
+              <template #default="scope">
+                <el-input v-model="scope.row.productName" placeholder="璇疯緭鍏ヤ骇鍝佸悕绉�" />
+              </template>
+            </el-table-column>
+            <el-table-column prop="specification" label="瑙勬牸鍨嬪彿" width="150">
+              <template #default="scope">
+                <el-input v-model="scope.row.specification" placeholder="瑙勬牸鍨嬪彿" />
+              </template>
+            </el-table-column>
+            <el-table-column prop="quantity" label="鏁伴噺" width="100">
+              <template #default="scope">
+                <el-input-number v-model="scope.row.quantity" :min="1" :precision="0" style="width: 100%" />
+              </template>
+            </el-table-column>
+            <el-table-column prop="unit" label="鍗曚綅" width="80">
+              <template #default="scope">
+                <el-input v-model="scope.row.unit" placeholder="鍗曚綅" />
+              </template>
+            </el-table-column>
+            <el-table-column prop="unitPrice" label="鍗曚环" width="120">
+              <template #default="scope">
+                <el-input-number v-model="scope.row.unitPrice" :min="0" :precision="2" style="width: 100%" @change="calculateAmount(scope.row)" />
+              </template>
+            </el-table-column>
+            <el-table-column prop="amount" label="閲戦" width="120">
+              <template #default="scope">
+                <span>楼{{ scope.row.amount.toFixed(2) }}</span>
+              </template>
+            </el-table-column>
+            <el-table-column label="鎿嶄綔" width="80" align="center">
+              <template #default="scope">
+                <el-button link type="danger" @click="removeProduct(scope.$index)">鍒犻櫎</el-button>
+              </template>
+            </el-table-column>
+          </el-table>
+        </el-card>
+
+        <!-- 璐圭敤淇℃伅 -->
+        <el-card class="form-card" shadow="never">
+          <template #header>
+            <span class="card-title">璐圭敤淇℃伅</span>
+          </template>
+          <el-row :gutter="20">
+            <el-col :span="8">
+              <el-form-item label="浜у搧灏忚">
+                <el-input-number v-model="form.subtotal" :precision="2" :min="0" style="width: 100%" readonly />
+              </el-form-item>
+            </el-col>
+            <el-col :span="8">
+              <el-form-item label="杩愯垂">
+                <el-input-number v-model="form.freight" :precision="2" :min="0" style="width: 100%" @change="calculateTotal" />
+              </el-form-item>
+            </el-col>
+            <el-col :span="8">
+              <el-form-item label="鍏朵粬璐圭敤">
+                <el-input-number v-model="form.otherFee" :precision="2" :min="0" style="width: 100%" @change="calculateTotal" />
+              </el-form-item>
+            </el-col>
+          </el-row>
+          <el-row :gutter="20">
+            <el-col :span="8">
+              <el-form-item label="鎶樻墸鐜�(%)">
+                <el-input-number v-model="form.discountRate" :precision="2" :min="0" :max="100" style="width: 100%" @change="calculateTotal" />
+              </el-form-item>
+            </el-col>
+            <el-col :span="8">
+              <el-form-item label="鎶樻墸閲戦">
+                <el-input-number v-model="form.discountAmount" :precision="2" :min="0" style="width: 100%" readonly />
+              </el-form-item>
+            </el-col>
+            <el-col :span="8">
+              <el-form-item label="鎶ヤ环鎬婚">
+                <el-input-number v-model="form.totalAmount" :precision="2" :min="0" style="width: 100%" readonly />
+              </el-form-item>
+            </el-col>
+          </el-row>
+        </el-card>
+
+        <!-- 澶囨敞淇℃伅 -->
+        <el-card class="form-card" shadow="never">
+          <template #header>
+            <span class="card-title">澶囨敞淇℃伅</span>
+          </template>
+          <el-form-item label="澶囨敞" prop="remark">
+            <el-input type="textarea" v-model="form.remark" placeholder="璇疯緭鍏ュ娉ㄤ俊鎭�" rows="3"></el-input>
+          </el-form-item>
+        </el-card>
+      </el-form>
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button @click="dialogVisible = false">鍙� 娑�</el-button>
+          <el-button type="primary" @click="handleSubmit">纭� 瀹�</el-button>
+        </div>
+      </template>
+    </el-dialog>
+
+    <!-- 鏌ョ湅璇︽儏瀵硅瘽妗� -->
+    <el-dialog v-model="viewDialogVisible" title="鎶ヤ环璇︽儏" width="800px">
+      <el-descriptions :column="2" border>
+        <el-descriptions-item label="鎶ヤ环鍗曞彿">{{ currentQuotation.quotationNo }}</el-descriptions-item>
+        <el-descriptions-item label="瀹㈡埛鍚嶇О">{{ currentQuotation.customer }}</el-descriptions-item>
+        <el-descriptions-item label="涓氬姟鍛�">{{ currentQuotation.salesperson }}</el-descriptions-item>
+        <el-descriptions-item label="鎶ヤ环鏃ユ湡">{{ currentQuotation.quotationDate }}</el-descriptions-item>
+        <el-descriptions-item label="鏈夋晥鏈熻嚦">{{ currentQuotation.validDate }}</el-descriptions-item>
+        <el-descriptions-item label="浠樻鏂瑰紡">{{ currentQuotation.paymentMethod }}</el-descriptions-item>
+        <el-descriptions-item label="浜よ揣鏈�">{{ currentQuotation.deliveryPeriod }}</el-descriptions-item>
+        <el-descriptions-item label="鎶ヤ环鐘舵��">
+          <el-tag :type="getStatusType(currentQuotation.status)">{{ currentQuotation.status }}</el-tag>
+        </el-descriptions-item>
+        <el-descriptions-item label="鎶ヤ环鎬婚" :span="2">
+          <span style="font-size: 18px; color: #e6a23c; font-weight: bold;">楼{{ currentQuotation.totalAmount?.toFixed(2) }}</span>
+        </el-descriptions-item>
+      </el-descriptions>
+      
+      <div style="margin-top: 20px;">
+        <h4>浜у搧鏄庣粏</h4>
+        <el-table :data="currentQuotation.products" border style="width: 100%">
+          <el-table-column prop="productName" label="浜у搧鍚嶇О" />
+          <el-table-column prop="specification" label="瑙勬牸鍨嬪彿" />
+          <el-table-column prop="quantity" label="鏁伴噺" />
+          <el-table-column prop="unit" label="鍗曚綅" />
+          <el-table-column prop="unitPrice" label="鍗曚环">
+            <template #default="scope">
+              楼{{ scope.row.unitPrice.toFixed(2) }}
+            </template>
+          </el-table-column>
+          <el-table-column prop="amount" label="閲戦">
+            <template #default="scope">
+              楼{{ scope.row.amount.toFixed(2) }}
+            </template>
+          </el-table-column>
+        </el-table>
+      </div>
+
+      <div v-if="currentQuotation.remark" style="margin-top: 20px;">
+        <h4>澶囨敞</h4>
+        <p>{{ currentQuotation.remark }}</p>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script setup>
+import { ref, reactive, computed } from 'vue'
+import { ElMessage, ElMessageBox } from 'element-plus'
+import { Search } from '@element-plus/icons-vue'
+import Pagination from '@/components/PIMTable/Pagination.vue'
+
+// 鍝嶅簲寮忔暟鎹�
+const loading = ref(false)
+const searchForm = reactive({
+  quotationNo: '',
+  customer: '',
+  status: ''
+})
+
+const quotationList = ref([
+  {
+    id: 1,
+    quotationNo: 'QT202312001',
+    customer: '涓婃捣绉戞妧鏈夐檺鍏徃',
+    salesperson: '闄堝織寮�',
+    quotationDate: '2023-12-01',
+    validDate: '2023-12-31',
+    totalAmount: 50000.00,
+    paymentMethod: '鍏ㄦ鍒颁粯',
+    deliveryPeriod: '30澶�',
+    status: '宸插彂閫�',
+    remark: '閲嶈瀹㈡埛鎶ヤ环',
+    products: [
+      { productName: '宸ヤ笟浼犳劅鍣�', specification: 'SEN-001', quantity: 10, unit: '涓�', unitPrice: 5000, amount: 50000 }
+    ]
+  },
+  {
+    id: 2,
+    quotationNo: 'QT202312002',
+    customer: '娣卞湷鐢靛瓙鏈夐檺鍏徃',
+    salesperson: '鍒橀泤濠�',
+    quotationDate: '2023-12-02',
+    validDate: '2023-12-31',
+    totalAmount: 35000.00,
+    paymentMethod: '鍒嗘湡浠樻',
+    deliveryPeriod: '20澶�',
+    status: '瀹㈡埛纭',
+    remark: '甯歌鎶ヤ环',
+    products: [
+      { productName: '鎺у埗妯″潡', specification: 'CTL-002', quantity: 5, unit: '涓�', unitPrice: 7000, amount: 35000 }
+    ]
+  },
+  {
+    id: 3,
+    quotationNo: 'QT202312003',
+    customer: '鍖椾含璐告槗鍏徃',
+    salesperson: '鐜嬪缓鍥�',
+    quotationDate: '2023-12-03',
+    validDate: '2023-12-31',
+    totalAmount: 28000.00,
+    paymentMethod: '鏈堢粨',
+    deliveryPeriod: '15澶�',
+    status: '鑽夌',
+    remark: '鏂板鎴锋姤浠�',
+    products: [
+      { productName: '鏁版嵁閲囬泦鍣�', specification: 'DAQ-003', quantity: 4, unit: '涓�', unitPrice: 7000, amount: 28000 }
+    ]
+  }
+])
+
+const pagination = reactive({
+  total: 3,
+  currentPage: 1,
+  pageSize: 10
+})
+
+const dialogVisible = ref(false)
+const viewDialogVisible = ref(false)
+const dialogTitle = ref('鏂板鎶ヤ环')
+const form = reactive({
+  customer: '',
+  salesperson: '',
+  quotationDate: '',
+  validDate: '',
+  paymentMethod: '',
+  deliveryPeriod: '',
+  status: '鑽夌',
+  remark: '',
+  products: [],
+  subtotal: 0,
+  freight: 0,
+  otherFee: 0,
+  discountRate: 0,
+  discountAmount: 0,
+  totalAmount: 0
+})
+
+const rules = {
+  customer: [{ required: true, message: '璇烽�夋嫨瀹㈡埛', trigger: 'change' }],
+  salesperson: [{ required: true, message: '璇烽�夋嫨涓氬姟鍛�', trigger: 'change' }],
+  quotationDate: [{ required: true, message: '璇烽�夋嫨鎶ヤ环鏃ユ湡', trigger: 'change' }],
+  validDate: [{ required: true, message: '璇烽�夋嫨鏈夋晥鏈�', trigger: 'change' }],
+  paymentMethod: [{ required: true, message: '璇烽�夋嫨浠樻鏂瑰紡', trigger: 'change' }],
+  deliveryPeriod: [{ required: true, message: '璇疯緭鍏ヤ氦璐ф湡', trigger: 'blur' }]
+}
+
+const isEdit = ref(false)
+const editId = ref(null)
+const currentQuotation = ref({})
+const formRef = ref()
+
+// 璁$畻灞炴��
+const filteredList = computed(() => {
+  let list = quotationList.value
+  if (searchForm.quotationNo) {
+    list = list.filter(item => item.quotationNo.includes(searchForm.quotationNo))
+  }
+  if (searchForm.customer) {
+    list = list.filter(item => item.customer === searchForm.customer)
+  }
+  if (searchForm.status) {
+    list = list.filter(item => item.status === searchForm.status)
+  }
+  return list
+})
+
+// 鏂规硶
+const getStatusType = (status) => {
+  const statusMap = {
+    '鑽夌': 'info',
+    '宸插彂閫�': 'primary',
+    '瀹㈡埛纭': 'success',
+    '宸茶繃鏈�': 'danger'
+  }
+  return statusMap[status] || 'info'
+}
+
+const handleSearch = () => {
+  // 鎼滅储閫昏緫宸插湪computed涓鐞�
+}
+
+const resetSearch = () => {
+  searchForm.quotationNo = ''
+  searchForm.customer = ''
+  searchForm.status = ''
+}
+
+const handleAdd = () => {
+  dialogTitle.value = '鏂板鎶ヤ环'
+  isEdit.value = false
+  resetForm()
+  dialogVisible.value = true
+}
+
+const handleView = (row) => {
+  currentQuotation.value = row
+  viewDialogVisible.value = true
+}
+
+const handleEdit = (row) => {
+  dialogTitle.value = '缂栬緫鎶ヤ环'
+  isEdit.value = true
+  editId.value = row.id
+  Object.assign(form, row)
+  dialogVisible.value = true
+}
+
+
+const handleDelete = (row) => {
+  ElMessageBox.confirm('纭鍒犻櫎璇ユ姤浠峰崟鍚楋紵', '鎻愮ず', {
+    confirmButtonText: '纭畾',
+    cancelButtonText: '鍙栨秷',
+    type: 'warning'
+  }).then(() => {
+    const index = quotationList.value.findIndex(item => item.id === row.id)
+    if (index > -1) {
+      quotationList.value.splice(index, 1)
+      pagination.total--
+      ElMessage.success('鍒犻櫎鎴愬姛')
+    }
+  })
+}
+
+const resetForm = () => {
+  form.customer = ''
+  form.salesperson = ''
+  form.quotationDate = ''
+  form.validDate = ''
+  form.paymentMethod = ''
+  form.deliveryPeriod = ''
+  form.status = '鑽夌'
+  form.remark = ''
+  form.products = []
+  form.subtotal = 0
+  form.freight = 0
+  form.otherFee = 0
+  form.discountRate = 0
+  form.discountAmount = 0
+  form.totalAmount = 0
+}
+
+const addProduct = () => {
+  form.products.push({
+    productName: '',
+    specification: '',
+    quantity: 1,
+    unit: '',
+    unitPrice: 0,
+    amount: 0
+  })
+}
+
+const removeProduct = (index) => {
+  form.products.splice(index, 1)
+  calculateSubtotal()
+}
+
+const calculateAmount = (product) => {
+  product.amount = product.quantity * product.unitPrice
+  calculateSubtotal()
+}
+
+const calculateSubtotal = () => {
+  form.subtotal = form.products.reduce((sum, product) => sum + product.amount, 0)
+  calculateTotal()
+}
+
+const calculateTotal = () => {
+  form.discountAmount = form.subtotal * (form.discountRate / 100)
+  form.totalAmount = form.subtotal + form.freight + form.otherFee - form.discountAmount
+}
+
+const handleCustomerChange = () => {
+  // 鍙互鏍规嵁瀹㈡埛淇℃伅鑷姩濉厖涓�浜涢粯璁ゅ��
+}
+
+const handleSubmit = () => {
+  formRef.value.validate((valid) => {
+    if (valid) {
+      if (form.products.length === 0) {
+        ElMessage.warning('璇疯嚦灏戞坊鍔犱竴涓骇鍝�')
+        return
+      }
+      
+      if (isEdit.value) {
+        // 缂栬緫
+        const index = quotationList.value.findIndex(item => item.id === editId.value)
+        if (index > -1) {
+          quotationList.value[index] = { ...form, id: editId.value }
+          ElMessage.success('缂栬緫鎴愬姛')
+        }
+      } else {
+        // 鏂板
+        const newId = Math.max(...quotationList.value.map(item => item.id)) + 1
+        const quotationNo = `QT${new Date().getFullYear()}${String(new Date().getMonth() + 1).padStart(2, '0')}${String(new Date().getDate()).padStart(2, '0')}${String(newId).padStart(3, '0')}`
+        quotationList.value.push({
+          ...form,
+          id: newId,
+          quotationNo: quotationNo
+        })
+        pagination.total++
+        ElMessage.success('鏂板鎴愬姛')
+      }
+      dialogVisible.value = false
+    }
+  })
+}
+
+const handleCurrentChange = (val) => {
+  pagination.currentPage = val.page
+  pagination.pageSize = val.limit
+}
+</script>
+
+<style scoped>
+.search-row {
+  margin-bottom: 20px;
+}
+
+.form-card {
+  margin-bottom: 20px;
+}
+
+.card-title {
+  font-weight: bold;
+  color: #303133;
+}
+
+.card-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+}
+
+.dialog-footer {
+  text-align: right;
+}
+</style>

--
Gitblit v1.9.3