From 9fe3ccfea5f06dd2474480aef7058a8ca907cb29 Mon Sep 17 00:00:00 2001
From: spring <2396852758@qq.com>
Date: 星期一, 19 一月 2026 16:53:38 +0800
Subject: [PATCH] fix: 新增协同办公、薪资功能。完成库存预警页面编写

---
 src/views/collaborativeApproval/notificationManagement/summary/index.vue         |  399 +
 src/views/personnelManagement/payrollManagement/components/formDia.vue           |    2 
 src/views/personnelManagement/payrollManagement/index.vue                        |   20 
 src/views/collaborativeApproval/rulesRegulationsManagement/index.vue             |  584 ++
 src/views/collaborativeApproval/notificationManagement/meetSetting/index.vue     |  320 +
 src/views/collaborativeApproval/approvalProcess/index.vue                        |  262 
 src/views/collaborativeApproval/notificationManagement/meetApplication/index.vue |  394 +
 src/views/inventoryManagement/stockWarningLedger/index.vue                       |  360 +
 src/views/collaborativeApproval/sealManagement/index.vue                         |  801 +++
 src/views/collaborativeApproval/approvalProcess/components/approvalDia.vue       |  194 
 src/views/collaborativeApproval/purchaseApproval/index.vue                       | 1064 ++++
 src/views/collaborativeApproval/approvalProcess/index5.vue                       |   22 
 src/views/collaborativeApproval/planTemplate/index.vue                           |  867 ++++
 src/views/collaborativeApproval/meetingManagement/index.vue                      |   63 
 src/views/collaborativeApproval/knowledgeBase/index.vue                          |  323 -
 src/api/inventoryManagement/stockWarningLedger.js                                |   10 
 src/views/collaborativeApproval/attendanceManagement/index.vue                   |  822 +++
 src/api/salesManagement/salesQuotation.js                                        |  112 
 src/views/collaborativeApproval/enterpriseBook/index.vue                         |  798 +++
 src/views/collaborativeApproval/notificationManagement/meetExamine/index.vue     |  414 +
 src/views/collaborativeApproval/reportGeneration/index.vue                       |  596 ++
 src/views/collaborativeApproval/meetingBoard/index.vue                           |  228 
 src/api/collaborativeApproval/meeting.js                                         |  118 
 src/views/collaborativeApproval/approvalProcess/components/infoFormDia.vue       |  137 
 src/views/collaborativeApproval/notificationManagement/meetIndex/index.vue       |  363 +
 src/views/collaborativeApproval/processTracking/index.vue                        |  498 ++
 src/views/collaborativeApproval/notificationManagement/index.vue                 |  341 
 src/views/collaborativeApproval/warningSystem/index.vue                          |    6 
 src/views/collaborativeApproval/notificationManagement/meetPublish/index.vue     |  412 +
 src/views/collaborativeApproval/approvalProcess/fileList.vue                     |   30 
 src/views/collaborativeApproval/officeSupplies/index.vue                         |  512 ++
 src/views/collaborativeApproval/notificationManagement/meetDraft/index.vue       |  495 ++
 src/views/collaborativeApproval/rpaManagement/index.vue                          |  214 
 src/views/collaborativeApproval/noticeManagement/index.vue                       |  958 ++-
 34 files changed, 11,321 insertions(+), 1,418 deletions(-)

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/inventoryManagement/stockWarningLedger.js b/src/api/inventoryManagement/stockWarningLedger.js
new file mode 100644
index 0000000..6d14808
--- /dev/null
+++ b/src/api/inventoryManagement/stockWarningLedger.js
@@ -0,0 +1,10 @@
+import request from "@/utils/request";
+
+// 鏌ヨ搴撳瓨棰勮鍙拌处鍒楄〃
+export const getStockWarningLedgerPage = (params) => {
+  return request({
+    url: "/stockWarningLedger/listPage",
+    method: "get",
+    params,
+  });
+};
diff --git a/src/api/salesManagement/salesQuotation.js b/src/api/salesManagement/salesQuotation.js
new file mode 100644
index 0000000..4329dd9
--- /dev/null
+++ b/src/api/salesManagement/salesQuotation.js
@@ -0,0 +1,112 @@
+// 閿�鍞姤浠烽〉闈㈡帴鍙�
+import request from "@/utils/request";
+
+// 鍒嗛〉鏌ヨ鎶ヤ环鍗曞垪琛�
+export function getQuotationList(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: "post",
+    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/views/collaborativeApproval/approvalProcess/components/approvalDia.vue b/src/views/collaborativeApproval/approvalProcess/components/approvalDia.vue
index 403cab6..c38ee89 100644
--- a/src/views/collaborativeApproval/approvalProcess/components/approvalDia.vue
+++ b/src/views/collaborativeApproval/approvalProcess/components/approvalDia.vue
@@ -6,7 +6,7 @@
       width="700px"
       @close="closeDia"
     >
-			<el-form :model="form" label-width="140px" label-position="top" ref="formRef">
+			<el-form :model="form" :rules="rules" label-width="140px" label-position="top" ref="formRef">
 				<el-row>
 					<el-col :span="24">
 						<el-form-item label="娴佺▼缂栧彿锛�" prop="approveId">
@@ -32,7 +32,7 @@
 						</el-form-item>
 					</el-col>
 				</el-row>
-				<el-row>
+				<el-row v-if="!isQuotationApproval">
 					<el-col :span="24">
 						<el-form-item label="瀹℃壒浜嬬敱锛�" prop="approveReason">
 							<el-input v-model="form.approveReason" placeholder="璇疯緭鍏�" clearable type="textarea" disabled/>
@@ -73,6 +73,54 @@
 					</el-col>
 				</el-row>
 			</el-form>
+
+      <!-- 鎶ヤ环瀹℃壒锛氬睍绀烘姤浠疯鎯咃紙澶嶇敤閿�鍞姤浠封�滄煡鐪嬭鎯呭璇濇鈥濆唴瀹圭粨鏋勶級 -->
+      <div v-if="isQuotationApproval" style="margin: 10px 0 18px;">
+        <el-divider content-position="left">鎶ヤ环璇︽儏</el-divider>
+        <el-skeleton :loading="quotationLoading" animated>
+          <template #template>
+            <el-skeleton-item variant="h3" style="width: 30%" />
+            <el-skeleton-item variant="text" style="width: 100%" />
+            <el-skeleton-item variant="text" style="width: 100%" />
+          </template>
+          <template #default>
+            <el-empty v-if="!currentQuotation || !currentQuotation.quotationNo" description="鏈煡璇㈠埌瀵瑰簲鎶ヤ环璇︽儏" />
+            <template v-else>
+              <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="鎶ヤ环鎬婚" :span="2">
+                  <span style="font-size: 18px; color: #e6a23c; font-weight: bold;">
+                    楼{{ Number(currentQuotation.totalAmount ?? 0).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="product" label="浜у搧鍚嶇О" />
+                  <el-table-column prop="specification" label="瑙勬牸鍨嬪彿" />
+                  <el-table-column prop="unit" label="鍗曚綅" />
+                  <el-table-column prop="unitPrice" label="鍗曚环">
+                    <template #default="scope">楼{{ Number(scope.row.unitPrice ?? 0).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>
+            </template>
+          </template>
+        </el-skeleton>
+      </div>
+
       <el-form :model="{ activities }" ref="formRef" label-position="top">
         <el-steps :active="getActiveStep()" finish-status="success" process-status="process" align-center direction="vertical">
           <el-step
@@ -121,33 +169,16 @@
       <template #footer v-if="operationType === 'approval'">
         <div class="dialog-footer">
           <el-button type="primary" @click="submitForm(2)">涓嶉�氳繃</el-button>
-          <el-button type="primary" @click="openSignatureDialog(1)">閫氳繃</el-button>
+          <el-button type="primary" @click="submitForm(1)">閫氳繃</el-button>
           <el-button @click="closeDia">鍙栨秷</el-button>
         </div>
       </template>
-    </el-dialog>
-    <!-- 鐢靛瓙绛惧悕寮圭獥锛坴ue3-signature-pad锛� -->
-    <el-dialog v-model="signatureDialogVisible" title="鐢靛瓙绛惧悕" width="600px" append-to-body>
-			<vueEsign
-				ref="esign"
-				class="mySign"
-				:width="800"
-				:height="300"
-				:isCrop="isCrop"
-				:lineWidth="lineWidth"
-				:lineColor="lineColor"
-			/>
-      <div style="margin-top:10px;">
-        <el-button @click="clearSignature">娓呴櫎</el-button>
-        <el-button type="primary" @click="confirmSignature">纭畾</el-button>
-      </div>
     </el-dialog>
   </div>
 </template>
 
 <script setup>
-import { getCurrentInstance, reactive, ref, toRefs } from "vue";
-import vueEsign from "vue-esign";
+import { computed, getCurrentInstance, reactive, ref, toRefs } from "vue";
 import {
 	approveProcessDetails,
 	getDept,
@@ -156,9 +187,16 @@
 import useUserStore from "@/store/modules/user.js";
 import {userListNoPageByTenantId} from "@/api/system/user.js";
 import { WarningFilled, Edit, Check, MoreFilled } from '@element-plus/icons-vue'
-import { getToken } from "@/utils/auth";
+import { getQuotationList } from "@/api/salesManagement/salesQuotation.js";
 const emit = defineEmits(['close'])
 const { proxy } = getCurrentInstance()
+
+const props = defineProps({
+  approveType: {
+    type: [Number, String],
+    default: 0
+  }
+})
 
 const dialogFormVisible = ref(false);
 const operationType = ref('')
@@ -167,6 +205,10 @@
 const userStore = useUserStore()
 const productOptions = ref([]);
 const userList = ref([])
+const quotationLoading = ref(false)
+const currentQuotation = ref({})
+const isQuotationApproval = computed(() => Number(props.approveType) === 6)
+
 const data = reactive({
 	form: {
 		approveTime: "",
@@ -176,23 +218,12 @@
 		approveReason: "",
 		checkResult: "",
 	},
+  rules: {
+    // 浣跨敤閮ㄩ棬ID鍋氬繀濉牎楠岋紝閬垮厤鍚嶇О鏈悓姝ュ鑷磋鎶�
+    approveDeptId: [{ required: true, message: "璇烽�夋嫨鐢宠閮ㄩ棬", trigger: "change" }],
+  },
 });
-const { form } = toRefs(data);
-const signatureDialogVisible = ref(false);
-const signatureImg = ref('');
-let submitStatus = null; // 涓存椂瀛樺偍閫氳繃/涓嶉�氳繃鐘舵��
-const isCrop = ref("");
-const esign = ref(null);
-const lineWidth = ref(0);
-const lineColor = ref("#000000");
-
-// 涓婁紶閰嶇疆
-const upload = reactive({
-  // 涓婁紶鐨勫湴鍧�
-  url: import.meta.env.VITE_APP_BASE_API + "/file/upload",
-  // 璁剧疆涓婁紶鐨勮姹傚ご閮�
-  headers: { Authorization: "Bearer " + getToken() },
-});
+const { form, rules } = toRefs(data);
 
 // 鑺傜偣鏍囬
 const getNodeTitle = (index, len) => {
@@ -219,11 +250,27 @@
 const openDialog = (type, row) => {
   operationType.value = type;
   dialogFormVisible.value = true;
+  currentQuotation.value = {}
 	userListNoPageByTenantId().then((res) => {
 		userList.value = res.data;
 	});
 	form.value = {...row}
 	getProductOptions()
+
+  // 鎶ヤ环瀹℃壒锛氱敤瀹℃壒浜嬬敱瀛楁鎵胯浇鐨勨�滄姤浠峰崟鍙封�濆幓鏌ユ姤浠峰垪琛�
+  if (isQuotationApproval.value) {
+    const quotationNo = row?.approveReason;
+    if (quotationNo) {
+      quotationLoading.value = true
+      getQuotationList({ quotationNo }).then((res) => {
+        const records = res?.data?.records || []
+        currentQuotation.value = records[0] || {}
+      }).finally(() => {
+        quotationLoading.value = false
+      })
+    }
+  }
+
   approveProcessDetails(row.approveId).then((res) => {
     activities.value = res.data
     // 澧炲姞isApproval瀛楁
@@ -248,77 +295,10 @@
 		productOptions.value = res.data;
 	});
 };
-// 鎵撳紑绛惧悕寮圭獥
-const openSignatureDialog = (status) => {
-  submitStatus = status;
-  signatureDialogVisible.value = true;
-};
-// 娓呴櫎绛惧悕
-const clearSignature = () => {
-	esign.value.reset();
-};
-// 纭绛惧悕
-const confirmSignature = () => {
-	esign.value.generate().then((res) => {
-		console.log(res);
-		// 灏哹ase64杞崲涓轰簩杩涘埗
-		const base64Data = res.split(',')[1]; // 绉婚櫎data:image/png;base64,鍓嶇紑
-		const binaryString = atob(base64Data);
-		const bytes = new Uint8Array(binaryString.length);
-		for (let i = 0; i < binaryString.length; i++) {
-			bytes[i] = binaryString.charCodeAt(i);
-		}
-		signatureImg.value = bytes;
-		
-		// 鍒涘缓鏂囦欢瀵硅薄鐢ㄤ簬涓婁紶
-		const blob = new Blob([bytes], { type: 'image/png' });
-		const file = new File([blob], 'signature.png', { type: 'image/png' });
-		
-		// 鍒涘缓FormData
-		const formData = new FormData();
-		formData.append('file', file);
-		
-		// 涓婁紶绛惧悕鍥剧墖
-		fetch(upload.url, {
-			method: 'POST',
-			headers: upload.headers,
-			body: formData
-		})
-		.then(response => response.json())
-		.then(data => {
-			if (data.code === 200) {
-				console.log('data---', data)
-				let tempFileIds = [];
-				tempFileIds.push(data.data.tempId);
-				signatureDialogVisible.value = false;
-				clearSignature();
-				// 鍙湁閫氳繃鏃舵墠浼犻�掔鍚嶆枃浠禝D
-				if (submitStatus === 1) {
-					submitForm(submitStatus, tempFileIds);
-				} else {
-					submitForm(submitStatus);
-				}
-			} else {
-				proxy.$modal.msgError("绛惧悕鍥剧墖涓婁紶澶辫触锛�" + data.msg);
-			}
-		})
-		.catch(error => {
-			console.error('涓婁紶澶辫触:', error);
-			proxy.$modal.msgError("绛惧悕鍥剧墖涓婁紶澶辫触");
-		});
-	}).catch((err) => {
-		console.log(err);
-		proxy.$modal.msgWarning("璇峰厛绛惧悕锛�");
-	})
-};
 // 鎻愪氦瀹℃壒
-const submitForm = (status, tempFileIds) => {
+const submitForm = (status) => {
   const filteredActivities = activities.value.filter(activity => activity.isShen);
   filteredActivities[0].approveNodeStatus = status;
-  // 鍙湁閫氳繃鏃舵墠闇�瑕佺鍚�
-  if (status === 1 && tempFileIds) {
-    filteredActivities[0].tempFileIds = tempFileIds;
-  }
   // 鍒ゆ柇鏄惁涓烘渶鍚庝竴姝�
   const isLast = activities.value.findIndex(a => a.isShen) === activities.value.length-1;
   updateApproveNode({ ...filteredActivities[0], isLast }).then(() => {
@@ -330,6 +310,8 @@
 const closeDia = () => {
   proxy.resetForm("formRef");
   dialogFormVisible.value = false;
+  quotationLoading.value = false
+  currentQuotation.value = {}
   emit('close')
 };
 defineExpose({
diff --git a/src/views/collaborativeApproval/approvalProcess/components/infoFormDia.vue b/src/views/collaborativeApproval/approvalProcess/components/infoFormDia.vue
index 83585a1..4c9fce3 100644
--- a/src/views/collaborativeApproval/approvalProcess/components/infoFormDia.vue
+++ b/src/views/collaborativeApproval/approvalProcess/components/infoFormDia.vue
@@ -16,11 +16,13 @@
         </el-row>
         <el-row>
           <el-col :span="24">
+            <!-- 鐢宠閮ㄩ棬锛氭牎楠屼娇鐢ㄩ儴闂↖D锛屼究浜庝笅鎷夐�夋嫨鍚庣珛鍗抽�氳繃鏍¢獙 -->
             <el-form-item label="鐢宠閮ㄩ棬锛�" prop="approveDeptId">
+<!--              <el-input v-model="form.approveDeptName" placeholder="璇疯緭鍏�" clearable/>-->
 							<el-select
-								disabled
 								v-model="form.approveDeptId"
 								placeholder="閫夋嫨閮ㄩ棬"
+                @change="handleDeptChange"
 							>
 								<el-option
 									v-for="user in productOptions"
@@ -34,8 +36,65 @@
         </el-row>
         <el-row>
           <el-col :span="24">
-            <el-form-item label="瀹℃壒浜嬬敱锛�" prop="approveReason">
+            <el-form-item :label="props.approveType == 5 ? '閲囪喘璇存槑锛�' : '瀹℃壒浜嬬敱锛�'" prop="approveReason">
               <el-input v-model="form.approveReason" placeholder="璇疯緭鍏�" clearable type="textarea" />
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <!-- 璇峰亣鏃堕棿锛堜粎褰� approveType 涓� 2 鏃舵樉绀猴級 -->
+        <el-row :gutter="30" v-if="props.approveType == 2">
+          <el-col :span="12">
+            <el-form-item label="璇峰亣寮�濮嬫椂闂达細" prop="startDate">
+              <el-date-picker
+                  v-model="form.startDate"
+                  type="date"
+                  placeholder="璇烽�夋嫨寮�濮嬫棩鏈�"
+                  value-format="YYYY-MM-DD"
+                  format="YYYY-MM-DD"
+                  clearable
+                  style="width: 100%"
+              />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="璇峰亣缁撴潫鏃堕棿锛�" prop="endDate">
+              <el-date-picker
+                  v-model="form.endDate"
+                  type="date"
+                  placeholder="璇烽�夋嫨缁撴潫鏃ユ湡"
+                  value-format="YYYY-MM-DD"
+                  format="YYYY-MM-DD"
+                  clearable
+                  style="width: 100%"
+              />
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <!-- 鎶ラ攢閲戦锛堜粎褰� approveType 涓� 4 鏃舵樉绀猴級 -->
+        <el-row v-if="props.approveType == 4">
+          <el-col :span="24">
+            <el-form-item label="鎶ラ攢閲戦锛�" prop="price">
+              <el-input-number
+                  v-model="form.price"
+                  placeholder="璇疯緭鍏ユ姤閿�閲戦"
+                  :min="0"
+                  :precision="2"
+                  :step="0.01"
+                  style="width: 100%"
+                  clearable
+              />
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <!-- 鍑哄樊鍦扮偣锛堜粎褰� approveType 涓� 3 鏃舵樉绀猴級 -->
+        <el-row v-if="props.approveType == 3">
+          <el-col :span="24">
+            <el-form-item label="澶囨敞锛�" prop="location">
+              <el-input
+                  v-model="form.location"
+                  placeholder="璇疯緭鍏ュ娉�"
+                  clearable
+              />
             </el-form-item>
           </el-col>
         </el-row>
@@ -88,6 +147,9 @@
 							<el-select
 								v-model="form.approveUser"
 								placeholder="閫夋嫨浜哄憳"
+                filterable
+                default-first-option
+                :reserve-keyword="false"
 							>
 								<el-option
 									v-for="user in userList"
@@ -155,6 +217,8 @@
 const { proxy } = getCurrentInstance()
 const emit = defineEmits(['close'])
 import useUserStore from "@/store/modules/user";
+import { getCurrentDate } from "@/utils/index.js";
+import log from "@/views/monitor/job/log.vue";
 const userStore = useUserStore();
 
 const dialogFormVisible = ref(false);
@@ -171,19 +235,29 @@
     approveTime: "",
     approveId: "",
     approveUser: "",
-		approveDeptId: "",
+    approveDeptId: "",
+    approveDeptName: "",
     approveReason: "",
     checkResult: "",
     tempFileIds: [],
-    approverList: [] // 鏂板瀛楁锛屽瓨鍌ㄦ墍鏈夎妭鐐圭殑瀹℃壒浜篿d
+    approverList: [], // 鏂板瀛楁锛屽瓨鍌ㄦ墍鏈夎妭鐐圭殑瀹℃壒浜篿d
+    startDate: "", // 璇峰亣寮�濮嬫椂闂�
+    endDate: "", // 璇峰亣缁撴潫鏃堕棿
+    price: null, // 鎶ラ攢閲戦
+    location: "" // 鍑哄樊鍦扮偣
   },
   rules: {
-    approveTime: [{ required: false, message: "璇疯緭鍏�", trigger: "change" },],
+    approveTime: [{ required: false, message: "璇疯緭鍏�", trigger: "change" }],
     approveId: [{ required: false, message: "璇疯緭鍏�", trigger: "blur" }],
     approveUser: [{ required: false, message: "璇疯緭鍏�", trigger: "blur" }],
-		approveDeptId: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+    // 浣跨敤閮ㄩ棬ID鍋氬繀濉牎楠岋紝閬垮厤鍚嶇О鏈悓姝ュ鑷磋鎶�
+    approveDeptId: [{ required: true, message: "璇烽�夋嫨鐢宠閮ㄩ棬", trigger: "change" }],
     approveReason: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
     checkResult: [{ required: false, message: "璇疯緭鍏�", trigger: "blur" }],
+    startDate: [{ required: true, message: "璇烽�夋嫨璇峰亣寮�濮嬫椂闂�", trigger: "change" }],
+    endDate: [{ required: true, message: "璇烽�夋嫨璇峰亣缁撴潫鏃堕棿", trigger: "change" }],
+    price: [{ required: true, message: "璇疯緭鍏ユ姤閿�閲戦", trigger: "blur" }],
+    location: [{ required: true, message: "璇疯緭鍏ュ嚭宸湴鐐�", trigger: "blur" }],
   },
 });
 const { form, rules } = toRefs(data);
@@ -208,10 +282,19 @@
 function removeApproverNode(index) {
   approverNodes.value.splice(index, 1)
 }
-
+// 澶勭悊閮ㄩ棬閫夋嫨鍙樺寲
+const handleDeptChange = (deptId) => {
+  if (deptId) {
+    const selectedDept = productOptions.value.find(dept => dept.deptId === deptId);
+    if (selectedDept) {
+      form.value.approveDeptName = selectedDept.deptName;
+    }
+  } else {
+    form.value.approveDeptName = '';
+  }
+};
 // 鎵撳紑寮规
 const openDialog = (type, row) => {
-  console.log('openDialog', type, row)
   operationType.value = type;
   dialogFormVisible.value = true;
 	userListNoPageByTenantId().then((res) => {
@@ -278,6 +361,36 @@
     proxy.$modal.msgError("璇蜂负鎵�鏈夊鎵硅妭鐐归�夋嫨瀹℃壒浜猴紒")
     return
   }
+  // 褰� approveType 涓� 2 鏃讹紝鏍¢獙璇峰亣鏃堕棿
+  if (props.approveType == 2) {
+    if (!form.value.startDate) {
+      proxy.$modal.msgError("璇烽�夋嫨璇峰亣寮�濮嬫椂闂达紒")
+      return
+    }
+    if (!form.value.endDate) {
+      proxy.$modal.msgError("璇烽�夋嫨璇峰亣缁撴潫鏃堕棿锛�")
+      return
+    }
+    // 鏍¢獙缁撴潫鏃堕棿涓嶈兘鏃╀簬寮�濮嬫椂闂�
+    if (new Date(form.value.endDate) < new Date(form.value.startDate)) {
+      proxy.$modal.msgError("璇峰亣缁撴潫鏃堕棿涓嶈兘鏃╀簬寮�濮嬫椂闂达紒")
+      return
+    }
+  }
+  // 褰� approveType 涓� 3 鏃讹紝鏍¢獙鍑哄樊鍦扮偣
+  if (props.approveType == 3) {
+    if (!form.value.location || form.value.location.trim() === '') {
+      proxy.$modal.msgError("璇疯緭鍏ュ嚭宸湴鐐癸紒")
+      return
+    }
+  }
+  // 褰� approveType 涓� 4 鏃讹紝鏍¢獙鎶ラ攢閲戦
+  if (props.approveType == 4) {
+    if (!form.value.price || form.value.price <= 0) {
+      proxy.$modal.msgError("璇疯緭鍏ユ湁鏁堢殑鎶ラ攢閲戦锛�")
+      return
+    }
+  }
   proxy.$refs.formRef.validate(valid => {
     if (valid) {
       if (operationType.value === "add" || currentApproveStatus.value == 3) {
@@ -301,14 +414,6 @@
   dialogFormVisible.value = false;
   emit('close')
 };
-// 鑾峰彇褰撳墠鏃ユ湡骞舵牸寮忓寲涓� 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}`;
-}
 
 // 涓婁紶鍓嶆牎妫�
 function handleBeforeUpload(file) {
diff --git a/src/views/collaborativeApproval/approvalProcess/fileList.vue b/src/views/collaborativeApproval/approvalProcess/fileList.vue
index e9e3b87..5cc65f1 100644
--- a/src/views/collaborativeApproval/approvalProcess/fileList.vue
+++ b/src/views/collaborativeApproval/approvalProcess/fileList.vue
@@ -1,11 +1,12 @@
 <template>
-  <el-dialog v-model="dialogVisible" title="闄勪欢" width="40%" :before-close="handleClose">
-    <el-table :data="tableData" border height="40vh" stripe>
+  <el-dialog v-model="dialogVisible" title="闄勪欢" width="40%" :before-close="handleClose" draggable>
+    <el-table :data="tableData" border height="40vh">
       <el-table-column label="闄勪欢鍚嶇О" prop="name" min-width="400" show-overflow-tooltip />
-      <el-table-column fixed="right" label="鎿嶄綔" width="100" align="center">
+      <el-table-column fixed="right" label="鎿嶄綔" width="150" align="center">
         <template #default="scope">
           <el-button link type="primary" size="small" @click="downLoadFile(scope.row)">涓嬭浇</el-button>
           <el-button link type="primary" size="small" @click="lookFile(scope.row)">棰勮</el-button>
+          <el-button link type="danger" size="small" @click="handleDelete(scope.row)">鍒犻櫎</el-button>
         </template>
       </el-table-column>
     </el-table>
@@ -16,6 +17,8 @@
 <script setup>
 import { ref } from 'vue'
 import filePreview from '@/components/filePreview/index.vue'
+import { ElMessageBox, ElMessage } from 'element-plus'
+import { delCommonFile } from '@/api/publicApi/commonFile.js'
 
 const dialogVisible = ref(false)
 const tableData = ref([])
@@ -35,6 +38,27 @@
 const lookFile = (row) => {
   filePreviewRef.value.open(row.url)
 }
+// 鍒犻櫎闄勪欢
+const handleDelete = (row) => {
+  ElMessageBox.confirm(`纭鍒犻櫎闄勪欢"${row.name}"鍚楋紵`, '鎻愮ず', {
+    confirmButtonText: '纭畾',
+    cancelButtonText: '鍙栨秷',
+    type: 'warning'
+  }).then(() => {
+    delCommonFile([row.id]).then(() => {
+      ElMessage.success('鍒犻櫎鎴愬姛')
+      // 浠庡垪琛ㄤ腑绉婚櫎宸插垹闄ょ殑闄勪欢
+      const index = tableData.value.findIndex(item => item.id === row.id)
+      if (index !== -1) {
+        tableData.value.splice(index, 1)
+      }
+    }).catch(() => {
+      ElMessage.error('鍒犻櫎澶辫触')
+    })
+  }).catch(() => {
+    ElMessage.info('宸插彇娑堝垹闄�')
+  })
+}
 defineExpose({
   open
 })
diff --git a/src/views/collaborativeApproval/approvalProcess/index.vue b/src/views/collaborativeApproval/approvalProcess/index.vue
index c3b713e..afc2529 100644
--- a/src/views/collaborativeApproval/approvalProcess/index.vue
+++ b/src/views/collaborativeApproval/approvalProcess/index.vue
@@ -1,5 +1,16 @@
 <template>
   <div class="app-container">
+    <!-- 鏍囩椤靛垏鎹笉鍚岀殑瀹℃壒绫诲瀷 -->
+    <el-tabs v-model="activeTab" @tab-change="handleTabChange" class="approval-tabs">
+      <el-tab-pane label="鍗忓悓瀹℃壒" name="1"></el-tab-pane>
+      <el-tab-pane label="璇峰亣绠$悊" name="2"></el-tab-pane>
+      <el-tab-pane label="閿�鍞鎵�" name="3"></el-tab-pane>
+      <el-tab-pane label="鎶ラ攢瀹℃壒" name="4"></el-tab-pane>
+      <el-tab-pane label="閲囪喘瀹℃壒" name="5"></el-tab-pane>
+      <el-tab-pane label="鎶ヤ环瀹℃壒" name="6"></el-tab-pane>
+      <el-tab-pane label="鍑哄簱瀹℃壒" name="7"></el-tab-pane>
+    </el-tabs>
+    
     <div class="search_form">
       <div>
         <span class="search_title">娴佺▼缂栧彿锛�</span>
@@ -24,15 +35,15 @@
         >
       </div>
       <div>
-        <el-button type="primary" @click="openForm('add')">鏂板</el-button>
-<!--        <el-button @click="handleOut">瀵煎嚭</el-button>-->
+        <el-button type="primary" @click="openForm('add')" v-if="currentApproveType !== 6">鏂板</el-button>
+        <el-button @click="handleOut">瀵煎嚭</el-button>
         <el-button type="danger" plain @click="handleDelete">鍒犻櫎</el-button>
       </div>
     </div>
     <div class="table_list">
       <PIMTable
           rowKey="id"
-          :column="tableColumn"
+          :column="tableColumnCopy"
           :tableData="tableData"
           :page="page"
           :isSelection="true"
@@ -42,8 +53,8 @@
           :total="page.total"
       ></PIMTable>
     </div>
-    <info-form-dia ref="infoFormDia" @close="handleQuery" :approveType="approveType"></info-form-dia>
-    <approval-dia ref="approvalDia" @close="handleQuery"></approval-dia>
+    <info-form-dia ref="infoFormDia" @close="handleQuery" :approveType="currentApproveType"></info-form-dia>
+    <approval-dia ref="approvalDia" @close="handleQuery" :approveType="currentApproveType"></approval-dia>
     <FileList ref="fileListRef" />
   </div>
 </template>
@@ -51,22 +62,33 @@
 <script setup>
 import FileList from "./fileList.vue";
 import { Search } from "@element-plus/icons-vue";
-import {onMounted, ref} from "vue";
+import {onMounted, ref, computed, reactive, toRefs, nextTick, getCurrentInstance} from "vue";
 import {ElMessageBox} from "element-plus";
+import { useRoute } from 'vue-router';
 import InfoFormDia from "@/views/collaborativeApproval/approvalProcess/components/infoFormDia.vue";
 import ApprovalDia from "@/views/collaborativeApproval/approvalProcess/components/approvalDia.vue";
 import {approveProcessDelete, approveProcessListPage} from "@/api/collaborativeApproval/approvalProcess.js";
 import useUserStore from "@/store/modules/user";
 
-// 瀹氫箟缁勪欢鎺ユ敹鐨刾rops
-const props = defineProps({
-  approveType: {
-    type: [Number, String],
-    default: 0
-  }
+const userStore = useUserStore();
+const route = useRoute();
+
+// 褰撳墠閫変腑鐨勬爣绛鹃〉锛岄粯璁や负鍏嚭绠$悊
+const activeTab = ref('1');
+
+// 褰撳墠瀹℃壒绫诲瀷锛屾牴鎹�変腑鐨勬爣绛鹃〉璁$畻
+const currentApproveType = computed(() => {
+  return Number(activeTab.value);
 });
 
-const userStore = useUserStore();
+// 鏍囩椤靛垏鎹㈠鐞�
+const handleTabChange = (tabName) => {
+  // 鍒囨崲鏍囩椤垫椂閲嶇疆鎼滅储鏉′欢鍜屽垎椤碉紝骞堕噸鏂板姞杞芥暟鎹�
+  searchForm.value.approveId = '';
+  searchForm.value.approveStatus = '';
+  page.current = 1;
+  getList();
+};
 
 
 const data = reactive({
@@ -76,75 +98,101 @@
   },
 });
 const { searchForm } = toRefs(data);
-const tableColumn = ref([
-  {
-    label: "瀹℃壒鐘舵��",
-    prop: "approveStatus",
-    dataType: "tag",
-		width: 100,
-    formatData: (params) => {
-      if (params == 0) {
-        return "寰呭鏍�";
-      } else if (params == 1) {
-        return "瀹℃牳涓�";
-      } else if (params == 2) {
-        return "瀹℃牳瀹屾垚";
-      } else if (params == 4) {
-        return "宸查噸鏂版彁浜�";
-      } else {
-        return '涓嶉�氳繃';
-      }
+
+// 鍔ㄦ�佽〃鏍煎垪閰嶇疆锛屾牴鎹鎵圭被鍨嬬敓鎴愬垪
+const tableColumnCopy = computed(() => {
+  const isLeaveType = currentApproveType.value === 2; // 璇峰亣绠$悊
+  const isReimburseType = currentApproveType.value === 4; // 鎶ラ攢绠$悊
+  const isQuotationType = currentApproveType.value === 6; // 鎶ヤ环瀹℃壒
+  
+  // 鍩虹鍒楅厤缃�
+  const baseColumns = [
+    {
+      label: "瀹℃壒鐘舵��",
+      prop: "approveStatus",
+      dataType: "tag",
+      width: 100,
+      formatData: (params) => {
+        if (params == 0) {
+          return "寰呭鏍�";
+        } else if (params == 1) {
+          return "瀹℃牳涓�";
+        } else if (params == 2) {
+          return "瀹℃牳瀹屾垚";
+        } else if (params == 4) {
+          return "宸查噸鏂版彁浜�";
+        } else {
+          return '涓嶉�氳繃';
+        }
+      },
+      formatType: (params) => {
+        if (params == 0) {
+          return "warning";
+        } else if (params == 1) {
+          return "primary";
+        } else if (params == 2) {
+          return "success";
+        } else if (params == 4) {
+          return "info";
+        } else {
+          return 'danger';
+        }
+      },
     },
-    formatType: (params) => {
-      if (params == 0) {
-        return "warning";
-      } else if (params == 1) {
-        return "primary";
-      } else if (params == 2) {
-        return "success";
-      } else if (params == 4) {
-        return "";
-      } else {
-        return 'danger';
-      }
+    {
+      label: "娴佺▼缂栧彿",
+      prop: "approveId",
+      width: 170
     },
-  },
-  {
-    label: "娴佺▼缂栧彿",
-    prop: "approveId",
-    width: 170
-  },
-  {
-    label: "鐢宠閮ㄩ棬",
-    prop: "approveDeptName",
-		width: 220
-  },
-  {
-    label: "瀹℃壒浜嬬敱",
-    prop: "approveReason",
-		width: 200
-  },
-  {
-    label: "鐢宠浜�",
-    prop: "approveUserName",
-    width: 120
-  },
-  {
-    label: "鐢宠鏃ユ湡",
-    prop: "approveTime",
-		width: 200
-  },
-  {
-    label: "缁撴潫鏃ユ湡",
-    prop: "approveOverTime",
-    width: 120
-  },
-  {
+    {
+      label: "鐢宠閮ㄩ棬",
+      prop: "approveDeptName",
+      width: 220
+    },
+    {
+      label: isQuotationType ? "鎶ヤ环鍗曞彿" : "瀹℃壒浜嬬敱",
+      prop: "approveReason",
+      width: 200
+    },
+    {
+      label: "鐢宠浜�",
+      prop: "approveUserName",
+      width: 120
+    }
+  ];
+  
+  // 閲戦鍒楋紙浠呮姤閿�绠$悊鏄剧ず锛�
+  if (isReimburseType) {
+    baseColumns.push({
+      label: "閲戦锛堝厓锛�",
+      prop: "price",
+      width: 120
+    });
+  }
+  
+  // 鏃ユ湡鍒楋紙鏍规嵁绫诲瀷鍔ㄦ�侀厤缃級
+  baseColumns.push(
+    {
+      label: isLeaveType ? "寮�濮嬫棩鏈�" : "鐢宠鏃ユ湡",
+      prop: isLeaveType ? "startDate" : "approveTime",
+      width: 200
+    },
+    {
+      label: "缁撴潫鏃ユ湡",
+      prop: isLeaveType ? "endDate" : "approveOverTime",
+      width: 120
+    }
+  );
+  
+  // 褰撳墠瀹℃壒浜哄垪
+  baseColumns.push({
     label: "褰撳墠瀹℃壒浜�",
     prop: "approveUserCurrentName",
     width: 120
-  },
-  {
+  });
+  
+  // 鎿嶄綔鍒�
+  baseColumns.push({
     dataType: "action",
     label: "鎿嶄綔",
     align: "center",
@@ -157,7 +205,7 @@
         clickFun: (row) => {
           openForm("edit", row);
         },
-				disabled: (row) => row.approveStatus == 2 || row.approveStatus == 1 || row.approveStatus == 4
+        disabled: (row) => currentApproveType.value === 6 || row.approveStatus == 2 || row.approveStatus == 1 || row.approveStatus == 4
       },
       {
         name: "瀹℃牳",
@@ -165,7 +213,7 @@
         clickFun: (row) => {
           openApprovalDia("approval", row);
         },
-				disabled: (row) => row.approveUserCurrentId == null || row.approveStatus == 2 || row.approveStatus == 3 || row.approveStatus == 4 || row.approveUserCurrentId !== userStore.id
+        disabled: (row) => row.approveUserCurrentId == null || row.approveStatus == 2 || row.approveStatus == 3 || row.approveStatus == 4 || row.approveUserCurrentId !== userStore.id
       },
       {
         name: "璇︽儏",
@@ -182,8 +230,10 @@
         },
       },
     ],
-  },
-]);
+  });
+  
+  return baseColumns;
+});
 const tableData = ref([]);
 const selectedRows = ref([]);
 const tableLoading = ref(false);
@@ -214,7 +264,7 @@
 };
 const getList = () => {
   tableLoading.value = true;
-  approveProcessListPage({...page, ...searchForm.value,approveType:props.approveType}).then(res => {
+  approveProcessListPage({...page, ...searchForm.value, approveType: currentApproveType.value}).then(res => {
     tableLoading.value = false;
     tableData.value = res.data.records
     page.total = res.data.total;
@@ -222,6 +272,33 @@
     tableLoading.value = false;
   })
 };
+// 瀵煎嚭
+const handleOut = () => {
+  const type = currentApproveType.value
+  const urlMap = {
+    0: "/approveProcess/exportZero",
+    1: "/approveProcess/exportOne",
+    2: "/approveProcess/exportTwo",
+    3: "/approveProcess/exportThree",
+    4: "/approveProcess/exportFour",
+    5: "/approveProcess/exportFive",
+    6: "/approveProcess/exportSix",
+    7: "/approveProcess/exportSeven",
+  }
+  const url = urlMap[type] || urlMap[0]
+  const nameMap = {
+    0: "鍗忓悓瀹℃壒绠$悊琛�",
+    1: "鍏嚭绠$悊瀹℃壒琛�",
+    2: "璇峰亣绠$悊瀹℃壒琛�",
+    3: "鍑哄樊绠$悊瀹℃壒琛�",
+    4: "鎶ラ攢绠$悊瀹℃壒琛�",
+    5: "閲囪喘鐢宠瀹℃壒琛�",
+    6: "鎶ヤ环瀹℃壒琛�",
+    7: "鍑哄簱瀹℃壒琛�",
+  }
+  const fileName = nameMap[type] || nameMap[0]
+  proxy.download(url, {}, `${fileName}.xlsx`)
+}
 // 琛ㄦ牸閫夋嫨鏁版嵁
 const handleSelectionChange = (selection) => {
   selectedRows.value = selection;
@@ -265,8 +342,27 @@
       });
 };
 onMounted(() => {
+  // 鏍规嵁URL鍙傛暟璁剧疆鏍囩椤靛拰鏌ヨ鏉′欢
+  const approveType = route.query.approveType;
+  const approveId = route.query.approveId;
+  
+  if (approveType) {
+    // 璁剧疆鏍囩椤碉紙approveType 瀵瑰簲 activeTab 鐨� name锛�
+    activeTab.value = String(approveType);
+  }
+  
+  if (approveId) {
+    // 璁剧疆娴佺▼缂栧彿鏌ヨ鏉′欢
+    searchForm.value.approveId = String(approveId);
+  }
+  
+  // 鏌ヨ鍒楄〃
   getList();
 });
 </script>
 
-<style scoped></style>
+<style scoped>
+.approval-tabs {
+  margin-bottom: 10px;
+}
+</style>
diff --git a/src/views/collaborativeApproval/approvalProcess/index5.vue b/src/views/collaborativeApproval/approvalProcess/index5.vue
new file mode 100644
index 0000000..2e0f4f3
--- /dev/null
+++ b/src/views/collaborativeApproval/approvalProcess/index5.vue
@@ -0,0 +1,22 @@
+<template>
+  <div class="container">
+    <!-- 寮曞叆index.vue缁勪欢骞朵紶閫掑弬鏁� -->
+    <ApprovalProcessIndex :approveType="5" />
+  </div>
+</template>
+
+<script setup>
+import ApprovalProcessIndex from './index.vue'
+
+// 瀹氫箟缁勪欢鍚嶇О
+defineOptions({
+  name: 'ApprovalProcessIndex1'
+})
+</script>
+
+<style scoped>
+.container {
+  width: 100%;
+  height: 100%;
+}
+</style>
\ No newline at end of file
diff --git a/src/views/collaborativeApproval/attendanceManagement/index.vue b/src/views/collaborativeApproval/attendanceManagement/index.vue
index 8db29fc..f6a3e3c 100644
--- a/src/views/collaborativeApproval/attendanceManagement/index.vue
+++ b/src/views/collaborativeApproval/attendanceManagement/index.vue
@@ -5,8 +5,8 @@
       <el-tab-pane label="鍋囨湡璁剧疆" name="holiday">
         <div class="tab-content">
           <el-button type="primary" @click="openDialog('holiday', 'add')">鏂板鍋囨湡</el-button>
-          
-          <el-table :data="holidayData" border style="width: 100%; margin-top: 20px;" stripe>
+
+          <el-table :data="holidayData" border style="width: 100%; margin-top: 20px;">
             <el-table-column prop="name" label="鍋囨湡鍚嶇О" />
             <el-table-column prop="type" label="鍋囨湡绫诲瀷">
               <template #default="scope">
@@ -37,9 +37,13 @@
       <el-tab-pane label="骞村亣璁剧疆" name="annual">
         <div class="tab-content">
           <el-button type="primary" @click="openDialog('annual', 'add')">鏂板骞村亣瑙勫垯</el-button>
-          
-          <el-table :data="annualData" border style="width: 100%; margin-top: 20px;" stripe>
-            <el-table-column prop="employeeType" label="鍛樺伐绫诲瀷"/>
+
+          <el-table :data="annualData" border style="width: 100%; margin-top: 20px;">
+            <el-table-column prop="employeeType" label="鍛樺伐绫诲瀷">
+              <template #default="scope">
+                <el-tag :type="getTagType(scope.row.employeeType)">{{ getTypeLabel(scope.row.employeeType) }}</el-tag>
+              </template>
+            </el-table-column>
             <el-table-column prop="workYears" label="宸ヤ綔骞撮檺" />
             <el-table-column prop="annualDays" label="骞村亣澶╂暟" align="center" />
             <el-table-column prop="maxCarryOver" label="鏈�澶х粨杞ぉ鏁�" align="center" />
@@ -64,8 +68,8 @@
       <el-tab-pane label="鍔犵彮璁剧疆" name="overtime">
         <div class="tab-content">
           <el-button type="primary" @click="openDialog('overtime', 'add')">鏂板鍔犵彮瑙勫垯</el-button>
-          
-          <el-table :data="overtimeData" border style="width: 100%; margin-top: 20px;" stripe>
+
+          <el-table :data="overtimeData" border style="width: 100%; margin-top: 20px;">
             <el-table-column prop="name" label="瑙勫垯鍚嶇О" />
             <el-table-column prop="type" label="鍔犵彮绫诲瀷" >
               <template #default="scope">
@@ -96,15 +100,15 @@
       <el-tab-pane label="涓婄彮鏃堕棿璁剧疆" name="worktime">
         <div class="tab-content">
           <el-button type="primary" @click="openDialog('worktime', 'add')">鏂板鏃堕棿娈�</el-button>
-          
-          <el-table :data="worktimeData" border style="width: 100%; margin-top: 20px;" stripe>
+
+          <el-table :data="worktimeData" border style="width: 100%; margin-top: 20px;">
             <el-table-column prop="name" label="鏃堕棿娈靛悕绉�"  />
             <el-table-column prop="startTime" label="涓婄彮鏃堕棿"/>
             <el-table-column prop="endTime" label="涓嬬彮鏃堕棿" />
             <el-table-column prop="flexibleStart" label="寮规�т笂鐝�">
               <template #default="scope">
-                <el-tag :type="scope.row.flexibleStart ? 'success' : 'info'">
-                  {{ scope.row.flexibleStart ? '鏄�' : '鍚�' }}
+                <el-tag :type="scope.row.flexibleStart === 'true' ? 'success' : 'info'">
+                  {{ scope.row.flexibleStart === 'true' ? '鏄�' : '鍚�' }}
                 </el-tag>
               </template>
             </el-table-column>
@@ -125,6 +129,52 @@
           </el-table>
         </div>
       </el-tab-pane>
+
+      <!-- 鎵撳崱璁板綍 -->
+      <el-tab-pane label="鎵撳崱璁板綍" name="attendance">
+        <div class="tab-content">
+          <div style="margin-bottom: 20px;">
+            <el-date-picker
+              v-model="attendanceDate"
+              type="date"
+              placeholder="閫夋嫨鏃ユ湡"
+              format="YYYY-MM-DD"
+              value-format="YYYY-MM-DD"
+              style="margin-right: 10px;"
+              @change="filterAttendanceData"
+            />
+            <el-select
+              v-model="attendanceStatus"
+              placeholder="閫夋嫨鐘舵��"
+              style="width: 120px; margin-right: 10px;"
+              @change="filterAttendanceData"
+            >
+              <el-option label="鍏ㄩ儴" value="" />
+              <el-option label="姝e父" value="normal" />
+              <el-option label="杩熷埌" value="late" />
+              <el-option label="鏃╅��" value="early" />
+              <el-option label="缂哄嫟" value="absent" />
+            </el-select>
+            <el-button type="primary" @click="exportAttendance">瀵煎嚭璁板綍</el-button>
+          </div>
+
+          <el-table :data="filteredAttendanceData" border style="width: 100%;">
+            <el-table-column prop="employeeName" label="鍛樺伐濮撳悕" width="120" />
+            <el-table-column prop="department" label="閮ㄩ棬" width="120" />
+            <el-table-column prop="date" label="鏃ユ湡" width="120" />
+            <el-table-column prop="clockInTime" label="涓婄彮鎵撳崱" width="120" />
+            <el-table-column prop="clockOutTime" label="涓嬬彮鎵撳崱" width="120" />
+            <el-table-column prop="workHours" label="宸ヤ綔鏃堕暱" width="100" align="center" />
+            <el-table-column prop="status" label="鐘舵��" width="100" align="center">
+              <template #default="scope">
+                <el-tag :type="getAttendanceTagType(scope.row.status)">{{ getAttendanceStatusLabel(scope.row.status) }}</el-tag>
+              </template>
+            </el-table-column>
+            <el-table-column prop="location" label="鎵撳崱鍦扮偣" width="150" />
+            <el-table-column prop="remark" label="澶囨敞" min-width="150" />
+          </el-table>
+        </div>
+      </el-tab-pane>
     </el-tabs>
 
     <!-- 閫氱敤寮圭獥 -->
@@ -133,23 +183,29 @@
         <el-form-item label="鍚嶇О" prop="name" v-if="currentType !== 'annual'">
           <el-input v-model="form.name" placeholder="璇疯緭鍏ュ悕绉�" />
         </el-form-item>
-        
+
         <el-form-item label="绫诲瀷" prop="type" v-if="currentType === 'holiday' || currentType === 'overtime'">
           <el-select v-model="form.type" placeholder="璇烽�夋嫨绫诲瀷" style="width: 100%">
-            <el-option 
-              v-for="option in getTypeOptions()" 
-              :key="option.value" 
-              :label="option.label" 
-              :value="option.value" 
+            <el-option
+              v-for="option in getTypeOptions()"
+              :key="option.value"
+              :label="option.label"
+              :value="option.value"
             />
           </el-select>
         </el-form-item>
 
         <el-form-item label="鍛樺伐绫诲瀷" prop="employeeType" v-if="currentType === 'annual'">
           <el-select v-model="form.employeeType" placeholder="璇烽�夋嫨鍛樺伐绫诲瀷" style="width: 100%">
-            <el-option label="姝e紡鍛樺伐" value="regular" />
+            <!-- <el-option label="姝e紡鍛樺伐" value="regular" />
             <el-option label="璇曠敤鏈熷憳宸�" value="probation" />
-            <el-option label="瀹炰範鐢�" value="intern" />
+            <el-option label="瀹炰範鐢�" value="intern" /> -->
+            <el-option
+              v-for="option in getTypeOptions()"
+              :key="option.value"
+              :label="option.label"
+              :value="option.value"
+            />
           </el-select>
         </el-form-item>
 
@@ -191,7 +247,7 @@
              @change="validateTimeField('startTime')"
            />
          </el-form-item>
-         
+
          <el-form-item label="缁撴潫鏃堕棿" prop="endTime" v-if="currentType === 'overtime'">
            <el-time-picker
              v-model="form.endTime"
@@ -237,14 +293,14 @@
           <el-input-number v-model="form.flexibleMinutes" :min="0" :max="120" style="width: 100%" />
         </el-form-item>
 
-                 <el-form-item label="鐘舵��" prop="status">
+        <el-form-item label="鐘舵��" prop="status">
            <el-radio-group v-model="form.status">
              <el-radio value="active">鍚敤</el-radio>
              <el-radio value="inactive">鍋滅敤</el-radio>
            </el-radio-group>
          </el-form-item>
       </el-form>
-      
+
       <template #footer>
         <span class="dialog-footer">
           <el-button @click="dialogVisible = false">鍙栨秷</el-button>
@@ -258,6 +314,7 @@
 <script setup>
 import { ref, reactive, onMounted, onUnmounted } from 'vue'
 import { ElMessage, ElMessageBox } from 'element-plus'
+import { listHolidaySettings, addHolidaySettings, updateHolidaySettings, delHolidaySettings, listAnnualLeaveSettingList, addAnnualLeaveSetting, updateAnnualLeaveSetting, delAnnualLeaveSetting, listOvertimeSettingList, addOvertimeSetting, updateOvertimeSetting, delOvertimeSetting, listWorkingHoursSettingList, addWorkingHoursSetting, updateWorkingHoursSetting, delWorkingHoursSetting } from '@/api/collaborativeApproval/attendanceManagement.js'
 
 // 褰撳墠婵�娲荤殑鏍囩椤�
 const activeTab = ref('holiday')
@@ -269,12 +326,29 @@
 const currentAction = ref('')
 const currentEditId = ref('')
 const formRef = ref()
+const page = {
+    current: 1,
+    size: 20,
+    total: 0,
+  }
+const holidayData = ref([])
+const annualData = ref([])
+const overtimeData = ref([])
+const worktimeData = ref([])
+
+// 鎵撳崱璁板綍鐩稿叧鏁版嵁
+const attendanceData = ref([])
+const filteredAttendanceData = ref([])
+const attendanceDate = ref('')
+const attendanceStatus = ref('')
 
 // 琛ㄥ崟鏁版嵁
 const form = reactive({
   name: '',
   type: '',
   dateRange: [],
+  startDate: '',
+  endDate: '',
   days: 0,
   employeeType: '',
   workYears: '',
@@ -300,9 +374,9 @@
   workYears: [{ required: true, message: '璇疯緭鍏ュ伐浣滃勾闄�', trigger: 'blur' }],
   annualDays: [{ required: true, message: '璇疯緭鍏ュ勾鍋囧ぉ鏁�', trigger: 'blur' }],
   maxCarryOver: [{ required: true, message: '璇疯緭鍏ユ渶澶х粨杞ぉ鏁�', trigger: 'blur' }],
-  startTime: [{ 
-    required: true, 
-    message: '璇烽�夋嫨寮�濮嬫椂闂�', 
+  startTime: [{
+    required: true,
+    message: '璇烽�夋嫨寮�濮嬫椂闂�',
     trigger: 'change',
     validator: (rule, value, callback) => {
       if (!value) {
@@ -312,9 +386,9 @@
       }
     }
   }],
-  endTime: [{ 
-    required: true, 
-    message: '璇烽�夋嫨缁撴潫鏃堕棿', 
+  endTime: [{
+    required: true,
+    message: '璇烽�夋嫨缁撴潫鏃堕棿',
     trigger: 'change',
     validator: (rule, value, callback) => {
       if (!value) {
@@ -324,9 +398,9 @@
       }
     }
   }],
-  workStartTime: [{ 
-    required: true, 
-    message: '璇烽�夋嫨涓婄彮鏃堕棿', 
+  workStartTime: [{
+    required: true,
+    message: '璇烽�夋嫨涓婄彮鏃堕棿',
     trigger: 'change',
     validator: (rule, value, callback) => {
       if (!value) {
@@ -336,9 +410,9 @@
       }
     }
   }],
-  workEndTime: [{ 
-    required: true, 
-    message: '璇烽�夋嫨涓嬬彮鏃堕棿', 
+  workEndTime: [{
+    required: true,
+    message: '璇烽�夋嫨涓嬬彮鏃堕棿',
     trigger: 'change',
     validator: (rule, value, callback) => {
       if (!value) {
@@ -350,37 +424,12 @@
   }],
   rate: [{ required: true, message: '璇疯緭鍏ュ�嶇巼', trigger: 'blur' }]
 }
-
-// 妯℃嫙鏁版嵁
-const holidayData = ref([
-  { id: '1', name: '鏄ヨ妭', type: 'legal', startDate: '2024-02-10', endDate: '2024-02-17', days: 8, status: 'active' },
-  { id: '2', name: '娓呮槑鑺�', type: 'legal', startDate: '2024-04-05', endDate: '2024-04-05', days: 1, status: 'active' },
-  { id: '3', name: '鍔冲姩鑺�', type: 'legal', startDate: '2024-05-01', endDate: '2024-05-05', days: 5, status: 'active' }
-])
-
-const annualData = ref([
-  { id: '1', employeeType: 'regular', workYears: '1-3骞�', annualDays: 5, maxCarryOver: 2, status: 'active' },
-  { id: '2', employeeType: 'regular', workYears: '3-5骞�', annualDays: 10, maxCarryOver: 5, status: 'active' },
-  { id: '3', employeeType: 'regular', workYears: '5骞翠互涓�', annualDays: 15, maxCarryOver: 10, status: 'active' }
-])
-
-const overtimeData = ref([
-  { id: '1', name: '宸ヤ綔鏃ュ姞鐝�', type: 'weekday', startTime: '18:00', endTime: '22:00', rate: 1.5, status: 'active' },
-  { id: '2', name: '鍛ㄦ湯鍔犵彮', type: 'weekend', startTime: '09:00', endTime: '18:00', rate: 2.0, status: 'active' },
-  { id: '3', name: '娣卞鍔犵彮', type: 'night', startTime: '22:00', endTime: '06:00', rate: 2.5, status: 'active' }
-])
-
-const worktimeData = ref([
-  { id: '1', name: '鏍囧噯宸ヤ綔鏃堕棿', startTime: '09:00', endTime: '18:00', flexibleStart: true, flexibleMinutes: 30, status: 'active' },
-  { id: '2', name: '鏃╃彮鏃堕棿', startTime: '08:00', endTime: '17:00', flexibleStart: false, flexibleMinutes: 0, status: 'active' },
-  { id: '3', name: '鏅氱彮鏃堕棿', startTime: '14:00', endTime: '23:00', flexibleStart: false, flexibleMinutes: 0, status: 'active' }
-])
-
 // 宸ュ叿鍑芥暟
 const getTagType = (type) => {
   const tagMap = {
     legal: 'success', adjustment: 'warning', special: 'info', company: 'primary',
-    weekday: 'primary', weekend: 'warning', holiday: 'danger', night: 'info'
+    weekday: 'primary', weekend: 'warning', holiday: 'danger', night: 'info',
+    regular: 'success', probation: 'info', intern: 'danger'
   }
   return tagMap[type] || 'info'
 }
@@ -388,9 +437,31 @@
 const getTypeLabel = (type) => {
   const labelMap = {
     legal: '娉曞畾鑺傚亣鏃�', adjustment: '璋冧紤鏃�', special: '鐗规畩鍋囨湡', company: '鍏徃鍋囨湡',
-    weekday: '宸ヤ綔鏃ュ姞鐝�', weekend: '鍛ㄦ湯鍔犵彮', holiday: '鑺傚亣鏃ュ姞鐝�', night: '娣卞鍔犵彮'
+    weekday: '宸ヤ綔鏃ュ姞鐝�', weekend: '鍛ㄦ湯鍔犵彮', holiday: '鑺傚亣鏃ュ姞鐝�', night: '娣卞鍔犵彮',
+    regular: '姝e紡鍛樺伐', probation: '璇曠敤鏈熷憳宸�', intern: '瀹炰範鐢�'
   }
   return labelMap[type] || type
+}
+
+// 鎵撳崱璁板綍鐩稿叧宸ュ叿鍑芥暟
+const getAttendanceTagType = (status) => {
+  const tagMap = {
+    normal: 'success',
+    late: 'warning', 
+    early: 'warning',
+    absent: 'danger'
+  }
+  return tagMap[status] || 'info'
+}
+
+const getAttendanceStatusLabel = (status) => {
+  const labelMap = {
+    normal: '姝e父',
+    late: '杩熷埌',
+    early: '鏃╅��', 
+    absent: '缂哄嫟'
+  }
+  return labelMap[status] || status
 }
 
 const getTypeOptions = () => {
@@ -408,6 +479,12 @@
       { label: '鑺傚亣鏃ュ姞鐝�', value: 'holiday' },
       { label: '娣卞鍔犵彮', value: 'night' }
     ]
+  } else if (currentType.value === 'annual') {
+    return [
+      { label: '姝e紡鍛樺伐', value: 'regular' },
+      { label: '璇曠敤鏈熷憳宸�', value: 'probation' },
+      { label: '瀹炰範鐢�', value: 'intern' }
+    ]
   }
   return []
 }
@@ -418,12 +495,14 @@
     if (form.dateRange && form.dateRange.length === 2 && form.dateRange[0] && form.dateRange[1]) {
       const start = new Date(form.dateRange[0])
       const end = new Date(form.dateRange[1])
-      
+      form.startDate = start.toISOString().split('T')[0]
+      form.endDate = end.toISOString().split('T')[0]
+
       if (isNaN(start.getTime()) || isNaN(end.getTime())) {
         console.warn('鏃犳晥鐨勬棩鏈熸牸寮�')
         return
       }
-      
+
       const diffTime = Math.abs(end - start)
       const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24)) + 1
       form.days = diffDays
@@ -434,14 +513,14 @@
 }
 
 // 楠岃瘉鏃堕棿鏍煎紡
-const validateTime = (time) => {
-  if (!time) return ''
-  if (typeof time === 'string') return time
-  if (time instanceof Date) {
-    return time.toTimeString().slice(0, 5)
-  }
-  return ''
-}
+// const validateTime = (time) => {
+//   if (!time) return ''
+//   if (typeof time === 'string') return time
+//   if (time instanceof Date) {
+//     return time.toTimeString().slice(0, 5)
+//   }
+//   return ''
+// }
 
 // 楠岃瘉鏃堕棿瀛楁
 const validateTimeField = (fieldName) => {
@@ -464,7 +543,7 @@
   try {
     currentType.value = type
     currentAction.value = action
-    
+
     if (action === 'add') {
       dialogTitle.value = `鏂板${getTypeName(type)}`
       currentEditId.value = ''
@@ -474,7 +553,7 @@
       currentEditId.value = row.id
       fillForm(row)
     }
-    
+
     dialogVisible.value = true
   } catch (error) {
     console.error('鎵撳紑寮圭獥澶辫触:', error)
@@ -497,6 +576,8 @@
     name: '',
     type: '',
     dateRange: [],
+    startDate: '',
+    endDate: '',
     days: 0,
     employeeType: '',
     workYears: '',
@@ -519,6 +600,8 @@
       name: row.name,
       type: row.type,
       dateRange: [new Date(row.startDate), new Date(row.endDate)],
+      startDate: row.startDate,
+      endDate: row.endDate,
       days: row.days,
       status: row.status
     })
@@ -558,15 +641,15 @@
       ElMessage.error('琛ㄥ崟寮曠敤涓嶅瓨鍦�')
       return
     }
-    
+
     await formRef.value.validate()
-    
+
     if (currentAction.value === 'add') {
       addItem()
     } else if (currentAction.value === 'edit') {
       editItem()
     }
-    
+
     dialogVisible.value = false
     ElMessage.success('鎿嶄綔鎴愬姛')
   } catch (error) {
@@ -576,85 +659,438 @@
 }
 
 const addItem = () => {
-  const newItem = { ...form, id: Date.now().toString() }
-  
+
   if (currentType.value === 'holiday') {
-    newItem.startDate = form.dateRange[0].toISOString().split('T')[0]
-    newItem.endDate = form.dateRange[1].toISOString().split('T')[0]
-    holidayData.value.push(newItem)
+    const params = {
+      name: form.name,
+      type: form.type,
+      startDate: form.startDate,
+      endDate: form.endDate,
+      days: form.days,
+      status: form.status
+    }
+    addHolidaySettings(params).then(res => {
+      if(res.code == 200){
+        ElMessage.success("娣诲姞鎴愬姛");
+        // dialogVisible.value = false;
+        getHolidaySettingsList()
+      }
+    }).catch(err => {
+      ElMessage.error(err.msg);
+    })
   } else if (currentType.value === 'annual') {
-    annualData.value.push(newItem)
+    // annualData.value.push(newItem)
+    const params = {
+      employeeType: form.employeeType,
+      workYears: form.workYears,
+      annualDays: form.annualDays,
+      maxCarryOver: form.maxCarryOver,
+      status: form.status
+    }
+    addAnnualLeaveSetting(params).then(res => {
+      if(res.code == 200){
+        ElMessage.success("娣诲姞鎴愬姛");
+        // dialogVisible.value = false;
+        getAnnualLeaveSettingList()
+      }
+    }).catch(err => {
+      ElMessage.error(err.msg);
+    })
   } else if (currentType.value === 'overtime') {
-    newItem.startTime = form.startTime || ''
-    newItem.endTime = form.endTime || ''
-    overtimeData.value.push(newItem)
+    const params = {
+      name: form.name,
+      type: form.type,
+      startTime: form.startTime || '',
+      endTime: form.endTime || '',
+      rate: form.rate,
+      status: form.status
+    }
+    addOvertimeSetting(params).then(res => {
+      if(res.code == 200){
+        ElMessage.success("娣诲姞鎴愬姛");
+        // dialogVisible.value = false;
+        getOvertimeSettingList()
+      }
+    }).catch(err => {
+      ElMessage.error(err.msg);
+    })
+    // newItem.startTime = form.startTime || ''
+    // newItem.endTime = form.endTime || ''
+    // overtimeData.value.push(newItem)
   } else if (currentType.value === 'worktime') {
-    newItem.startTime = form.workStartTime || ''
-    newItem.endTime = form.workEndTime || ''
-    worktimeData.value.push(newItem)
+    const params = {
+      name: form.name,
+      startTime: form.workStartTime || '',
+      endTime: form.workEndTime || '',
+      flexibleStart: form.flexibleStart,
+      flexibleMinutes: form.flexibleMinutes,
+      status: form.status
+    }
+    addWorkingHoursSetting(params).then(res => {
+      if(res.code == 200){
+        ElMessage.success("娣诲姞鎴愬姛");
+        getWorkingHoursSettingList()
+      }
+    }).catch(err => {
+      ElMessage.error(err.msg);
+    })
+    // newItem.startTime = form.workStartTime || ''
+    // newItem.endTime = form.workEndTime || ''
+    // worktimeData.value.push(newItem)
   }
 }
 
 const editItem = () => {
   let dataArray
   let index
-  
+
   if (currentType.value === 'holiday') {
-    dataArray = holidayData.value
-    index = dataArray.findIndex(item => item.id === currentEditId.value)
-    if (index > -1) {
-      dataArray[index] = { 
-        ...dataArray[index],
-        name: form.name,
-        type: form.type,
-        startDate: form.dateRange[0].toISOString().split('T')[0],
-        endDate: form.dateRange[1].toISOString().split('T')[0],
-        days: form.days,
-        status: form.status
-      }
+    const params = {
+      id: currentEditId.value,
+      name: form.name,
+      type: form.type,
+      startDate: form.dateRange[0].toISOString().split('T')[0],
+      endDate: form.dateRange[1].toISOString().split('T')[0],
+      days: form.days,
+      status: form.status
     }
+    updateHolidaySettings(params).then(res => {
+      if(res.code == 200){
+        ElMessage.success("鏇存柊鎴愬姛");
+        // dialogVisible.value = false;
+        getHolidaySettingsList()
+      }
+    }).catch(err => {
+      ElMessage.error(err.msg);
+    })
   } else if (currentType.value === 'annual') {
-    dataArray = annualData.value
-    index = dataArray.findIndex(item => item.id === currentEditId.value)
-    if (index > -1) {
-      dataArray[index] = { 
-        ...dataArray[index],
-        employeeType: form.employeeType,
-        workYears: form.workYears,
-        annualDays: form.annualDays,
-        maxCarryOver: form.maxCarryOver,
-        status: form.status
-      }
+    const params = {
+      id: currentEditId.value,
+      employeeType: form.employeeType,
+      workYears: form.workYears,
+      annualDays: form.annualDays,
+      maxCarryOver: form.maxCarryOver,
+      status: form.status
     }
+    updateAnnualLeaveSetting(params).then(res => {
+      if(res.code == 200){
+        ElMessage.success("鏇存柊鎴愬姛");
+        getAnnualLeaveSettingList()
+      }
+    }).catch(err => {
+      ElMessage.error(err.msg);
+    })
   } else if (currentType.value === 'overtime') {
-    dataArray = overtimeData.value
-    index = dataArray.findIndex(item => item.id === currentEditId.value)
-    if (index > -1) {
-      dataArray[index] = { 
-        ...dataArray[index],
-        name: form.name,
-        type: form.type,
-        startTime: form.startTime || '',
-        endTime: form.endTime || '',
-        rate: form.rate,
-        status: form.status
-      }
+    const params = {
+      id: currentEditId.value,
+      name: form.name,
+      type: form.type,
+      startTime: form.startTime || '',
+      endTime: form.endTime || '',
+      rate: form.rate,
+      status: form.status
     }
+    updateOvertimeSetting(params).then(res => {
+      if(res.code == 200){
+        ElMessage.success("鏇存柊鎴愬姛");
+        getOvertimeSettingList()
+      }
+    }).catch(err => {
+      ElMessage.error(err.msg);
+    })
+
+    // dataArray = overtimeData.value
+    // index = dataArray.findIndex(item => item.id === currentEditId.value)
+    // if (index > -1) {
+    //   dataArray[index] = {
+    //     ...dataArray[index],
+    //     name: form.name,
+    //     type: form.type,
+    //     startTime: form.startTime || '',
+    //     endTime: form.endTime || '',
+    //     rate: form.rate,
+    //     status: form.status
+    //   }
+    // }
   } else if (currentType.value === 'worktime') {
-    dataArray = worktimeData.value
-    index = dataArray.findIndex(item => item.id === currentEditId.value)
-    if (index > -1) {
-      dataArray[index] = { 
-        ...dataArray[index],
-        name: form.name,
-        startTime: form.workStartTime || '',
-        endTime: form.workEndTime || '',
-        flexibleStart: form.flexibleStart,
-        flexibleMinutes: form.flexibleMinutes,
-        status: form.status
-      }
+    const params = {
+      id: currentEditId.value,
+      name: form.name,
+      startTime: form.workStartTime || '',
+      endTime: form.workEndTime || '',
+      flexibleStart: form.flexibleStart,
+      flexibleMinutes: form.flexibleMinutes,
+      status: form.status
     }
+    updateWorkingHoursSetting(params).then(res => {
+      if(res.code == 200){
+        ElMessage.success("鏇存柊鎴愬姛");
+        getWorkingHoursSettingList()
+      }
+    }).catch(err => {
+      ElMessage.error(err.msg);
+    })
+    // dataArray = worktimeData.value
+    // index = dataArray.findIndex(item => item.id === currentEditId.value)
+    // if (index > -1) {
+    //   dataArray[index] = {
+    //     ...dataArray[index],
+    //     name: form.name,
+    //     startTime: form.workStartTime || '',
+    //     endTime: form.workEndTime || '',
+    //     flexibleStart: form.flexibleStart,
+    //     flexibleMinutes: form.flexibleMinutes,
+    //     status: form.status
+    //   }
+    // }
   }
+}
+
+// 鎵撳崱璁板綍杩囨护鍔熻兘
+const filterAttendanceData = () => {
+  let filtered = attendanceData.value
+  
+  // 鎸夋棩鏈熻繃婊�
+  if (attendanceDate.value) {
+    filtered = filtered.filter(item => item.date === attendanceDate.value)
+  }
+  
+  // 鎸夌姸鎬佽繃婊�
+  if (attendanceStatus.value) {
+    filtered = filtered.filter(item => item.status === attendanceStatus.value)
+  }
+  
+  filteredAttendanceData.value = filtered
+}
+
+// 瀵煎嚭鎵撳崱璁板綍
+const exportAttendance = () => {
+  ElMessage.success('瀵煎嚭鍔熻兘寮�鍙戜腑...')
+}
+
+// 鍒濆鍖栨墦鍗¤褰曞亣鏁版嵁
+const initAttendanceData = () => {
+  const mockData = [
+    {
+      id: 1,
+      employeeName: '闄堝織寮�',
+      department: '鎶�鏈儴',
+      date: '2025-08-15',
+      clockInTime: '09:00:00',
+      clockOutTime: '18:00:00',
+      workHours: '8.0h',
+      status: 'normal',
+      location: '鍏徃鎬婚儴',
+      remark: ''
+    },
+    {
+      id: 2,
+      employeeName: '鏉庨洩姊�',
+      department: '甯傚満閮�',
+      date: '2025-08-16',
+       clockInTime: '08:58:00',
+       clockOutTime: '18:05:00',
+       workHours: '8.12h',
+       status: 'normal',
+       location: '鍏徃鎬婚儴',
+       remark: ''
+     },
+     {
+       id: 3,
+       employeeName: '鐜嬪缓鍗�',
+       department: '浜轰簨閮�',
+       date: '2025-08-16',
+       clockInTime: '09:02:00',
+       clockOutTime: '18:00:00',
+       workHours: '7.97h',
+       status: 'normal',
+       location: '鍏徃鎬婚儴',
+       remark: ''
+     },
+     {
+       id: 4,
+       employeeName: '璧垫檽涓�',
+       department: '璐㈠姟閮�',
+       date: '2025-09-02',
+       clockInTime: '08:55:00',
+       clockOutTime: '18:10:00',
+       workHours: '8.25h',
+       status: 'normal',
+       location: '鍏徃鎬婚儴',
+       remark: ''
+     },
+     {
+       id: 5,
+       employeeName: '寮犲浗搴�',
+       department: '鎶�鏈儴',
+       date: '2025-09-02',
+       clockInTime: '09:00:00',
+       clockOutTime: '18:30:00',
+       workHours: '8.5h',
+       status: 'normal',
+       location: '鍏徃鎬婚儴',
+       remark: '鍔犵彮'
+     },
+     {
+       id: 6,
+       employeeName: '鍒樻槑杈�',
+       department: '杩愯惀閮�',
+       date: '2025-09-03',
+       clockInTime: '09:05:00',
+       clockOutTime: '18:00:00',
+       workHours: '7.92h',
+       status: 'normal',
+       location: '鍏徃鎬婚儴',
+       remark: ''
+     },
+     {
+       id: 7,
+       employeeName: '瀛欎附鍗�',
+       department: '璁捐閮�',
+       date: '2025-09-03',
+       clockInTime: '08:59:00',
+       clockOutTime: '18:02:00',
+       workHours: '8.05h',
+       status: 'normal',
+       location: '鍏徃鎬婚儴',
+       remark: ''
+     },
+     {
+       id: 8,
+       employeeName: '鍛ㄥ缓鍐�',
+       department: '閿�鍞儴',
+       date: '2025-09-04',
+       clockInTime: '09:15:00',
+       clockOutTime: '18:00:00',
+       workHours: '7.75h',
+       status: 'late',
+       location: '鍏徃鎬婚儴',
+       remark: '浜ら�氬牭濉�'
+     },
+     {
+       id: 9,
+       employeeName: '鍚村皬鑺�',
+       department: '瀹㈡湇閮�',
+       date: '2025-09-04',
+       clockInTime: '09:01:00',
+       clockOutTime: '18:00:00',
+       workHours: '7.98h',
+       status: 'normal',
+       location: '鍏徃鎬婚儴',
+       remark: ''
+     },
+     {
+       id: 10,
+       employeeName: '椹枃鏉�',
+       department: '鎶�鏈儴',
+       date: '2025-09-05',
+       clockInTime: '08:57:00',
+       clockOutTime: '17:30:00',
+       workHours: '7.55h',
+       status: 'early',
+       location: '鍏徃鎬婚儴',
+       remark: '鏈夋�ヤ簨鎻愬墠绂诲紑'
+     },
+     {
+       id: 11,
+       employeeName: '鏋楁檽涓�',
+       department: '琛屾斂閮�',
+       date: '2025-09-05',
+       clockInTime: '09:03:00',
+       clockOutTime: '18:08:00',
+       workHours: '8.08h',
+       status: 'normal',
+       location: '鍏徃鎬婚儴',
+       remark: ''
+     },
+     {
+       id: 12,
+       employeeName: '榛勭編鐜�',
+       department: '璐㈠姟閮�',
+       date: '2025-09-06',
+       clockInTime: '',
+       clockOutTime: '',
+       workHours: '0h',
+       status: 'absent',
+       location: '',
+       remark: '璇风梾鍋�'
+     },
+    {
+      id: 13,
+      employeeName: '閮戞捣娑�',
+      department: '甯傚満閮�',
+      date: '2025-08-14',
+      clockInTime: '09:00:00',
+      clockOutTime: '18:00:00',
+      workHours: '8.0h',
+      status: 'normal',
+      location: '鍏徃鎬婚儴',
+      remark: ''
+    },
+    {
+      id: 14,
+      employeeName: '璋附濞�',
+      department: '浜轰簨閮�',
+      date: '2025-08-20',
+      clockInTime: '08:58:00',
+      clockOutTime: '18:03:00',
+      workHours: '8.08h',
+      status: 'normal',
+      location: '鍏徃鎬婚儴',
+      remark: ''
+    },
+    {
+      id: 15,
+      employeeName: '浣曞織浼�',
+      department: '鎶�鏈儴',
+      date: '2025-08-21',
+      clockInTime: '09:10:00',
+      clockOutTime: '18:00:00',
+      workHours: '7.83h',
+      status: 'late',
+      location: '鍏徃鎬婚儴',
+      remark: ''
+    },
+    {
+      id: 16,
+      employeeName: '璁搁泤鑺�',
+      department: '璁捐閮�',
+      date: '2025-08-22',
+      clockInTime: '09:01:00',
+      clockOutTime: '18:00:00',
+      workHours: '7.98h',
+      status: 'normal',
+      location: '鍏徃鎬婚儴',
+      remark: ''
+    },
+    {
+      id: 17,
+      employeeName: '閭撳缓骞�',
+      department: '杩愯惀閮�',
+      date: '2025-09-10',
+      clockInTime: '08:59:00',
+      clockOutTime: '18:05:00',
+      workHours: '8.1h',
+      status: 'normal',
+      location: '鍏徃鎬婚儴',
+      remark: ''
+    },
+    {
+      id: 18,
+      employeeName: '鏇惧皬绾�',
+      department: '瀹㈡湇閮�',
+      date: '2025-09-11',
+      clockInTime: '09:02:00',
+      clockOutTime: '18:00:00',
+      workHours: '7.97h',
+      status: 'normal',
+      location: '鍏徃鎬婚儴',
+      remark: ''
+    }
+  ]
+  
+  attendanceData.value = mockData
+  filteredAttendanceData.value = mockData
 }
 
 // 鍒犻櫎椤圭洰
@@ -664,21 +1100,115 @@
     cancelButtonText: '鍙栨秷',
     type: 'warning'
   }).then(() => {
+    let ids = [];
     let dataArray
-    if (type === 'holiday') dataArray = holidayData.value
-    else if (type === 'annual') dataArray = annualData.value
-    else if (type === 'overtime') dataArray = overtimeData.value
-    else if (type === 'worktime') dataArray = worktimeData.value
-    
-    const index = dataArray.findIndex(item => item.id === row.id)
-    if (index > -1) {
-      dataArray.splice(index, 1)
-      ElMessage.success('鍒犻櫎鎴愬姛')
+    if (type === 'holiday') {
+      ids.push(row.id)
+      delHolidaySettings(ids).then(res => {
+        if(res.code == 200){
+          ElMessage.success("鍒犻櫎鎴愬姛");
+          ids = []
+          getHolidaySettingsList()
+        }
+      }).catch(err => {
+        ElMessage.error(err.msg);
+      })
     }
+    else if (type === 'annual') {
+      ids.push(row.id)
+      delAnnualLeaveSetting(ids).then(res => {
+        if(res.code == 200){
+          ElMessage.success("鍒犻櫎鎴愬姛");
+          ids = []
+          getAnnualLeaveSettingList()
+        }
+      }).catch(err => {
+        ElMessage.error(err.msg);
+      })
+    }
+    else if (type === 'overtime') {
+      ids.push(row.id)
+      delOvertimeSetting(ids).then(res => {
+        if(res.code == 200){
+          ElMessage.success("鍒犻櫎鎴愬姛");
+          ids = []
+          getOvertimeSettingList()
+        }
+      }).catch(err => {
+        ElMessage.error(err.msg);
+      })
+    }
+    else if (type === 'worktime') {
+      ids.push(row.id)
+      delWorkingHoursSetting(ids).then(res => {
+        if(res.code == 200){
+          ElMessage.success("鍒犻櫎鎴愬姛");
+          ids = []
+          getWorkingHoursSettingList()
+        }
+      }).catch(err => {
+        ElMessage.error(err.msg);
+      })
+    }
+
+    // const index = dataArray.findIndex(item => item.id === row.id)
+    // if (index > -1) {
+    //   dataArray.splice(index, 1)
+    //   ElMessage.success('鍒犻櫎鎴愬姛')
+    // }
   })
 }
+// 鑾峰彇鍋囨湡璁剧疆鍒楄〃
+const getHolidaySettingsList = () => {
+  // tableLoading.value = true;
+  listHolidaySettings({...page.value})
+  .then(res => {
+    // tableLoading.value = false;
+    holidayData.value = res.data.records
+    page.total = res.data.total;
+  }).catch(err => {
+    // tableLoading.value = false;
+  })
+};
+// 鑾峰彇骞村亣瑙勫垯鍒楄〃
+const getAnnualLeaveSettingList = () => {
 
+  listAnnualLeaveSettingList({...page.value})
+  .then(res => {
+    // console.log(res.data)
+    annualData.value = res.data.records
+    page.total = res.data.total;
+  }).catch(err => {
+  })
+};
+// 鑾峰彇鍔犵彮瑙勫垯鍒楄〃
+const getOvertimeSettingList = () => {
+
+  listOvertimeSettingList({...page.value})
+  .then(res => {
+    // console.log(res.data)
+    overtimeData.value = res.data.records
+    page.total = res.data.total;
+  }).catch(err => {
+  })
+};
+// 鑾峰彇宸ヤ綔鏃堕棿瑙勫垯鍒楄〃
+const getWorkingHoursSettingList = () => {
+
+  listWorkingHoursSettingList({...page.value})
+  .then(res => {
+    // console.log(res.data)
+    worktimeData.value = res.data.records
+    page.total = res.data.total;
+  }).catch(err => {
+  })
+};
 onMounted(() => {
+  getHolidaySettingsList()
+  getAnnualLeaveSettingList()
+  getOvertimeSettingList()
+  getWorkingHoursSettingList()
+  initAttendanceData()
   console.log('鑰冨嫟绠$悊椤甸潰鍔犺浇瀹屾垚')
 })
 
diff --git a/src/views/collaborativeApproval/enterpriseBook/index.vue b/src/views/collaborativeApproval/enterpriseBook/index.vue
new file mode 100644
index 0000000..0b33a32
--- /dev/null
+++ b/src/views/collaborativeApproval/enterpriseBook/index.vue
@@ -0,0 +1,798 @@
+<template>
+  <div class="app-container">
+    <!-- 澶撮儴瀵艰埅 -->
+    <!-- <div class="header">
+      <h2>浼佷笟閫氳褰曠鐞�</h2>
+      <p>绠$悊涓汉銆佸叕鍏卞拰鍗曚綅鐨勮仈绯绘柟寮�</p>
+    </div> -->
+
+    <!-- 鏍囩椤靛垏鎹� -->
+    <el-tabs v-model="activeTab" @tab-change="handleTabChange" type="border-card">
+      <el-tab-pane label="涓汉閫氳褰�" name="personal">
+        <div class="tab-content">
+          <!-- 鎼滅储妗� -->
+          <el-input
+            v-model="personalSearch.staffName" 
+            placeholder="鎼滅储鑱旂郴浜�"
+            clearable
+            prefix-icon="Search"
+            class="search-input"
+            @keyup.enter="getPersonalContactsList"
+          />
+          <el-button style="margin: 0 0 20px 20px;" type="primary" @click="showAddContactDialog=true">娣诲姞鑱旂郴浜�</el-button>
+          <!-- 鑱旂郴浜哄垪琛� -->
+          <div class="contact-list">
+            <div 
+              v-for="contact in personalContacts" 
+              :key="contact.id"
+              class="contact-card"
+              @click="showContactDetail(contact)"
+            >
+              <div class="contact-avatar">{{ contact.staffName.charAt(0) }}</div>
+              <div class="contact-info">
+                <h4>{{ contact.staffName }}</h4>
+                <p>{{ contact.profession }} - {{ contact.postJob }}</p>
+                <div class="contact-phone">{{ contact.phone }}</div>
+              </div>
+              <div class="contact-actions">
+                <!-- <el-button 
+                  type="text" 
+                  icon="Phone"
+                  @click.stop="callContact(contact)"
+                ></el-button> -->
+                <el-button 
+                  type="text" 
+                  icon="Message"
+                  @click.stop="messageContact(contact)"
+                ></el-button>
+                <el-button 
+                  type="text" 
+                  icon="Delete"
+                  @click.stop="removeFromPersonalContacts(contact.id)"
+                ></el-button>
+              </div>
+            </div>
+            
+            <!-- 绌虹姸鎬�
+            <div v-if="personalContacts.length === 0 && !loading" class="empty-state">
+              <el-empty description="鏆傛棤鑱旂郴浜�" />
+              <el-button type="primary" @click="showAddContactDialog=true">娣诲姞鑱旂郴浜�</el-button>
+            </div> -->
+          </div>
+        </div>
+      </el-tab-pane>
+      
+      <el-tab-pane label="鍏叡閫氳褰�" name="public">
+        <div class="tab-content">
+          <!-- 鎼滅储妗� -->
+          <el-input
+            v-model="publicSearch.staffName" 
+            placeholder="鎼滅储鍏叡鑱旂郴浜�"
+            clearable
+            prefix-icon="Search"
+            class="search-input"
+            @keyup.enter="getPublicContactsList"
+          />
+          
+          <!-- 鑱旂郴浜哄垪琛� publicContacts-->
+          <div class="contact-list">
+            <div 
+              v-for="contact in EmployeeList" 
+              :key="contact.id"
+              class="contact-card"
+              @click="showContactDetail(contact)"
+            >
+              <div class="contact-avatar">{{ contact.staffName.charAt(0) }}</div>
+              <div class="contact-info">
+                <h4>{{ contact.staffName }}</h4>
+                <p>{{ contact.postJob }} - {{ contact.profession }}</p>
+                <div class="contact-phone">{{ contact.phone }}</div>
+              </div>
+              <div class="contact-actions">
+                <!-- <el-button 
+                  type="text" 
+                  icon="Phone"
+                  @click.stop="callContact(contact)"
+                ></el-button> -->
+                <el-button 
+                  type="text" 
+                  icon="Message"
+                  @click.stop="messageContact(contact)"
+                ></el-button>
+                <el-button 
+                  type="text" 
+                  icon="Delete"
+                  :type="isInPersonalContacts(contact.id) ? 'primary' : ''"
+                  @click.stop="togglePersonalContact(contact)"
+                ></el-button>
+              </div>
+            </div>
+          </div>
+        </div>
+      </el-tab-pane>
+      
+      <el-tab-pane label="鍗曚綅閫氳褰�" name="company">
+        <div class="tab-content">
+          <div class="company-contacts-layout">
+            <!-- 宸︿晶閮ㄩ棬鏍� -->
+            <div class="department-tree">
+              <!-- <h3>閮ㄩ棬缁撴瀯</h3>
+              <el-tree
+                :data="departmentTree"
+                :props="{ label: 'deptName', children: 'children' }"
+                node-key="deptId"
+                ref="departmentTreeRef"
+                highlight-current
+                default-expand-all
+                @node-click="handleDepartmentClick"
+              /> -->
+              <el-col >
+                <div class="head-container">
+                  <el-input
+                    v-model="deptName"
+                    placeholder="璇疯緭鍏ラ儴闂ㄥ悕绉�"
+                    clearable
+                    prefix-icon="Search"
+                    style="margin-bottom: 20px"
+                  />
+                </div>
+                <div class="head-container">
+                  <el-tree
+                    :data="departmentTree"
+                    :props="{ label: 'label', children: 'children' }"
+                    :expand-on-click-node="false"
+                    :filter-node-method="filterNode"
+                    ref="deptTreeRef"
+                    node-key="id"
+                    highlight-current
+                    default-expand-all
+                    @node-click="handleDepartmentClick"
+                  />
+                </div>
+              </el-col>
+            </div>
+            
+            <!-- 鍙充晶閮ㄩ棬鎴愬憳 -->
+            <div class="department-members">
+              <h3>{{ currentDepartment?.label || '鍏ㄩ儴鎴愬憳' }}</h3>
+              <el-input
+                v-model="companySearch.staffName" 
+                placeholder="鎼滅储閮ㄩ棬鎴愬憳"
+                clearable
+                prefix-icon="Search"
+                class="search-input"
+                @keyup.enter="getCompanyContactsList"
+              />
+              
+              <div class="contact-list">
+                <div 
+                  v-for="contact in companyContacts" 
+                  :key="contact.id"
+                  class="contact-card"
+                  @click="showContactDetail(contact)"
+                >
+                  <div class="contact-avatar">{{ contact.staffName.charAt(0) }}</div>
+                  <div class="contact-info">
+                    <h4>{{ contact.staffName }}</h4>
+                    <p>{{ contact.profession }}</p>
+                    <div class="contact-phone">{{ contact.phone }}</div>
+                  </div>
+                  <div class="contact-actions">
+                    
+                    <el-button 
+                      type="text" 
+                      icon="Message"
+                      @click.stop="messageContact(contact)"
+                    ></el-button>
+                    <el-button 
+                      type="text" 
+                      icon="Delete"
+                      :type="isInPersonalContacts(contact.id) ? 'primary' : ''"
+                      @click.stop="togglePersonalContact(contact)"
+                    ></el-button>
+                  </div>
+                </div>
+              </div>
+            </div>
+          </div>
+        </div>
+      </el-tab-pane>
+    </el-tabs>
+    
+    <!-- 鑱旂郴浜鸿鎯呭脊绐� -->
+    <el-dialog 
+      v-model="showDetailDialog" 
+      title="鑱旂郴浜鸿鎯�"
+      width="400px"
+    >
+      <div v-if="selectedContact" class="contact-detail">
+        <div class="detail-avatar">{{ selectedContact.staffName?.charAt(0) }}</div>
+        <h3>{{ selectedContact.staffName }}</h3>
+        <p class="detail-position">{{ selectedContact.profession }} - {{ selectedContact.postJob }}</p>
+        
+        <div class="detail-info">
+          <div class="info-item">
+            <span class="label">缂栧彿锛�</span>
+            <span class="value">{{ selectedContact.staffNo }}</span>
+          </div>
+          <div class="info-item">
+            <span class="label">鎵嬫満鍙风爜锛�</span>
+            <span class="value">{{ selectedContact.phone }}</span>
+          </div>
+          <div class="info-item">
+            <span class="label">閭锛�</span>
+            <span class="value">{{ selectedContact.sex }}</span>
+          </div>
+          <div class="info-item">
+            <span class="label">浣忓潃锛�</span>
+            <span class="value">{{ selectedContact.adress || '鏆傛棤' }}</span>
+          </div>
+        </div>
+      </div>
+      <template #footer>
+        <el-button @click="showDetailDialog = false">鍏抽棴</el-button>
+        <el-button 
+          type="primary" 
+          v-if="activeTab !== 'personal'"
+          @click="togglePersonalContact(selectedContact); showDetailDialog = false"
+        >
+          {{ isInPersonalContacts(selectedContact?.id) ? '浠庝釜浜洪�氳褰曠Щ闄�' : '娣诲姞鍒颁釜浜洪�氳褰�' }}
+        </el-button>
+      </template>
+    </el-dialog>
+    
+    <!-- 娣诲姞鑱旂郴浜哄脊绐� -->
+    <el-dialog 
+      v-model="showAddContactDialog"
+      title="娣诲姞鑱旂郴浜�"
+      width="500px"
+    >
+      <el-form :model="addContactForm" ref="addContactFormRef" label-width="80px">
+        <!-- <el-form-item label="濮撳悕" prop="name">
+          <el-input v-model="addContactForm.name" placeholder="璇疯緭鍏ュ鍚�" />
+        </el-form-item>
+        <el-form-item label="鎵嬫満鍙风爜" prop="phone">
+          <el-input v-model="addContactForm.phone" placeholder="璇疯緭鍏ユ墜鏈哄彿鐮�" />
+        </el-form-item>
+        <el-form-item label="閭" prop="email">
+          <el-input v-model="addContactForm.email" placeholder="璇疯緭鍏ラ偖绠�" />
+        </el-form-item>
+        <el-form-item label="閮ㄩ棬" prop="department">
+          <el-input v-model="addContactForm.department" placeholder="璇疯緭鍏ラ儴闂�" />
+        </el-form-item> -->
+        <el-form-item label="濮撳悕" prop="name">
+          <!-- <select v-model="addContactForm.contactId">
+            <option v-for="item in EmployeeList" :key="item.id" :value="item.id">{{ item.staffName }}</option> 
+          </select> -->
+          <el-select v-model="addContactForm.contactId" placeholder="璇烽�夋嫨" style="width: 100%">
+            <el-option
+              v-for="option in EmployeeList"
+              :key="option.id"
+              :label="option.staffName"
+              :value="option.id"
+            />
+          </el-select>
+        </el-form-item>
+      </el-form>
+      <template #footer>
+        <el-button @click="showAddContactDialog = false">鍙栨秷</el-button>
+        <el-button type="primary" @click="addContact">纭畾</el-button>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+
+<script setup>
+import { ref, onMounted, reactive, computed } from 'vue'
+import { ElMessage, ElMessageBox } from 'element-plus'
+import {
+  getPersonalContacts,
+  addPersonalContact,
+  removePersonalContact,
+  getPublicContacts,
+  getCompanyContacts,
+  getDepartmentTree,
+  getEmployeeDetail
+} from '@/api/collaborativeApproval/enterpriseBook.js'
+import { getUserProfile } from '@/api/system/user.js'
+import {staffJoinListPage} from "@/api/personnelManagement/onboarding.js";
+import {
+  changeUserStatus,
+  listUser,
+  resetUserPwd,
+  delUser,
+  getUser,
+  updateUser,
+  addUser,
+  deptTreeSelect,
+} from "@/api/system/user";
+
+// 鏍囩椤电姸鎬�
+const activeTab = ref('personal')
+const loading = ref(false)
+const EmployeeList = ref([])
+const page = reactive({
+  pageNum: 1,
+  pageSize: 10,
+  total: 0,
+})
+// 涓汉閫氳褰曟暟鎹�
+const personalContacts = ref([])
+const personalSearch = ref({
+  staffName: '',
+})
+
+// 鍏叡閫氳褰曟暟鎹�
+const publicContacts = ref([])
+const publicSearch = ref({
+  staffName: '',
+  staffState: 1
+})
+
+// 鍗曚綅閫氳褰曟暟鎹�
+const companyContacts = ref([])
+const companySearch = ref({
+  staffName: '',
+  staffState: 1
+})
+const departmentTree = ref([])
+const departmentTreeRef = ref(null)
+const currentDepartment = ref(null)
+
+// 寮圭獥鐘舵��
+const showDetailDialog = ref(false)
+const showAddContactDialog = ref(false)
+const selectedContact = ref(null)
+
+// 娣诲姞鑱旂郴浜鸿〃鍗�
+const addContactForm = reactive({
+  contactId: '',
+  name: '',
+  phone: '',
+  email: '',
+  department: '',
+  position: ''
+})
+const addContactFormRef = ref(null)
+
+// 鍒濆鍖栨暟鎹�
+onMounted(() => {
+  getEmployeeList()
+  getPersonalContactsList()
+  if (activeTab.value === 'public') {
+    getPublicContactsList()
+  } else if (activeTab.value === 'company') {
+    getDepartmentTreeData()
+    getCompanyContactsList()
+  }
+})
+
+// 澶勭悊鏍囩椤靛垏鎹�
+const handleTabChange = (tabName) => {
+  if (tabName === 'public') {
+    getPublicContactsList()
+  } else if (tabName === 'company') {
+    getDepartmentTreeData()
+    getCompanyContactsList()
+  }
+}
+
+// 鑾峰彇涓汉閫氳褰曞垪琛�
+const getPersonalContactsList = async () => {
+  loading.value = true
+  getPersonalContacts(page,personalSearch.value).then(res => {
+    personalContacts.value = res.data.records
+  })
+  loading.value = false
+}
+
+// 鑾峰彇鍏叡閫氳褰曞垪琛�
+const getPublicContactsList = async () => {
+  loading.value = true
+  getEmployeeList()
+  // publicContacts.value = generateMockPublicContacts()
+  loading.value = false
+}
+  //鑾峰彇鍛樺伐鍒楄〃
+const getEmployeeList = async () => {
+  staffJoinListPage(publicSearch.value).then(res => {
+    console.log(res.data.records)
+      EmployeeList.value = res.data.records
+    }).catch(err => {})
+}
+// 鑾峰彇鍗曚綅閫氳褰曞垪琛�
+const getCompanyContactsList = async () => {
+  loading.value = true
+    staffJoinListPage(companySearch.value).then(res => {
+    // console.log(res.data.records)
+      companyContacts.value = res.data.records
+    }).catch(err => {})
+
+  loading.value = false
+ loading.value = false
+  // }
+}
+
+// 鑾峰彇閮ㄩ棬鏍戠粨鏋�
+const getDepartmentTreeData = async () => {
+    deptTreeSelect().then((response) => {
+    // console.log("Tree",response.data)
+    departmentTree.value = response.data;
+    // enabledDeptOptions.value = filterDisabledDept(
+    //   JSON.parse(JSON.stringify(response.data))
+    // );
+  });
+}
+// /** 杩囨护绂佺敤鐨勯儴闂� */
+// function filterDisabledDept(deptList) {
+//   return deptList.filter((dept) => {
+//     if (dept.disabled) {
+//       return false;
+//     }
+//     if (dept.children && dept.children.length) {
+//       dept.children = filterDisabledDept(dept.children);
+//     }
+//     return true;
+//   });
+// }
+// 澶勭悊閮ㄩ棬鐐瑰嚮
+const handleDepartmentClick = (data) => {
+  // console.log("鐐瑰嚮",data)
+  companySearch.value = {
+    ...companySearch.value,
+    deptId: data.id,
+  }
+  // currentDepartment.value = data.id
+  // 鑾峰彇璇ラ儴闂ㄧ殑鎴愬憳鍒楄〃
+
+  getCompanyContactsList()
+}
+
+// 鏄剧ず鑱旂郴浜鸿鎯�
+const showContactDetail = async (contact) => {
+  selectedContact.value = contact
+  showDetailDialog.value = true
+}
+
+// 鎷ㄦ墦鐢佃瘽
+const callContact = (contact) => {
+  ElMessage.info(`姝e湪鎷ㄦ墦 ${contact.name} 鐨勭數璇�: ${contact.phone}`)
+}
+
+// 鍙戦�佹秷鎭�
+const messageContact = (contact) => {
+  ElMessage.info(`姝e湪鍙戦�佹秷鎭粰 ${contact.name}`)
+}
+
+
+// 娣诲姞鑱旂郴浜�
+const addContact = async () => {
+  
+  try {
+    // 琛ㄥ崟楠岃瘉
+    // if (!addContactForm.name || !addContactForm.phone) {
+    //   ElMessage.warning('璇峰~鍐欏鍚嶅拰鎵嬫満鍙风爜')
+    //   return
+    // }
+    
+    const res = await addPersonalContact(addContactForm)
+    if (res.code === 200) {
+      ElMessage.success('娣诲姞鎴愬姛')
+      showAddContactDialog.value = false
+      getPersonalContactsList()
+      // 閲嶇疆琛ㄥ崟
+      Object.keys(addContactForm).forEach(key => {
+        addContactForm[key] = ''
+      })
+    }
+  } catch (error) {
+    ElMessage.error('娣诲姞澶辫触')
+    // 妯℃嫙娣诲姞鎴愬姛
+    personalContacts.value.push({
+      ...addContactForm,
+      id: Date.now(),
+      createTime: new Date().toISOString()
+    })
+    ElMessage.success('娣诲姞鎴愬姛')
+    showAddContactDialog.value = false
+    // 閲嶇疆琛ㄥ崟
+    Object.keys(addContactForm).forEach(key => {
+      addContactForm[key] = ''
+    })
+  }
+}
+
+// 浠庝釜浜洪�氳褰曠Щ闄�
+const removeFromPersonalContacts = async (contactId) => {
+  ElMessageBox.confirm(
+    '纭畾瑕佷粠涓汉閫氳褰曚腑绉婚櫎璇ヨ仈绯讳汉鍚楋紵',
+    '鎻愮ず',
+    {
+      confirmButtonText: '纭畾',
+      cancelButtonText: '鍙栨秷',
+      type: 'warning'
+    }
+  ).then(async () => {
+    try {
+      const res = await removePersonalContact(contactId)
+      if (res.code === 200) {
+        ElMessage.success('绉婚櫎鎴愬姛')
+        getPersonalContactsList()
+      }
+    } catch (error) {
+      ElMessage.error('绉婚櫎澶辫触')
+      // 妯℃嫙绉婚櫎鎴愬姛
+      // personalContacts.value = personalContacts.value.filter(item => item.id !== contactId)
+      ElMessage.success('绉婚櫎鎴愬姛')
+    }
+  })
+}
+
+// 鍒囨崲涓汉閫氳褰�
+const togglePersonalContact = async (contact) => {
+  const isInPersonal = isInPersonalContacts(contact.id)
+  const contactId = contact.id
+  if (isInPersonal) {
+    // 浠庝釜浜洪�氳褰曠Щ闄�
+    //鏍规嵁contactId鏌ユ壘personalContacts涓搴旂殑椤癸紝鐒跺悗鍒犻櫎璇ラ」
+    const index = personalContacts.value.findIndex(item => item.contactId === contactId)
+    const personId = personalContacts.value[index].id
+    // console.log(personId)
+    await removeFromPersonalContacts(personId)
+  } else {
+    // 娣诲姞鍒颁釜浜洪�氳褰�
+    try {
+      const res = await addPersonalContact({contactId: contactId})
+      if (res.code === 200) {
+        ElMessage.success('娣诲姞鎴愬姛')
+        getPersonalContactsList()
+      }
+    } catch (error) {
+      ElMessage.error('娣诲姞澶辫触')
+      // 妯℃嫙娣诲姞鎴愬姛
+      // personalContacts.value.push({
+      //   ...contact,
+      //   id: contact.id || Date.now(),
+      //   createTime: new Date().toISOString()
+      // })
+      // ElMessage.success('娣诲姞鎴愬姛')
+    }
+  }
+}
+
+// 妫�鏌ユ槸鍚﹀湪涓汉閫氳褰曚腑
+const isInPersonalContacts = (contactId) => {
+  return personalContacts.value.some(item => item.contactId === contactId)
+}
+
+// 鐢熸垚妯℃嫙閮ㄩ棬鏍戞暟鎹�
+const generateMockDepartmentTree = () => {
+  return [
+    {
+      deptId: 1,
+      deptName: '鎶�鏈儴',
+      children: [
+        {
+          deptId: 101,
+          deptName: '鍓嶇缁�'
+        },
+        {
+          deptId: 102,
+          deptName: '鍚庣缁�'
+        },
+        {
+          deptId: 103,
+          deptName: '娴嬭瘯缁�'
+        }
+      ]
+    },
+    {
+      deptId: 2,
+      deptName: '浜у搧閮�'
+    },
+    {
+      deptId: 3,
+      deptName: '浜轰簨閮�'
+    },
+    {
+      deptId: 4,
+      deptName: '璐㈠姟閮�'
+    }
+  ]
+}
+
+// 鐢熸垚妯℃嫙鍗曚綅閫氳褰曟暟鎹�
+// const generateMockCompanyContacts = (deptName) => {
+//   const allContacts = getEmployeeList()
+  
+//   if (deptName) {
+//     return allContacts.filter(contact => contact.postJob === deptName)
+//   }
+//   return allContacts
+// }
+
+</script>
+
+<style scoped>
+.header {
+  margin-bottom: 20px;
+  padding: 15px;
+  background: #f5f7fa;
+  border-radius: 8px;
+}
+
+.header h2 {
+  margin: 0 0 5px 0;
+  color: #303133;
+}
+
+.header p {
+  margin: 0;
+  color: #909399;
+  font-size: 14px;
+}
+
+.tab-content {
+  padding: 15px;
+  background: #fff;
+  border-radius: 8px;
+  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
+}
+
+.search-input {
+  margin-bottom: 20px;
+  width: 300px;
+}
+
+.contact-list {
+  display: flex;
+  flex-wrap: wrap;
+  gap: 15px;
+}
+
+.contact-card {
+  display: flex;
+  align-items: center;
+  padding: 15px;
+  width: 500px;
+  background: #f8f9fa;
+  border-radius: 8px;
+  cursor: pointer;
+  transition: all 0.3s;
+}
+
+.contact-card:hover {
+  background: #e9ecef;
+  transform: translateY(-2px);
+  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
+}
+
+.contact-avatar {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  width: 48px;
+  height: 48px;
+  background: #409eff;
+  color: #fff;
+  font-size: 20px;
+  font-weight: bold;
+  border-radius: 50%;
+  margin-right: 15px;
+}
+
+.contact-info {
+  flex: 1;
+}
+
+.contact-info h4 {
+  margin: 0 0 5px 0;
+  color: #303133;
+  font-size: 16px;
+}
+
+.contact-info p {
+  margin: 0 0 5px 0;
+  color: #606266;
+  font-size: 14px;
+}
+
+.contact-phone {
+  color: #409eff;
+  font-size: 14px;
+}
+
+.contact-actions {
+  display: flex;
+  gap: 5px;
+}
+
+.empty-state {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: center;
+  padding: 60px 20px;
+  color: #909399;
+}
+
+.company-contacts-layout {
+  display: flex;
+  gap: 20px;
+}
+
+.department-tree {
+  width: 250px;
+  padding: 15px;
+  background: #f8f9fa;
+  border-radius: 8px;
+}
+
+.department-tree h3 {
+  margin: 0 0 15px 0;
+  padding-bottom: 10px;
+  border-bottom: 1px solid #e4e7ed;
+  color: #303133;
+  font-size: 16px;
+}
+
+.department-members {
+  flex: 1;
+}
+
+.department-members h3 {
+  margin: 0 0 15px 0;
+  color: #303133;
+  font-size: 16px;
+}
+
+.contact-detail {
+  text-align: center;
+}
+
+.detail-avatar {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  width: 80px;
+  height: 80px;
+  background: #409eff;
+  color: #fff;
+  font-size: 32px;
+  font-weight: bold;
+  border-radius: 50%;
+  margin: 0 auto 20px;
+}
+
+.contact-detail h3 {
+  margin: 0 0 10px 0;
+  color: #303133;
+  font-size: 20px;
+}
+
+.detail-position {
+  margin: 0 0 30px 0;
+  color: #606266;
+  font-size: 14px;
+}
+
+.detail-info {
+  text-align: left;
+}
+
+.info-item {
+  margin-bottom: 15px;
+}
+
+.info-item .label {
+  display: inline-block;
+  width: 100px;
+  color: #909399;
+  font-size: 14px;
+}
+
+.info-item .value {
+  color: #303133;
+  font-size: 14px;
+}
+</style>
\ No newline at end of file
diff --git a/src/views/collaborativeApproval/knowledgeBase/index.vue b/src/views/collaborativeApproval/knowledgeBase/index.vue
index f944859..aeb1ba4 100644
--- a/src/views/collaborativeApproval/knowledgeBase/index.vue
+++ b/src/views/collaborativeApproval/knowledgeBase/index.vue
@@ -13,22 +13,24 @@
         />
         <span class="search_title ml10">鐭ヨ瘑绫诲瀷锛�</span>
         <el-select v-model="searchForm.type" clearable @change="handleQuery" style="width: 240px">
-          <el-option label="鍚堝悓鐗规壒" :value="'contract'" />
-          <el-option label="瀹℃壒妗堜緥" :value="'approval'" />
-          <el-option label="瑙e喅鏂规" :value="'solution'" />
-          <el-option label="缁忛獙鎬荤粨" :value="'experience'" />
-          <el-option label="鎿嶄綔鎸囧崡" :value="'guide'" />
+          <el-option
+              v-for="item in knowledgeTypeOptions"
+              :key="item.value"
+              :label="item.label"
+              :value="item.value"
+          />
         </el-select>
         <el-button type="primary" @click="handleQuery" style="margin-left: 10px">
           鎼滅储
         </el-button>
       </div>
       <div>
+        <el-button @click="handleExport" style="margin-right: 10px">瀵煎嚭</el-button>
         <el-button type="primary" @click="openForm('add')">鏂板鐭ヨ瘑</el-button>
         <el-button type="danger" plain @click="handleDelete">鍒犻櫎</el-button>
       </div>
     </div>
-    
+
     <div class="table_list">
       <PIMTable
         rowKey="id"
@@ -60,11 +62,12 @@
           <el-col :span="12">
             <el-form-item label="鐭ヨ瘑绫诲瀷" prop="type">
               <el-select v-model="form.type" placeholder="璇烽�夋嫨鐭ヨ瘑绫诲瀷" style="width: 100%">
-                <el-option label="鍚堝悓鐗规壒" value="contract" />
-                <el-option label="瀹℃壒妗堜緥" value="approval" />
-                <el-option label="瑙e喅鏂规" value="solution" />
-                <el-option label="缁忛獙鎬荤粨" value="experience" />
-                <el-option label="鎿嶄綔鎸囧崡" value="guide" />
+                <el-option
+                    v-for="item in knowledgeTypeOptions"
+                    :key="item.value"
+                    :label="item.label"
+                    :value="item.value"
+                />
               </el-select>
             </el-form-item>
           </el-col>
@@ -221,7 +224,7 @@
         <span class="dialog-footer">
           <el-button @click="viewDialogVisible = false">鍏抽棴</el-button>
           <el-button type="primary" @click="copyKnowledge">澶嶅埗鐭ヨ瘑</el-button>
-          <el-button type="success" @click="markAsFavorite">鏀惰棌</el-button>
+          <!-- <el-button type="success" @click="markAsFavorite">鏀惰棌@</el-button> -->
         </span>
       </template>
     </el-dialog>
@@ -230,9 +233,10 @@
 
 <script setup>
 import { Search } from "@element-plus/icons-vue";
-import { onMounted, ref, reactive, toRefs } from "vue";
+import { onMounted, ref, reactive, toRefs, getCurrentInstance, computed } from "vue";
 import { ElMessage, ElMessageBox } from "element-plus";
 import PIMTable from "@/components/PIMTable/PIMTable.vue";
+import { listKnowledgeBase, delKnowledgeBase,addKnowledgeBase,updateKnowledgeBase } from "@/api/collaborativeApproval/knowledgeBase.js";
 
 // 琛ㄥ崟楠岃瘉瑙勫垯
 const rules = {
@@ -259,7 +263,7 @@
   tableLoading: false,
   page: {
     current: 1,
-    size: 100,
+    size: 20,
     total: 0,
   },
   tableData: [],
@@ -268,7 +272,7 @@
     title: "",
     type: "",
     scenario: "",
-    efficiency: "medium",
+    efficiency: "",
     problem: "",
     solution: "",
     keyPoints: "",
@@ -282,11 +286,11 @@
   currentKnowledge: {}
 });
 
-const { 
-  searchForm, 
-  tableLoading, 
-  page, 
-  tableData, 
+const {
+  searchForm,
+  tableLoading,
+  page,
+  tableData,
   selectedIds,
   form,
   dialogVisible,
@@ -311,24 +315,10 @@
     prop: "type",
     dataType: "tag",
     formatData: (params) => {
-      const typeMap = {
-        contract: "鍚堝悓鐗规壒",
-        approval: "瀹℃壒妗堜緥",
-        solution: "瑙e喅鏂规",
-        experience: "缁忛獙鎬荤粨",
-        guide: "鎿嶄綔鎸囧崡"
-      };
-      return typeMap[params] || params;
+      return getKnowledgeTypeLabel(params);
     },
     formatType: (params) => {
-      const typeMap = {
-        contract: "success",
-        approval: "warning",
-        solution: "primary",
-        experience: "info",
-        guide: "danger"
-      };
-      return typeMap[params] || "info";
+      return getKnowledgeTypeTagType(params);
     }
   },
   {
@@ -399,111 +389,6 @@
   }
 ]);
 
-// 妯℃嫙鏁版嵁
-let mockData = [
-  {
-    id: "1",
-    title: "鐗规畩鍚堝悓瀹℃壒娴佺▼浼樺寲鏂规",
-    type: "contract",
-    scenario: "澶ч鍚堝悓蹇�熷鎵�",
-    efficiency: "high",
-    problem: "澶ч鍚堝悓瀹℃壒娴佺▼澶嶆潅锛屽鎵规椂闂撮暱锛屽奖鍝嶄笟鍔¤繘灞�",
-    solution: "寤虹珛缁胯壊閫氶亾锛屽绗﹀悎鏉′欢鐨勫悎鍚岄噰鐢ㄧ畝鍖栧鎵规祦绋嬶紝鐢遍儴闂ㄨ礋璐d汉鐩存帴瀹℃壒锛屽钩鍧囧鎵规椂闂翠粠3澶╃缉鐭嚦1澶�",
-    keyPoints: "缁胯壊閫氶亾鏉′欢,绠�鍖栨祦绋�,瀹℃壒鏉冮檺,鏃堕棿鎺у埗",
-    creator: "寮犵粡鐞�",
-    usageCount: 15,
-    createTime: "2024-01-15 10:30:00"
-  },
-  {
-    id: "2",
-    title: "璺ㄩ儴闂ㄥ崗浣滃鎵圭粡楠屾�荤粨",
-    type: "experience",
-    scenario: "澶氶儴闂ㄥ崗浣滈」鐩�",
-    efficiency: "medium",
-    problem: "璺ㄩ儴闂ㄩ」鐩鎵规椂锛屽悇閮ㄩ棬鎰忚涓嶇粺涓�锛屽鎵硅繘搴︾紦鎱�",
-    solution: "寤虹珛椤圭洰鍗忚皟鏈哄埗锛屾寚瀹氶」鐩礋璐d汉锛屽畾鏈熷彫寮�鍗忚皟浼氳锛岀粺涓�鍚勬柟鎰忚鍚庡啀杩涜瀹℃壒",
-    keyPoints: "椤圭洰鍗忚皟,瀹氭湡浼氳,缁熶竴鎰忚,璐熻矗浜哄埗搴�",
-    creator: "鏉庝富绠�",
-    usageCount: 8,
-    createTime: "2024-01-14 15:20:00"
-  },
-  {
-    id: "3",
-    title: "绱ф�ラ噰璐鎵规搷浣滄寚鍗�",
-    type: "guide",
-    scenario: "绱ф�ラ噰璐渶姹�",
-    efficiency: "high",
-    problem: "绱ф�ラ噰璐椂瀹℃壒娴佺▼澶嶆潅锛屾棤娉曟弧瓒崇揣鎬ラ渶姹�",
-    solution: "鍒跺畾绱ф�ラ噰璐鎵规爣鍑嗭紝鏄庣‘绱ф�ョ▼搴﹀垎绾э紝涓嶅悓绾у埆閲囩敤涓嶅悓瀹℃壒娴佺▼锛岀‘淇濈揣鎬ラ渶姹傚緱鍒板強鏃跺鐞�",
-    keyPoints: "绱ф�ュ垎绾�,鏍囧噯鍒跺畾,娴佺▼绠�鍖�,鍙婃椂澶勭悊",
-    creator: "鐜嬩笓鍛�",
-    usageCount: 12,
-    createTime: "2024-01-13 09:15:00"
-  }
-];
-
-// 鐭ヨ瘑鏍囬妯℃澘
-const titleTemplates = [
-  "{type}瀹℃壒娴佺▼浼樺寲鏂规",
-  "{scenario}澶勭悊缁忛獙鎬荤粨",
-  "{type}鐗规畩鎯呭喌澶勭悊鎸囧崡",
-  "{scenario}蹇�熷鎵规柟妗�",
-  "{type}鏍囧噯鍖栨搷浣滄祦绋�",
-  "{scenario}闂瑙e喅鏂规",
-  "{type}鏈�浣冲疄璺垫�荤粨",
-  "{scenario}鏁堢巼鎻愬崌鏂规"
-];
-
-// 鐭ヨ瘑绫诲瀷閰嶇疆
-const knowledgeTypes = [
-  { type: "contract", label: "鍚堝悓鐗规壒", efficiency: "high" },
-  { type: "approval", label: "瀹℃壒妗堜緥", efficiency: "medium" },
-  { type: "solution", label: "瑙e喅鏂规", efficiency: "high" },
-  { type: "experience", label: "缁忛獙鎬荤粨", efficiency: "medium" },
-  { type: "guide", label: "鎿嶄綔鎸囧崡", efficiency: "low" }
-];
-
-// 鍦烘櫙鍒楄〃
-const scenarios = ["澶ч鍚堝悓瀹℃壒", "璺ㄩ儴闂ㄥ崗浣�", "绱ф�ラ噰璐�", "鐗规畩鐢宠", "娴佺▼浼樺寲", "闂澶勭悊", "鏍囧噯鍖栧缓璁�", "鏁堢巼鎻愬崌"];
-
-// 鑷姩鐢熸垚鏂版暟鎹�
-const generateNewData = () => {
-  const newId = (mockData.length + 1).toString();
-  const now = new Date();
-  const randomType = knowledgeTypes[Math.floor(Math.random() * knowledgeTypes.length)];
-  const randomScenario = scenarios[Math.floor(Math.random() * scenarios.length)];
-  
-  // 鐢熸垚闅忔満鏍囬
-  let title = titleTemplates[Math.floor(Math.random() * titleTemplates.length)];
-  title = title
-    .replace('{type}', randomType.label)
-    .replace('{scenario}', randomScenario);
-  
-  const newKnowledge = {
-    id: newId,
-    title: title,
-    type: randomType.type,
-    scenario: randomScenario,
-    efficiency: randomType.efficiency,
-    problem: `鍦�${randomScenario}杩囩▼涓亣鍒扮殑闂鎻忚堪...`,
-    solution: `閽堝${randomScenario}鐨勮В鍐虫柟妗堝拰鎿嶄綔姝ラ...`,
-    keyPoints: "鍏抽敭瑕佺偣1,鍏抽敭瑕佺偣2,鍏抽敭瑕佺偣3,鍏抽敭瑕佺偣4",
-    creator: ["寮犵粡鐞�", "鏉庝富绠�", "鐜嬩笓鍛�", "鍒樻�荤洃"][Math.floor(Math.random() * 4)],
-    usageCount: Math.floor(Math.random() * 20) + 1,
-    createTime: now.toLocaleString()
-  };
-  
-  // 娣诲姞鍒版暟鎹紑澶�
-  mockData.unshift(newKnowledge);
-  
-  // 淇濇寔鏁版嵁閲忓湪鍚堢悊鑼冨洿鍐咃紙鏈�澶氫繚鐣�30鏉★級
-  if (mockData.length > 30) {
-    mockData = mockData.slice(0, 30);
-  }
-  
-  console.log(`[${new Date().toLocaleString()}] 鑷姩鐢熸垚鏂扮煡璇�: ${title}`);
-};
-
 // 鐢熷懡鍛ㄦ湡
 onMounted(() => {
   getList();
@@ -513,7 +398,6 @@
 // 寮�濮嬭嚜鍔ㄥ埛鏂�
 const startAutoRefresh = () => {
   setInterval(() => {
-    generateNewData();
     getList();
   }, 600000); // 10鍒嗛挓鍒锋柊涓�娆� (10 * 60 * 1000 = 600000ms)
 };
@@ -526,24 +410,14 @@
 
 const getList = () => {
   tableLoading.value = true;
-  
-  setTimeout(() => {
-    let filteredData = [...mockData];
-    
-    if (searchForm.value.title) {
-      filteredData = filteredData.filter(item => 
-        item.title.toLowerCase().includes(searchForm.value.title.toLowerCase())
-      );
-    }
-    
-    if (searchForm.value.type) {
-      filteredData = filteredData.filter(item => item.type === searchForm.value.type);
-    }
-    
-    tableData.value = filteredData;
-    page.value.total = filteredData.length;
+  listKnowledgeBase({...page.value, ...searchForm.value})
+  .then(res => {
     tableLoading.value = false;
-  }, 500);
+    tableData.value = res.data.records
+    page.total = res.data.total;
+  }).catch(err => {
+    tableLoading.value = false;
+  })
 };
 
 // 鍒嗛〉澶勭悊
@@ -568,7 +442,7 @@
       title: "",
       type: "",
       scenario: "",
-      efficiency: "medium",
+      efficiency: "",
       problem: "",
       solution: "",
       keyPoints: "",
@@ -578,6 +452,7 @@
   } else if (type === "edit" && row) {
     dialogTitle.value = "缂栬緫鐭ヨ瘑";
     Object.assign(form.value, {
+      id: row.id,
       title: row.title,
       type: row.type,
       scenario: row.scenario,
@@ -612,14 +487,7 @@
 
 // 鑾峰彇绫诲瀷鏍囩鏂囨湰
 const getTypeLabel = (type) => {
-  const typeMap = {
-    contract: "鍚堝悓鐗规壒",
-    approval: "瀹℃壒妗堜緥",
-    solution: "瑙e喅鏂规",
-    experience: "缁忛獙鎬荤粨",
-    guide: "鎿嶄綔鎸囧崡"
-  };
-  return typeMap[type] || type;
+  return getKnowledgeTypeLabel(type);
 };
 
 // 鑾峰彇鏁堢巼鏍囩绫诲瀷
@@ -665,15 +533,15 @@
 // 澶嶅埗鐭ヨ瘑
 const copyKnowledge = () => {
   const knowledgeText = `
-鐭ヨ瘑鏍囬锛�${currentKnowledge.value.title}
-鐭ヨ瘑绫诲瀷锛�${getTypeLabel(currentKnowledge.value.type)}
-閫傜敤鍦烘櫙锛�${currentKnowledge.value.scenario}
-闂鎻忚堪锛�${currentKnowledge.value.problem}
-瑙e喅鏂规锛�${currentKnowledge.value.solution}
-鍏抽敭瑕佺偣锛�${currentKnowledge.value.keyPoints}
-鍒涘缓浜猴細${currentKnowledge.value.creator}
+    鐭ヨ瘑鏍囬锛�${currentKnowledge.value.title}
+    鐭ヨ瘑绫诲瀷锛�${getTypeLabel(currentKnowledge.value.type)}
+    閫傜敤鍦烘櫙锛�${currentKnowledge.value.scenario}
+    闂鎻忚堪锛�${currentKnowledge.value.problem}
+    瑙e喅鏂规锛�${currentKnowledge.value.solution}
+    鍏抽敭瑕佺偣锛�${currentKnowledge.value.keyPoints}
+    鍒涘缓浜猴細${currentKnowledge.value.creator}
   `.trim();
-  
+
   // 澶嶅埗鍒板壀璐存澘
   navigator.clipboard.writeText(knowledgeText).then(() => {
     ElMessage.success("鐭ヨ瘑鍐呭宸插鍒跺埌鍓创鏉�");
@@ -682,62 +550,32 @@
   });
 };
 
-// 鏀惰棌鐭ヨ瘑
-const markAsFavorite = () => {
-  // 澧炲姞浣跨敤娆℃暟
-  const index = mockData.findIndex(item => item.id === currentKnowledge.value.id);
-  if (index !== -1) {
-    mockData[index].usageCount += 1;
-    currentKnowledge.value.usageCount += 1;
-  }
-  
-  ElMessage.success("宸叉敹钘忥紝浣跨敤娆℃暟+1");
-};
-
 // 鎻愪氦鐭ヨ瘑琛ㄥ崟
 const submitForm = async () => {
   try {
     await formRef.value.validate();
-    
     if (dialogType.value === "add") {
       // 鏂板鐭ヨ瘑
-      const newKnowledge = {
-        id: (mockData.length + 1).toString(),
-        title: form.value.title,
-        type: form.value.type,
-        scenario: form.value.scenario,
-        efficiency: form.value.efficiency,
-        problem: form.value.problem,
-        solution: form.value.solution,
-        keyPoints: form.value.keyPoints,
-        creator: form.value.creator,
-        usageCount: form.value.usageCount,
-        createTime: new Date().toLocaleString()
-      };
-      
-      mockData.unshift(newKnowledge);
-      ElMessage.success("鐭ヨ瘑鍒涘缓鎴愬姛");
+      addKnowledgeBase({...form.value}).then(res => {
+        if(res.code == 200){
+          ElMessage.success("娣诲姞鎴愬姛");
+          dialogVisible.value = false;
+          getList();
+        }
+      }).catch(err => {
+        ElMessage.error(err.msg);
+      })
     } else {
-      // 缂栬緫鐭ヨ瘑
-      const index = mockData.findIndex(item => item.id === selectedIds.value[0]);
-      if (index !== -1) {
-        Object.assign(mockData[index], {
-          title: form.value.title,
-          type: form.value.type,
-          scenario: form.value.scenario,
-          efficiency: form.value.efficiency,
-          problem: form.value.problem,
-          solution: form.value.solution,
-          keyPoints: form.value.keyPoints,
-          creator: form.value.creator,
-          usageCount: form.value.usageCount
-        });
-        ElMessage.success("鐭ヨ瘑鏇存柊鎴愬姛");
-      }
+      updateKnowledgeBase({...form.value}).then(res => {
+        if(res.code == 200){
+          ElMessage.success("鏇存柊鎴愬姛");
+          dialogVisible.value = false;
+          getList();
+        }
+      }).catch(err => {
+        ElMessage.error(err.msg);
+      })
     }
-    
-    dialogVisible.value = false;
-    getList();
   } catch (error) {
     console.error("琛ㄥ崟楠岃瘉澶辫触:", error);
   }
@@ -749,27 +587,42 @@
     ElMessage.warning("璇烽�夋嫨瑕佸垹闄ょ殑鐭ヨ瘑");
     return;
   }
-  
+
   ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "鍒犻櫎", {
     confirmButtonText: "纭",
     cancelButtonText: "鍙栨秷",
     type: "warning",
   }).then(() => {
-    // 浠巑ockData涓垹闄ら�変腑鐨勯」
-    selectedIds.value.forEach(id => {
-      const index = mockData.findIndex(item => item.id === id);
-      if (index !== -1) {
-        mockData.splice(index, 1);
+    // console.log(selectedIds.value);
+    delKnowledgeBase(selectedIds.value).then(res => {
+      if(res.code == 200){
+        ElMessage.success("鍒犻櫎鎴愬姛");
+        selectedIds.value = [];
+        getList();
       }
-    });
-    
-    ElMessage.success("鍒犻櫎鎴愬姛");
-    selectedIds.value = [];
-    getList();
+    })
   }).catch(() => {
     // 鐢ㄦ埛鍙栨秷
   });
 };
+
+// 瀵煎嚭
+const { proxy } = getCurrentInstance()
+const { knowledge_type } = proxy.useDict("knowledge_type")
+
+// 瀛楀吀宸ュ叿
+const knowledgeTypeOptions = computed(() => knowledge_type?.value || [])
+const getKnowledgeTypeLabel = (val) => {
+  const item = knowledgeTypeOptions.value.find(i => String(i.value) === String(val))
+  return item ? item.label : val
+}
+const getKnowledgeTypeTagType = (val) => {
+  const item = knowledgeTypeOptions.value.find(i => String(i.value) === String(val))
+  return item?.elTagType || "info"
+}
+const handleExport = () => {
+  proxy.download('/knowledgeBase/export', { ...searchForm.value }, '鐭ヨ瘑搴�.xlsx')
+}
 </script>
 
 <style scoped>
diff --git a/src/views/collaborativeApproval/meetingBoard/index.vue b/src/views/collaborativeApproval/meetingBoard/index.vue
index 63c74f9..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: '2024-01-15 09:00:00',
-    endTime: '2024-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: '2024-01-15 14:00:00',
-    endTime: '2024-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: '2024-01-14 16:00:00',
-    endTime: '2024-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/meetingManagement/index.vue b/src/views/collaborativeApproval/meetingManagement/index.vue
new file mode 100644
index 0000000..69b0275
--- /dev/null
+++ b/src/views/collaborativeApproval/meetingManagement/index.vue
@@ -0,0 +1,63 @@
+<template>
+  <div class="app-container">
+    <div class="tabs-wrapper">
+      <el-tabs
+        v-model="activeTab"
+        class="meeting-tabs"
+        @tab-change="handleTabChange"
+      >
+        <el-tab-pane label="浼氳璁剧疆" name="setting" />
+        <el-tab-pane label="浼氳鍒楄〃" name="index" />
+        <el-tab-pane label="浼氳鐢宠" name="application" />
+        <el-tab-pane label="浼氳瀹℃壒" name="examine" />
+        <el-tab-pane label="浼氳鍙戝竷" name="publish" />
+        <el-tab-pane label="浼氳鎬荤粨" name="summary" />
+      </el-tabs>
+    </div>
+
+    <div class="tab-content">
+      <keep-alive>
+        <component :is="currentComponent" />
+      </keep-alive>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, computed } from 'vue'
+import MeetSetting from '../notificationManagement/meetSetting/index.vue'
+import MeetIndex from '../notificationManagement/meetIndex/index.vue'
+import MeetApplication from '../notificationManagement/meetApplication/index.vue'
+import MeetExamine from '../notificationManagement/meetExamine/index.vue'
+import MeetPublish from '../notificationManagement/meetPublish/index.vue'
+import MeetSummary from '../notificationManagement/summary/index.vue'
+
+const activeTab = ref('setting')
+
+const tabComponentMap = {
+  setting: MeetSetting,
+  index: MeetIndex,
+  application: MeetApplication,
+  examine: MeetExamine,
+  publish: MeetPublish,
+  summary: MeetSummary
+}
+
+const currentComponent = computed(() => tabComponentMap[activeTab.value] || MeetSetting)
+
+function handleTabChange(name) {
+  activeTab.value = name
+}
+</script>
+
+<style scoped lang="scss">
+
+.tabs-wrapper {
+  margin-bottom: 10px;
+}
+
+.tab-content {
+  min-height: 400px;
+}
+</style>
+
diff --git a/src/views/collaborativeApproval/noticeManagement/index.vue b/src/views/collaborativeApproval/noticeManagement/index.vue
index daa4cd7..d92adea 100644
--- a/src/views/collaborativeApproval/noticeManagement/index.vue
+++ b/src/views/collaborativeApproval/noticeManagement/index.vue
@@ -3,159 +3,116 @@
     <!-- 鎼滅储琛ㄥ崟 -->
     <div class="search_form">
       <div>
-        <span class="search_title">鍏憡鏍囬锛�</span>
-        <el-input
-          v-model="searchForm.noticeTitle"
-          style="width: 240px"
-          placeholder="璇疯緭鍏ュ叕鍛婃爣棰樻悳绱�"
-          @change="handleQuery"
-          clearable
-          :prefix-icon="Search"
-        />
-        <span class="search_title ml10">鍏憡绫诲瀷锛�</span>
-        <el-select v-model="searchForm.noticeType" clearable @change="handleQuery" style="width: 240px">
-          <el-option label="鏀惧亣閫氱煡" value="1" />
-          <el-option label="璁惧缁翠慨閫氱煡" value="2" />
-        </el-select>
-        <span class="search_title ml10">鐘舵�侊細</span>
-        <el-select v-model="searchForm.status" clearable @change="handleQuery" style="width: 240px">
-          <el-option label="鑽夌" value="0" />
-          <el-option label="宸插彂甯�" value="1" />
-          <el-option label="宸蹭笅绾�" value="2" />
-        </el-select>
-        <el-button type="primary" @click="handleQuery" style="margin-left: 10px">鎼滅储</el-button>
-        <el-button @click="resetQuery" style="margin-left: 10px">閲嶇疆</el-button>
-      </div>
-      <div>
         <el-button type="primary" @click="openForm('add')">鏂板鍏憡</el-button>
-        <el-button type="danger" plain @click="handleDelete" :disabled="!selectedIds.length">鍒犻櫎</el-button>
+        <el-button type="info" @click="openNoticeTypeDialog">鍏憡绫诲瀷閰嶇疆</el-button>
       </div>
     </div>
 
     <!-- 閫氱煡鍏憡鏉� -->
     <div class="notice-board">
-      <!-- 鏀惧亣閫氱煡鍖哄煙 -->
-      <div class="notice-section" v-if="holidayNotices.length > 0">
-        <div class="section-header">
-          <h3>馃搮 鏀惧亣閫氱煡</h3>
-          <span class="section-count">{{ holidayNotices.length }}鏉�</span>
-        </div>
-        <div class="notice-cards">
-          <div 
-            v-for="notice in holidayNotices" 
-            :key="notice.id"
-            class="notice-card holiday-card"
-            :class="{ 'urgent': notice.priority === '3' }"
-          >
-            <div class="card-header">
-              <div class="card-title">
-                <el-icon class="holiday-icon"><Calendar /></el-icon>
-                {{ notice.noticeTitle }}
-              </div>
-              <div class="card-actions">
-                <el-button link type="primary" @click="handleEdit(notice)">缂栬緫</el-button>
-                <el-button link type="danger" @click="handleDelete(notice.id)">鍒犻櫎</el-button>
+      <el-tabs v-model="activeNoticeTypeTab" @tab-change="handleNoticeTypeTabChange">
+        <el-tab-pane
+            v-for="noticeType in noticeTypeList"
+            :key="noticeType.id"
+            :label="noticeType.noticeType"
+            :name="String(noticeType.id)"
+        >
+          <template #label>
+            <span>{{ noticeType.noticeType }}
+              <span class="tab-count" v-if="getNoticeCountByType(noticeType.id) > 0">
+                ({{ getNoticeCountByType(noticeType.id) }})
+              </span>
+            </span>
+          </template>
+          
+          <div class="notice-section">
+            <div class="notice-cards">
+              <div
+                  v-for="notice in getNoticesByType(noticeType.id)"
+                  :key="notice.id"
+                  class="notice-card"
+                  :class="{ 'urgent': notice.priority === '3' }"
+              >
+                <div class="card-header">
+                  <div class="card-title">
+                    <el-icon class="notice-icon">
+                      <Calendar/>
+                    </el-icon>
+                    {{ notice.title }}
+                  </div>
+                  <div class="card-actions">
+                    <el-button link type="primary" @click="handleEdit(notice)" :disabled="isNoticeExpired(notice)" v-if="notice.status !== 1">缂栬緫</el-button>
+                    <el-button link type="success" @click="handlePublish(notice)" v-if="notice.status === 0">鍙戝竷</el-button>
+                    <el-button link type="danger" @click="handleDelete(notice.id)" v-if="notice.status !== 1">鍒犻櫎</el-button>
+                  </div>
+                </div>
+                <div class="card-content">
+                  <p>{{ notice.content }}</p>
+                </div>
+                <div class="card-footer">
+                  <div class="card-meta">
+                    <span class="priority" :class="'priority-' + notice.priority">
+                      {{ getPriorityText(notice.priority) }}
+                    </span>
+                    <span class="status" :class="'status-' + getNoticeStatus(notice)">
+                      {{ getStatusText(getNoticeStatus(notice)) }}
+                    </span>
+                  </div>
+                  <div class="card-info">
+                    <span class="creator">{{ notice.createUserName }}</span>
+                    <span class="expiration" v-if="notice.expirationDate">鎴鏃ユ湡锛歿{ notice.expirationDate }}</span>
+                  </div>
+                </div>
+                <div class="card-remark" v-if="notice.remark">
+                  <el-icon>
+                    <InfoFilled/>
+                  </el-icon>
+                  <span>{{ notice.remark }}</span>
+                </div>
               </div>
             </div>
-            <div class="card-content">
-              <p>{{ notice.noticeContent }}</p>
-            </div>
-            <div class="card-footer">
-              <div class="card-meta">
-                <span class="priority" :class="'priority-' + notice.priority">
-                  {{ getPriorityText(notice.priority) }}
-                </span>
-                <span class="status" :class="'status-' + notice.status">
-                  {{ getStatusText(notice.status) }}
-                </span>
-              </div>
-              <div class="card-info">
-                <span class="creator">{{ notice.createBy }}</span>
-                <span class="time">{{ notice.createTime }}</span>
-              </div>
-            </div>
-            <div class="card-remark" v-if="notice.remark">
-              <el-icon><InfoFilled /></el-icon>
-              <span>{{ notice.remark }}</span>
+            
+            <pagination
+                v-if="getNoticePageByType(noticeType.id).total > 0"
+                :total="getNoticePageByType(noticeType.id).total"
+                :page="getNoticePageByType(noticeType.id).current"
+                :limit="getNoticePageByType(noticeType.id).size"
+                @pagination="(val) => handleNoticeCurrentChange(noticeType.id, val)"
+            />
+            
+            <!-- 绌虹姸鎬� -->
+            <div class="empty-state" v-if="getNoticesByType(noticeType.id).length === 0">
+              <el-empty description="鏆傛棤閫氱煡鍏憡"/>
             </div>
           </div>
-        </div>
-      </div>
-
-      <!-- 璁惧缁翠慨閫氱煡鍖哄煙 -->
-      <div class="notice-section" v-if="maintenanceNotices.length > 0">
-        <div class="section-header">
-          <h3>馃敡 璁惧缁翠慨閫氱煡</h3>
-          <span class="section-count">{{ maintenanceNotices.length }}鏉�</span>
-        </div>
-        <div class="notice-cards">
-          <div 
-            v-for="notice in maintenanceNotices" 
-            :key="notice.id"
-            class="notice-card maintenance-card"
-            :class="{ 'urgent': notice.priority === '3' }"
-          >
-            <div class="card-header">
-              <div class="card-title">
-                <el-icon class="maintenance-icon"><Tools /></el-icon>
-                {{ notice.noticeTitle }}
-              </div>
-              <div class="card-actions">
-                <el-button link type="primary" @click="handleEdit(notice)">缂栬緫</el-button>
-                <el-button link type="danger" @click="handleDelete(notice.id)">鍒犻櫎</el-button>
-              </div>
-            </div>
-            <div class="card-content">
-              <p>{{ notice.noticeContent }}</p>
-            </div>
-            <div class="card-footer">
-              <div class="card-meta">
-                <span class="priority" :class="'priority-' + notice.priority">
-                  {{ getPriorityText(notice.priority) }}
-                </span>
-                <span class="status" :class="'status-' + notice.status">
-                  {{ getStatusText(notice.status) }}
-                </span>
-              </div>
-              <div class="card-info">
-                <span class="creator">{{ notice.createBy }}</span>
-                <span class="time">{{ notice.createTime }}</span>
-              </div>
-            </div>
-            <div class="card-remark" v-if="notice.remark">
-              <el-icon><InfoFilled /></el-icon>
-              <span>{{ notice.remark }}</span>
-            </div>
-          </div>
-        </div>
-      </div>
-
-      <!-- 绌虹姸鎬� -->
-      <div class="empty-state" v-if="filteredNotices.length === 0">
-        <el-empty description="鏆傛棤閫氱煡鍏憡" />
-      </div>
+        </el-tab-pane>
+      </el-tabs>
     </div>
 
     <!-- 鏂板/缂栬緫瀵硅瘽妗� -->
-    <el-dialog 
-      :title="dialogTitle" 
-      v-model="dialogVisible" 
-      width="800px" 
-      append-to-body
-      @close="resetForm"
+    <el-dialog
+        :title="dialogTitle"
+        v-model="dialogVisible"
+        width="800px"
+        append-to-body
+        @close="resetForm"
     >
       <el-form ref="formRef" :model="form" :rules="rules" label-width="100px">
         <el-row>
           <el-col :span="12">
-            <el-form-item label="鍏憡鏍囬" prop="noticeTitle">
-              <el-input v-model="form.noticeTitle" placeholder="璇疯緭鍏ュ叕鍛婃爣棰�" />
+            <el-form-item label="鍏憡鏍囬" prop="title">
+              <el-input v-model="form.title" placeholder="璇疯緭鍏ュ叕鍛婃爣棰�"/>
             </el-form-item>
           </el-col>
           <el-col :span="12">
-            <el-form-item label="鍏憡绫诲瀷" prop="noticeType">
-              <el-select v-model="form.noticeType" placeholder="璇烽�夋嫨鍏憡绫诲瀷" style="width: 100%">
-                <el-option label="鏀惧亣閫氱煡" value="1" />
-                <el-option label="璁惧缁翠慨閫氱煡" value="2" />
+            <el-form-item label="鍏憡绫诲瀷" prop="type">
+              <el-select v-model="form.type" placeholder="璇烽�夋嫨鍏憡绫诲瀷" style="width: 100%">
+                <el-option
+                    v-for="item in noticeTypeList"
+                    :key="item.id"
+                    :label="item.noticeType"
+                    :value="item.id"
+                />
               </el-select>
             </el-form-item>
           </el-col>
@@ -164,32 +121,39 @@
           <el-col :span="12">
             <el-form-item label="鐘舵��">
               <el-radio-group v-model="form.status">
-                <el-radio value="0">鑽夌</el-radio>
-                <el-radio value="1">宸插彂甯�</el-radio>
-                <el-radio value="2">宸蹭笅绾�</el-radio>
+                <el-radio :value="0">鑽夌</el-radio>
+                <el-radio :value="1">姝e紡鍙戝竷</el-radio>
               </el-radio-group>
             </el-form-item>
           </el-col>
           <el-col :span="12">
             <el-form-item label="浼樺厛绾�">
               <el-select v-model="form.priority" placeholder="璇烽�夋嫨浼樺厛绾�" style="width: 100%">
-                <el-option label="鏅��" value="1" />
-                <el-option label="閲嶈" value="2" />
-                <el-option label="绱ф��" value="3" />
+                <el-option label="鏅��" :value="1"/>
+                <el-option label="閲嶈" :value="2"/>
+                <el-option label="绱ф��" :value="3"/>
               </el-select>
             </el-form-item>
           </el-col>
         </el-row>
         <el-row>
+          <el-col :span="12">
+            <el-form-item label="杩囨湡鏃堕棿" prop="expirationDate">
+							<el-date-picker  v-model="form.expirationDate" value-format="YYYY-MM-DD" format="YYYY-MM-DD" type="date"
+															 placeholder="璇烽�夋嫨" clearable />
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row>
           <el-col :span="24">
-            <el-form-item label="鍏憡鍐呭" prop="noticeContent">
+            <el-form-item label="鍏憡鍐呭" prop="content">
               <el-input
-                v-model="form.noticeContent"
-                type="textarea"
-                :rows="6"
-                placeholder="璇疯緭鍏ュ叕鍛婂唴瀹�"
-                maxlength="500"
-                show-word-limit
+                  v-model="form.content"
+                  type="textarea"
+                  :rows="6"
+                  placeholder="璇疯緭鍏ュ叕鍛婂唴瀹�"
+                  maxlength="500"
+                  show-word-limit
               />
             </el-form-item>
           </el-col>
@@ -198,12 +162,12 @@
           <el-col :span="24">
             <el-form-item label="澶囨敞">
               <el-input
-                v-model="form.remark"
-                type="textarea"
-                :rows="3"
-                placeholder="璇疯緭鍏ュ娉ㄤ俊鎭�"
-                maxlength="200"
-                show-word-limit
+                  v-model="form.remark"
+                  type="textarea"
+                  :rows="3"
+                  placeholder="璇疯緭鍏ュ娉ㄤ俊鎭�"
+                  maxlength="200"
+                  show-word-limit
               />
             </el-form-item>
           </el-col>
@@ -216,177 +180,168 @@
         </div>
       </template>
     </el-dialog>
+
+    <!-- 鍏憡绫诲瀷閰嶇疆寮规 -->
+    <el-dialog
+        v-model="noticeTypeDialogVisible"
+        title="鍏憡绫诲瀷閰嶇疆"
+        width="800px"
+        @close="handleNoticeTypeDialogClose"
+    >
+      <div class="notice-type-container">
+        <div class="notice-type-header">
+          <el-button type="primary" @click="handleAddNoticeType">鏂板绫诲瀷</el-button>
+        </div>
+        <el-table :data="noticeTypeList" border style="width: 100%">
+          <el-table-column prop="id" label="ID" width="80" align="center"/>
+          <el-table-column prop="noticeType" label="鍏憡绫诲瀷" align="center">
+            <template #default="scope">
+              <el-input
+                  v-if="scope.row.editing"
+                  v-model="scope.row.noticeType"
+                  placeholder="璇疯緭鍏ュ叕鍛婄被鍨�"
+              />
+              <span v-else>{{ scope.row.noticeType }}</span>
+            </template>
+          </el-table-column>
+          <el-table-column label="鎿嶄綔" width="200" align="center">
+            <template #default="scope">
+              <el-button
+                  v-if="scope.row.editing"
+                  link
+                  type="primary"
+                  size="small"
+                  @click="handleSaveNoticeType(scope.row)"
+              >
+                淇濆瓨
+              </el-button>
+              <el-button
+                  v-if="scope.row.editing"
+                  link
+                  type="info"
+                  size="small"
+                  @click="handleCancelEdit(scope.row)"
+              >
+                鍙栨秷
+              </el-button>
+              <el-button
+                  v-if="!scope.row.editing"
+                  link
+                  type="primary"
+                  size="small"
+                  @click="handleEditNoticeType(scope.row)"
+              >
+                缂栬緫
+              </el-button>
+              <el-button
+                  v-if="!scope.row.editing"
+                  link
+                  type="danger"
+                  size="small"
+                  @click="handleDeleteNoticeType(scope.row)"
+              >
+                鍒犻櫎
+              </el-button>
+            </template>
+          </el-table-column>
+        </el-table>
+      </div>
+    </el-dialog>
   </div>
 </template>
 
 <script setup>
-import { Search, Calendar, Tools, InfoFilled } from "@element-plus/icons-vue";
-import { onMounted, ref, reactive, toRefs, computed } from "vue";
-import { ElMessage, ElMessageBox } from "element-plus";
+import {Calendar, InfoFilled} from "@element-plus/icons-vue";
+import {onMounted, ref, reactive, toRefs, computed} from "vue";
+import {ElMessage, ElMessageBox} from "element-plus";
+import {useRoute} from "vue-router";
 import useUserStore from "@/store/modules/user";
+import {
+  addNotice,
+  delNotice,
+  getCount,
+  listNotice,
+  updateNotice,
+  listNoticeType,
+  addNoticeType,
+  delNoticeType
+} from "../../../api/collaborativeApproval/noticeManagement.js";
+import pagination from "../../../components/PIMTable/Pagination.vue";
 
 const userStore = useUserStore();
+const route = useRoute();
 
 // 鍝嶅簲寮忔暟鎹�
 const data = reactive({
   searchForm: {
-    noticeTitle: "",
-    noticeType: "",
-    status: "",
+    title: "",
+    type: undefined,
+    status: undefined,
   },
   form: {
     id: undefined,
-    noticeTitle: "",
-    noticeType: "",
-    noticeContent: "",
-    status: "0",
-    priority: "1",
+    title: "",
+    type: null,
+    content: "",
+    status: 0,
+    priority: 1,
     remark: "",
-    createBy: "",
-    createTime: "",
+		expirationDate: "",
   },
   rules: {
-    noticeTitle: [
-      { required: true, message: "鍏憡鏍囬涓嶈兘涓虹┖", trigger: "blur" }
+    title: [
+      {required: true, message: "鍏憡鏍囬涓嶈兘涓虹┖", trigger: "blur"}
     ],
-    noticeType: [
-      { required: true, message: "璇烽�夋嫨鍏憡绫诲瀷", trigger: "change" }
+    type: [
+      {required: true, message: "璇烽�夋嫨鍏憡绫诲瀷", trigger: "change"}
     ],
-    noticeContent: [
-      { required: true, message: "鍏憡鍐呭涓嶈兘涓虹┖", trigger: "blur" }
+    content: [
+      {required: true, message: "鍏憡鍐呭涓嶈兘涓虹┖", trigger: "blur"}
+    ],
+		expirationDate: [
+      {required: true, message: "璇烽�夋嫨鏃ユ湡", trigger: "change"}
     ]
   }
 });
 
-const { searchForm, form, rules } = toRefs(data);
+const {searchForm, form, rules} = toRefs(data);
 
 // 椤甸潰鐘舵��
 const dialogVisible = ref(false);
 const dialogTitle = ref("");
-const selectedIds = ref([]);
 const formRef = ref();
 
-// 妯℃嫙鏁版嵁 - 鏍规嵁娉曞畾鑺傚亣鏃ヨ璁�
-const mockData = [
-  {
-    id: 1,
-    noticeTitle: "2024骞存槬鑺傛斁鍋囬�氱煡",
-    noticeType: "1",
-    priority: "2",
-    status: "1",
-    noticeContent: "鏍规嵁鍥藉姟闄㈠姙鍏巺閫氱煡锛�2024骞存槬鑺傛斁鍋囧畨鎺掑涓嬶細2鏈�10鏃ワ紙鍒濅竴锛夎嚦2鏈�17鏃ワ紙鍒濆叓锛夋斁鍋囪皟浼戯紝鍏�8澶┿��2鏈�4鏃ワ紙鏄熸湡鏃ワ級銆�2鏈�18鏃ワ紙鏄熸湡鏃ワ級涓婄彮銆傝鍚勯儴闂ㄦ彁鍓嶅仛濂藉伐浣滃畨鎺掋��",
-    remark: "鏀惧亣鏈熼棿璇蜂繚鎸佹墜鏈虹晠閫氾紝濡傛湁绱ф�ヤ簨鍔″強鏃惰仈绯�",
-    createBy: "浜轰簨閮�",
-    createTime: "2024-01-15 10:30:00"
-  },
-  {
-    id: 2,
-    noticeTitle: "2024骞存竻鏄庤妭鏀惧亣閫氱煡",
-    noticeType: "1",
-    priority: "1",
-    status: "1",
-    noticeContent: "鏍规嵁鍥藉姟闄㈠姙鍏巺閫氱煡锛�2024骞存竻鏄庤妭鏀惧亣瀹夋帓濡備笅锛�4鏈�4鏃ワ紙鏄熸湡鍥涳級鑷�4鏈�6鏃ワ紙鏄熸湡鍏級鏀惧亣璋冧紤锛屽叡3澶┿��4鏈�7鏃ワ紙鏄熸湡鏃ワ級涓婄彮銆�",
-    remark: "璇峰悇閮ㄩ棬鍋氬ソ鍊肩彮瀹夋帓锛岀‘淇濊妭鏃ユ湡闂村悇椤瑰伐浣滄甯歌繍杞�",
-    createBy: "琛屾斂閮�",
-    createTime: "2024-01-14 14:20:00"
-  },
-  {
-    id: 3,
-    noticeTitle: "2024骞村姵鍔ㄨ妭鏀惧亣閫氱煡",
-    noticeType: "1",
-    priority: "1",
-    status: "1",
-    noticeContent: "鏍规嵁鍥藉姟闄㈠姙鍏巺閫氱煡锛�2024骞村姵鍔ㄨ妭鏀惧亣瀹夋帓濡備笅锛�5鏈�1鏃ワ紙鏄熸湡涓夛級鑷�5鏈�5鏃ワ紙鏄熸湡鏃ワ級鏀惧亣璋冧紤锛屽叡5澶┿��4鏈�28鏃ワ紙鏄熸湡鏃ワ級銆�5鏈�11鏃ワ紙鏄熸湡鍏級涓婄彮銆�",
-    remark: "鏀惧亣鍓嶈鍏抽棴鐢垫簮锛岄攣濂介棬绐楋紝娉ㄦ剰瀹夊叏",
-    createBy: "琛屾斂閮�",
-    createTime: "2024-01-13 09:15:00"
-  },
-  {
-    id: 4,
-    noticeTitle: "2024骞寸鍗堣妭鏀惧亣閫氱煡",
-    noticeType: "1",
-    priority: "1",
-    status: "1",
-    noticeContent: "鏍规嵁鍥藉姟闄㈠姙鍏巺閫氱煡锛�2024骞寸鍗堣妭鏀惧亣瀹夋帓濡備笅锛�6鏈�8鏃ワ紙鏄熸湡鍏級鑷�6鏈�10鏃ワ紙鏄熸湡涓�锛夋斁鍋囪皟浼戯紝鍏�3澶┿��6鏈�11鏃ワ紙鏄熸湡浜岋級涓婄彮銆�",
-    remark: "绁濆ぇ瀹剁鍗堣妭蹇箰锛岄槚瀹跺垢绂忥紒",
-    createBy: "琛屾斂閮�",
-    createTime: "2024-01-12 16:30:00"
-  },
-  {
-    id: 5,
-    noticeTitle: "2024骞翠腑绉嬭妭鏀惧亣閫氱煡",
-    noticeType: "1",
-    priority: "1",
-    status: "1",
-    noticeContent: "鏍规嵁鍥藉姟闄㈠姙鍏巺閫氱煡锛�2024骞翠腑绉嬭妭鏀惧亣瀹夋帓濡備笅锛�9鏈�15鏃ワ紙鏄熸湡鏃ワ級鑷�9鏈�17鏃ワ紙鏄熸湡浜岋級鏀惧亣璋冧紤锛屽叡3澶┿��9鏈�14鏃ワ紙鏄熸湡鍏級涓婄彮銆�",
-    remark: "涓浣宠妭锛岀澶у鍥㈠渾缇庢弧锛屽垢绂忓畨搴凤紒",
-    createBy: "琛屾斂閮�",
-    createTime: "2024-01-11 11:20:00"
-  },
-  {
-    id: 6,
-    noticeTitle: "2024骞村浗搴嗚妭鏀惧亣閫氱煡",
-    noticeType: "1",
-    priority: "2",
-    status: "1",
-    noticeContent: "鏍规嵁鍥藉姟闄㈠姙鍏巺閫氱煡锛�2024骞村浗搴嗚妭鏀惧亣瀹夋帓濡備笅锛�10鏈�1鏃ワ紙鏄熸湡浜岋級鑷�10鏈�7鏃ワ紙鏄熸湡涓�锛夋斁鍋囪皟浼戯紝鍏�7澶┿��9鏈�29鏃ワ紙鏄熸湡鏃ワ級銆�10鏈�12鏃ワ紙鏄熸湡鍏級涓婄彮銆�",
-    remark: "鍥藉簡鏈熼棿璇峰悇閮ㄩ棬鍋氬ソ鍊肩彮瀹夋帓锛岀‘淇濆畨鍏ㄧǔ瀹�",
-    createBy: "琛屾斂閮�",
-    createTime: "2024-01-10 15:45:00"
-  },
-  {
-    id: 7,
-    noticeTitle: "A杞﹂棿鐢熶骇绾垮勾搴︽淇�氱煡",
-    noticeType: "2",
-    priority: "2",
-    status: "1",
-    noticeContent: "A杞﹂棿鐢熶骇绾垮皢浜�2024骞�1鏈�20鏃ワ紙鍛ㄥ叚锛夎繘琛屽勾搴︽淇淮鎶わ紝棰勮鍋滃伐8灏忔椂銆傛淇唴瀹瑰寘鎷細璁惧娓呮磥銆佹鼎婊戜繚鍏汇�佸畨鍏ㄨ缃鏌ョ瓑銆傝鐢熶骇閮ㄩ棬鎻愬墠璋冩暣鐢熶骇璁″垝銆�",
-    remark: "缁翠慨鏈熼棿璇风浉鍏充汉鍛橀厤鍚堬紝纭繚妫�淇伐浣滃畨鍏ㄩ『鍒╄繘琛�",
-    createBy: "璁惧閮�",
-    createTime: "2024-01-14 14:20:00"
-  },
-  {
-    id: 8,
-    noticeTitle: "B杞﹂棿璁惧棰勯槻鎬х淮鎶ら�氱煡",
-    noticeType: "2",
-    priority: "1",
-    status: "1",
-    noticeContent: "B杞﹂棿鍏抽敭璁惧灏嗕簬2024骞�1鏈�25鏃ヨ繘琛岄闃叉�х淮鎶わ紝棰勮鍋滃伐4灏忔椂銆傜淮鎶ゅ唴瀹瑰寘鎷細璁惧妫�鏌ャ�侀浂浠舵洿鎹€�佹�ц兘娴嬭瘯绛夈�傝鐩稿叧閮ㄩ棬閰嶅悎銆�",
-    remark: "缁存姢瀹屾垚鍚庡皢杩涜璇曡繍琛岋紝纭繚璁惧姝e父杩愯",
-    createBy: "璁惧閮�",
-    createTime: "2024-01-13 09:15:00"
-  }
-];
+// 鍏憡绫诲瀷閰嶇疆鐩稿叧
+const noticeTypeDialogVisible = ref(false);
+const noticeTypeList = ref([]);
+const activeNoticeTypeTab = ref('');
+
+// 閫氱煡鏁版嵁 - 浣跨敤 Map 瀛樺偍锛宬ey 涓虹被鍨� id
+const noticesMap = ref({});
+const noticePagesMap = ref({});
+
 
 // 璁$畻灞炴��
 const filteredNotices = computed(() => {
   let filtered = [...mockData];
-  
+
   if (searchForm.value.noticeTitle) {
-    filtered = filtered.filter(item => 
-      item.noticeTitle.includes(searchForm.value.noticeTitle)
+    filtered = filtered.filter(item =>
+        item.noticeTitle.includes(searchForm.value.noticeTitle)
     );
   }
   if (searchForm.value.noticeType) {
-    filtered = filtered.filter(item => 
-      item.noticeType === searchForm.value.noticeType
+    filtered = filtered.filter(item =>
+        item.noticeType === searchForm.value.noticeType
     );
   }
   if (searchForm.value.status !== "") {
-    filtered = filtered.filter(item => 
-      item.status === searchForm.value.status
+    filtered = filtered.filter(item =>
+        item.status === searchForm.value.status
     );
   }
-  
+
   return filtered;
-});
-
-const holidayNotices = computed(() => {
-  return filteredNotices.value.filter(notice => notice.noticeType === "1");
-});
-
-const maintenanceNotices = computed(() => {
-  return filteredNotices.value.filter(notice => notice.noticeType === "2");
 });
 
 // 鏂规硶瀹氫箟
@@ -396,20 +351,44 @@
 
 const resetQuery = () => {
   searchForm.value = {
-    noticeTitle: "",
-    noticeType: "",
+    title: "",
+    type: "",
     status: ""
   };
 };
 
 const getPriorityText = (priority) => {
-  const priorityMap = { "1": "鏅��", "2": "閲嶈", "3": "绱ф��" };
+  const priorityMap = {"1": "鏅��", "2": "閲嶈", "3": "绱ф��"};
   return priorityMap[priority] || "鏅��";
 };
 
 const getStatusText = (status) => {
-  const statusMap = { "0": "鑽夌", "1": "宸插彂甯�", "2": "宸蹭笅绾�" };
+  const statusMap = {"0": "鑽夌", "1": "宸插彂甯�", "2": "宸茶繃鏈�"};
   return statusMap[status] || "鏈煡";
+};
+
+const isNoticeExpired = (notice) => {
+  if (!notice || !notice.expirationDate) {
+    return false;
+  }
+
+  const expiration = new Date(notice.expirationDate);
+
+  if (Number.isNaN(expiration.getTime())) {
+    return false;
+  }
+
+  expiration.setHours(23, 59, 59, 999);
+
+  return new Date() > expiration;
+};
+
+const getNoticeStatus = (notice) => {
+  const normalizedStatus = notice && notice.status !== undefined && notice.status !== null
+      ? String(notice.status)
+      : "0";
+
+  return isNoticeExpired(notice) ? "2" : normalizedStatus;
 };
 
 const openForm = (type) => {
@@ -417,44 +396,64 @@
     dialogTitle.value = "鏂板鍏憡";
     form.value = {
       id: undefined,
-      noticeTitle: "",
-      noticeType: "",
-      noticeContent: "",
-      status: "0",
-      priority: "1",
+      title: "",
+      type: undefined,
+      content: "",
+      status: 0,
+      priority: 1,
       remark: "",
-      createBy: userStore.name || "褰撳墠鐢ㄦ埛",
-      createTime: new Date().toLocaleString()
+      expirationDate: "",
     };
   }
   dialogVisible.value = true;
 };
 
 const handleEdit = (row) => {
+  if (isNoticeExpired(row)) {
+    ElMessage.warning("宸茶繃鏈熺殑鍏憡涓嶅彲缂栬緫");
+    return;
+  }
   dialogTitle.value = "缂栬緫鍏憡";
-  form.value = { ...row };
+  form.value = {...row};
   dialogVisible.value = true;
-};
-
-const handleSelectionChange = (selection) => {
-  selectedIds.value = selection.map(item => item.id);
 };
 
 const handleDelete = (id) => {
   ElMessageBox.confirm(
-    "纭鍒犻櫎杩欐潯鍏憡鍚楋紵",
-    "鎻愮ず",
-    {
-      confirmButtonText: "纭畾",
-      cancelButtonText: "鍙栨秷",
-      type: "warning"
-    }
+      "纭鍒犻櫎杩欐潯鍏憡鍚楋紵",
+      "鎻愮ず",
+      {
+        confirmButtonText: "纭畾",
+        cancelButtonText: "鍙栨秷",
+        type: "warning"
+      }
   ).then(() => {
-    const index = mockData.findIndex(item => item.id === id);
-    if (index > -1) {
-      mockData.splice(index, 1);
+    delNotice(id).then(res => {
       ElMessage.success("鍒犻櫎鎴愬姛");
-    }
+      resetTable()
+    })
+  });
+};
+
+const handlePublish = (notice) => {
+  ElMessageBox.confirm(
+      "纭鍙戝竷杩欐潯鍏憡鍚楋紵",
+      "鎻愮ず",
+      {
+        confirmButtonText: "纭畾",
+        cancelButtonText: "鍙栨秷",
+        type: "info"
+      }
+  ).then(() => {
+    updateNotice({
+      ...notice,
+      status: 1
+    }).then(res => {
+      if (res.code === 200) {
+        ElMessage.success("鍙戝竷鎴愬姛");
+        resetTable()
+      }
+    })
   });
 };
 
@@ -463,24 +462,85 @@
     if (valid) {
       if (form.value.id) {
         // 缂栬緫妯″紡
-        const index = mockData.findIndex(item => item.id === form.value.id);
-        if (index > -1) {
-          mockData[index] = { ...form.value };
-        }
-        ElMessage.success("淇敼鎴愬姛");
+        updateNotice(form.value).then(res => {
+          ElMessage.success("淇敼鎴愬姛");
+          resetTable()
+        })
       } else {
         // 鏂板妯″紡
-        const newId = Math.max(...mockData.map(item => item.id)) + 1;
-        const newNotice = {
-          ...form.value,
-          id: newId,
-          createTime: new Date().toLocaleString()
-        };
-        mockData.unshift(newNotice);
-        ElMessage.success("鏂板鎴愬姛");
+        addNotice(form.value).then(res => {
+          ElMessage.success("鏂板鎴愬姛");
+          resetTable()
+        })
       }
       dialogVisible.value = false;
     }
+  });
+};
+
+// 鍒濆鍖栨煇涓被鍨嬬殑鍒嗛〉鏁版嵁
+const initNoticePage = (typeId) => {
+  if (!noticePagesMap.value[typeId]) {
+    noticePagesMap.value[typeId] = {
+      total: 0,
+      current: 1,
+      size: 10
+    };
+  }
+  if (!noticesMap.value[typeId]) {
+    noticesMap.value[typeId] = [];
+  }
+};
+
+// 鑾峰彇鏌愪釜绫诲瀷鐨勯�氱煡鍒楄〃
+const getNoticesByType = (typeId) => {
+  return noticesMap.value[typeId] || [];
+};
+
+// 鑾峰彇鏌愪釜绫诲瀷鐨勫垎椤垫暟鎹�
+const getNoticePageByType = (typeId) => {
+  return noticePagesMap.value[typeId] || { total: 0, current: 1, size: 10 };
+};
+
+// 鑾峰彇鏌愪釜绫诲瀷鐨勬暟閲�
+const getNoticeCountByType = (typeId) => {
+  return getNoticePageByType(typeId).total || 0;
+};
+
+// 鑾峰彇鏌愪釜绫诲瀷鐨勯�氱煡鏁版嵁
+const fetchNoticesByType = (typeId) => {
+  initNoticePage(typeId);
+  const pageData = noticePagesMap.value[typeId];
+  listNotice({...pageData, type: typeId}).then(res => {
+    if (res.code === 200) {
+      noticesMap.value[typeId] = res.data.records || [];
+      noticePagesMap.value[typeId].total = res.data.total || 0;
+    }
+  });
+};
+
+// 澶勭悊鍒嗛〉鍙樺寲
+const handleNoticeCurrentChange = (typeId, val) => {
+  initNoticePage(typeId);
+  noticePagesMap.value[typeId].size = val.limit;
+  noticePagesMap.value[typeId].current = val.page;
+  fetchNoticesByType(typeId);
+};
+
+// 澶勭悊 tab 鍒囨崲
+const handleNoticeTypeTabChange = (tabName) => {
+  activeNoticeTypeTab.value = tabName;
+  const typeId = Number(tabName);
+  fetchNoticesByType(typeId);
+};
+
+const resetTable = () => {
+  // 閲嶇疆鎵�鏈夌被鍨嬬殑鍒嗛〉骞堕噸鏂拌幏鍙栨暟鎹�
+  noticeTypeList.value.forEach(type => {
+    initNoticePage(type.id);
+    noticePagesMap.value[type.id].current = 1;
+    noticePagesMap.value[type.id].size = 10;
+    fetchNoticesByType(type.id);
   });
 };
 
@@ -488,9 +548,187 @@
   formRef.value?.resetFields();
 };
 
+// 鍏憡绫诲瀷閰嶇疆鐩稿叧鏂规硶
+const openNoticeTypeDialog = () => {
+  noticeTypeDialogVisible.value = true;
+  fetchNoticeTypeList();
+};
+
+const fetchNoticeTypeList = () => {
+  return listNoticeType().then(res => {
+    if (res.code === 200) {
+      noticeTypeList.value = res.data.map(item => ({
+        ...item,
+        editing: false
+      }));
+      
+      // 妫�鏌ヨ矾鐢卞弬鏁颁腑鐨� type
+      const routeType = route.query.type;
+      let targetTypeId = null;
+      
+      if (routeType) {
+        // 濡傛灉璺敱鍙傛暟涓湁 type锛屾煡鎵惧搴旂殑绫诲瀷
+        const typeId = Number(routeType);
+        const foundType = noticeTypeList.value.find(item => item.id === typeId);
+        if (foundType) {
+          targetTypeId = typeId;
+        }
+      }
+      
+      // 濡傛灉鏈夌被鍨嬫暟鎹�
+      if (noticeTypeList.value.length > 0) {
+        // 濡傛灉璺敱鍙傛暟鎸囧畾浜嗙被鍨嬩笖瀛樺湪锛屼娇鐢ㄨ矾鐢卞弬鏁扮殑绫诲瀷
+        // 鍚﹀垯濡傛灉娌℃湁閫変腑 tab锛岄粯璁ら�変腑绗竴涓�
+        if (targetTypeId !== null) {
+          activeNoticeTypeTab.value = String(targetTypeId);
+          fetchNoticesByType(targetTypeId);
+        } else if (!activeNoticeTypeTab.value) {
+          activeNoticeTypeTab.value = String(noticeTypeList.value[0].id);
+          fetchNoticesByType(noticeTypeList.value[0].id);
+        }
+      }
+    }
+  });
+};
+
+const handleAddNoticeType = () => {
+  const newItem = {
+    id: undefined,
+    noticeType: '',
+    editing: true
+  };
+  noticeTypeList.value.push(newItem);
+};
+
+const handleEditNoticeType = (row) => {
+  // 淇濆瓨鍘熷鍊�
+  row.originalNoticeType = row.noticeType;
+  row.editing = true;
+};
+
+const handleSaveNoticeType = (row) => {
+  if (!row.noticeType || row.noticeType.trim() === '') {
+    ElMessage.warning('鍏憡绫诲瀷涓嶈兘涓虹┖');
+    return;
+  }
+  
+  const data = {
+    noticeType: row.noticeType.trim()
+  };
+  
+  if (row.id) {
+    // 缂栬緫妯″紡 - 鍏堝垹闄ゅ啀娣诲姞锛堝洜涓哄彧鏈� add 鍜� del 鎺ュ彛锛�
+    delNoticeType(row.id).then(res => {
+      if (res.code === 200) {
+        addNoticeType(data).then(addRes => {
+          if (addRes.code === 200) {
+            ElMessage.success('缂栬緫鎴愬姛');
+            row.editing = false;
+            delete row.originalNoticeType;
+            fetchNoticeTypeList().then(() => {
+              // 濡傛灉褰撳墠閫変腑鐨勭被鍨嬭缂栬緫锛岄渶瑕侀噸鏂拌幏鍙栨暟鎹�
+              if (activeNoticeTypeTab.value === String(row.id)) {
+                fetchNoticesByType(addRes.data?.id || row.id);
+              }
+            });
+          }
+        });
+      }
+    });
+  } else {
+    // 鏂板妯″紡
+    addNoticeType(data).then(res => {
+      if (res.code === 200) {
+        ElMessage.success('鏂板鎴愬姛');
+        row.editing = false;
+        fetchNoticeTypeList();
+      }
+    });
+  }
+};
+
+const handleDeleteNoticeType = (row) => {
+  // 濡傛灉娌℃湁id锛岃鏄庢槸鏂板浣嗘湭淇濆瓨鐨勮锛岀洿鎺ヤ粠鍓嶇鍒犻櫎
+  if (!row.id) {
+    const index = noticeTypeList.value.indexOf(row);
+    if (index > -1) {
+      noticeTypeList.value.splice(index, 1);
+    }
+    return;
+  }
+  
+  // 濡傛灉鏈塱d锛岃皟鐢ㄥ悗绔帴鍙e垹闄�
+  ElMessageBox.confirm(
+      "纭鍒犻櫎杩欎釜鍏憡绫诲瀷鍚楋紵",
+      "鎻愮ず",
+      {
+        confirmButtonText: "纭畾",
+        cancelButtonText: "鍙栨秷",
+        type: "warning"
+      }
+  ).then(() => {
+    delNoticeType(row.id).then(res => {
+      if (res.code === 200) {
+        ElMessage.success("鍒犻櫎鎴愬姛");
+        // 濡傛灉鍒犻櫎鐨勬槸褰撳墠閫変腑鐨勭被鍨嬶紝鍒囨崲鍒扮涓�涓被鍨�
+        if (activeNoticeTypeTab.value === String(row.id)) {
+          fetchNoticeTypeList().then(() => {
+            if (noticeTypeList.value.length > 0) {
+              activeNoticeTypeTab.value = String(noticeTypeList.value[0].id);
+              fetchNoticesByType(noticeTypeList.value[0].id);
+            } else {
+              activeNoticeTypeTab.value = '';
+            }
+          });
+        } else {
+          fetchNoticeTypeList();
+        }
+      }
+    });
+  });
+};
+
+const handleCancelEdit = (row) => {
+  if (!row.id) {
+    // 濡傛灉鏄柊澧炰絾鏈繚瀛樼殑琛岋紝绉婚櫎瀹�
+    const index = noticeTypeList.value.indexOf(row);
+    if (index > -1) {
+      noticeTypeList.value.splice(index, 1);
+    }
+  } else {
+    // 濡傛灉鏄紪杈戜腑鐨勮锛屽彇娑堢紪杈戠姸鎬佸苟鎭㈠鍘熷��
+    row.editing = false;
+    if (row.originalNoticeType !== undefined) {
+      row.noticeType = row.originalNoticeType;
+      delete row.originalNoticeType;
+    }
+  }
+};
+
+const handleNoticeTypeDialogClose = () => {
+  // 鍏抽棴寮规鏃讹紝鍙栨秷鎵�鏈夌紪杈戠姸鎬�
+  noticeTypeList.value.forEach(item => {
+    if (item.editing && !item.id) {
+      // 濡傛灉鏄柊澧炰絾鏈繚瀛樼殑琛岋紝绉婚櫎瀹�
+      const index = noticeTypeList.value.indexOf(item);
+      if (index > -1) {
+        noticeTypeList.value.splice(index, 1);
+      }
+    } else if (item.editing) {
+      // 濡傛灉鏄紪杈戜腑鐨勮锛屽彇娑堢紪杈戠姸鎬佸苟鎭㈠鍘熷��
+      item.editing = false;
+      if (item.originalNoticeType !== undefined) {
+        item.noticeType = item.originalNoticeType;
+        delete item.originalNoticeType;
+      }
+    }
+  });
+};
+
 // 鐢熷懡鍛ㄦ湡
 onMounted(() => {
-  // 椤甸潰鍔犺浇瀹屾垚
+  // 鍏堣幏鍙栧叕鍛婄被鍨嬪垪琛紝鐒跺悗鏍规嵁绫诲瀷鑾峰彇閫氱煡鏁版嵁
+  fetchNoticeTypeList();
 });
 </script>
 
@@ -569,12 +807,16 @@
   box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15);
 }
 
-.holiday-card {
-  border-left-color: #67c23a;
+.notice-icon {
+  color: #409eff;
+  margin-right: 8px;
+  font-size: 18px;
 }
 
-.maintenance-card {
-  border-left-color: #e6a23c;
+.tab-count {
+  color: #909399;
+  font-size: 12px;
+  margin-left: 4px;
 }
 
 .urgent {
@@ -598,17 +840,6 @@
   flex: 1;
 }
 
-.holiday-icon {
-  color: #67c23a;
-  margin-right: 8px;
-  font-size: 18px;
-}
-
-.maintenance-icon {
-  color: #e6a23c;
-  margin-right: 8px;
-  font-size: 18px;
-}
 
 .card-actions {
   display: flex;
@@ -624,6 +855,9 @@
   color: #606266;
   line-height: 1.6;
   font-size: 14px;
+  word-break: break-all;
+  white-space: pre-wrap;
+  overflow-wrap: break-word;
 }
 
 .card-footer {
@@ -645,13 +879,35 @@
   font-weight: 500;
 }
 
-.priority-1 { background: #f0f9ff; color: #0369a1; }
-.priority-2 { background: #fef3c7; color: #d97706; }
-.priority-3 { background: #fef2f2; color: #dc2626; }
+.priority-1 {
+  background: #f0f9ff;
+  color: #0369a1;
+}
 
-.status-0 { background: #f3f4f6; color: #6b7280; }
-.status-1 { background: #d1fae5; color: #059669; }
-.status-2 { background: #fef3c7; color: #d97706; }
+.priority-2 {
+  background: #fef3c7;
+  color: #d97706;
+}
+
+.priority-3 {
+  background: #fef2f2;
+  color: #dc2626;
+}
+
+.status-0 {
+  background: #f3f4f6;
+  color: #6b7280;
+}
+
+.status-1 {
+  background: #d1fae5;
+  color: #059669;
+}
+
+.status-2 {
+  background: #fef3c7;
+  color: #d97706;
+}
 
 .card-info {
   display: flex;
@@ -664,6 +920,10 @@
 .creator {
   font-weight: 500;
   margin-bottom: 2px;
+}
+
+.expiration {
+  margin-top: 2px;
 }
 
 .card-remark {
@@ -687,17 +947,27 @@
   text-align: right;
 }
 
+.notice-type-container {
+  padding: 10px 0;
+}
+
+.notice-type-header {
+  margin-bottom: 15px;
+  display: flex;
+  justify-content: flex-end;
+}
+
 /* 鍝嶅簲寮忚璁� */
 @media (max-width: 768px) {
   .notice-cards {
     grid-template-columns: 1fr;
   }
-  
+
   .search_form {
     flex-direction: column;
     gap: 15px;
   }
-  
+
   .search_form > div {
     width: 100%;
   }
diff --git a/src/views/collaborativeApproval/notificationManagement/index.vue b/src/views/collaborativeApproval/notificationManagement/index.vue
index 288acf1..fb3f7a8 100644
--- a/src/views/collaborativeApproval/notificationManagement/index.vue
+++ b/src/views/collaborativeApproval/notificationManagement/index.vue
@@ -87,6 +87,8 @@
                 v-model="form.expireDate"
                 type="date"
                 placeholder="璇烽�夋嫨鏈夋晥鏈�"
+                value-format="YYYY-MM-DD"
+                format="YYYY-MM-DD"
                 style="width: 100%"
               />
             </el-form-item>
@@ -152,6 +154,8 @@
               <el-date-picker
                 v-model="meetingForm.startTime"
                 type="datetime"
+                value-format="YYYY-MM-DD HH:mm:ss"
+                format="YYYY-MM-DD HH:mm:ss"
                 placeholder="璇烽�夋嫨寮�濮嬫椂闂�"
                 style="width: 100%"
               />
@@ -318,7 +322,9 @@
 import { ElMessage, ElMessageBox } from "element-plus";
 import PIMTable from "@/components/PIMTable/PIMTable.vue";
 import { userListNoPageByTenantId } from "@/api/system/user.js";
-import { staffOnJobListPage } from "@/api/personnelManagement/employeeRecord.js";
+import { staffOnJobListPage } from "@/api/personnelManagement/staffOnJob.js";
+import { listNotification, addNotification, updateNotification, delNotification,addOnlineMeeting,addFileSharing } from "@/api/collaborativeApproval/notificationManagement.js";
+import { id } from "element-plus/es/locales.mjs";
 
 // 琛ㄥ崟楠岃瘉瑙勫垯
 const rules = {
@@ -364,7 +370,7 @@
   tableLoading: false,
   page: {
     current: 1,
-    size: 100,
+    size: 20,
     total: 0,
   },
   tableData: [],
@@ -373,7 +379,7 @@
   form: {
     title: "",
     type: "",
-    priority: "medium",
+    priority: "",
     content: "",
     departments: [],
     expireDate: "",
@@ -403,11 +409,11 @@
   fileList: []
 });
 
-const { 
-  searchForm, 
-  tableLoading, 
-  page, 
-  tableData, 
+const {
+  searchForm,
+  tableLoading,
+  page,
+  tableData,
   selectedIds,
   form,
   dialogVisible,
@@ -543,7 +549,6 @@
         clickFun: (row) => {
           publishNotification(row);
         },
-        // disabled: (row) => row.status === "published"
       },
       {
         name: "鎾ゅ洖",
@@ -551,52 +556,10 @@
         clickFun: (row) => {
           revokeNotification(row);
         },
-        // disabled: (row) => row.status !== "published"
       }
     ]
   }
 ]);
-
-// 妯℃嫙鏁版嵁
-let mockData = [
-  {
-    id: "1",
-    title: "2024骞存槬鑺傛斁鍋囬�氱煡",
-    type: "holiday",
-    priority: "high",
-    status: "published",
-    content: "鏍规嵁鍥藉瑙勫畾锛岀粨鍚堝叕鍙稿疄闄呮儏鍐碉紝鐜板皢2024骞存槬鑺傛斁鍋囧畨鎺掗�氱煡濡備笅...",
-    departments: ["鎶�鏈儴", "閿�鍞儴", "浜轰簨閮�", "璐㈠姟閮�", "杩愯惀閮�", "甯傚満閮�", "瀹㈡湇閮�"],
-    expireDate: "2024-02-15",
-    syncMethods: ["wechat", "dingtalk", "email"],
-    createTime: "2024-01-15 10:30:00"
-  },
-  {
-    id: "2",
-    title: "鎶�鏈儴鍛ㄤ緥浼氶�氱煡",
-    type: "meeting",
-    priority: "medium",
-    status: "published",
-    content: "鎶�鏈儴瀹氫簬姣忓懆浜斾笅鍗�2鐐瑰彫寮�鍛ㄤ緥浼氾紝璇峰悇浣嶅悓浜嬪噯鏃跺弬鍔�...",
-    departments: ["鎶�鏈儴"],
-    expireDate: "2024-01-20",
-    syncMethods: ["wechat", "dingtalk"],
-    createTime: "2024-01-14 15:20:00"
-  },
-  {
-    id: "3",
-    title: "鍛樺伐琛屼负瑙勮寖澶勭綒閫氱煡",
-    type: "penalty",
-    priority: "high",
-    status: "draft",
-    content: "涓虹淮鎶ゅ叕鍙告甯哥З搴忥紝瑙勮寖鍛樺伐琛屼负锛岀幇瀵硅繚鍙嶅叕鍙歌瀹氱殑琛屼负杩涜澶勭綒...",
-    departments: ["浜轰簨閮�", "鎶�鏈儴", "閿�鍞儴"],
-    expireDate: "2024-02-13",
-    syncMethods: ["wechat", "email"],
-    createTime: "2024-01-13 09:15:00"
-  }
-];
-
 // 閫氱煡鏍囬妯℃澘
 const titleTemplates = [
   "鍏充簬{year}骞磠holiday}鏀惧亣瀹夋帓鐨勯�氱煡",
@@ -631,7 +594,7 @@
     employeesLoading.value = true;
     // 浼樺厛浣跨敤绯荤粺鐢ㄦ埛鎺ュ彛锛堟寜绉熸埛鑾峰彇锛�
     const userResponse = await userListNoPageByTenantId();
-    
+
     if (userResponse.data) {
       employees.value = userResponse.data.map(user => ({
         label: user.nickName || user.userName || '鏈煡濮撳悕',
@@ -643,12 +606,12 @@
       })).filter(user => user.status === '0'); // 鍙樉绀烘甯哥姸鎬佺殑鐢ㄦ埛
     } else {
       // 濡傛灉绯荤粺鐢ㄦ埛鎺ュ彛澶辫触锛屼娇鐢ㄥ憳宸ュ彴璐︽帴鍙�
-      const response = await staffOnJobListPage({ 
-        pageNum: 1, 
-        pageSize: 1000, 
+      const response = await staffOnJobListPage({
+        pageNum: 1,
+        pageSize: 1000,
         staffState: 1 // 鍦ㄨ亴鐘舵��
       });
-      
+
       if (response.data && response.data.records) {
         employees.value = response.data.records.map(employee => ({
           label: employee.staffName || employee.name || '鏈煡濮撳悕',
@@ -683,7 +646,7 @@
     }
     groups[dept].push(employee);
   });
-  
+
   // 鎸夐儴闂ㄥ悕绉版帓搴忥紝纭繚鏄剧ず椤哄簭涓�鑷�
   return Object.keys(groups)
     .sort()
@@ -697,7 +660,7 @@
 const filterEmployees = (query) => {
   if (query !== '') {
     const lowerQuery = query.toLowerCase();
-    return employees.value.filter(employee => 
+    return employees.value.filter(employee =>
       employee.label.toLowerCase().includes(lowerQuery) ||
       employee.dept.toLowerCase().includes(lowerQuery) ||
       (employee.phone && employee.phone.includes(query)) ||
@@ -712,18 +675,18 @@
 const refreshEmployees = async () => {
   ElMessage.info("姝e湪鍒锋柊鍛樺伐鍒楄〃...");
   await getEmployeesList();
-  
+
   // 缁熻鍚勯儴闂ㄤ汉鏁�
   const deptStats = {};
   employees.value.forEach(emp => {
     const dept = emp.dept || '鍏朵粬閮ㄩ棬';
     deptStats[dept] = (deptStats[dept] || 0) + 1;
   });
-  
+
   const deptInfo = Object.entries(deptStats)
     .map(([dept, count]) => `${dept}: ${count}浜篳)
     .join(', ');
-  
+
   ElMessage.success(`鍛樺伐鍒楄〃鍒锋柊瀹屾垚锛屽叡 ${employees.value.length} 浜� (${deptInfo})`);
 };
 
@@ -737,7 +700,7 @@
 const getEmployeeInfo = (employeeId) => {
   const employee = employees.value.find(emp => emp.value === employeeId);
   if (!employee) return null;
-  
+
   return {
     name: employee.label,
     dept: employee.dept,
@@ -776,7 +739,7 @@
   const now = new Date();
   const randomType = notificationTypes[Math.floor(Math.random() * notificationTypes.length)];
   const randomDept = departments[Math.floor(Math.random() * departments.length)];
-  
+
   // 鐢熸垚闅忔満鏍囬
   let title = titleTemplates[Math.floor(Math.random() * titleTemplates.length)];
   title = title
@@ -788,15 +751,15 @@
     .replace('{company}', ['鍏徃', '闆嗗洟', '鎬婚儴'][Math.floor(Math.random() * 4)])
     .replace('{project}', ['鏁板瓧鍖栬浆鍨�', '浜у搧鍗囩骇', '甯傚満鎷撳睍', '浜烘墠鍩瑰吇'][Math.floor(Math.random() * 4)])
     .replace('{policy}', ['鑰冨嫟', '钖叕', '绂忓埄', '鏅嬪崌'][Math.floor(Math.random() * 4)]);
-  
+
   // 闅忔満鐘舵��
   const statuses = ['draft', 'published'];
   const randomStatus = statuses[Math.floor(Math.random() * statuses.length)];
-  
+
   // 闅忔満浼樺厛绾�
   const priorities = ['low', 'medium', 'high'];
   const randomPriority = priorities[Math.floor(Math.random() * priorities.length)];
-  
+
   const newNotification = {
     id: newId,
     title: title,
@@ -809,15 +772,15 @@
     syncMethods: ["wechat", "dingtalk"],
     createTime: now.toLocaleString()
   };
-  
+
   // 娣诲姞鍒版暟鎹紑澶�
   mockData.unshift(newNotification);
-  
+
   // 淇濇寔鏁版嵁閲忓湪鍚堢悊鑼冨洿鍐咃紙鏈�澶氫繚鐣�20鏉★級
   if (mockData.length > 20) {
     mockData = mockData.slice(0, 20);
   }
-  
+
   console.log(`[${new Date().toLocaleString()}] 鑷姩鐢熸垚鏂伴�氱煡: ${title}`);
 };
 
@@ -844,24 +807,14 @@
 
 const getList = () => {
   tableLoading.value = true;
-  
-  setTimeout(() => {
-    let filteredData = [...mockData];
-    
-    if (searchForm.value.title) {
-      filteredData = filteredData.filter(item => 
-        item.title.toLowerCase().includes(searchForm.value.title.toLowerCase())
-      );
-    }
-    
-    if (searchForm.value.type) {
-      filteredData = filteredData.filter(item => item.type === searchForm.value.type);
-    }
-    
-    tableData.value = filteredData;
-    page.value.total = filteredData.length;
+  listNotification({...page.value, ...searchForm.value})
+  .then(res => {
     tableLoading.value = false;
-  }, 500);
+    tableData.value = res.data.records
+    page.value.total = res.data.total;
+  }).catch(err => {
+    tableLoading.value = false;
+  })
 };
 
 // 鍒嗛〉澶勭悊
@@ -883,23 +836,27 @@
     dialogTitle.value = "鏂板閫氱煡";
     // 閲嶇疆琛ㄥ崟
     Object.assign(form.value, {
+      id: "",
       title: "",
       type: "",
-      priority: "medium",
+      priority: "",
       content: "",
       departments: [],
       expireDate: "",
+      status: "draft",
       syncMethods: []
     });
   } else if (type === "edit" && row) {
     dialogTitle.value = "缂栬緫閫氱煡";
     Object.assign(form.value, {
+      id: row.id,
       title: row.title,
       type: row.type,
       priority: row.priority,
       content: row.content || "",
       departments: row.departments || [],
       expireDate: row.expireDate || "",
+      status: row.status,
       syncMethods: row.syncMethods || []
     });
   }
@@ -944,43 +901,30 @@
 const submitForm = async () => {
   try {
     await formRef.value.validate();
-    
+
     if (dialogType.value === "add") {
       // 鏂板閫氱煡
-      const newNotification = {
-        id: (mockData.length + 1).toString(),
-        title: form.value.title,
-        type: form.value.type,
-        priority: form.value.priority,
-        status: "draft",
-        content: form.value.content,
-        departments: form.value.departments,
-        expireDate: form.value.expireDate,
-        syncMethods: form.value.syncMethods,
-        createTime: new Date().toLocaleString()
-      };
-      
-      mockData.unshift(newNotification);
-      ElMessage.success("閫氱煡鍒涘缓鎴愬姛");
+      addNotification({...form.value}).then(res => {
+        if(res.code == 200){
+          ElMessage.success("娣诲姞鎴愬姛");
+          dialogVisible.value = false;
+          getList();
+        }
+      }).catch(err => {
+        ElMessage.error(err.msg);
+      })
     } else {
       // 缂栬緫閫氱煡
-      const index = mockData.findIndex(item => item.id === selectedIds.value[0]);
-      if (index !== -1) {
-        Object.assign(mockData[index], {
-          title: form.value.title,
-          type: form.value.type,
-          priority: form.value.priority,
-          content: form.value.content,
-          departments: form.value.departments,
-          expireDate: form.value.expireDate,
-          syncMethods: form.value.syncMethods
-        });
-        ElMessage.success("閫氱煡鏇存柊鎴愬姛");
-      }
+      updateNotification({...form.value}).then(res => {
+        if(res.code == 200){
+          ElMessage.success("鏇存柊鎴愬姛");
+          dialogVisible.value = false;
+          getList();
+        }
+      }).catch(err => {
+        ElMessage.error(err.msg);
+      })
     }
-    
-    dialogVisible.value = false;
-    getList();
   } catch (error) {
     console.error("琛ㄥ崟楠岃瘉澶辫触:", error);
   }
@@ -990,7 +934,7 @@
 const createMeeting = async () => {
   try {
     await meetingFormRef.value.validate();
-    
+
     // 妯℃嫙鍒涘缓浼氳
     const meetingInfo = {
       title: meetingForm.value.title,
@@ -998,22 +942,28 @@
       duration: meetingForm.value.duration,
       participants: meetingForm.value.participants,
       description: meetingForm.value.description,
-      platform: meetingForm.value.platform,
-      meetingId: `MTG${Date.now()}`
+      platform: meetingForm.value.platform
     };
-    
+    // 鏂板浼氳
+    addOnlineMeeting({...meetingInfo}).then(res => {
+      if(res.code == 200){
+        ElMessage.success("浼氳娣诲姞鎴愬姛");
+        meetingDialogVisible.value = false;
+        getList();
+      }
+    }).catch(err => {
+      ElMessage.error(err.msg);
+    })
     // 妯℃嫙鍙戦�佸埌浼佷笟寰俊/閽夐拤
-    const platformName = meetingPlatforms.find(p => p.value === meetingForm.value.platform)?.label || "鏈煡骞冲彴";
-    
-    ElMessage.success(`浼氳鍒涘缓鎴愬姛锛佷細璁甀D: ${meetingInfo.meetingId}锛屽皢閫氳繃${platformName}鍙戦�侀�氱煡`);
-    meetingDialogVisible.value = false;
-    
-         // 鑾峰彇鍙備細浜哄憳淇℃伅
+    // const platformName = meetingPlatforms.find(p => p.value === meetingForm.value.platform)?.label || "鏈煡骞冲彴";
+    // ElMessage.success(`浼氳鍒涘缓鎴愬姛锛佷細璁甀D: ${meetingInfo.meetingId}锛屽皢閫氳繃${platformName}鍙戦�侀�氱煡`);
+
+    // 鑾峰彇鍙備細浜哄憳淇℃伅
      const participantNames = meetingForm.value.participants.map(participantId => {
        const employee = employees.value.find(emp => emp.value === participantId);
        return employee ? employee.label : '鏈煡浜哄憳';
      }).join('銆�');
-     
+
      // 鑾峰彇鍙備細浜哄憳璇︾粏淇℃伅
      const participantDetails = meetingForm.value.participants.map(participantId => {
        const employee = employees.value.find(emp => emp.value === participantId);
@@ -1024,23 +974,29 @@
          email: employee.email
        } : null;
      }).filter(Boolean);
-    
+
     // 灏嗕細璁俊鎭坊鍔犲埌閫氱煡鍒楄〃
     const meetingNotification = {
-      id: (mockData.length + 1).toString(),
       title: `[浼氳閫氱煡] ${meetingInfo.title}`,
       type: "meeting",
       priority: "high",
       status: "published",
-             content: `浼氳鏃堕棿: ${meetingInfo.startTime}锛屾椂闀�: ${meetingInfo.duration}鍒嗛挓锛屽钩鍙�: ${meetingPlatforms.find(p => p.value === meetingForm.value.platform)?.label || "鏈煡骞冲彴"}锛屽弬浼氫汉鍛�: ${participantNames}锛屽叡${participantDetails.length}浜篳,
+      content: `浼氳鏃堕棿: ${meetingInfo.startTime}锛屾椂闀�: ${meetingInfo.duration}鍒嗛挓锛屽钩鍙�: ${meetingPlatforms.find(p => p.value === meetingForm.value.platform)?.label || "鏈煡骞冲彴"}锛屽弬浼氫汉鍛�: ${participantNames}锛屽叡${participantDetails.length}浜篳,
       departments: [],
       expireDate: "",
-      syncMethods: [meetingForm.value.platform],
-      createTime: new Date().toLocaleString()
+      syncMethods: [meetingForm.value.platform]
     };
-    
-    mockData.unshift(meetingNotification);
-    getList();
+    addNotification({...meetingNotification}).then(res => {
+        if(res.code == 200){
+          ElMessage.success("娣诲姞鎴愬姛");
+          // dialogVisible.value = false;
+          getList();
+        }
+      }).catch(err => {
+        ElMessage.error(err.msg);
+      })
+    // mockData.unshift(meetingNotification);
+    // getList();
   } catch (error) {
     console.error("浼氳琛ㄥ崟楠岃瘉澶辫触:", error);
   }
@@ -1053,16 +1009,16 @@
     ElMessage.error("涓婁紶鏂囦欢澶у皬涓嶈兘瓒呰繃 10MB!");
     return false;
   }
-  
+
   const fileInfo = {
     name: file.name,
     size: file.size,
     type: file.type,
     uid: file.uid
   };
-  
+
   fileList.value.push(fileInfo);
-  fileShareForm.value.files.push(fileInfo);
+  fileShareForm.value.files.push(fileInfo.name);
   return false; // 闃绘鑷姩涓婁紶
 };
 
@@ -1082,27 +1038,34 @@
 const shareFiles = async () => {
   try {
     await fileShareFormRef.value.validate();
-    
+
     if (fileShareForm.value.files.length === 0) {
       ElMessage.warning("璇疯嚦灏戦�夋嫨涓�涓枃浠�");
       return;
     }
-    
+
     // 妯℃嫙鏂囦欢鍏变韩
     const shareInfo = {
       title: fileShareForm.value.title,
       description: fileShareForm.value.description,
       departments: fileShareForm.value.departments,
       files: fileShareForm.value.files,
-      shareId: `FILE${Date.now()}`
     };
-    
-    ElMessage.success(`鏂囦欢鍏变韩鎴愬姛锛佸叡浜獻D: ${shareInfo.shareId}锛屽凡閫氱煡鐩稿叧閮ㄩ棬`);
-    fileShareDialogVisible.value = false;
-    
+    addFileSharing({...shareInfo}).then(res => {
+      if(res.code == 200){
+        ElMessage.success("鏂囦欢鍏变韩鎴愬姛");
+        fileShareDialogVisible.value = false;
+        getList();
+      }
+    }).catch(err => {
+      ElMessage.error(err.msg);
+    })
+
+    // ElMessage.success(`鏂囦欢鍏变韩鎴愬姛锛佸叡浜獻D: ${shareInfo.shareId}锛屽凡閫氱煡鐩稿叧閮ㄩ棬`);
+
+
     // 灏嗘枃浠跺叡浜俊鎭坊鍔犲埌閫氱煡鍒楄〃
     const fileShareNotification = {
-      id: (mockData.length + 1).toString(),
       title: `[鏂囦欢鍏变韩] ${shareInfo.title}`,
       type: "temporary",
       priority: "medium",
@@ -1111,11 +1074,19 @@
       departments: shareInfo.departments,
       expireDate: "",
       syncMethods: ["wechat", "dingtalk"],
-      createTime: new Date().toLocaleString()
     };
-    
-    mockData.unshift(fileShareNotification);
-    getList();
+    addNotification({...fileShareNotification}).then(res => {
+      if(res.code == 200){
+        ElMessage.success("娣诲姞鎴愬姛");
+        // dialogVisible.value = false;
+        getList();
+      }
+    }).catch(err => {
+      ElMessage.error(err.msg);
+    })
+
+    // mockData.unshift(fileShareNotification);
+    // getList();
   } catch (error) {
     console.error("鏂囦欢鍏变韩琛ㄥ崟楠岃瘉澶辫触:", error);
   }
@@ -1123,33 +1094,75 @@
 
 // 鍙戝竷閫氱煡
 const publishNotification = (row) => {
-  row.status = "published";
-  ElMessage.success("閫氱煡鍙戝竷鎴愬姛");
-  getList();
+  Object.assign(form.value, {
+    id: row.id,
+    title: row.title,
+    type: row.type,
+    priority: row.priority,
+    content: row.content || "",
+    departments: row.departments || [],
+    expireDate: row.expireDate || "",
+    status: row.status,
+    syncMethods: row.syncMethods || []
+  });
+  form.value.status = "published";
+  updateNotification({...form.value}).then(res => {
+        if(res.code == 200){
+          ElMessage.success("閫氱煡鍙戝竷鎴愬姛");
+          getList();
+        }
+      }).catch(err => {
+        ElMessage.error(err.msg);
+      })
 };
 
 // 鎾ゅ洖閫氱煡
 const revokeNotification = (row) => {
-  row.status = "draft";
-  ElMessage.success("閫氱煡宸叉挙鍥�");
-  getList();
+    Object.assign(form.value, {
+    id: row.id,
+    title: row.title,
+    type: row.type,
+    priority: row.priority,
+    content: row.content || "",
+    departments: row.departments || [],
+    expireDate: row.expireDate || "",
+    status: row.status,
+    syncMethods: row.syncMethods || []
+  });
+  form.value.status = "draft";
+  updateNotification({...form.value}).then(res => {
+        if(res.code == 200){
+          ElMessage.success("閫氱煡宸叉挙鍥�");
+          getList();
+        }
+      }).catch(err => {
+        ElMessage.error(err.msg);
+      })
 };
 
 // 鍒犻櫎閫氱煡
 const handleDelete = () => {
-  if (selectedIds.value.length === 0) {
+  let ids = [];
+  if (selectedIds.value.length > 0) {
+    ids = selectedIds.value;
+  }else{
     ElMessage.warning("璇烽�夋嫨瑕佸垹闄ょ殑閫氱煡");
     return;
   }
-  
   ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "鍒犻櫎", {
     confirmButtonText: "纭",
     cancelButtonText: "鍙栨秷",
     type: "warning",
   }).then(() => {
-    ElMessage.success("鍒犻櫎鎴愬姛");
-    selectedIds.value = [];
-    getList();
+    delNotification(ids).then(res => {
+      if(res.code == 200){
+        ElMessage.success("鍒犻櫎鎴愬姛");
+        selectedIds.value = [];
+        getList();
+      }
+    }).catch(err => {
+      ElMessage.error(err.msg);
+    })
   }).catch(() => {
     // 鐢ㄦ埛鍙栨秷
   });
diff --git a/src/views/collaborativeApproval/notificationManagement/meetApplication/index.vue b/src/views/collaborativeApproval/notificationManagement/meetApplication/index.vue
new file mode 100644
index 0000000..7781593
--- /dev/null
+++ b/src/views/collaborativeApproval/notificationManagement/meetApplication/index.vue
@@ -0,0 +1,394 @@
+<template>
+  <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..11d1774
--- /dev/null
+++ b/src/views/collaborativeApproval/notificationManagement/meetDraft/index.vue
@@ -0,0 +1,495 @@
+<template>
+  <div>
+    <!-- 椤甸潰鏍囬 -->
+    <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..83747a0
--- /dev/null
+++ b/src/views/collaborativeApproval/notificationManagement/meetExamine/index.vue
@@ -0,0 +1,414 @@
+<template>
+  <div>
+
+    <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-table v-loading="loading" :data="approvalList" border :height="tableHeight">
+        <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)
+
+// 琛ㄦ牸楂樺害锛堟牴鎹獥鍙i珮搴﹁嚜閫傚簲锛�
+const tableHeight = ref(window.innerHeight - 380)
+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..9b5325f
--- /dev/null
+++ b/src/views/collaborativeApproval/notificationManagement/meetIndex/index.vue
@@ -0,0 +1,363 @@
+<template>
+  <div>
+    <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 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..2351293
--- /dev/null
+++ b/src/views/collaborativeApproval/notificationManagement/meetPublish/index.vue
@@ -0,0 +1,412 @@
+<template>
+  <div>
+
+    <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-table v-loading="loading" :data="approvalList" border :height="tableHeight">
+        <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)
+
+// 琛ㄦ牸楂樺害锛堟牴鎹獥鍙i珮搴﹁嚜閫傚簲锛�
+const tableHeight = ref(window.innerHeight - 380)
+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..ad4931a
--- /dev/null
+++ b/src/views/collaborativeApproval/notificationManagement/meetSetting/index.vue
@@ -0,0 +1,320 @@
+<template>
+  <div>
+    <!-- 鎼滅储鍖哄煙 -->
+    <el-form :model="searchForm" label-width="100px" class="search-form">
+      <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-item class="search-actions">
+        <el-button @click="handleExport">瀵煎嚭</el-button>
+        <el-button type="primary" @click="handleAdd">
+          <el-icon><Plus /></el-icon>
+          鏂板浼氳瀹�
+        </el-button>
+      </el-form-item>
+    </el-form>
+
+    <!-- 浼氳瀹ゅ垪琛� -->
+    <el-card>
+      <el-table v-loading="loading" :data="meetingRoomList" border :height="tableHeight">
+        <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, getCurrentInstance } 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)
+
+// 琛ㄦ牸楂樺害锛堟牴鎹獥鍙i珮搴﹁嚜閫傚簲锛�
+const tableHeight = ref(window.innerHeight - 380)
+
+// 浼氳瀹ゅ垪琛ㄦ暟鎹�
+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()
+      })
+    }
+  })
+}
+
+// 瀵煎嚭
+const { proxy } = getCurrentInstance()
+const handleExport = () => {
+  proxy.download('/meeting/export', { ...searchForm }, '浼氳瀹よ缃�.xlsx')
+}
+
+// 椤甸潰鍔犺浇鏃惰幏鍙栨暟鎹�
+onMounted(() => {
+  getList()
+})
+</script>
+
+<style scoped>
+.app-container {
+  padding: 20px;
+}
+
+.search-form {
+  display: flex;
+  /* align-items: center; */
+}
+
+.search-actions {
+  margin-left: auto;
+}
+
+.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..a00316d
--- /dev/null
+++ b/src/views/collaborativeApproval/notificationManagement/summary/index.vue
@@ -0,0 +1,399 @@
+<template>
+  <div>
+
+    <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-table v-loading="loading" :data="meetingList" border :height="tableHeight">
+        <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)
+
+// 琛ㄦ牸楂樺害锛堟牴鎹獥鍙i珮搴﹁嚜閫傚簲锛�
+const tableHeight = ref(window.innerHeight - 380)
+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/collaborativeApproval/officeSupplies/index.vue b/src/views/collaborativeApproval/officeSupplies/index.vue
new file mode 100644
index 0000000..a2d1c6d
--- /dev/null
+++ b/src/views/collaborativeApproval/officeSupplies/index.vue
@@ -0,0 +1,512 @@
+<template>
+  <div class="app-container">
+    <el-card class="box-card">
+      <template #header>
+        <div class="card-header">
+          <span>鍔炲叕鐗╄祫鐢宠绠$悊</span>
+          <el-button type="primary" @click="openShow()">
+            <el-icon><Plus /></el-icon>
+            鏂板缓鐢宠
+          </el-button>
+        </div>
+      </template>
+
+             <!-- 鎼滅储鍖哄煙 -->
+       <el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch">
+         <el-form-item label="鐢宠缂栧彿" prop="code">
+           <el-input
+             v-model="queryParams.code"
+             placeholder="璇疯緭鍏ョ敵璇风紪鍙�"
+             clearable
+             style="width: 200px"
+             @keyup.enter="handleQuery"
+           />
+         </el-form-item>
+         <el-form-item label="鐢宠浜�" prop="applicant">
+           <el-input
+             v-model="queryParams.applicant"
+             placeholder="璇疯緭鍏ョ敵璇蜂汉"
+             clearable
+             style="width: 200px"
+             @keyup.enter="handleQuery"
+           />
+         </el-form-item>
+         <el-form-item label="鐢宠鐘舵��" prop="status">
+           <el-select v-model="queryParams.status" placeholder="璇烽�夋嫨鐘舵��" clearable style="width: 200px">
+             <el-option label="寰呭鎵�" value="1" />
+             <el-option label="宸查�氳繃" value="3" />
+             <el-option label="宸叉嫆缁�" value="2" />
+             <el-option label="宸插彂鏀�" value="4" />
+           </el-select>
+         </el-form-item>
+         <el-form-item>
+           <el-button type="primary" @click="handleQuery">
+             <el-icon><Search /></el-icon>
+             鎼滅储
+           </el-button>
+           <el-button @click="resetQuery">
+             <el-icon><Refresh /></el-icon>
+             閲嶇疆
+           </el-button>
+         </el-form-item>
+         <el-form-item>
+            <el-button type="primary" @click="handleExport">
+            <el-icon><Download /></el-icon>
+            瀵煎嚭
+          </el-button>
+         </el-form-item>
+       </el-form>
+
+      <!-- 琛ㄦ牸鍖哄煙 -->
+      <el-table
+        v-loading="loading"
+        :data="officeList"
+        @selection-change="handleSelectionChange"
+        style="width: 100%"
+      >
+        <el-table-column type="selection" width="55" align="center" />
+        <el-table-column label="鐢宠缂栧彿" align="center" prop="code" width="180" />
+        <el-table-column label="鐢宠浜�" align="center" prop="applicant" width="120" />
+        <el-table-column label="閮ㄩ棬" align="center" prop="dept" width="120" />
+        <el-table-column label="鐗╄祫绫诲瀷" align="center" prop="materialType" width="120">
+          <template #default="scope">
+            <el-tag v-if="scope.row.materialType === 1" type="info">鍏朵粬</el-tag>
+            <el-tag v-if="scope.row.materialType === 2" type="success">娓呮磥鐢ㄥ搧</el-tag>
+            <el-tag v-if="scope.row.materialType === 3" type="warning">鐢靛瓙璁惧</el-tag>
+            <el-tag v-if="scope.row.materialType === 4" type="danger">鍔炲叕鐢ㄥ搧</el-tag>
+          </template>
+        </el-table-column>
+        <el-table-column label="鐢宠鏁伴噺" align="center" prop="applyNum" width="100" />
+        <el-table-column label="鐢宠鍘熷洜" align="center" prop="reason" min-width="200" show-overflow-tooltip />
+        <el-table-column label="鐢宠鐘舵��" align="center" prop="status" width="100">
+          <template #default="scope">
+            <el-tag :type="getStatusType(scope.row.status)">
+              {{ getStatusText(scope.row.status) }}
+            </el-tag>
+          </template>
+        </el-table-column>
+        <el-table-column label="鐢宠鏃堕棿" align="center" prop="applyTime" width="180" />
+        <el-table-column label="瀹℃壒浜�" align="center" prop="approval" width="120" />
+        <el-table-column label="瀹℃壒鏃堕棿" align="center" prop="approvalTime" width="180" />
+        <el-table-column label="鍙戞斁鏃堕棿" align="center" prop="issueTime" width="180" />
+        <el-table-column label="鎿嶄綔" align="center" fixed="right" class-name="small-padding fixed-width" width="200">
+          <template #default="scope">
+            <el-button
+              v-if="scope.row.status === 1"
+              type="primary"
+              link
+              @click="handleApprove(scope.row)"
+            >
+              瀹℃壒
+            </el-button>
+            <el-button
+              v-if="scope.row.status === 3"
+              type="success"
+							link
+              @click="handleIssue(scope.row)"
+            >
+              鍙戞斁
+            </el-button>
+            <el-button
+              type="info"
+							link
+              @click="handleDetail(scope.row)"
+            >
+              璇︽儏
+            </el-button>
+            <el-button
+              v-if="scope.row.status === 2"
+              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
+      v-model="showApplyDialog"
+      title="鍔炲叕鐗╄祫鐢宠"
+      width="600px"
+      append-to-body
+    >
+      <el-form ref="applyFormRef" :model="applyForm" :rules="applyRules" label-width="100px">
+        <el-form-item label="鐢宠浜�" prop="applicant">
+          <el-input v-model="applyForm.applicant" placeholder="璇疯緭鍏ョ敵璇蜂汉鍚嶇О" />
+        </el-form-item>
+        <el-form-item label="閮ㄩ棬" prop="dept">
+          <el-input v-model="applyForm.dept" placeholder="璇疯緭鍏ラ儴闂ㄥ悕绉�" />
+        </el-form-item>
+        <el-form-item label="鐗╄祫绫诲瀷" prop="materialType">
+          <el-select v-model="applyForm.materialType" placeholder="璇烽�夋嫨鐗╄祫绫诲瀷" style="width: 100%">
+            <el-option label="鍔炲叕鐢ㄥ搧" value="4" />
+            <el-option label="鐢靛瓙璁惧" value="3" />
+            <el-option label="娓呮磥鐢ㄥ搧" value="2" />
+            <el-option label="鍏朵粬" value="1" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="鍏蜂綋鐗╁搧" prop="itemName">
+          <el-input v-model="applyForm.itemName" placeholder="璇疯緭鍏ュ叿浣撶墿鍝佸悕绉�" />
+        </el-form-item>
+        <el-form-item label="鐢宠鏁伴噺" prop="applyNum">
+          <el-input-number v-model="applyForm.applyNum" :min="1" :max="999" style="width: 100%" />
+        </el-form-item>
+        <el-form-item label="鐢宠鍘熷洜" prop="reason">
+          <el-input
+            v-model="applyForm.reason"
+            type="textarea"
+            :rows="3"
+            placeholder="璇疯緭鍏ョ敵璇峰師鍥�"
+          />
+        </el-form-item>
+        <el-form-item label="绱ф�ョ▼搴�" prop="urgency">
+          <el-radio-group v-model="applyForm.urgency">
+            <el-radio label="1">鏅��</el-radio>
+            <el-radio label="2">绱ф��</el-radio>
+            <el-radio label="3">闈炲父绱ф��</el-radio>
+          </el-radio-group>
+        </el-form-item>
+      </el-form>
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button @click="showApplyDialog = false">鍙� 娑�</el-button>
+          <el-button type="primary" @click="submitApply">纭� 瀹�</el-button>
+        </div>
+      </template>
+    </el-dialog>
+
+    <!-- 瀹℃壒瀵硅瘽妗� -->
+    <el-dialog
+      v-model="showApproveDialog"
+      title="瀹℃壒鐢宠"
+      width="500px"
+      append-to-body
+    >
+      <el-form ref="approveFormRef" :model="approveForm" :rules="approveRules" label-width="100px">
+        <el-form-item label="瀹℃壒缁撴灉" prop="approveResult">
+          <el-radio-group v-model="approveForm.approveResult">
+            <el-radio label="3">閫氳繃</el-radio>
+            <el-radio label="2">鎷掔粷</el-radio>
+          </el-radio-group>
+        </el-form-item>
+        <el-form-item label="瀹℃壒鎰忚" prop="approvalOpinions">
+          <el-input
+            v-model="approveForm.approvalOpinions"
+            type="textarea"
+            :rows="3"
+            placeholder="璇疯緭鍏ュ鎵规剰瑙�"
+          />
+        </el-form-item>
+      </el-form>
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button @click="showApproveDialog = false">鍙� 娑�</el-button>
+          <el-button type="primary" @click="submitApprove">纭� 瀹�</el-button>
+        </div>
+      </template>
+    </el-dialog>
+
+    <!-- 璇︽儏瀵硅瘽妗� -->
+    <el-dialog
+      v-model="showDetailDialog"
+      title="鐢宠璇︽儏"
+      width="700px"
+      append-to-body
+    >
+      <el-descriptions :column="2" border>
+        <el-descriptions-item label="鐢宠缂栧彿">{{ currentDetail.code }}</el-descriptions-item>
+        <el-descriptions-item label="鐢宠浜�">{{ currentDetail.applicant }}</el-descriptions-item>
+        <el-descriptions-item label="閮ㄩ棬">{{ currentDetail.dept }}</el-descriptions-item>
+        <el-descriptions-item label="鐗╄祫绫诲瀷">{{ currentDetail.materialType }}</el-descriptions-item>
+        <el-descriptions-item label="鍏蜂綋鐗╁搧">{{ currentDetail.itemName }}</el-descriptions-item>
+        <el-descriptions-item label="鐢宠鏁伴噺">{{ currentDetail.applyNum }}</el-descriptions-item>
+        <el-descriptions-item label="鐢宠鍘熷洜" :span="2">{{ currentDetail.reason }}</el-descriptions-item>
+        <el-descriptions-item label="鐢宠鐘舵��">
+          <el-tag :type="getStatusType(currentDetail.status)">
+            {{ getStatusText(currentDetail.status) }}
+          </el-tag>
+        </el-descriptions-item>
+        <el-descriptions-item label="鐢宠鏃堕棿">{{ currentDetail.applyTime }}</el-descriptions-item>
+        <el-descriptions-item label="瀹℃壒浜�">{{ currentDetail.approval || '-' }}</el-descriptions-item>
+        <el-descriptions-item label="瀹℃壒鏃堕棿">{{ currentDetail.approvalTime || '-' }}</el-descriptions-item>
+        <el-descriptions-item label="瀹℃壒鎰忚" :span="2">{{ currentDetail.approvalOpinions || '-' }}</el-descriptions-item>
+        <el-descriptions-item label="鍙戞斁鏃堕棿">{{ currentDetail.issueTime || '-' }}</el-descriptions-item>
+        <el-descriptions-item label="鍙戞斁浜�">{{ currentDetail.issueUser || '-' }}</el-descriptions-item>
+      </el-descriptions>
+    </el-dialog>
+  </div>
+</template>
+
+<script setup>
+import {listPage,add,update,deleteOff} from "@/api/collaborativeApproval/officeSupplies.js"
+import {ref, reactive, onMounted, getCurrentInstance} from 'vue'
+import Cookies from 'js-cookie'
+import { ElMessage, ElMessageBox } from 'element-plus'
+import { Plus, Search, Refresh, Download, Check } from '@element-plus/icons-vue'
+
+// 鍝嶅簲寮忔暟鎹�
+const loading = ref(false)
+const showSearch = ref(true)
+const showApplyDialog = ref(false)
+const showApproveDialog = ref(false)
+const showDetailDialog = ref(false)
+const multipleSelection = ref([])
+const officeList = ref([])
+const total = ref(0)
+const suppliesList = ref([])
+const currentDetail = ref({})
+
+// 鏌ヨ鍙傛暟
+const queryParams = reactive({
+  current: 1,
+  size: 10,
+  code: '',
+  applicant: '',
+  status: ''
+})
+
+// 鐢宠琛ㄥ崟
+const applyForm = reactive({
+  applicant: '',
+  dept: '',
+  materialType: '',
+  itemName: '',
+  applyNum: 1,
+  reason: '',
+  urgency: '1'
+})
+
+// 瀹℃壒琛ㄥ崟
+const approveForm = reactive({
+  approveResult: '3',
+  approvalOpinions: ''
+})
+
+// 琛ㄥ崟鏍¢獙瑙勫垯
+const applyRules = {
+  applicant: [{ required: true, message: '璇烽�夋嫨鐗╄祫绫诲瀷', trigger: 'blur' }],
+  dept: [{ required: true, message: '璇烽�夋嫨鐗╄祫绫诲瀷', trigger: 'blur' }],
+  materialType: [{ required: true, message: '璇烽�夋嫨鐗╄祫绫诲瀷', trigger: 'change' }],
+  itemName: [{ required: true, message: '璇疯緭鍏ュ叿浣撶墿鍝佸悕绉�', trigger: 'blur' }],
+  applyNum: [{ required: true, message: '璇疯緭鍏ョ敵璇锋暟閲�', trigger: 'blur' }],
+  reason: [{ required: true, message: '璇疯緭鍏ョ敵璇峰師鍥�', trigger: 'blur' }]
+}
+
+const approveRules = {
+  approveResult: [{ required: true, message: '璇烽�夋嫨瀹℃壒缁撴灉', trigger: 'change' }],
+  approvalOpinions: [{ required: true, message: '璇疯緭鍏ュ鎵规剰瑙�', trigger: 'blur' }]
+}
+
+const openShow = () => {
+  showApplyDialog.value = true
+  resetApplyForm()
+}
+
+// 鑾峰彇鍒楄〃鏁版嵁
+const getList = () => {
+  loading.value = true
+  listPage(queryParams).then(res => {
+    total.value = res.data.total
+    loading.value = false
+    officeList.value = res.data.records
+  })
+}
+
+// 鏌ヨ
+const handleQuery = () => {
+  queryParams.current = 1
+  getList()
+}
+
+// 閲嶇疆鏌ヨ
+const resetQuery = () => {
+  queryParams.code = ''
+  queryParams.applicant = ''
+  queryParams.status = ''
+  handleQuery()
+}
+
+// 澶氶��
+const handleSelectionChange = (selection) => {
+  multipleSelection.value = selection
+}
+
+// 鑾峰彇鐘舵�佺被鍨�
+const getStatusType = (status) => {
+  const statusMap = {
+    1: 'warning',
+    3: 'success',
+    2: 'danger',
+    4: 'info'
+  }
+  return statusMap[status] || 'info'
+}
+
+// 鑾峰彇鐘舵�佹枃鏈�
+const getStatusText = (status) => {
+  const statusMap = {
+    1: '寰呭鎵�',
+    3: '宸查�氳繃',
+    2: '宸叉嫆缁�',
+    4: '宸插彂鏀�'
+  }
+  return statusMap[status] || status
+}
+
+// 鎻愪氦鐢宠
+const submitApply = () => {
+  add(applyForm).then(() => {
+    ElMessage.success('鐢宠鎴愬姛')
+    getList()
+    showApplyDialog.value = false
+    resetApplyForm()
+  })
+
+  
+
+}
+
+//閲嶇疆琛ㄥ崟
+const resetApplyForm = () => {
+  // 閲嶇疆琛ㄥ崟
+  Object.assign(applyForm, {
+    applicant: '',
+    dept: '',
+    materialType: '',
+    itemName: '',
+    applyNum: 1,
+    reason: '',
+    urgency: '1'
+  })
+}
+
+// 瀹℃壒
+const handleApprove = (row) => {
+  currentDetail.value = row
+  showApproveDialog.value = true
+}
+
+const formatDate = (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 sends = String(date.getSeconds()).padStart(2, '0')
+  return `${year}-${month}-${day} ${hours}:${minutes}:${sends}`
+}
+
+// 鎻愪氦瀹℃壒
+const submitApprove = () => {
+  currentDetail.value.status = approveForm.approveResult
+  // 浠巆ookie涓幏鍙栧綋鍓嶇櫥褰曠敤鎴峰悕绉�
+  currentDetail.value.approval = Cookies.get('username')
+  currentDetail.value.approvalTime = formatDate(new Date())
+  currentDetail.value.approvalOpinions = approveForm.approvalOpinions
+  update(currentDetail.value).then((res) => {
+    if(res.code === 200){
+      showApproveDialog.value = false
+      ElMessage.success('瀹℃壒瀹屾垚')
+      getList()
+
+      // 閲嶇疆琛ㄥ崟
+      Object.assign(approveForm, {
+        approveResult: '3',
+        approvalOpinions: ''
+      })
+    }
+  })
+
+}
+
+// 鍙戞斁
+const handleIssue = (row) => {
+  row.status = 4
+  row.issueTime = formatDate(new Date())
+  row.issueUser = Cookies.get('username')
+  update(row).then((res) =>{
+    if(res.code === 200){
+      ElMessage.success('鍙戞斁瀹屾垚')
+      getList()
+    }
+  })
+}
+
+// 鏌ョ湅璇︽儏
+const handleDetail = (row) => {
+  currentDetail.value = row
+  showDetailDialog.value = true
+}
+
+// 鍒犻櫎
+const handleDelete = (row) => {
+  ElMessageBox.confirm('纭鍒犻櫎璇ョ敵璇峰悧锛�', '鎻愮ず', {
+    confirmButtonText: '纭畾',
+    cancelButtonText: '鍙栨秷',
+    type: 'warning'
+  }).then(() => {
+    let ids = [row.id]
+    deleteOff(ids).then((res) =>{
+      ElMessage.success('鍒犻櫎鎴愬姛')
+      getList()
+    })
+  })
+}
+const { proxy } = getCurrentInstance();
+// 瀵煎嚭
+const handleExport = () => {
+  ElMessageBox.confirm("鎵�鏈夌殑鍐呭灏嗚瀵煎嚭锛屾槸鍚︾‘璁ゅ鍑猴紵", "瀵煎嚭", {
+    confirmButtonText: "纭",
+    cancelButtonText: "鍙栨秷",
+    type: "warning",
+  })
+      .then(() => {
+        proxy.download("/officeSupplies/export", {}, "鍔炲叕鐗╄祫.xlsx");
+      })
+      .catch(() => {
+        proxy.$modal.msg("宸插彇娑�");
+      });
+}
+
+// 椤甸潰鍔犺浇鏃惰幏鍙栨暟鎹�
+onMounted(() => {
+  getList()
+})
+</script>
+
+<style scoped>
+.app-container {
+  padding: 20px;
+}
+
+.card-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+}
+
+.mb8 {
+  margin-bottom: 8px;
+}
+
+.dialog-footer {
+  text-align: right;
+}
+
+:deep(.el-descriptions__label) {
+  width: 120px;
+}
+</style>
diff --git a/src/views/collaborativeApproval/planTemplate/index.vue b/src/views/collaborativeApproval/planTemplate/index.vue
new file mode 100644
index 0000000..0af6d8b
--- /dev/null
+++ b/src/views/collaborativeApproval/planTemplate/index.vue
@@ -0,0 +1,867 @@
+<template>
+  <div class="app-container">
+    <!-- 椤堕儴鎿嶄綔鏍� -->
+    <div class="header-actions">
+      <div class="left-actions">
+        <el-select v-model="currentLevel" placeholder="閫夋嫨璁″垝绾у埆" style="width: 150px" @change="handleLevelChange">
+          <el-option label="涓汉璁″垝" value="personal" />
+          <el-option label="灏忕粍璁″垝" value="group" />
+          <el-option label="閮ㄩ棬璁″垝" value="department" />
+          <el-option label="鍏徃璁″垝" value="company" />
+        </el-select>
+        <el-select v-model="currentPeriod" placeholder="閫夋嫨鏃堕棿鍛ㄦ湡" style="width: 120px; margin-left: 10px" @change="handlePeriodChange">
+          <el-option label="鍛ㄨ鍒�" value="week" />
+          <el-option label="鏈堣鍒�" value="month" />
+          <el-option label="骞磋鍒�" value="year" />
+        </el-select>
+        <el-date-picker
+          v-model="currentDate"
+          :type="datePickerType"
+          placeholder="閫夋嫨鏃ユ湡"
+          format="YYYY-MM-DD"
+          value-format="YYYY-MM-DD"
+          style="width: 180px; margin-left: 10px"
+          @change="handleDateChange"
+        />
+      </div>
+      <div class="right-actions">
+        <el-button type="primary" @click="handleAddPlan">鏂板璁″垝</el-button>
+        <el-button @click="handleExport">瀵煎嚭璁″垝</el-button>
+        <!-- <el-button @click="handleShare">鍏变韩璁″垝@</el-button> -->
+      </div>
+    </div>
+
+    <!-- 璁″垝姒傝鍗$墖 -->
+    <div class="overview-cards">
+      <el-row :gutter="20">
+        <el-col :span="6">
+          <el-card class="overview-card">
+            <div class="card-content">
+              <div class="card-icon personal">
+                <el-icon><User /></el-icon>
+              </div>
+              <div class="card-info">
+                <div class="card-title">涓汉璁″垝</div>
+                <div class="card-number">{{ overviewData.personal.total }}</div>
+                <div class="card-progress">
+                  <el-progress :percentage="overviewData.personal.completion" :stroke-width="6" />
+                </div>
+              </div>
+            </div>
+          </el-card>
+        </el-col>
+        <el-col :span="6">
+          <el-card class="overview-card">
+            <div class="card-content">
+              <div class="card-icon group">
+                <el-icon><UserFilled /></el-icon>
+              </div>
+              <div class="card-info">
+                <div class="card-title">灏忕粍璁″垝</div>
+                <div class="card-number">{{ overviewData.group.total }}</div>
+                <div class="card-progress">
+                  <el-progress :percentage="overviewData.group.completion" :stroke-width="6" />
+                </div>
+              </div>
+            </div>
+          </el-card>
+        </el-col>
+        <el-col :span="6">
+          <el-card class="overview-card">
+            <div class="card-content">
+              <div class="card-icon department">
+                <el-icon><OfficeBuilding /></el-icon>
+              </div>
+              <div class="card-info">
+                <div class="card-title">閮ㄩ棬璁″垝</div>
+                <div class="card-number">{{ overviewData.department.total }}</div>
+                <div class="card-progress">
+                  <el-progress :percentage="overviewData.department.completion" :stroke-width="6" />
+                </div>
+              </div>
+            </div>
+          </el-card>
+        </el-col>
+        <el-col :span="6">
+          <el-card class="overview-card">
+            <div class="card-content">
+              <div class="card-icon company">
+                <el-icon><House /></el-icon>
+              </div>
+              <div class="card-info">
+                <div class="card-title">鍏徃璁″垝</div>
+                <div class="card-number">{{ overviewData.company.total }}</div>
+                <div class="card-progress">
+                  <el-progress :percentage="overviewData.company.completion" :stroke-width="6" />
+                </div>
+              </div>
+            </div>
+          </el-card>
+        </el-col>
+      </el-row>
+    </div>
+
+    <!-- 璁″垝鍒楄〃 -->
+    <div class="plan-content">
+      <el-card>
+        <template #header>
+          <div class="card-header">
+            <span>{{ getCurrentLevelText() }} - {{ getCurrentPeriodText() }}</span>
+            <div>
+              <el-button size="small" @click="handleRefresh">鍒锋柊</el-button>
+              <!-- <el-button size="small" @click="handleFilter">绛涢�堾</el-button> -->
+            </div>
+          </div>
+        </template>
+        
+        <div class="plan-list">
+          <div v-for="plan in planList" :key="plan.id" class="plan-item">
+            <div class="plan-header">
+              <div class="plan-title">
+                <el-tag :type="getPriorityType(plan.priority)" size="small">{{ getPriorityText(plan.priority) }}</el-tag>
+                <span class="title-text">{{ plan.title }}</span>
+              </div>
+              <div class="plan-actions">
+                <el-button size="small" @click="handleEditPlan(plan)">缂栬緫</el-button>
+                <el-button size="small" @click="handleViewDetail(plan)">璇︽儏</el-button>
+                <el-dropdown @command="(command) => handleMoreAction(plan, command)">
+                  <el-button size="small">
+                    鏇村<el-icon class="el-icon--right"><ArrowDown /></el-icon>
+                  </el-button>
+                  <template #dropdown>
+                    <el-dropdown-menu>
+                      <!-- <el-dropdown-item command="share">鍏变韩@</el-dropdown-item> -->
+                      <el-dropdown-item command="copy">澶嶅埗</el-dropdown-item>
+                      <el-dropdown-item command="delete" divided>鍒犻櫎</el-dropdown-item>
+                    </el-dropdown-menu>
+                  </template>
+                </el-dropdown>
+              </div>
+            </div>
+            
+            <div class="plan-content">
+              <div class="plan-description">{{ plan.description }}</div>
+              <div class="plan-meta">
+                <div class="meta-item">
+                  <el-icon><Calendar /></el-icon>
+                  <span>{{ plan.startDate }} - {{ plan.endDate }}</span>
+                </div>
+                <div class="meta-item">
+                  <el-icon><User /></el-icon>
+                  <span>{{ plan.assignee }}</span>
+                </div>
+                <div class="meta-item">
+                  <el-icon><Clock /></el-icon>
+                  <span>杩涘害: {{ plan.progress }}%</span>
+                </div>
+                <div class="meta-item">
+                  <el-icon><Flag /></el-icon>
+                  <span>{{ getStatusText(plan.status) }}</span>
+                </div>
+              </div>
+              
+              <div class="plan-progress">
+                <el-progress 
+                  :percentage="plan.progress" 
+                  :color="getProgressColor(plan.progress)"
+                  :stroke-width="8"
+                />
+              </div>
+              
+              <div class="plan-tags">
+                <el-tag v-for="tag in plan.tags" :key="tag" size="small" style="margin-right: 5px">
+                  {{ tag }}
+                </el-tag>
+              </div>
+            </div>
+          </div>
+        </div>
+      </el-card>
+    </div>
+
+    <!-- 鏂板/缂栬緫璁″垝瀵硅瘽妗� -->
+    <el-dialog
+      v-model="planDialogVisible"
+      :title="operationType === 'add' ? '鍙戝竷璁″垝' : '缂栬緫璁″垝'"
+      width="600px"
+      @close="handleDialogClose"
+    >
+      <el-form :model="planForm" :rules="planRules" ref="planFormRef" label-width="100px">
+        <el-form-item label="璁″垝鏍囬" prop="title">
+          <el-input v-model="planForm.title" placeholder="璇疯緭鍏ヨ鍒掓爣棰�" />
+        </el-form-item>
+        <el-form-item label="璁″垝鎻忚堪" prop="description">
+          <el-input
+            v-model="planForm.description"
+            type="textarea"
+            :rows="3"
+            placeholder="璇疯緭鍏ヨ鍒掓弿杩�"
+          />
+        </el-form-item>
+        <el-form-item label="璁″垝绾у埆" prop="level">
+          <el-select v-model="planForm.level" placeholder="閫夋嫨璁″垝绾у埆" style="width: 100%">
+            <el-option label="涓汉璁″垝" value="personal" />
+            <el-option label="灏忕粍璁″垝" value="group" />
+            <el-option label="閮ㄩ棬璁″垝" value="department" />
+            <el-option label="鍏徃璁″垝" value="company" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="鏃堕棿鍛ㄦ湡" prop="period">
+          <el-select v-model="planForm.period" placeholder="閫夋嫨鏃堕棿鍛ㄦ湡" style="width: 100%">
+            <el-option label="鍛ㄨ鍒�" value="week" />
+            <el-option label="鏈堣鍒�" value="month" />
+            <el-option label="骞磋鍒�" value="year" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="寮�濮嬫椂闂�" prop="startDate">
+          <el-date-picker
+            v-model="planForm.startDate"
+            type="date"
+            value-format="YYYY-MM-DD"
+            format="YYYY-MM-DD"
+            placeholder="閫夋嫨寮�濮嬫椂闂�"
+            style="width: 100%"
+          />
+        </el-form-item>
+        <el-form-item label="缁撴潫鏃堕棿" prop="endDate">
+          <el-date-picker
+            v-model="planForm.endDate"
+            type="date"
+            value-format="YYYY-MM-DD"
+            format="YYYY-MM-DD"
+            placeholder="閫夋嫨缁撴潫鏃堕棿"
+            style="width: 100%"
+          />
+        </el-form-item>
+        <el-form-item label="璐熻矗浜�" prop="assignee">
+          <el-input v-model="planForm.assignee" placeholder="璇疯緭鍏ヨ礋璐d汉" />
+        </el-form-item>
+        <el-form-item label="浼樺厛绾�" prop="priority">
+          <el-select v-model="planForm.priority" placeholder="閫夋嫨浼樺厛绾�" style="width: 100%">
+            <el-option label="楂�" value="high" />
+            <el-option label="涓�" value="medium" />
+            <el-option label="浣�" value="low" />
+          </el-select>
+        </el-form-item>
+        <!-- <el-form-item label="鏍囩">
+          <el-input v-model="planForm.tags" placeholder="璇疯緭鍏ユ爣绛撅紝鐢ㄩ�楀彿鍒嗛殧" />
+        </el-form-item> -->
+        <el-form-item label="鏍囩" prop="tags">
+          <!-- <el-checkbox-group v-model="planForm.tags">
+            <el-checkbox label="all"></el-checkbox>
+            <el-checkbox label="manager">绠$悊灞�</el-checkbox>
+            <el-checkbox label="hr">浜轰簨閮ㄩ棬</el-checkbox>
+            <el-checkbox label="finance">璐㈠姟閮ㄩ棬</el-checkbox>
+            <el-checkbox label="tech">鎶�鏈儴闂�</el-checkbox>
+          </el-checkbox-group> -->
+          <el-select
+            v-model="planForm.tags"
+            multiple
+            placeholder="璇烽�夋嫨鏍囩"
+            style="width: 100%"
+          >
+            <el-option
+              v-for="dept in departments"
+              :key="dept"
+              :label="dept"
+              :value="dept"
+            />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="鐘舵��" prop="status">
+          <el-select v-model="planForm.status" placeholder="閫夋嫨鐘舵��" style="width: 100%">
+            <el-option label="鏈紑濮�" value="not_started" />
+            <el-option label="杩涜涓�" value="in_progress" />
+            <el-option label="宸插畬鎴�" value="completed" />
+            <el-option label="宸叉殏鍋�" value="paused" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="杩涘害" prop="progress">
+          <el-input-number
+            v-model="planForm.progress"
+            min="0"
+            max="100"
+            step="1"
+            placeholder="璇疯緭鍏ヨ繘搴�"
+            style="width: 100%"
+          />
+        </el-form-item>
+      </el-form>
+      <template #footer>
+        <span class="dialog-footer">
+          <el-button @click="planDialogVisible = false">鍙栨秷</el-button>
+          <el-button type="primary" @click="handleSavePlan">淇濆瓨</el-button>
+        </span>
+      </template>
+    </el-dialog>
+    <!-- 璁″垝璇︽儏瀵硅瘽妗� -->
+    <el-dialog v-model="showPlanDetailDialog" title="璁″垝璇︽儏" width="700px">
+      <div v-if="currentPlanDetail" class="mb10">
+        <el-descriptions :column="2" border>
+          <el-descriptions-item label="璁″垝鏍囬">{{ currentPlanDetail.title }}</el-descriptions-item>
+          <el-descriptions-item label="璁″垝鎻忚堪">{{ currentPlanDetail.description }}</el-descriptions-item>
+          <el-descriptions-item label="璁″垝绾у埆">{{ getCurrentLevelText(currentPlanDetail.level) }}</el-descriptions-item>
+          <el-descriptions-item label="鏃堕棿鍛ㄦ湡">{{ getCurrentPeriodText(currentPlanDetail.period) }}</el-descriptions-item>
+          <el-descriptions-item label="寮�濮嬫椂闂�">{{ currentPlanDetail.startDate }}</el-descriptions-item>
+          <el-descriptions-item label="缁撴潫鏃堕棿">{{ currentPlanDetail.endDate }}</el-descriptions-item>
+          <el-descriptions-item label="璐熻矗浜�">{{ currentPlanDetail.assignee }}</el-descriptions-item>
+          <el-descriptions-item label="浼樺厛绾�">{{ getPriorityText(currentPlanDetail.priority) }}</el-descriptions-item>
+          <el-descriptions-item label="鏍囩">{{ currentPlanDetail.tags.join(', ') }}</el-descriptions-item>
+          <el-descriptions-item label="鐘舵��">{{ getStatusText(currentPlanDetail.status) }}</el-descriptions-item>
+          <el-descriptions-item label="杩涘害">{{ currentPlanDetail.progress }}%</el-descriptions-item>
+        </el-descriptions>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script setup>
+import { ref, reactive, computed, onMounted } from 'vue'
+import { ElMessage, ElMessageBox } from 'element-plus'
+const { proxy } = getCurrentInstance();
+import {
+  User,
+  UserFilled,
+  OfficeBuilding,
+  House,
+  Calendar,
+  Clock,
+  Flag,
+  ArrowDown
+} from '@element-plus/icons-vue'
+import { listDutyPlan, addDutyPlan, updateDutyPlan, delDutyPlan,NumDutyPlan,exportDutyPlan } from '@/api/collaborativeApproval/planTemplate.js'
+
+// 鍝嶅簲寮忔暟鎹�
+const operationType = ref('add')
+const currentLevel = ref('personal')
+const currentPeriod = ref('week')
+const currentDate = ref(new Date())
+const planDialogVisible = ref(false)
+const dialogTitle = ref('鏂板璁″垝')
+const planFormRef = ref()
+const showPlanDetailDialog = ref(false)
+const currentPlanDetail = ref(null)
+
+// 琛ㄥ崟鏁版嵁
+const planForm = reactive({
+  id: '',
+  title: '',
+  description: '',
+  level: 'personal',
+  period: 'week',
+  startDate: '',
+  endDate: '',
+  assignee: '',
+  priority: 'medium',
+  tags: [],
+  status: '',
+  progress: 0
+})
+
+// 琛ㄥ崟楠岃瘉瑙勫垯
+const planRules = {
+  title: [{ required: true, message: '璇疯緭鍏ヨ鍒掓爣棰�', trigger: 'blur' }],
+  description: [{ required: true, message: '璇疯緭鍏ヨ鍒掓弿杩�', trigger: 'blur' }],
+  level: [{ required: true, message: '璇烽�夋嫨璁″垝绾у埆', trigger: 'change' }],
+  period: [{ required: true, message: '璇烽�夋嫨鏃堕棿鍛ㄦ湡', trigger: 'change' }],
+  startDate: [{ required: true, message: '璇烽�夋嫨寮�濮嬫椂闂�', trigger: 'change' }],
+  endDate: [{ required: true, message: '璇烽�夋嫨缁撴潫鏃堕棿', trigger: 'change' }],
+  assignee: [{ required: true, message: '璇疯緭鍏ヨ礋璐d汉', trigger: 'blur' }],
+  priority: [{ required: true, message: '璇烽�夋嫨浼樺厛绾�', trigger: 'change' }]
+}
+const departments = ["浜у搧", "鍒嗘瀽", "璋冪爺",'鎶�鏈�', '鏋舵瀯', '璁捐','甯傚満', '鎺ㄥ箍', '钀ラ攢'];
+// 姒傝鏁版嵁
+const overviewData = reactive({
+  personal: { total: 0, completion: 0 },
+  group: { total: 0, completion: 0 },
+  department: { total: 0, completion: 0 },
+  company: { total: 0, completion: 0 }
+})
+
+// 璁″垝鍒楄〃鏁版嵁
+const planList = ref([])
+
+// 璁$畻灞炴��
+const datePickerType = computed(() => {
+  switch (currentPeriod.value) {
+    case 'week':
+      return 'week'
+    case 'month':
+      return 'month'
+    case 'year':
+      return 'year'
+    default:
+      return 'date'
+  }
+})
+
+// 鏂规硶
+const handleLevelChange = (value) => {
+  console.log('璁″垝绾у埆鍙樻洿:', value)
+  getPlanList()
+  // 杩欓噷鍙互鏍规嵁绾у埆绛涢�夋暟鎹�
+}
+
+const handlePeriodChange = (value) => {
+  console.log('鏃堕棿鍛ㄦ湡鍙樻洿:', value)
+  getPlanList()
+  // 杩欓噷鍙互鏍规嵁鍛ㄦ湡绛涢�夋暟鎹�
+}
+
+const handleDateChange = (value) => {
+  console.log('鏃ユ湡鍙樻洿:', value)
+  getPlanList()
+  // 杩欓噷鍙互鏍规嵁鏃ユ湡绛涢�夋暟鎹�
+}
+
+const handleAddPlan = () => {
+  operationType.value = 'add'
+  dialogTitle.value = '鏂板璁″垝'
+  planDialogVisible.value = true
+  // 閲嶇疆琛ㄥ崟
+  Object.keys(planForm).forEach(key => {
+    planForm[key] = ''
+  })
+  planForm.level = 'personal'
+  planForm.period = 'week'
+  planForm.priority = 'medium'
+  planForm.status = 'not_started'
+  planForm.progress = 0
+}
+
+const handleEditPlan = (plan) => {
+  operationType.value = 'edit'
+  dialogTitle.value = '缂栬緫璁″垝'
+  planDialogVisible.value = true
+  Object.assign(planForm, plan)
+  // // 濉厖琛ㄥ崟鏁版嵁
+  // Object.keys(planForm).forEach(key => {
+  //   if (key === 'tags') {
+  //     planForm[key] = plan[key].join(', ')
+  //   } else {
+  //     planForm[key] = plan[key]
+  //   }
+  // })
+}
+
+const handleViewDetail = (plan) => {
+  currentPlanDetail.value = plan
+  showPlanDetailDialog.value = true
+  // ElMessage.info(`鏌ョ湅璁″垝璇︽儏: ${plan.title}`)
+}
+
+const handleMoreAction = async(plan,command) => {
+  let ids = [];
+  ids.push(plan.id);
+  console.log("ids",ids)
+  switch (command) {
+    case 'share':
+      ElMessage.success('璁″垝宸插叡浜�')
+      break
+    case 'copy':
+      const knowledgeText = `
+        璁″垝鏍囬锛�${plan.title}
+        璁″垝鎻忚堪锛�${plan.description}
+        璁″垝绾у埆锛�${getCurrentLevelText(plan.level)}
+        鏃堕棿鍛ㄦ湡锛�${getCurrentPeriodText(plan.period)}
+        寮�濮嬫椂闂达細${plan.startDate}
+        缁撴潫鏃堕棿锛�${plan.endDate}
+        璐熻矗浜猴細${plan.assignee}
+        浼樺厛绾э細${getPriorityText(plan.priority)}
+        鏍囩锛�${plan.tags.join(', ')}
+        鐘舵�侊細${getStatusText(plan.status)}
+        杩涘害锛�${plan.progress}%
+      `.trim();
+
+        // 澶嶅埗鍒板壀璐存澘
+        navigator.clipboard.writeText(knowledgeText).then(() => {
+          ElMessage.success("鐭ヨ瘑鍐呭宸插鍒跺埌鍓创鏉�");
+        }).catch(() => {
+          ElMessage.error("澶嶅埗澶辫触锛岃鎵嬪姩澶嶅埗");
+        });
+      // ElMessage.success('璁″垝宸插鍒�')
+      break
+    case 'delete':
+      ElMessageBox.confirm('纭畾瑕佸垹闄よ繖涓鍒掑悧锛�', '鎻愮ず', {
+        confirmButtonText: '纭畾',
+        cancelButtonText: '鍙栨秷',
+        type: 'warning'
+      }).then(() => {
+
+        delDutyPlan(ids).then(res => {
+          if (res.code === 200) {
+            ElMessage.success('璁″垝宸插垹闄�')
+            ids.value = [];
+            getPlanList()
+          }
+        })
+      })
+      break
+  }
+}
+//
+const handleSavePlan = async () => {
+  try {
+    await planFormRef.value.validate()
+    if (operationType.value === 'add') {
+      addDutyPlan(planForm).then(res => {
+        if (res.code === 200) {
+          ElMessage.success('璁″垝淇濆瓨鎴愬姛')
+          planDialogVisible.value = false
+        }
+        getPlanList()
+      })
+    } else {
+
+      updateDutyPlan(planForm).then(res => {
+        if (res.code === 200) {
+          ElMessage.success('璁″垝淇濆瓨鎴愬姛')
+          planDialogVisible.value = false
+        }
+        getPlanList()
+      })
+    }
+  } catch (error) {
+    console.log('琛ㄥ崟楠岃瘉澶辫触:', error)
+  }
+}
+
+const handleDialogClose = () => {
+  planFormRef.value?.resetFields()
+}
+
+const handleRefresh = () => {
+  getPlanList()
+  // ElMessage.success('鏁版嵁宸插埛鏂�')
+}
+
+const handleFilter = () => {
+  ElMessage.info('鎵撳紑绛涢�夐潰鏉�')
+}
+
+const handleExport = () => {
+  ElMessageBox.confirm("鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
+    confirmButtonText: "纭",
+    cancelButtonText: "鍙栨秷",
+    type: "warning",
+  })
+    .then(() => {
+      // exportDutyPlan().then(res => {
+        
+      // })
+      proxy.download("/dutyPlan/export", {}, "璁″垝绠$悊.xlsx");
+    })
+    .catch(() => {
+      proxy.$modal.msg("宸插彇娑�");
+    });
+};
+const handleShare = () => {
+  ElMessage.success('璁″垝宸插叡浜�')
+}
+
+const getCurrentLevelText = () => {
+  const levelMap = {
+    personal: '涓汉璁″垝',
+    group: '灏忕粍璁″垝',
+    department: '閮ㄩ棬璁″垝',
+    company: '鍏徃璁″垝'
+  }
+  return levelMap[currentLevel.value] || '涓汉璁″垝'
+}
+
+const getCurrentPeriodText = () => {
+  const periodMap = {
+    week: '鍛ㄨ鍒�',
+    month: '鏈堣鍒�',
+    year: '骞磋鍒�'
+  }
+  return periodMap[currentPeriod.value] || '鍛ㄨ鍒�'
+}
+
+const getPriorityType = (priority) => {
+  const typeMap = {
+    high: 'danger',
+    medium: 'warning',
+    low: 'info'
+  }
+  return typeMap[priority] || 'info'
+}
+
+const getPriorityText = (priority) => {
+  const textMap = {
+    high: '楂�',
+    medium: '涓�',
+    low: '浣�'
+  }
+  return textMap[priority] || '涓�'
+}
+
+const getStatusText = (status) => {
+  const statusMap = {
+    not_started: '鏈紑濮�',
+    in_progress: '杩涜涓�',
+    completed: '宸插畬鎴�',
+    paused: '宸叉殏鍋�'
+  }
+  return statusMap[status] || '鏈煡'
+}
+
+const getProgressColor = (progress) => {
+  if (progress >= 80) return '#67C23A'
+  if (progress >= 50) return '#E6A23C'
+  return '#F56C6C'
+}
+//鑾峰彇鏁版嵁鍒楄〃
+const getPlanList = async () => {
+  const params = {
+    level: currentLevel.value,
+    period: currentPeriod.value,
+    queryDate:currentDate.value
+  }
+  listDutyPlan(params).then(res => {
+    if (res.code === 200) {
+      planList.value = res.data.records
+    }
+  }).catch(err => {
+    console.log(err)
+  })
+}
+//鑾峰彇鏁版嵁
+const getPlanNum = async () => {
+  NumDutyPlan().then(res => {
+    if (res.code === 200) {
+      // console.log(res.data)
+      //璁茬粨鏋滈噷闈㈢殑鏁版嵁鏍规嵁level 璧嬪�肩粰overviewData
+      res.data.forEach(item => {
+        overviewData[item.level].total = item.num
+        overviewData[item.level].completion = item.completion
+      })
+      
+    }
+  }).catch(err => {
+    console.log(err)
+  })
+}
+
+onMounted(() => {
+  getPlanList()
+  getPlanNum()
+  console.log('澶氱骇璁″垝妯℃澘椤甸潰宸插姞杞�')
+})
+</script>
+
+<style scoped>
+.app-container {
+  padding: 20px;
+  background-color: #f5f5f5;
+  min-height: 100vh;
+}
+
+.header-actions {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  margin-bottom: 20px;
+  background: white;
+  padding: 20px;
+  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+}
+
+.left-actions {
+  display: flex;
+  align-items: center;
+}
+
+.right-actions {
+  display: flex;
+  gap: 10px;
+}
+
+.overview-cards {
+  margin-bottom: 20px;
+}
+
+.overview-card {
+  height: 120px;
+}
+
+.card-content {
+  display: flex;
+  align-items: center;
+  height: 100%;
+}
+
+.card-icon {
+  width: 60px;
+  height: 60px;
+  border-radius: 50%;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  margin-right: 15px;
+  font-size: 24px;
+  color: white;
+}
+
+.card-icon.personal {
+  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+}
+
+.card-icon.group {
+  background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
+}
+
+.card-icon.department {
+  background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
+}
+
+.card-icon.company {
+  background: linear-gradient(135deg, #43e97b 0%, #38f9d7 100%);
+}
+
+.card-info {
+  flex: 1;
+}
+
+.card-title {
+  font-size: 14px;
+  color: #666;
+  margin-bottom: 5px;
+}
+
+.card-number {
+  font-size: 24px;
+  font-weight: bold;
+  color: #333;
+  margin-bottom: 10px;
+}
+
+.card-progress {
+  width: 100%;
+}
+
+.plan-content {
+  background: white;
+  border-radius: 8px;
+  overflow: hidden;
+}
+
+.card-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  font-weight: bold;
+  color: #333;
+}
+
+.header-actions {
+  display: flex;
+  gap: 10px;
+}
+
+.plan-list {
+  padding: 20px 0;
+}
+
+.plan-item {
+  border: 1px solid #e4e7ed;
+  border-radius: 8px;
+  margin-bottom: 15px;
+  padding: 20px;
+  transition: all 0.3s ease;
+}
+
+.plan-item:hover {
+  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
+  transform: translateY(-2px);
+}
+
+.plan-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  margin-bottom: 15px;
+}
+
+.plan-title {
+  display: flex;
+  align-items: center;
+  gap: 10px;
+}
+
+.title-text {
+  font-size: 16px;
+  font-weight: bold;
+  color: #333;
+}
+
+.plan-actions {
+  display: flex;
+  gap: 10px;
+}
+
+.plan-content {
+  margin-bottom: 15px;
+}
+
+.plan-description {
+  color: #666;
+  margin-bottom: 15px;
+  line-height: 1.6;
+}
+
+.plan-meta {
+  display: flex;
+  flex-wrap: wrap;
+  gap: 20px;
+  margin-bottom: 15px;
+}
+
+.meta-item {
+  display: flex;
+  align-items: center;
+  gap: 5px;
+  color: #666;
+  font-size: 14px;
+}
+
+.plan-progress {
+  margin-bottom: 15px;
+}
+
+.plan-tags {
+  display: flex;
+  flex-wrap: wrap;
+  gap: 5px;
+}
+
+.dialog-footer {
+  display: flex;
+  justify-content: flex-end;
+  gap: 10px;
+}
+
+/* 鍝嶅簲寮忚璁� */
+@media (max-width: 768px) {
+  .header-actions {
+    flex-direction: column;
+    gap: 15px;
+  }
+  
+  .left-actions {
+    flex-wrap: wrap;
+    gap: 10px;
+  }
+  
+  .plan-meta {
+    flex-direction: column;
+    gap: 10px;
+  }
+  
+  .plan-header {
+    flex-direction: column;
+    align-items: flex-start;
+    gap: 10px;
+  }
+}
+</style>
diff --git a/src/views/collaborativeApproval/processTracking/index.vue b/src/views/collaborativeApproval/processTracking/index.vue
new file mode 100644
index 0000000..67f5106
--- /dev/null
+++ b/src/views/collaborativeApproval/processTracking/index.vue
@@ -0,0 +1,498 @@
+<template>
+  <div class="process-tracking">
+    <div class="header">
+      <h2>杩囩▼杩借釜</h2>
+      <el-button type="primary" @click="refreshData">鍒锋柊鏁版嵁</el-button>
+    </div>
+
+    <!-- 椤圭洰鐘舵�佺粺璁� -->
+    <div class="status-cards">
+      <el-row :gutter="20">
+        <el-col :span="6" v-for="(item, index) in statusStats" :key="index">
+          <el-card class="status-card" :class="item.type">
+            <div class="card-content">
+              <div class="card-icon">
+                <el-icon :size="24">
+                  <component :is="item.icon" />
+                </el-icon>
+              </div>
+              <div class="card-info">
+                <div class="card-title">{{ item.label }}</div>
+                <div class="card-count">{{ item.count }}</div>
+              </div>
+            </div>
+          </el-card>
+        </el-col>
+      </el-row>
+    </div>
+
+    <!-- 椤圭洰鍒楄〃 -->
+    <el-card class="project-list">
+      <template #header>
+        <div class="card-header">
+          <span>椤圭洰鍒楄〃</span>
+          <el-button type="text" @click="toggleView">
+            {{ viewMode === 'table' ? '鍒囨崲鍒扮敇鐗瑰浘' : '鍒囨崲鍒板垪琛�' }}
+          </el-button>
+        </div>
+      </template>
+
+      <!-- 琛ㄦ牸瑙嗗浘 -->
+      <div v-if="viewMode === 'table'">
+        <el-table :data="projectList" style="width: 100%">
+          <el-table-column prop="name" label="椤圭洰鍚嶇О"  />
+          <el-table-column prop="manager" label="璐熻矗浜�"/>
+          <el-table-column label="鐘舵��" >
+            <template #default="{ row }">
+              <el-tag :type="getStatusType(row.status)">
+                {{ getStatusText(row.status) }}
+              </el-tag>
+            </template>
+          </el-table-column>
+          <el-table-column label="杩涘害" width="150">
+            <template #default="{ row }">
+              <el-progress :percentage="row.progress" :status="getProgressStatus(row.status)" />
+            </template>
+          </el-table-column>
+          <el-table-column prop="startDate" label="寮�濮嬫椂闂�" width="120" />
+          <el-table-column prop="endDate" label="缁撴潫鏃堕棿" width="120" />
+          <el-table-column label="鎿嶄綔" width="150">
+            <template #default="{ row }">
+              <el-button type="text" @click="updateStatus(row)">鏇存柊鐘舵��</el-button>
+              <el-button type="text" @click="viewDetails(row)">璇︽儏</el-button>
+            </template>
+          </el-table-column>
+        </el-table>
+      </div>
+
+      <!-- 鐢樼壒鍥捐鍥� -->
+      <div v-else class="gantt-container">
+        <div ref="ganttChart" style="width: 100%; height: 400px;"></div>
+      </div>
+    </el-card>
+
+    <!-- 鐘舵�佹洿鏂板璇濇 -->
+    <el-dialog v-model="statusDialogVisible" title="鏇存柊椤圭洰鐘舵��" width="400px">
+      <el-form :model="statusForm" label-width="80px">
+        <el-form-item label="椤圭洰鍚嶇О">
+          <el-input v-model="statusForm.name" disabled />
+        </el-form-item>
+        <el-form-item label="褰撳墠鐘舵��">
+          <el-select v-model="statusForm.status" placeholder="璇烽�夋嫨鐘舵��">
+            <el-option label="鏈紑濮�" value="not_started" />
+            <el-option label="杩涜涓�" value="in_progress" />
+            <el-option label="宸插畬鎴�" value="completed" />
+            <el-option label="寤舵湡" value="delayed" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="杩涘害">
+          <el-slider v-model="statusForm.progress" :max="100" />
+        </el-form-item>
+      </el-form>
+      <template #footer>
+        <el-button @click="statusDialogVisible = false">鍙栨秷</el-button>
+        <el-button type="primary" @click="confirmStatusUpdate">纭</el-button>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+
+<script setup>
+import { ref, reactive, onMounted, nextTick } from 'vue'
+import { ElMessage } from 'element-plus'
+import { Clock, Loading, Check, Warning } from '@element-plus/icons-vue'
+import * as echarts from 'echarts'
+
+// 鍝嶅簲寮忔暟鎹�
+const viewMode = ref('table')
+const statusDialogVisible = ref(false)
+const ganttChart = ref(null)
+let chartInstance = null
+
+// 鐘舵�佺粺璁℃暟鎹�
+const statusStats = reactive([
+  { label: '鏈紑濮�', count: 3, type: 'not-started', icon: Clock },
+  { label: '杩涜涓�', count: 5, type: 'in-progress', icon: Loading },
+  { label: '宸插畬鎴�', count: 8, type: 'completed', icon: Check },
+  { label: '寤舵湡', count: 2, type: 'delayed', icon: Warning }
+])
+
+// 椤圭洰鍒楄〃鏁版嵁
+const projectList = reactive([
+  {
+    id: 1,
+    name: '姹囨槦閽欎笟鐢熶骇绾挎墿寤洪」鐩�',
+    manager: '闄堝織寮�',
+    status: 'completed',
+    progress: 100,
+    startDate: '2024-01-01',
+    endDate: '2024-01-15'
+  },
+  {
+    id: 2,
+    name: '鏂板瀷鐜繚閽欑矇宸ヨ壓鐮斿彂',
+    manager: '鏋楅洩宄�',
+    status: 'in_progress',
+    progress: 75,
+    startDate: '2024-01-10',
+    endDate: '2024-01-25'
+  },
+  {
+    id: 3,
+    name: '姹囨槦閽欎笟ERP绯荤粺鍗囩骇',
+    manager: '鐜嬮泤鐞�',
+    status: 'in_progress',
+    progress: 60,
+    startDate: '2024-01-20',
+    endDate: '2024-02-10'
+  },
+  {
+    id: 4,
+    name: '鐭垮北寮�閲囪鍙瘉缁湡鐢宠',
+    manager: '璧典紵涓�',
+    status: 'in_progress',
+    progress: 45,
+    startDate: '2024-01-25',
+    endDate: '2024-02-15'
+  },
+  {
+    id: 5,
+    name: '鐜繚璁惧鍗囩骇鏀归��',
+    manager: '鏉庝匠娆�',
+    status: 'delayed',
+    progress: 30,
+    startDate: '2024-01-15',
+    endDate: '2024-01-30'
+  },
+  {
+    id: 6,
+    name: '骞村害瀹夊叏鐢熶骇鍩硅璁″垝',
+    manager: '寮犲缓鍥�',
+    status: 'not_started',
+    progress: 0,
+    startDate: '2024-02-01',
+    endDate: '2024-02-20'
+  }
+])
+
+// 鐘舵�佹洿鏂拌〃鍗�
+const statusForm = reactive({
+  id: null,
+  name: '',
+  status: '',
+  progress: 0
+})
+
+// 鑾峰彇鐘舵�佺被鍨�
+const getStatusType = (status) => {
+  const typeMap = {
+    not_started: 'info',
+    in_progress: 'warning',
+    completed: 'success',
+    delayed: 'danger'
+  }
+  return typeMap[status] || 'info'
+}
+
+// 鑾峰彇鐘舵�佹枃鏈�
+const getStatusText = (status) => {
+  const textMap = {
+    not_started: '鏈紑濮�',
+    in_progress: '杩涜涓�',
+    completed: '宸插畬鎴�',
+    delayed: '寤舵湡'
+  }
+  return textMap[status] || '鏈煡'
+}
+
+// 鑾峰彇杩涘害鐘舵��
+const getProgressStatus = (status) => {
+  if (status === 'completed') return 'success'
+  if (status === 'delayed') return 'exception'
+  return null
+}
+
+// 鍒囨崲瑙嗗浘妯″紡
+const toggleView = () => {
+  viewMode.value = viewMode.value === 'table' ? 'gantt' : 'table'
+  if (viewMode.value === 'gantt') {
+    nextTick(() => {
+      initGanttChart()
+    })
+  }
+}
+
+// 鍒濆鍖栫敇鐗瑰浘
+const initGanttChart = () => {
+  if (!ganttChart.value) return
+  
+  if (chartInstance) {
+    chartInstance.dispose()
+  }
+  
+  chartInstance = echarts.init(ganttChart.value)
+  
+  // 鍑嗗鐢樼壒鍥炬暟鎹�
+  const data = projectList.map((project, index) => ({
+    name: project.name,
+    value: [
+      index,
+      new Date(project.startDate).getTime(),
+      new Date(project.endDate).getTime(),
+      project.progress
+    ],
+    itemStyle: {
+      color: getGanttColor(project.status)
+    }
+  }))
+  
+  const option = {
+    title: {
+      text: '椤圭洰鐢樼壒鍥�',
+      left: 'center'
+    },
+    tooltip: {
+      formatter: (params) => {
+        const project = projectList[params.value[0]]
+        return `
+          <div>
+            <strong>${project.name}</strong><br/>
+            璐熻矗浜�: ${project.manager}<br/>
+            鐘舵��: ${getStatusText(project.status)}<br/>
+            杩涘害: ${project.progress}%<br/>
+            寮�濮嬫椂闂�: ${project.startDate}<br/>
+            缁撴潫鏃堕棿: ${project.endDate}
+          </div>
+        `
+      }
+    },
+    grid: {
+      left: '15%',
+      right: '10%',
+      top: '15%',
+      bottom: '15%'
+    },
+    xAxis: {
+      type: 'time',
+      axisLabel: {
+        formatter: (value) => {
+          return echarts.format.formatTime('MM-dd', value)
+        }
+      }
+    },
+    yAxis: {
+      type: 'category',
+      data: projectList.map(p => p.name),
+      inverse: true
+    },
+    series: [{
+      type: 'custom',
+      renderItem: (params, api) => {
+        const categoryIndex = api.value(0)
+        const start = api.coord([api.value(1), categoryIndex])
+        const end = api.coord([api.value(2), categoryIndex])
+        const height = api.size([0, 1])[1] * 0.6
+        
+        return {
+          type: 'rect',
+          shape: {
+            x: start[0],
+            y: start[1] - height / 2,
+            width: end[0] - start[0],
+            height: height
+          },
+          style: api.style()
+        }
+      },
+      data: data
+    }]
+  }
+  
+  chartInstance.setOption(option)
+}
+
+// 鑾峰彇鐢樼壒鍥鹃鑹�
+const getGanttColor = (status) => {
+  const colorMap = {
+    not_started: '#909399',
+    in_progress: '#E6A23C',
+    completed: '#67C23A',
+    delayed: '#F56C6C'
+  }
+  return colorMap[status] || '#909399'
+}
+
+// 鏇存柊鐘舵��
+const updateStatus = (project) => {
+  statusForm.id = project.id
+  statusForm.name = project.name
+  statusForm.status = project.status
+  statusForm.progress = project.progress
+  statusDialogVisible.value = true
+}
+
+// 纭鐘舵�佹洿鏂�
+const confirmStatusUpdate = () => {
+  const project = projectList.find(p => p.id === statusForm.id)
+  if (project) {
+    project.status = statusForm.status
+    project.progress = statusForm.progress
+    
+    // 鏇存柊缁熻鏁版嵁
+    updateStatusStats()
+    
+    // 濡傛灉鏄敇鐗瑰浘瑙嗗浘锛岄噸鏂版覆鏌�
+    if (viewMode.value === 'gantt') {
+      nextTick(() => {
+        initGanttChart()
+      })
+    }
+    
+    ElMessage.success('鐘舵�佹洿鏂版垚鍔�')
+  }
+  statusDialogVisible.value = false
+}
+
+// 鏇存柊鐘舵�佺粺璁�
+const updateStatusStats = () => {
+  const stats = {
+    not_started: 0,
+    in_progress: 0,
+    completed: 0,
+    delayed: 0
+  }
+  
+  projectList.forEach(project => {
+    stats[project.status]++
+  })
+  
+  statusStats[0].count = stats.not_started
+  statusStats[1].count = stats.in_progress
+  statusStats[2].count = stats.completed
+  statusStats[3].count = stats.delayed
+}
+
+// 鏌ョ湅璇︽儏
+const viewDetails = (project) => {
+  ElMessage.info(`鏌ョ湅椤圭洰璇︽儏: ${project.name}`)
+}
+
+// 鍒锋柊鏁版嵁
+const refreshData = () => {
+  // 妯℃嫙瀹炴椂鏇存柊
+  const randomProject = projectList[Math.floor(Math.random() * projectList.length)]
+  if (randomProject.status === 'in_progress') {
+    randomProject.progress = Math.min(100, randomProject.progress + Math.floor(Math.random() * 10))
+    if (randomProject.progress === 100) {
+      randomProject.status = 'completed'
+    }
+  }
+  
+  updateStatusStats()
+  
+  if (viewMode.value === 'gantt') {
+    nextTick(() => {
+      initGanttChart()
+    })
+  }
+  
+  ElMessage.success('鏁版嵁宸插埛鏂�')
+}
+
+onMounted(() => {
+  updateStatusStats()
+})
+</script>
+
+<style scoped>
+.process-tracking {
+  padding: 20px;
+}
+
+.header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  margin-bottom: 20px;
+}
+
+.header h2 {
+  margin: 0;
+  color: #303133;
+}
+
+.status-cards {
+  margin-bottom: 20px;
+}
+
+.status-card {
+  cursor: pointer;
+  transition: all 0.3s;
+}
+
+.status-card:hover {
+  transform: translateY(-2px);
+  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
+}
+
+.card-content {
+  display: flex;
+  align-items: center;
+}
+
+.card-icon {
+  margin-right: 15px;
+  padding: 10px;
+  border-radius: 8px;
+}
+
+.status-card.not-started .card-icon {
+  background-color: #f4f4f5;
+  color: #909399;
+}
+
+.status-card.in-progress .card-icon {
+  background-color: #fdf6ec;
+  color: #E6A23C;
+}
+
+.status-card.completed .card-icon {
+  background-color: #f0f9ff;
+  color: #67C23A;
+}
+
+.status-card.delayed .card-icon {
+  background-color: #fef0f0;
+  color: #F56C6C;
+}
+
+.card-info {
+  flex: 1;
+}
+
+.card-title {
+  font-size: 14px;
+  color: #909399;
+  margin-bottom: 5px;
+}
+
+.card-count {
+  font-size: 24px;
+  font-weight: bold;
+  color: #303133;
+}
+
+.project-list {
+  margin-top: 20px;
+}
+
+.card-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+}
+
+.gantt-container {
+  min-height: 400px;
+}
+</style>
\ No newline at end of file
diff --git a/src/views/collaborativeApproval/purchaseApproval/index.vue b/src/views/collaborativeApproval/purchaseApproval/index.vue
new file mode 100644
index 0000000..af17bbe
--- /dev/null
+++ b/src/views/collaborativeApproval/purchaseApproval/index.vue
@@ -0,0 +1,1064 @@
+<template>
+  <div class="app-container">
+    <div class="search_form">
+      <div>
+        <el-form :model="searchForm" :inline="true">
+          <el-form-item label="渚涘簲鍟嗗悕绉帮細">
+            <el-input v-model="searchForm.supplierName" placeholder="璇疯緭鍏�" clearable prefix-icon="Search"
+                      @change="handleQuery" />
+          </el-form-item>
+          <el-form-item label="閲囪喘鍚堝悓鍙凤細">
+            <el-input
+                v-model="searchForm.purchaseContractNumber"
+                style="width: 240px"
+                placeholder="璇疯緭鍏�"
+                @change="handleQuery"
+                clearable
+                :prefix-icon="Search"
+            />
+          </el-form-item>
+          <el-form-item label="閿�鍞悎鍚屽彿锛�">
+            <el-input v-model="searchForm.salesContractNo" placeholder="璇疯緭鍏�" clearable prefix-icon="Search"
+                      @change="handleQuery" />
+          </el-form-item>
+          <el-form-item label="椤圭洰鍚嶇О锛�">
+            <el-input v-model="searchForm.projectName" placeholder="璇疯緭鍏�" clearable prefix-icon="Search"
+                      @change="handleQuery" />
+          </el-form-item>
+          <el-form-item>
+            <el-button type="primary" @click="handleQuery"> 鎼滅储 </el-button>
+          </el-form-item>
+        </el-form>
+      </div>
+
+    </div>
+    <div class="table_list">
+      <div style="display: flex;justify-content: flex-end;margin-bottom: 20px;">
+        <el-button @click="handleOut">瀵煎嚭</el-button>
+        <el-button type="danger" plain @click="handleDelete">鍒犻櫎</el-button>
+      </div>
+      <el-table
+        :data="tableData"
+        border
+        v-loading="tableLoading"
+        @selection-change="handleSelectionChange"
+        :expand-row-keys="expandedRowKeys"
+        :row-key="(row) => row.id"
+        show-summary
+        :summary-method="summarizeMainTable"
+        @expand-change="expandChange"
+        height="calc(100vh - 18.5em)"
+        :row-class-name="tableRowClassName"
+      >
+        <el-table-column align="center" type="selection" width="55" />
+        <el-table-column type="expand">
+          <template #default="props">
+            <el-table
+              :data="props.row.children"
+              border
+              show-summary
+              :summary-method="summarizeChildrenTable"
+            >
+              <el-table-column
+                align="center"
+                label="搴忓彿"
+                type="index"
+                width="60"
+              />
+              <el-table-column label="浜у搧澶х被" prop="productCategory" />
+              <el-table-column label="瑙勬牸鍨嬪彿" prop="specificationModel" />
+              <el-table-column label="鍗曚綅" prop="unit" />
+              <el-table-column label="鏁伴噺" prop="quantity" />
+              <el-table-column label="绋庣巼(%)" prop="taxRate" />
+              <el-table-column
+                label="鍚◣鍗曚环(鍏�)"
+                prop="taxInclusiveUnitPrice"
+                :formatter="formattedNumber"
+              />
+              <el-table-column
+                label="鍚◣鎬讳环(鍏�)"
+                prop="taxInclusiveTotalPrice"
+                :formatter="formattedNumber"
+              />
+              <el-table-column
+                label="涓嶅惈绋庢�讳环(鍏�)"
+                prop="taxExclusiveTotalPrice"
+                :formatter="formattedNumber"
+              />
+            </el-table>
+          </template>
+        </el-table-column>
+        <el-table-column align="center" label="搴忓彿" type="index" width="60" />
+        <el-table-column
+          label="閲囪喘鍚堝悓鍙�"
+          prop="purchaseContractNumber"
+          width="200"
+          show-overflow-tooltip
+        />
+        <el-table-column
+          label="閿�鍞悎鍚屽彿"
+          prop="salesContractNo"
+          width="200"
+          show-overflow-tooltip
+        />
+        <el-table-column
+          label="渚涘簲鍟嗗悕绉�"
+          width="240"
+          prop="supplierName"
+          show-overflow-tooltip
+        />
+        <el-table-column label="璁㈠崟鐘舵��" width="100" align="center">
+          <template #default="scope">
+            <el-tag v-if="scope.row.isInvalid" type="danger" size="small">澶辨晥</el-tag>
+            <el-tag v-else type="success" size="small">姝e父</el-tag>
+          </template>
+        </el-table-column>
+        <el-table-column
+          label="椤圭洰鍚嶇О"
+          prop="projectName"
+          width="420"
+          show-overflow-tooltip
+        />
+        <el-table-column
+            label="瀹℃壒鐘舵��"
+            prop="approvalStatus"
+            width="200"
+            show-overflow-tooltip
+        >
+          <template #default="scope">
+            <el-tag
+                size="small"
+            >
+              {{ approvalStatusText[scope.row.approvalStatus] || '鏈煡鐘舵��' }}
+            </el-tag>
+          </template>
+        </el-table-column>
+        <el-table-column
+          label="浠樻鏂瑰紡"
+          width="100"
+          prop="paymentMethod"
+          show-overflow-tooltip
+        />
+        <el-table-column
+          label="鍚堝悓閲戦(鍏�)"
+          prop="contractAmount"
+           width="200"
+          show-overflow-tooltip
+          :formatter="formattedNumber"
+        />
+        <el-table-column
+          label="褰曞叆浜�"
+          prop="recorderName"
+           width="100"
+          show-overflow-tooltip
+        />
+        <el-table-column
+          label="褰曞叆鏃ユ湡"
+          prop="entryDate"
+           width="100"
+          show-overflow-tooltip
+        />
+        <el-table-column
+          fixed="right"
+          label="鎿嶄綔"
+          min-width="150"
+          align="center"
+        >
+          <template #default="scope">
+            <el-button
+              link
+              type="primary"
+              size="small"
+              @click="approvePurchase(scope.row)"
+              :disabled="scope.row.approvalStatus !== 0"
+              >瀹℃壒</el-button
+            >
+            <el-button
+                link
+                type="primary"
+                size="small"
+                @click="rejectPurchase(scope.row)"
+                :disabled="scope.row.approvalStatus !== 0"
+            >鎷掔粷瀹℃壒</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>
+  </div>
+</template>
+
+<script setup>
+import { getToken } from "@/utils/auth";
+import pagination from "@/components/PIMTable/Pagination.vue";
+import { ref, onMounted, reactive, toRefs, getCurrentInstance, nextTick } from "vue";
+import { Search } from "@element-plus/icons-vue";
+import { ElMessageBox } from "element-plus";
+import { userListNoPage } from "@/api/system/user.js";
+import {
+  getSalesLedgerWithProducts,
+  addOrUpdateSalesLedgerProduct,
+  delProduct,
+  delLedgerFile,
+  getProductInfoByContractNo,
+} from "@/api/salesManagement/salesLedger.js";
+import {
+  addOrEditPurchase,
+  delPurchase,
+  getSalesNo,
+  purchaseListPage,
+  productList,
+  getPurchaseById,
+  getOptions,
+  createPurchaseNo, updateApprovalStatus,
+} from "@/api/procurementManagement/procurementLedger.js";
+import useFormData from "@/hooks/useFormData.js";
+import QRCode from "qrcode";
+
+
+const { proxy } = getCurrentInstance();
+const tableData = ref([]);
+const productData = ref([]);
+const selectedRows = ref([]);
+const productSelectedRows = ref([]);
+const modelOptions = ref([]);
+const userList = ref([]);
+const productOptions = ref([]);
+const salesContractList = ref([]);
+const supplierList = ref([]);
+const tableLoading = ref(false);
+const page = reactive({
+  current: 1,
+  size: 100,
+});
+const total = ref(0);
+const fileList = ref([]);
+import useUserStore from "@/store/modules/user";
+import { modelList, productTreeList } from "@/api/basicData/product.js";
+import dayjs from "dayjs";
+import { getCurrentDate } from "@/utils/index.js";
+
+const userStore = useUserStore();
+
+// 浜岀淮鐮佺浉鍏冲彉閲�
+const qrCodeDialogVisible = ref(false);
+const qrCodeUrl = ref("");
+
+// 璁㈠崟瀹℃壒鐘舵�佹樉绀烘枃鏈�
+const approvalStatusText = {
+  0: '寰呭鎵�',
+  1: '瀹℃壒閫氳繃',
+  2: '瀹℃壒澶辫触'
+};
+
+// 鐢ㄦ埛淇℃伅琛ㄥ崟寮规鏁版嵁
+const operationType = ref("");
+const dialogFormVisible = ref(false);
+const data = reactive({
+  searchForm: {
+    supplierName: "", // 渚涘簲鍟嗗悕绉�
+    purchaseContractNumber: "", // 閲囪喘鍚堝悓缂栧彿
+    salesContractNo: "", // 閿�鍞悎鍚岀紪鍙�
+    projectName: "", // 椤圭洰鍚嶇О
+    entryDate: null, // 褰曞叆鏃ユ湡
+    entryDateStart: undefined,
+    entryDateEnd: undefined,
+  },
+  form: {
+    purchaseContractNumber: "",
+    salesLedgerId: "",
+    projectName: "",
+    recorderId: "",
+    entryDate: "",
+    productData: [],
+    supplierName: "",
+    supplierId: "",
+    paymentMethod: "",
+		executionDate: "",
+    approvalStatus: "0",
+  },
+  rules: {
+    purchaseContractNumber: [
+      { required: true, message: "璇疯緭鍏�", trigger: "blur" },
+    ],
+    projectName: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+    supplierId: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+		entryDate: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+		executionDate: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+  },
+});
+const {  form, rules } = toRefs(data);
+const { form: searchForm } = useFormData(data.searchForm);
+
+// 浜у搧琛ㄥ崟寮规鏁版嵁
+const productFormVisible = ref(false);
+const productOperationType = ref("");
+const productOperationIndex = ref("");
+const currentId = ref("");
+const productFormData = reactive({
+  productForm: {
+    productId: "",
+    productCategory: "",
+    productModelId: "",
+    specificationModel: "",
+    unit: "",
+    quantity: "",
+    taxInclusiveUnitPrice: "",
+    taxRate: "",
+    taxInclusiveTotalPrice: "",
+    taxExclusiveTotalPrice: "",
+    invoiceType: "",
+		warnNum: "",
+  },
+  productRules: {
+    productId: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+    productModelId: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+    unit: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+    quantity: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+    taxInclusiveUnitPrice: [
+      { required: true, message: "璇疯緭鍏�", trigger: "blur" },
+    ],
+    taxRate: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+		warnNum: [{ required: false, message: "璇烽�夋嫨", trigger: "change" }],
+    taxInclusiveTotalPrice: [
+      { required: true, message: "璇疯緭鍏�", trigger: "blur" },
+    ],
+    taxExclusiveTotalPrice: [
+      { required: true, message: "璇疯緭鍏�", trigger: "blur" },
+    ],
+    invoiceType: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+  },
+});
+const { productForm, productRules } = toRefs(productFormData);
+const upload = reactive({
+  // 涓婁紶鐨勫湴鍧�
+  url: import.meta.env.VITE_APP_BASE_API + "/file/upload",
+  // 璁剧疆涓婁紶鐨勮姹傚ご閮�
+  headers: { Authorization: "Bearer " + getToken() },
+});
+
+const changeDaterange = (value) => {
+  if (value) {
+    searchForm.entryDateStart = dayjs(value[0]).format("YYYY-MM-DD");
+    searchForm.entryDateEnd = dayjs(value[1]).format("YYYY-MM-DD");
+  } else {
+    searchForm.entryDateStart = undefined;
+    searchForm.entryDateEnd = undefined;
+  }
+  handleQuery();
+};
+
+const formattedNumber = (row, column, cellValue) => {
+  return parseFloat(cellValue).toFixed(2);
+};
+// 鏌ヨ鍒楄〃
+/** 鎼滅储鎸夐挳鎿嶄綔 */
+const handleQuery = () => {
+  page.current = 1;
+  getList();
+};
+// 瀛愯〃鍚堣鏂规硶
+const summarizeChildrenTable = (param) => {
+  return proxy.summarizeTable(
+    param,
+    [
+      "taxInclusiveUnitPrice",
+      "taxInclusiveTotalPrice",
+      "taxExclusiveTotalPrice",
+      "ticketsNum",
+      "ticketsAmount",
+      "futureTickets",
+      "futureTicketsAmount",
+    ],
+    {
+      ticketsNum: { noDecimal: true }, // 涓嶄繚鐣欏皬鏁�
+      futureTickets: { noDecimal: true }, // 涓嶄繚鐣欏皬鏁�
+    }
+  );
+};
+const paginationChange = (obj) => {
+  page.current = obj.page;
+  page.size = obj.limit;
+  getList();
+};
+const getList = () => {
+  tableLoading.value = true;
+  const { entryDate, ...rest } = searchForm;
+  purchaseListPage({ ...rest, ...page })
+    .then((res) => {
+      tableLoading.value = false;
+      // tableData.value = res.data.records;
+      // 澶勭悊鏁版嵁锛屾坊鍔犲け鏁堢姸鎬佹爣璁�
+      tableData.value = res.data.records.map(record => ({
+        ...record,
+        isInvalid: record.isWhite === 1
+      }));
+      tableData.value.map((item) => {
+        item.children = [];
+      });
+      total.value = res.data.total;
+      expandedRowKeys.value = [];
+    })
+    .catch(() => {
+      tableLoading.value = false;
+    });
+};
+// 琛ㄦ牸閫夋嫨鏁版嵁
+const handleSelectionChange = (selection) => {
+  selectedRows.value = selection;
+};
+const productSelected = (selectedRows) => {
+  productSelectedRows.value = selectedRows;
+};
+const expandedRowKeys = ref([]);
+// 灞曞紑琛�
+const expandChange = (row, expandedRows) => {
+  if (expandedRows.length > 0) {
+    expandedRowKeys.value = [];
+    try {
+      productList({ salesLedgerId: row.id, type: 2 }).then((res) => {
+        const index = tableData.value.findIndex((item) => item.id === row.id);
+        if (index > -1) {
+          tableData.value[index].children = res.data;
+        }
+        expandedRowKeys.value.push(row.id);
+      });
+    } catch (error) {
+      console.log(error);
+    }
+  } else {
+    expandedRowKeys.value = [];
+  }
+};
+// 涓昏〃鍚堣鏂规硶
+const summarizeMainTable = (param) => {
+  return proxy.summarizeTable(param, ["contractAmount"]);
+};
+// 瀛愯〃鍚堣鏂规硶
+const summarizeProTable = (param) => {
+  return proxy.summarizeTable(param, [
+    "taxInclusiveUnitPrice",
+    "taxInclusiveTotalPrice",
+    "taxExclusiveTotalPrice",
+  ]);
+};
+// 鎵撳紑寮规
+const openForm = (type, row) => {
+  operationType.value = type;
+  form.value = {};
+  productData.value = [];
+  fileList.value = [];
+  if (operationType.value == "add") {
+    createPurchaseNo().then((res) => {
+      form.value.purchaseContractNumber = res.data;
+    });
+  }
+  userListNoPage().then((res) => {
+    userList.value = res.data;
+  });
+  getSalesNo().then((res) => {
+    salesContractList.value = res;
+  });
+  getOptions().then((res) => {
+    // 渚涘簲鍟嗚繃婊ゅ嚭isWhite=0 鐨勬暟鎹�
+    supplierList.value = res.data.filter((item) => item.isWhite == 0);
+  });
+  form.value.recorderId = userStore.id;
+  form.value.entryDate = getCurrentDate();
+  if (type === "edit") {
+    currentId.value = row.id;
+    getPurchaseById({ id: row.id, type: 2 }).then((res) => {
+      form.value = { ...res };
+      productData.value = form.value.productData;
+      if (form.value.salesLedgerFiles) {
+        fileList.value = form.value.salesLedgerFiles;
+      } else {
+        fileList.value = [];
+      }
+    });
+  }
+  dialogFormVisible.value = true;
+};
+// 涓婁紶鍓嶆牎妫�
+function handleBeforeUpload(file) {
+  // 鏍℃鏂囦欢澶у皬
+  if (file.size > 1024 * 1024 * 10) {
+    proxy.$modal.msgError("涓婁紶鏂囦欢澶у皬涓嶈兘瓒呰繃10MB!");
+    return false;
+  }
+  proxy.$modal.loading("姝e湪涓婁紶鏂囦欢锛岃绋嶅��...");
+  return true;
+}
+// 涓婁紶澶辫触
+function handleUploadError(err) {
+  proxy.$modal.msgError("涓婁紶鏂囦欢澶辫触");
+  proxy.$modal.closeLoading();
+}
+// 涓婁紶鎴愬姛鍥炶皟
+function handleUploadSuccess(res, file, uploadFiles) {
+  proxy.$modal.closeLoading();
+  if (res.code === 200) {
+    file.tempId = res.data.tempId;
+    proxy.$modal.msgSuccess("涓婁紶鎴愬姛");
+  } else {
+    proxy.$modal.msgError(res.msg);
+    proxy.$refs.fileUpload.handleRemove(file);
+  }
+}
+// 绉婚櫎鏂囦欢
+function handleRemove(file) {
+  console.log("handleRemove", file.id);
+  if (file.size > 1024 * 1024 * 10) { 
+    // 浠呭墠绔竻鐞嗭紝涓嶈皟鐢ㄥ垹闄ゆ帴鍙e拰鎻愮ず
+    return; 
+  }
+  if (operationType.value === "edit") {
+    let ids = [];
+    ids.push(file.id);
+    delLedgerFile(ids).then((res) => {
+      proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+    });
+  }
+}
+// 鎻愪氦琛ㄥ崟
+const submitForm = (n) => {
+  proxy.$refs["formRef"].validate((valid) => {
+    if (valid) {
+      if (productData.value.length > 0) {
+        form.value.productData = proxy.HaveJson(productData.value);
+      } else {
+        proxy.$modal.msgWarning("璇锋坊鍔犱骇鍝佷俊鎭�");
+        return;
+      }
+      let tempFileIds = [];
+      if (fileList.value.length > 0) {
+        tempFileIds = fileList.value.map((item) => item.tempId);
+      }
+      form.value.tempFileIds = tempFileIds;
+      form.value.type = 2;
+      form.value.approvalStatus = n;
+      addOrEditPurchase(form.value).then((res) => {
+        proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+        closeDia();
+        getList();
+      });
+    }
+  });
+};
+// 鍏抽棴寮规
+const closeDia = () => {
+  proxy.resetForm("formRef");
+  dialogFormVisible.value = false;
+};
+// 鎵撳紑浜у搧寮规
+const openProductForm = (type, row, index) => {
+  productOperationType.value = type;
+  productOperationIndex.value = index;
+  productForm.value = {};
+  proxy.resetForm("productFormRef");
+  if (type === "edit") {
+    productForm.value = { ...row };
+  }
+  productFormVisible.value = true;
+  getProductOptions();
+};
+const getProductOptions = () => {
+  productTreeList().then((res) => {
+    productOptions.value = convertIdToValue(res);
+  });
+};
+const getModels = (value) => {
+  if (value) {
+    productForm.value.productCategory = findNodeById(productOptions.value, value) || "";
+    modelList({ id: value }).then((res) => {
+      modelOptions.value = res;
+    });
+  } else {
+    productForm.value.productCategory = "";
+    modelOptions.value = [];
+  }
+};
+const getProductModel = (value) => {
+  const index = modelOptions.value.findIndex((item) => item.id === value);
+  if (index !== -1) {
+    productForm.value.specificationModel = modelOptions.value[index].model;
+    productForm.value.unit = modelOptions.value[index].unit;
+  } else {
+    productForm.value.specificationModel = null;
+    productForm.value.unit = null;
+  }
+};
+const findNodeById = (nodes, productId) => {
+  for (let i = 0; i < nodes.length; i++) {
+    if (nodes[i].value === productId) {
+      return nodes[i].label; // 鎵惧埌鑺傜偣锛岃繑鍥炶鑺傜偣鐨刲abel
+    }
+    if (nodes[i].children && nodes[i].children.length > 0) {
+      const foundNode = findNodeById(nodes[i].children, productId);
+      if (foundNode) {
+        return foundNode; // 鍦ㄥ瓙鑺傜偣涓壘鍒帮紝鐩存帴杩斿洖锛堝凡缁忔槸label瀛楃涓诧級
+      }
+    }
+  }
+  return null; // 娌℃湁鎵惧埌鑺傜偣锛岃繑鍥瀗ull
+};
+function convertIdToValue(data) {
+  return data.map((item) => {
+    const { id, children, ...rest } = item;
+    const newItem = {
+      ...rest,
+      value: id, // 灏� id 鏀逛负 value
+    };
+    if (children && children.length > 0) {
+      newItem.children = convertIdToValue(children);
+    }
+
+    return newItem;
+  });
+}
+// 鎻愪氦浜у搧琛ㄥ崟
+const submitProduct = () => {
+  proxy.$refs["productFormRef"].validate((valid) => {
+    if (valid) {
+      if (operationType.value === "edit") {
+        submitProductEdit();
+      } else {
+        if (productOperationType.value === "add") {
+          productData.value.push({ ...productForm.value });
+          console.log("productData.value---", productData.value);
+        } else {
+          productData.value[productOperationIndex.value] = {
+            ...productForm.value,
+          };
+        }
+        closeProductDia();
+      }
+    }
+  });
+};
+const submitProductEdit = () => {
+  productForm.value.salesLedgerId = currentId.value;
+  productForm.value.type = 2;
+  addOrUpdateSalesLedgerProduct(productForm.value).then((res) => {
+    proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+    closeProductDia();
+    getPurchaseById({ id: currentId.value, type: 2 }).then((res) => {
+      productData.value = res.productData;
+    });
+  });
+};
+// 鍒犻櫎浜у搧
+const deleteProduct = () => {
+  if (productSelectedRows.value.length === 0) {
+    proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
+    return;
+  }
+  if (operationType.value === "add") {
+    productSelectedRows.value.forEach((selectedRow) => {
+      const index = productData.value.findIndex(
+        (product) => product.id === selectedRow.id
+      );
+      if (index !== -1) {
+        productData.value.splice(index, 1);
+      }
+    });
+  } else {
+    let ids = [];
+    if (productSelectedRows.value.length > 0) {
+      ids = productSelectedRows.value.map((item) => item.id);
+    }
+    ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "瀵煎嚭", {
+      confirmButtonText: "纭",
+      cancelButtonText: "鍙栨秷",
+      type: "warning",
+    })
+      .then(() => {
+        delProduct(ids).then((res) => {
+          proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+          closeProductDia();
+          getSalesLedgerWithProducts({ id: currentId.value, type: 2 }).then(
+            (res) => {
+              productData.value = res.productData;
+            }
+          );
+        });
+      })
+      .catch(() => {
+        proxy.$modal.msg("宸插彇娑�");
+      });
+  }
+};
+// 鍏抽棴浜у搧寮规
+const closeProductDia = () => {
+  proxy.resetForm("productFormRef");
+  productFormVisible.value = false;
+};
+// 瀹℃壒閫氳繃鏂规硶
+const approvePurchase = (row) => {
+  ElMessageBox.confirm(`纭閫氳繃閲囪喘鍚堝悓鍙蜂负 ${row.purchaseContractNumber} 鐨勫鎵癸紵`, '瀹℃壒纭', {
+    confirmButtonText: '纭',
+    cancelButtonText: '鍙栨秷',
+    type: 'warning',
+  }).then(() => {
+    updateApprovalStatus({ id: row.id, approvalStatus: 1}).then((res)=>{
+      proxy.$modal.msgSuccess('瀹℃壒鎴愬姛');
+      getList();
+    })
+  }).catch(() => {
+    proxy.$modal.msg('宸插彇娑堝鎵�');
+  });
+};
+
+// 瀹℃壒鎷掔粷鏂规硶
+const rejectPurchase = (row) => {
+  ElMessageBox.confirm(`纭鎷掔粷閲囪喘鍚堝悓鍙蜂负 ${row.purchaseContractNumber} 鐨勫鎵癸紵`, '瀹℃壒纭', {
+    confirmButtonText: '纭',
+    cancelButtonText: '鍙栨秷',
+    type: 'warning',
+  }).then(() => {
+    updateApprovalStatus({ id: row.id, approvalStatus: 2}).then((res)=>{
+      proxy.$modal.msgSuccess('瀹℃壒鎴愬姛');
+      getList();
+    })
+  }).catch(() => {
+    proxy.$modal.msg('宸插彇娑堝鎵�');
+  });
+};
+
+// 瀵煎嚭
+const handleOut = () => {
+  ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚鍑猴紝鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
+    confirmButtonText: "纭",
+    cancelButtonText: "鍙栨秷",
+    type: "warning",
+  })
+    .then(() => {
+      proxy.download("/purchase/ledger/export", {}, "閲囪喘鍙拌处.xlsx");
+    })
+    .catch(() => {
+      proxy.$modal.msg("宸插彇娑�");
+    });
+};
+// 鍒犻櫎
+const handleDelete = () => {
+  let ids = [];
+  if (selectedRows.value.length > 0) {
+		// 妫�鏌ユ槸鍚︽湁浠栦汉缁存姢鐨勬暟鎹�
+		const unauthorizedData = selectedRows.value.filter(item => item.recorderName !== userStore.nickName);
+		if (unauthorizedData.length > 0) {
+			proxy.$modal.msgWarning("涓嶅彲鍒犻櫎浠栦汉缁存姢鐨勬暟鎹�");
+			return;
+		}
+    ids = selectedRows.value.map((item) => item.id);
+  } else {
+    proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
+    return;
+  }
+  ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "瀵煎嚭", {
+    confirmButtonText: "纭",
+    cancelButtonText: "鍙栨秷",
+    type: "warning",
+  })
+    .then(() => {
+      delPurchase(ids).then((res) => {
+        proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+        getList();
+      });
+    })
+    .catch(() => {
+      proxy.$modal.msg("宸插彇娑�");
+    });
+};
+const mathNum = () => {
+	if (!productForm.value.taxRate) {
+		proxy.$modal.msgWarning("璇峰厛閫夋嫨绋庣巼");
+		return;
+	}
+  if (!productForm.value.taxInclusiveUnitPrice) {
+    return;
+  }
+  if (!productForm.value.quantity) {
+    return;
+  }
+  // 鍚◣鎬讳环璁$畻
+  productForm.value.taxInclusiveTotalPrice =
+    proxy.calculateTaxIncludeTotalPrice(
+      productForm.value.taxInclusiveUnitPrice,
+      productForm.value.quantity
+    );
+  if (productForm.value.taxRate) {
+    // 涓嶅惈绋庢�讳环璁$畻
+    productForm.value.taxExclusiveTotalPrice =
+      proxy.calculateTaxExclusiveTotalPrice(
+        productForm.value.taxInclusiveTotalPrice,
+        productForm.value.taxRate
+      );
+  }
+};
+const reverseMathNum = (field) => {
+	if (!productForm.value.taxRate) {
+		proxy.$modal.msgWarning("璇峰厛閫夋嫨绋庣巼");
+		return;
+	}
+  const taxRate = Number(productForm.value.taxRate);
+  if (!taxRate) return;
+  if (field === 'taxInclusiveTotalPrice') {
+    // 宸茬煡鍚◣鎬讳环鍜屾暟閲忥紝鍙嶇畻鍚◣鍗曚环
+    if (productForm.value.quantity) {
+      productForm.value.taxInclusiveUnitPrice = 
+        (Number(productForm.value.taxInclusiveTotalPrice) / Number(productForm.value.quantity)).toFixed(2);
+    }
+    // 宸茬煡鍚◣鎬讳环鍜屽惈绋庡崟浠凤紝鍙嶇畻鏁伴噺
+    else if (productForm.value.taxInclusiveUnitPrice) {
+      productForm.value.quantity = 
+        (Number(productForm.value.taxInclusiveTotalPrice) / Number(productForm.value.taxInclusiveUnitPrice)).toFixed(2);
+    }
+    // 鍙嶇畻涓嶅惈绋庢�讳环
+    productForm.value.taxExclusiveTotalPrice = 
+      (Number(productForm.value.taxInclusiveTotalPrice) / (1 + taxRate / 100)).toFixed(2);
+  } else if (field === 'taxExclusiveTotalPrice') {
+    // 鍙嶇畻鍚◣鎬讳环
+    productForm.value.taxInclusiveTotalPrice = 
+      (Number(productForm.value.taxExclusiveTotalPrice) * (1 + taxRate / 100)).toFixed(2);
+    // 宸茬煡鏁伴噺锛屽弽绠楀惈绋庡崟浠�
+    if (productForm.value.quantity) {
+      productForm.value.taxInclusiveUnitPrice = 
+        (Number(productForm.value.taxInclusiveTotalPrice) / Number(productForm.value.quantity)).toFixed(2);
+    }
+    // 宸茬煡鍚◣鍗曚环锛屽弽绠楁暟閲�
+    else if (productForm.value.taxInclusiveUnitPrice) {
+      productForm.value.quantity = 
+        (Number(productForm.value.taxInclusiveTotalPrice) / Number(productForm.value.taxInclusiveUnitPrice)).toFixed(2);
+    }
+  }
+};
+// 閿�鍞悎鍚岄�夋嫨鏀瑰彉鏂规硶
+const salesLedgerChange = async (row) => {
+  console.log("row", row);
+  var index = salesContractList.value.findIndex((item) => item.id == row);
+  console.log("index", index);
+  if (index > -1) {
+    form.value.projectName = salesContractList.value[index].projectName;
+    await querygProductInfoByContractNo();
+  }
+};
+
+const querygProductInfoByContractNo = async () => {
+  const { code, data } = await getProductInfoByContractNo({
+    contractNo: form.value.salesLedgerId,
+  });
+  if (code == 200) {
+    productData.value = data;
+  }
+};
+
+// 鏄剧ず浜岀淮鐮�
+const showQRCode = async (row) => {
+  try {
+    // 鏋勫缓浜岀淮鐮佸唴瀹癸紝鍙寘鍚噰璐悎鍚屽彿锛堢函鏂囨湰锛�
+    const qrContent = row.purchaseContractNumber || '';
+    // 妫�鏌ュ唴瀹规槸鍚︿负绌�
+    if (!qrContent || qrContent.trim() === '') {
+      proxy.$modal.msgWarning("璇ヨ娌℃湁閲囪喘鍚堝悓鍙凤紝鏃犳硶鐢熸垚浜岀淮鐮�");
+      return;
+    }
+    qrCodeUrl.value = await QRCode.toDataURL(qrContent, {
+      width: 200,
+      margin: 2,
+      color: {
+        dark: '#000000',
+        light: '#FFFFFF'
+      }
+    });
+    qrCodeDialogVisible.value = true;
+  } catch (error) {
+    console.error('鐢熸垚浜岀淮鐮佸け璐�:', error);
+    proxy.$modal.msgError("鐢熸垚浜岀淮鐮佸け璐ワ細" + error.message);
+  }
+};
+
+// 涓嬭浇浜岀淮鐮�
+const downloadQRCode = () => {
+  if (!qrCodeUrl.value) {
+    proxy.$modal.msgWarning("浜岀淮鐮佹湭鐢熸垚");
+    return;
+  }
+  
+  const a = document.createElement('a');
+  a.href = qrCodeUrl.value;
+  a.download = `閲囪喘鍚堝悓鍙蜂簩缁寸爜_${new Date().getTime()}.png`;
+  document.body.appendChild(a);
+  a.click();
+  document.body.removeChild(a);
+  proxy.$modal.msgSuccess("涓嬭浇鎴愬姛");
+};
+
+// 鎵爜鏂板瀵硅瘽妗嗙浉鍏冲彉閲�
+const scanAddDialogVisible = ref(false);
+const scanAddForm = reactive({
+  scanContent: "",
+  purchaseContractNumber: "",
+  supplierName: "",
+  projectName: "",
+  contractAmount: "",
+  paymentMethod: "",
+  recorderName: "",
+  scanRemark: "",
+});
+const scanAddRules = {
+  purchaseContractNumber: [{ required: true, message: "璇疯緭鍏ラ噰璐悎鍚屽彿", trigger: "blur" }],
+  supplierName: [{ required: true, message: "璇疯緭鍏ヤ緵搴斿晢鍚嶇О", trigger: "blur" }],
+  projectName: [{ required: true, message: "璇疯緭鍏ラ」鐩悕绉�", trigger: "blur" }],
+};
+
+// 鎵爜鐧昏瀵硅瘽妗嗙浉鍏冲彉閲�
+const scanDialogVisible = ref(false);
+const scanForm = reactive({
+  purchaseContractNumber: "",
+  supplierName: "",
+  projectName: "",
+  scanTime: "",
+  scannerName: "",
+  scanStatus: "鏈壂鐮�",
+  scanRemark: "",
+});
+const scanRules = {
+  scanRemark: [{ required: true, message: "璇疯緭鍏ユ壂鐮佸娉�", trigger: "blur" }],
+};
+const scanRecords = ref([]);
+
+// 鎵撳紑鎵爜鏂板瀵硅瘽妗�
+const openScanAddDialog = () => {
+  scanAddForm.scanContent = "";
+  scanAddForm.purchaseContractNumber = "";
+  scanAddForm.supplierName = "";
+  scanAddForm.projectName = "";
+  scanAddForm.contractAmount = "";
+  scanAddForm.paymentMethod = "";
+  scanAddForm.recorderName = userStore.nickName;
+  scanAddForm.scanRemark = "";
+  scanAddDialogVisible.value = true;
+};
+
+// 瑙f瀽鎵爜鍐呭锛堟ā鎷熻В鏋愪簩缁寸爜鏁版嵁锛�
+const parseScanContent = (content) => {
+  if (!content) return;
+  
+  // 妯℃嫙瑙f瀽浜岀淮鐮佸唴瀹癸紝杩欓噷鍙互鏍规嵁瀹為檯闇�姹傝皟鏁磋В鏋愰�昏緫
+  // 鍋囪鎵爜鍐呭鏍煎紡涓猴細鍚堝悓鍙穦渚涘簲鍟唡椤圭洰|閲戦|浠樻鏂瑰紡
+  const parts = content.split('|');
+  if (parts.length >= 3) {
+    scanAddForm.purchaseContractNumber = parts[0] || "";
+    scanAddForm.supplierName = parts[1] || "";
+    scanAddForm.projectName = parts[2] || "";
+    scanAddForm.contractAmount = parts[3] || "";
+    scanAddForm.paymentMethod = parts[4] || "";
+  }
+};
+
+// 鍏抽棴鎵爜鏂板瀵硅瘽妗�
+const closeScanAddDialog = () => {
+  scanAddDialogVisible.value = false;
+  proxy.resetForm("scanAddFormRef");
+};
+
+// 鎻愪氦鎵爜鏂板
+const submitScanAdd = () => {
+  proxy.$refs["scanAddFormRef"].validate((valid) => {
+    if (valid) {
+      // 鏋勫缓鏂板鏁版嵁
+      const newData = {
+        purchaseContractNumber: scanAddForm.purchaseContractNumber,
+        supplierName: scanAddForm.supplierName,
+        projectName: scanAddForm.projectName,
+        contractAmount: scanAddForm.contractAmount,
+        paymentMethod: scanAddForm.paymentMethod,
+        recorderName: scanAddForm.recorderName,
+        entryDate: getCurrentDate(),
+        remark: scanAddForm.scanRemark,
+        type: 2
+      };
+      
+      // 妯℃嫙鏂板鎴愬姛
+      proxy.$modal.msgSuccess("鎵爜鏂板鎴愬姛锛�");
+      closeScanAddDialog();
+      
+      // 鍙互閫夋嫨鏄惁鍒锋柊鍒楄〃
+      // getList();
+    }
+  });
+};
+
+// 鎵撳紑鎵爜鐧昏瀵硅瘽妗�
+const openScanDialog = (row) => {
+  scanForm.purchaseContractNumber = row.purchaseContractNumber;
+  scanForm.supplierName = row.supplierName;
+  scanForm.projectName = row.projectName;
+  scanForm.scanTime = getCurrentDateTime();
+  scanForm.scannerName = userStore.nickName;
+  scanForm.scanStatus = "鏈壂鐮�";
+  scanForm.scanRemark = "";
+  scanRecords.value = [];
+  scanDialogVisible.value = true;
+};
+
+// 鍏抽棴鎵爜鐧昏瀵硅瘽妗�
+const closeScanDialog = () => {
+  scanDialogVisible.value = false;
+  proxy.resetForm("scanFormRef");
+};
+
+// 鎻愪氦鎵爜鐧昏
+const submitScan = () => {
+  proxy.$refs["scanFormRef"].validate((valid) => {
+    if (valid) {
+      // 娣诲姞鎵爜璁板綍
+      scanRecords.value.push({
+        ...scanForm,
+        id: Date.now(), // 妯℃嫙ID
+        scanTime: getCurrentDateTime(),
+      });
+      scanForm.scanStatus = "宸叉壂鐮�";
+      scanForm.scanRemark = scanForm.scanRemark || "鏃�";
+      proxy.$modal.msgSuccess("鎵爜鐧昏鎴愬姛锛�");
+      closeScanDialog();
+    }
+  });
+};
+
+// 鑾峰彇褰撳墠鏃ユ湡鏃堕棿
+function getCurrentDateTime() {
+  const now = new Date();
+  const year = now.getFullYear();
+  const month = String(now.getMonth() + 1).padStart(2, "0");
+  const day = String(now.getDate()).padStart(2, "0");
+  const hours = String(now.getHours()).padStart(2, "0");
+  const minutes = String(now.getMinutes()).padStart(2, "0");
+  const seconds = String(now.getSeconds()).padStart(2, "0");
+  return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
+}
+
+// 娣诲姞琛岀被鍚嶆柟娉�
+const tableRowClassName = ({ row }) => {
+  return row.isInvalid ? 'invalid-row' : '';
+};
+
+onMounted(() => {
+  getList();
+});
+</script>
+
+<style scoped lang="scss">
+.invalid-row {
+  opacity: 0.6;
+  background-color: #f5f7fa;
+}
+</style>
diff --git a/src/views/collaborativeApproval/reportGeneration/index.vue b/src/views/collaborativeApproval/reportGeneration/index.vue
new file mode 100644
index 0000000..c160ad7
--- /dev/null
+++ b/src/views/collaborativeApproval/reportGeneration/index.vue
@@ -0,0 +1,596 @@
+<template>
+  <div class="report-generation">
+    <!-- 椤甸潰澶撮儴 -->
+    <div class="page-header">
+      <h2>椤圭洰鎬荤粨鎶ュ憡鐢熸垚</h2>
+      <div class="header-actions">
+        <el-button v-if="!reportGenerated" type="primary" @click="generateReport" :loading="generating">
+          <el-icon><Document /></el-icon>
+          鐢熸垚鎶ュ憡
+        </el-button>
+        <el-button v-if="reportGenerated" type="primary" @click="resetConfig">
+          <el-icon><Refresh /></el-icon>
+          鐢熸垚鏂版姤鍛�
+        </el-button>
+        <el-button @click="exportReport" :disabled="!reportGenerated">
+          <el-icon><Download /></el-icon>
+          瀵煎嚭鎶ュ憡
+        </el-button>
+      </div>
+    </div>
+
+    <!-- 鎶ュ憡閰嶇疆鍖哄煙 -->
+    <el-card class="config-card" v-if="!reportGenerated">
+      <template #header>
+        <span>鎶ュ憡閰嶇疆</span>
+      </template>
+      <el-form :model="reportConfig" label-width="120px">
+        <el-row :gutter="20">
+          <el-col :span="12">
+            <el-form-item label="椤圭洰鍚嶇О">
+              <el-select v-model="reportConfig.projectId" placeholder="璇烽�夋嫨椤圭洰">
+                <el-option
+                  v-for="project in projectList"
+                  :key="project.id"
+                  :label="project.name"
+                  :value="project.id"
+                />
+              </el-select>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="鎶ュ憡鍛ㄦ湡">
+              <el-date-picker
+                v-model="reportConfig.dateRange"
+                type="daterange"
+                range-separator="鑷�"
+                start-placeholder="寮�濮嬫棩鏈�"
+                end-placeholder="缁撴潫鏃ユ湡"
+                format="YYYY-MM-DD"
+                value-format="YYYY-MM-DD"
+              />
+            </el-form-item>
+          </el-col>
+        </el-row>
+      </el-form>
+    </el-card>
+
+    <!-- 鎶ュ憡鍐呭灞曠ず鍖哄煙 -->
+    <div v-if="reportGenerated" class="report-content">
+      <!-- 椤圭洰鍩烘湰淇℃伅 -->
+      <el-card class="report-section">
+        <template #header>
+          <span>椤圭洰鍩烘湰淇℃伅</span>
+        </template>
+        <el-descriptions :column="2" border>
+          <el-descriptions-item label="椤圭洰鍚嶇О">{{ reportData.projectInfo.name }}</el-descriptions-item>
+          <el-descriptions-item label="椤圭洰缁忕悊">{{ reportData.projectInfo.manager }}</el-descriptions-item>
+          <el-descriptions-item label="寮�濮嬫椂闂�">{{ reportData.projectInfo.startDate }}</el-descriptions-item>
+          <el-descriptions-item label="缁撴潫鏃堕棿">{{ reportData.projectInfo.endDate }}</el-descriptions-item>
+          <el-descriptions-item label="椤圭洰鐘舵��">
+            <el-tag :type="getStatusType(reportData.projectInfo.status)">
+              {{ reportData.projectInfo.status }}
+            </el-tag>
+          </el-descriptions-item>
+          <el-descriptions-item label="鎬婚绠�">{{ reportData.projectInfo.budget }}</el-descriptions-item>
+        </el-descriptions>
+      </el-card>
+
+      <!-- 浠诲姟瀹屾垚鐜囩粺璁� -->
+      <el-card class="report-section">
+        <template #header>
+          <span>浠诲姟瀹屾垚鐜囩粺璁�</span>
+        </template>
+        <el-row :gutter="20">
+          <el-col :span="12">
+            <div class="completion-stats">
+              <div class="stat-item">
+                <div class="stat-label">鎬讳换鍔℃暟</div>
+                <div class="stat-value">{{ reportData.taskStats.total }}</div>
+              </div>
+              <div class="stat-item">
+                <div class="stat-label">宸插畬鎴�</div>
+                <div class="stat-value completed">{{ reportData.taskStats.completed }}</div>
+              </div>
+              <div class="stat-item">
+                <div class="stat-label">杩涜涓�</div>
+                <div class="stat-value in-progress">{{ reportData.taskStats.inProgress }}</div>
+              </div>
+              <div class="stat-item">
+                <div class="stat-label">鏈紑濮�</div>
+                <div class="stat-value pending">{{ reportData.taskStats.pending }}</div>
+              </div>
+            </div>
+          </el-col>
+          <el-col :span="12">
+            <div class="completion-rate">
+              <el-progress
+                type="circle"
+                :percentage="reportData.taskStats.completionRate"
+                :width="150"
+                :stroke-width="8"
+              >
+                <template #default="{ percentage }">
+                  <span class="percentage-value">{{ percentage }}%</span>
+                  <div class="percentage-label">瀹屾垚鐜�</div>
+                </template>
+              </el-progress>
+            </div>
+          </el-col>
+        </el-row>
+      </el-card>
+
+      <!-- 闂璁板綍缁熻 -->
+      <el-card class="report-section">
+        <template #header>
+          <span>闂璁板綍缁熻</span>
+        </template>
+        <el-row :gutter="20">
+          <el-col :span="8">
+            <div class="issue-summary">
+              <div class="summary-item">
+                <div class="summary-label">鎬婚棶棰樻暟</div>
+                <div class="summary-value">{{ reportData.issueStats.total }}</div>
+              </div>
+              <div class="summary-item">
+                <div class="summary-label">宸茶В鍐�</div>
+                <div class="summary-value resolved">{{ reportData.issueStats.resolved }}</div>
+              </div>
+              <div class="summary-item">
+                <div class="summary-label">寰呰В鍐�</div>
+                <div class="summary-value pending">{{ reportData.issueStats.pending }}</div>
+              </div>
+            </div>
+          </el-col>
+          <el-col :span="16">
+            <el-table :data="reportData.issueStats.topIssues" size="small">
+              <el-table-column prop="title" label="涓昏闂" />
+              <el-table-column prop="severity" label="涓ラ噸绋嬪害" width="100">
+                <template #default="{ row }">
+                  <el-tag :type="getSeverityType(row.severity)" size="small">
+                    {{ row.severity }}
+                  </el-tag>
+                </template>
+              </el-table-column>
+              <el-table-column prop="status" label="鐘舵��" width="80">
+                <template #default="{ row }">
+                  <el-tag :type="row.status === '宸茶В鍐�' ? 'success' : 'warning'" size="small">
+                    {{ row.status }}
+                  </el-tag>
+                </template>
+              </el-table-column>
+            </el-table>
+          </el-col>
+        </el-row>
+      </el-card>
+
+      <!-- 寤惰鍒嗘瀽 -->
+      <el-card class="report-section">
+        <template #header>
+          <span>寤惰鍒嗘瀽</span>
+        </template>
+        <el-row :gutter="20">
+          <el-col :span="12">
+            <div class="delay-stats">
+              <div class="delay-item">
+                <div class="delay-label">寤惰浠诲姟鏁�</div>
+                <div class="delay-value">{{ reportData.delayAnalysis.delayedTasks }}</div>
+              </div>
+              <div class="delay-item">
+                <div class="delay-label">骞冲潎寤惰澶╂暟</div>
+                <div class="delay-value">{{ reportData.delayAnalysis.avgDelayDays }}</div>
+              </div>
+              <div class="delay-item">
+                <div class="delay-label">鏈�澶у欢璇ぉ鏁�</div>
+                <div class="delay-value">{{ reportData.delayAnalysis.maxDelayDays }}</div>
+              </div>
+            </div>
+          </el-col>
+          <el-col :span="12">
+            <div class="delay-reasons">
+              <h4>涓昏寤惰鍘熷洜</h4>
+              <ul>
+                <li v-for="reason in reportData.delayAnalysis.reasons" :key="reason.reason">
+                  {{ reason.reason }} ({{ reason.count }}娆�)
+                </li>
+              </ul>
+            </div>
+          </el-col>
+        </el-row>
+      </el-card>
+
+      <!-- 鍥㈤槦缁╂晥 -->
+      <el-card class="report-section">
+        <template #header>
+          <span>鍥㈤槦缁╂晥</span>
+        </template>
+        <el-table :data="reportData.teamPerformance" size="small">
+          <el-table-column prop="name" label="鎴愬憳濮撳悕" />
+          <el-table-column prop="completedTasks" label="瀹屾垚浠诲姟鏁�" />
+          <el-table-column prop="completionRate" label="瀹屾垚鐜�" width="100">
+            <template #default="{ row }">
+              <el-progress :percentage="row.completionRate" :show-text="false" />
+              <span style="margin-left: 10px;">{{ row.completionRate }}%</span>
+            </template>
+          </el-table-column>
+          <el-table-column prop="performance" label="缁╂晥璇勭骇" width="100">
+            <template #default="{ row }">
+              <el-tag :type="getPerformanceType(row.performance)">
+                {{ row.performance }}
+              </el-tag>
+            </template>
+          </el-table-column>
+        </el-table>
+      </el-card>
+
+      <!-- 鎬荤粨涓庡缓璁� -->
+      <el-card class="report-section">
+        <template #header>
+          <span>鎬荤粨涓庡缓璁�</span>
+        </template>
+        <div class="summary-content">
+          <h4>椤圭洰鎬荤粨</h4>
+          <p>{{ reportData.summary.conclusion }}</p>
+          
+          <h4>鏀硅繘寤鸿</h4>
+          <ul>
+            <li v-for="suggestion in reportData.summary.suggestions" :key="suggestion">
+              {{ suggestion }}
+            </li>
+          </ul>
+        </div>
+      </el-card>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, reactive, onMounted } from 'vue'
+import { Document, Download, Refresh } from '@element-plus/icons-vue'
+import { ElMessage } from 'element-plus'
+
+// 鍝嶅簲寮忔暟鎹�
+const generating = ref(false)
+const reportGenerated = ref(false)
+
+// 鎶ュ憡閰嶇疆
+const reportConfig = reactive({
+  projectId: '',
+  dateRange: []
+})
+
+// 椤圭洰鍒楄〃
+const projectList = ref([
+  { id: 1, name: '浜у搧搴撳瓨绠$悊绯荤粺' },
+  { id: 2, name: '瀹㈡埛鍏崇郴绠$悊骞冲彴' },
+  { id: 3, name: '璐㈠姟绠$悊绯荤粺鍗囩骇' },
+  { id: 4, name: '绉诲姩绔簲鐢ㄥ紑鍙�' }
+])
+
+// 鎶ュ憡鏁版嵁
+const reportData = ref({})
+
+// 妯℃嫙鎶ュ憡鏁版嵁
+const mockReportData = {
+  projectInfo: {
+    name: '浜у搧搴撳瓨绠$悊绯荤粺',
+    manager: '寮犱笁',
+    startDate: '2024-01-01',
+    endDate: '2024-03-31',
+    status: '宸插畬鎴�',
+    budget: '楼500,000'
+  },
+  taskStats: {
+    total: 45,
+    completed: 38,
+    inProgress: 5,
+    pending: 2,
+    completionRate: 84
+  },
+  issueStats: {
+    total: 12,
+    resolved: 9,
+    pending: 3,
+    topIssues: [
+      { title: '鏁版嵁搴撹繛鎺ヨ秴鏃�', severity: '楂�', status: '宸茶В鍐�' },
+      { title: '鍓嶇椤甸潰鍝嶅簲鎱�', severity: '涓�', status: '宸茶В鍐�' },
+      { title: '鏉冮檺楠岃瘉寮傚父', severity: '楂�', status: '寰呰В鍐�' },
+      { title: '鎶ヨ〃瀵煎嚭鍔熻兘缂哄け', severity: '涓�', status: '寰呰В鍐�' }
+    ]
+  },
+  delayAnalysis: {
+    delayedTasks: 8,
+    avgDelayDays: 3.5,
+    maxDelayDays: 12,
+    reasons: [
+      { reason: '闇�姹傚彉鏇�', count: 3 },
+      { reason: '鎶�鏈毦棰�', count: 2 },
+      { reason: '璧勬簮涓嶈冻', count: 2 },
+      { reason: '澶栭儴渚濊禆', count: 1 }
+    ]
+  },
+  teamPerformance: [
+    { name: '鏉庡洓', completedTasks: 12, completionRate: 92, performance: '浼樼' },
+    { name: '鐜嬩簲', completedTasks: 10, completionRate: 85, performance: '鑹ソ' },
+    { name: '璧靛叚', completedTasks: 8, completionRate: 78, performance: '鑹ソ' },
+    { name: '閽变竷', completedTasks: 8, completionRate: 72, performance: '涓�鑸�' }
+  ],
+  summary: {
+    conclusion: '鏈」鐩暣浣撴墽琛屾儏鍐佃壇濂斤紝浠诲姟瀹屾垚鐜囪揪鍒�84%锛屽洟闃熷崗浣滄晥鐜囪緝楂樸�備富瑕侀棶棰橀泦涓湪鎶�鏈疄鐜板拰闇�姹傚彉鏇存柟闈紝閫氳繃鍙婃椂娌熼�氬拰鎶�鏈敾鍏筹紝澶ч儴鍒嗛棶棰樺凡寰楀埌瑙e喅銆�',
+    suggestions: [
+      '鍔犲己闇�姹傚垎鏋愰樁娈电殑宸ヤ綔锛屽噺灏戝悗鏈熼渶姹傚彉鏇�',
+      '寤虹珛鎶�鏈毦棰橀璀︽満鍒讹紝鎻愬墠璇嗗埆鍜岃В鍐虫妧鏈闄�',
+      '浼樺寲鍥㈤槦璧勬簮閰嶇疆锛屾彁楂樻暣浣撳伐浣滄晥鐜�',
+      '瀹屽杽椤圭洰绠$悊娴佺▼锛屽姞寮鸿繃绋嬬洃鎺�'
+    ]
+  }
+}
+
+// 鐢熸垚鎶ュ憡
+const generateReport = async () => {
+  if (!reportConfig.projectId) {
+    ElMessage.warning('璇烽�夋嫨椤圭洰')
+    return
+  }
+  
+  generating.value = true
+  
+  // 妯℃嫙鐢熸垚鎶ュ憡鐨勮繃绋�
+  setTimeout(() => {
+    reportData.value = mockReportData
+    reportGenerated.value = true
+    generating.value = false
+    ElMessage.success('鎶ュ憡鐢熸垚鎴愬姛')
+  }, 2000)
+}
+
+// 瀵煎嚭鎶ュ憡
+const exportReport = () => {
+  ElMessage.success('鎶ュ憡瀵煎嚭鍔熻兘寮�鍙戜腑...')
+}
+
+// 閲嶇疆閰嶇疆锛岀敓鎴愭柊鎶ュ憡
+const resetConfig = () => {
+  reportGenerated.value = false
+  reportData.value = {}
+  // 閲嶇疆閰嶇疆涓洪粯璁ゅ��
+  reportConfig.projectId = 1
+  const endDate = new Date()
+  const startDate = new Date()
+  startDate.setDate(startDate.getDate() - 30)
+  reportConfig.dateRange = [
+    startDate.toISOString().split('T')[0],
+    endDate.toISOString().split('T')[0]
+  ]
+  ElMessage.success('宸查噸缃厤缃紝鍙互鐢熸垚鏂版姤鍛�')
+}
+
+// 鑾峰彇鐘舵�佺被鍨�
+const getStatusType = (status) => {
+  const statusMap = {
+    '宸插畬鎴�': 'success',
+    '杩涜涓�': 'warning',
+    '鏈紑濮�': 'info',
+    '宸叉殏鍋�': 'danger'
+  }
+  return statusMap[status] || 'info'
+}
+
+// 鑾峰彇涓ラ噸绋嬪害绫诲瀷
+const getSeverityType = (severity) => {
+  const severityMap = {
+    '楂�': 'danger',
+    '涓�': 'warning',
+    '浣�': 'success'
+  }
+  return severityMap[severity] || 'info'
+}
+
+// 鑾峰彇缁╂晥绫诲瀷
+const getPerformanceType = (performance) => {
+  const performanceMap = {
+    '浼樼': 'success',
+    '鑹ソ': 'primary',
+    '涓�鑸�': 'warning',
+    '寰呮敼杩�': 'danger'
+  }
+  return performanceMap[performance] || 'info'
+}
+
+// 缁勪欢鎸傝浇鏃跺垵濮嬪寲
+onMounted(() => {
+  // 璁剧疆榛樿椤圭洰
+  reportConfig.projectId = 1
+  // 璁剧疆榛樿鏃ユ湡鑼冨洿锛堟渶杩�30澶╋級
+  const endDate = new Date()
+  const startDate = new Date()
+  startDate.setDate(startDate.getDate() - 30)
+  reportConfig.dateRange = [
+    startDate.toISOString().split('T')[0],
+    endDate.toISOString().split('T')[0]
+  ]
+})
+</script>
+
+<style scoped>
+.report-generation {
+  padding: 20px;
+}
+
+.page-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  margin-bottom: 20px;
+}
+
+.page-header h2 {
+  margin: 0;
+  color: #303133;
+}
+
+.header-actions {
+  display: flex;
+  gap: 10px;
+}
+
+.config-card {
+  margin-bottom: 20px;
+}
+
+.report-content {
+  display: flex;
+  flex-direction: column;
+  gap: 20px;
+}
+
+.report-section {
+  margin-bottom: 20px;
+}
+
+.completion-stats {
+  display: flex;
+  justify-content: space-around;
+  padding: 20px 0;
+}
+
+.stat-item {
+  text-align: center;
+}
+
+.stat-label {
+  font-size: 14px;
+  color: #909399;
+  margin-bottom: 8px;
+}
+
+.stat-value {
+  font-size: 24px;
+  font-weight: bold;
+  color: #303133;
+}
+
+.stat-value.completed {
+  color: #67c23a;
+}
+
+.stat-value.in-progress {
+  color: #e6a23c;
+}
+
+.stat-value.pending {
+  color: #909399;
+}
+
+.completion-rate {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  height: 200px;
+}
+
+.percentage-value {
+  font-size: 20px;
+  font-weight: bold;
+  color: #409eff;
+}
+
+.percentage-label {
+  font-size: 12px;
+  color: #909399;
+  margin-top: 4px;
+}
+
+.issue-summary {
+  display: flex;
+  flex-direction: column;
+  gap: 20px;
+  padding: 20px 0;
+}
+
+.summary-item {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+}
+
+.summary-label {
+  font-size: 14px;
+  color: #606266;
+}
+
+.summary-value {
+  font-size: 18px;
+  font-weight: bold;
+  color: #303133;
+}
+
+.summary-value.resolved {
+  color: #67c23a;
+}
+
+.summary-value.pending {
+  color: #e6a23c;
+}
+
+.delay-stats {
+  display: flex;
+  flex-direction: column;
+  gap: 20px;
+  padding: 20px 0;
+}
+
+.delay-item {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+}
+
+.delay-label {
+  font-size: 14px;
+  color: #606266;
+}
+
+.delay-value {
+  font-size: 18px;
+  font-weight: bold;
+  color: #e6a23c;
+}
+
+.delay-reasons h4 {
+  margin: 0 0 15px 0;
+  color: #303133;
+}
+
+.delay-reasons ul {
+  margin: 0;
+  padding-left: 20px;
+}
+
+.delay-reasons li {
+  margin-bottom: 8px;
+  color: #606266;
+}
+
+.summary-content h4 {
+  margin: 0 0 10px 0;
+  color: #303133;
+}
+
+.summary-content p {
+  line-height: 1.6;
+  color: #606266;
+  margin-bottom: 20px;
+}
+
+.summary-content ul {
+  margin: 0;
+  padding-left: 20px;
+}
+
+.summary-content li {
+  margin-bottom: 8px;
+  color: #606266;
+  line-height: 1.5;
+}
+</style>
\ No newline at end of file
diff --git a/src/views/collaborativeApproval/rpaManagement/index.vue b/src/views/collaborativeApproval/rpaManagement/index.vue
index 51cef73..9e5b504 100644
--- a/src/views/collaborativeApproval/rpaManagement/index.vue
+++ b/src/views/collaborativeApproval/rpaManagement/index.vue
@@ -22,6 +22,7 @@
         </el-button>
       </div>
       <div>
+        <el-button @click="handleExport" style="margin-right: 10px">瀵煎嚭</el-button>
         <el-button type="primary" @click="openForm('add')">鏂板</el-button>
         <el-button type="danger" plain @click="handleDelete">鍒犻櫎</el-button>
       </div>
@@ -89,10 +90,10 @@
 
 <script setup>
 import { Search } from "@element-plus/icons-vue";
-import { onMounted, ref, reactive, toRefs } from "vue";
+import { onMounted, ref, reactive, toRefs, getCurrentInstance } from "vue";
 import { ElMessage, ElMessageBox } from "element-plus";
 import PIMTable from "@/components/PIMTable/PIMTable.vue";
-
+import {listRpa, addRpa, updateRpa, delRpa, delRpaBatch} from "@/api/collaborativeApproval/rpaManagement.js";
 // 鍝嶅簲寮忔暟鎹�
 const data = reactive({
   searchForm: {
@@ -100,20 +101,17 @@
     status: "",
   },
   form: {
-    id: "",
     programName: "",
-    status: "stopped",
-    description: "",
-    createTime: "",
+    status: "",
+    description: ""
   },
   dialogVisible: false,
   dialogTitle: "",
   dialogType: "add",
-  selectedIds: [],
   tableLoading: false,
   page: {
     current: 1,
-    size: 100,
+    size: 20,
     total: 0,
   },
   tableData: [],
@@ -123,6 +121,8 @@
 
 // 琛ㄥ崟寮曠敤
 const formRef = ref();
+// 閫夋嫨鐨勮鏁版嵁
+const selectedRows = ref([]);
 
 // 琛ㄥ崟楠岃瘉瑙勫垯
 const rules = {
@@ -179,7 +179,7 @@
     label: "鎿嶄綔",
     align: "center",
     fixed: "right",
-    width: 230,
+    width: 150,
     operation: [
       {
         name: "缂栬緫",
@@ -188,50 +188,26 @@
           openForm("edit", row);
         }
       },
-      {
-        name: "寮�濮�",
-        type: "text",
-        clickFun: (row) => {
-          handleStart(row);
-        },
-        disabled: (row) => row.status !== 'stopped'
-      },
-      {
-        name: "鍋滄",
-        type: "text",
-        clickFun: (row) => {
-          handleStop(row);
-        },
-        disabled: (row) => row.status === 'stopped'
-      }
+      // {
+      //   name: "寮�濮�",
+      //   type: "text",
+      //   clickFun: (row) => {
+      //     handleStart(row);
+      //   },
+      //   disabled: (row) => row.status !== 'stopped'
+      // },
+      // {
+      //   name: "鍋滄",
+      //   type: "text",
+      //   clickFun: (row) => {
+      //     handleStop(row);
+      //   },
+      //   disabled: (row) => row.status === 'stopped'
+      // }
     ]
   }
 ]);
 
-// 妯℃嫙鏁版嵁
-const mockData = [
-  {
-    id: "1",
-    programName: "璁㈠崟澶勭悊RPA",
-    status: "running",
-    description: "鑷姩澶勭悊瀹㈡埛璁㈠崟锛屽寘鎷獙璇併�佸垎閰嶅拰纭",
-    createTime: "2024-01-15 10:30:00"
-  },
-  {
-    id: "2",
-    programName: "搴撳瓨鍚屾RPA",
-    status: "stopped",
-    description: "鍚屾澶氫釜浠撳簱鐨勫簱瀛樻暟鎹紝纭繚鏁版嵁涓�鑷存��",
-    createTime: "2024-01-14 15:20:00"
-  },
-  {
-    id: "3",
-    programName: "鎶ヨ〃鐢熸垚RPA",
-    status: "error",
-    description: "鑷姩鐢熸垚姣忔棩閿�鍞姤琛ㄥ拰搴撳瓨鎶ヨ〃",
-    createTime: "2024-01-13 09:15:00"
-  }
-];
 
 // 鐢熷懡鍛ㄦ湡
 onMounted(() => {
@@ -240,32 +216,20 @@
 
 // 鏌ヨ鏁版嵁
 const handleQuery = () => {
-  page.value.current = 1;
+  // page.value.current = 1;
   getList();
 };
 
 const getList = () => {
   tableLoading.value = true;
-  
-  // 妯℃嫙API璋冪敤寤惰繜
-  setTimeout(() => {
-    let filteredData = [...mockData];
-    
-    // 鏍规嵁鎼滅储鏉′欢杩囨护鏁版嵁
-    if (searchForm.value.programName) {
-      filteredData = filteredData.filter(item => 
-        item.programName.toLowerCase().includes(searchForm.value.programName.toLowerCase())
-      );
-    }
-    
-    if (searchForm.value.status) {
-      filteredData = filteredData.filter(item => item.status === searchForm.value.status);
-    }
-    
-    tableData.value = filteredData;
-    page.value.total = filteredData.length;
+  listRpa({...page.value, ...searchForm.value})
+  .then(res => {
     tableLoading.value = false;
-  }, 500);
+    tableData.value = res.data.records
+    page.total = res.data.total;
+  }).catch(err => {
+    tableLoading.value = false;
+  })
 };
 
 // 鍒嗛〉澶勭悊
@@ -277,23 +241,16 @@
 
 // 閫夋嫨鍙樺寲澶勭悊
 const handleSelectionChange = (selection) => {
-  selectedIds.value = selection.map(item => item.id);
+  selectedRows.value = selection;
 };
 
 // 鎵撳紑琛ㄥ崟
 const openForm = (type, row) => {
   dialogType.value = type;
   dialogVisible.value = true;
-  
+
   if (type === "add") {
     dialogTitle.value = "娣诲姞RPA";
-    form.value = {
-      id: "",
-      programName: "",
-      status: "stopped",
-      description: "",
-      createTime: "",
-    };
   } else {
     dialogTitle.value = "缂栬緫RPA";
     form.value = { ...row };
@@ -303,33 +260,38 @@
 // 鎻愪氦琛ㄥ崟
 const submitForm = async () => {
   if (!formRef.value) return;
-  
+
   try {
     await formRef.value.validate();
-    
+
     if (dialogType.value === "add") {
       // 娣诲姞鏂癛PA
-      const newRPA = {
-        id: Date.now().toString(),
-        programName: form.value.programName,
-        status: form.value.status,
-        description: form.value.description,
-        createTime: new Date().toLocaleString(),
-      };
-      
-      mockData.unshift(newRPA);
-      ElMessage.success("RPA娣诲姞鎴愬姛");
+      addRpa({...form.value}).then(res => {
+        if(res.code == 200){
+          ElMessage.success("娣诲姞鎴愬姛");
+            form.value = {
+            programName: "",
+            status: "",
+            description: ""
+          },
+          dialogVisible.value = false;
+          getList();
+        }
+      }).catch(err => {
+        ElMessage.error(err.msg);
+      })
     } else {
       // 缂栬緫RPA
-      const index = mockData.findIndex(item => item.id === form.value.id);
-      if (index !== -1) {
-        mockData[index] = { ...form.value };
-        ElMessage.success("RPA鏇存柊鎴愬姛");
-      }
+      updateRpa({...form.value}).then(res => {
+        if(res.code == 200){
+          ElMessage.success("鏇存柊鎴愬姛");
+          dialogVisible.value = false;
+          getList();
+        }
+      }).catch(err => {
+        ElMessage.error(err.msg);
+      })
     }
-    
-    dialogVisible.value = false;
-    getList();
   } catch (error) {
     console.error("琛ㄥ崟楠岃瘉澶辫触:", error);
   }
@@ -368,33 +330,37 @@
 // 鍒犻櫎RPA
 const handleDelete = () => {
   let ids = [];
-  if (selectedIds.value.length > 0) {
-    ids = selectedIds.value.map((item) => item.id);
-  } else {
-    ElMessage.warning("璇烽�夋嫨瑕佸垹闄ょ殑RPA");
-    return;
-  }
-  
-  ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "鍒犻櫎", {
-    confirmButtonText: "纭",
-    cancelButtonText: "鍙栨秷",
-    type: "warning",
-  }).then(() => {
-    // 浠庢ā鎷熸暟鎹腑鍒犻櫎閫変腑鐨勯」
-    ids.forEach(id => {
-      const index = mockData.findIndex(item => item.id === id);
-      if (index !== -1) {
-        mockData.splice(index, 1);
-      }
-    });
-    
-    ElMessage.success("鍒犻櫎鎴愬姛");
-    selectedIds.value = [];
-    getList();
-  }).catch(() => {
-    // 鐢ㄦ埛鍙栨秷
-  });
+	if (selectedRows.value.length > 0) {
+		ids = selectedRows.value.map((item) => item.id);
+	} else {
+		proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
+		return;
+	}
+  ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "鍒犻櫎鎻愮ず", {
+		confirmButtonText: "纭",
+		cancelButtonText: "鍙栨秷",
+		type: "warning",
+	})
+	.then(() => {
+		delRpa(ids).then((res) => {
+				if(res.code == 200){
+					ElMessage.success("鍒犻櫎鎴愬姛");
+					getList();
+				}
+			}).catch(err => {
+				ElMessage.error(err.msg);
+			})
+	})
+	.catch(() => {
+		proxy.$modal.msg("宸插彇娑�");
+	});
 };
+
+// 瀵煎嚭鍔熻兘
+const { proxy } = getCurrentInstance()
+const handleExport = () => {
+  proxy.download('/rpaProcessAutomation/export', { ...searchForm.value }, 'RPA绠$悊.xlsx')
+}
 </script>
 
 <style scoped></style>
diff --git a/src/views/collaborativeApproval/rulesRegulationsManagement/index.vue b/src/views/collaborativeApproval/rulesRegulationsManagement/index.vue
new file mode 100644
index 0000000..91a6468
--- /dev/null
+++ b/src/views/collaborativeApproval/rulesRegulationsManagement/index.vue
@@ -0,0 +1,584 @@
+<template>
+  <div class="app-container">
+    
+        <!-- 瑙勭珷鍒跺害绠$悊-->
+          <el-card class="box-card">
+            <template #header>
+              <div class="card-header">
+                <span>瑙勭珷鍒跺害鍙戝竷</span>
+              </div>
+            </template>
+            <div class="tab-content">
+              <el-row :gutter="20" class="mb-20">
+                <span class="ml-10">鍒跺害鏍囬锛�</span>
+                <el-col :span="6">
+                  <el-input v-model="regulationSearchForm.title" placeholder="璇疯緭鍏ュ埗搴︽爣棰�" clearable />
+                </el-col>
+                <span class="search_title">鍒跺害鍒嗙被锛�</span>
+                <el-col :span="4">
+                  <el-select v-model="regulationSearchForm.category" placeholder="鍒跺害鍒嗙被" clearable>
+                    <el-option label="浜轰簨鍒跺害" value="hr" />
+                    <el-option label="璐㈠姟鍒跺害" value="finance" />
+                    <el-option label="瀹夊叏鍒跺害" value="safety" />
+                    <el-option label="鎶�鏈埗搴�" value="tech" />
+                  </el-select>
+                </el-col>
+                <el-col :span="8">
+                  <el-button type="primary" @click="searchRegulations">鎼滅储</el-button>
+                  <el-button @click="resetRegulationSearch">閲嶇疆</el-button>
+                  <el-button @click="handleExport">瀵煎嚭</el-button>
+                  <el-button type="success" @click="handleAdd">
+                    鍙戝竷鍒跺害
+                  </el-button>
+                </el-col>
+              </el-row>
+
+              <el-table :data="regulations" border v-loading="tableLoading"  style="width: 100%">
+                <el-table-column prop="regulationNum" label="鍒跺害缂栧彿" width="120" />
+                <el-table-column prop="title" label="鍒跺害鏍囬" min-width="150" />
+                <el-table-column prop="category" label="鍒嗙被" width="120">
+                  <template #default="scope">
+                    <el-tag>{{ getCategoryText(scope.row.category) }}</el-tag>
+                  </template>
+                </el-table-column>
+                <el-table-column prop="version" label="鐗堟湰" width="120" />
+                <el-table-column prop="createUserName" label="鍙戝竷浜�" width="120" />
+                <el-table-column prop="createTime" label="鍙戝竷鏃堕棿" width="180" />
+                <el-table-column prop="status" label="鐘舵��" width="100">
+                  <template #default="scope">
+                    <el-tag :type="scope.row.status === 'active' ? 'success' : 'info'">
+                      {{ scope.row.status === 'active' ? '鐢熸晥涓�' : '宸插簾姝�' }}
+                    </el-tag>
+                  </template>
+                </el-table-column>
+                <el-table-column prop="readCount" label="宸茶浜烘暟" width="100" />
+                <el-table-column label="鎿嶄綔" width="320" fixed="right">
+                  <template #default="scope">
+                    <el-button link @click="viewRegulation(scope.row)">鏌ョ湅</el-button>
+                    <el-button link type="primary" @click="handleEdit(scope.row)">缂栬緫</el-button>
+                    <el-button link type="danger" @click="repealEdit(scope.row)">搴熷純</el-button>
+                    <el-button link type="success" @click="viewVersionHistory(scope.row)">鐗堟湰鍘嗗彶</el-button>
+                    <el-button link type="warning" @click="viewReadStatus(scope.row)">闃呰鐘舵��</el-button>
+                    <el-button link type="primary" @click="openFileDialog(scope.row)">闄勪欢</el-button>
+                  </template>
+                </el-table-column>
+              </el-table>
+            </div>
+          </el-card>
+
+    <!-- 鐢ㄥ嵃鐢宠瀵硅瘽妗嗭紙宸茬Щ闄わ級 -->
+
+    <!-- 瑙勭珷鍒跺害鍙戝竷瀵硅瘽妗� -->
+    <el-dialog v-model="showRegulationDialog" :title="operationType === 'add' ? '鍙戝竷鍒跺害' : '缂栬緫鍒跺害'" width="800px">
+      <el-form :model="regulationForm" :rules="regulationRules" ref="regulationFormRef" label-width="100px">
+        <el-form-item label="鍒跺害缂栧彿" prop="regulationNum">
+          <el-input v-model="regulationForm.regulationNum" placeholder="璇疯緭鍏ュ埗搴︾紪鍙�" />
+        </el-form-item>
+        <el-form-item label="鍒跺害鏍囬" prop="title">
+          <el-input v-model="regulationForm.title" placeholder="璇疯緭鍏ュ埗搴︽爣棰�" />
+        </el-form-item>
+        <el-form-item label="鍒跺害鍒嗙被" prop="category">
+          <el-select v-model="regulationForm.category" placeholder="璇烽�夋嫨鍒跺害鍒嗙被" style="width: 100%">
+            <el-option label="浜轰簨鍒跺害" value="hr" />
+            <el-option label="璐㈠姟鍒跺害" value="finance" />
+            <el-option label="瀹夊叏鍒跺害" value="safety" />
+            <el-option label="鎶�鏈埗搴�" value="tech" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="鍒跺害鍐呭" prop="content">
+          <el-input v-model="regulationForm.content" type="textarea" :rows="10" placeholder="璇疯緭鍏ュ埗搴﹁缁嗗唴瀹�" />
+        </el-form-item>
+        <el-form-item label="鍒跺害鐗堟湰" prop="version">
+          <el-input v-model="regulationForm.version" placeholder="璇疯緭鍏ュ埗搴︾増鏈�" />
+        </el-form-item>
+        <el-form-item label="鐢熸晥鏃堕棿" prop="effectiveTime">
+          <el-date-picker v-model="regulationForm.effectiveTime" type="datetime" format="YYYY-MM-DD HH:mm:ss"
+             value-format="YYYY-MM-DD HH:mm:ss" placeholder="閫夋嫨鐢熸晥鏃堕棿" style="width: 100%" />
+        </el-form-item>
+        <el-form-item label="閫傜敤鑼冨洿" prop="scope">
+          <el-checkbox-group v-model="regulationForm.scope">
+            <el-checkbox label="all">鍏ㄤ綋鍛樺伐</el-checkbox>
+            <el-checkbox label="manager">绠$悊灞�</el-checkbox>
+            <el-checkbox label="hr">浜轰簨閮ㄩ棬</el-checkbox>
+            <el-checkbox label="finance">璐㈠姟閮ㄩ棬</el-checkbox>
+            <el-checkbox label="tech">鎶�鏈儴闂�</el-checkbox>
+          </el-checkbox-group>
+        </el-form-item>
+        <el-form-item label="鏄惁闇�瑕佺‘璁�" prop="requireConfirm">
+          <el-switch v-model="regulationForm.requireConfirm" />
+          <span class="ml-10">寮�鍚悗鍛樺伐闇�瑕侀槄璇荤‘璁�</span>
+        </el-form-item>
+      </el-form>
+      <template #footer>
+        <span class="dialog-footer">
+          <el-button @click="showRegulationDialog = false">鍙栨秷</el-button>
+          <el-button type="primary" @click="submitRegulation">鍙戝竷鍒跺害</el-button>
+        </span>
+      </template>
+    </el-dialog>
+
+    <!-- 鐢ㄥ嵃璇︽儏瀵硅瘽妗嗭紙宸茬Щ闄わ級 -->
+
+    <!-- 瑙勭珷鍒跺害璇︽儏瀵硅瘽妗� -->
+    <el-dialog v-model="showRegulationDetailDialog" title="瑙勭珷鍒跺害璇︽儏" width="800px">
+      <div v-if="currentRegulationDetail">
+        <el-descriptions :column="2" border>
+          <el-descriptions-item label="鍒跺害缂栧彿">{{ currentRegulationDetail.id }}</el-descriptions-item>
+          <el-descriptions-item label="鍒跺害鏍囬">{{ currentRegulationDetail.title }}</el-descriptions-item>
+          <el-descriptions-item label="鍒嗙被">{{ getCategoryText(currentRegulationDetail.category) }}</el-descriptions-item>
+          <el-descriptions-item label="鐗堟湰">{{ currentRegulationDetail.version }}</el-descriptions-item>
+          <el-descriptions-item label="鍙戝竷浜�">{{ currentRegulationDetail.createUserName }}</el-descriptions-item>
+          <el-descriptions-item label="鍙戝竷鏃堕棿">{{ currentRegulationDetail.createTime }}</el-descriptions-item>
+        </el-descriptions>
+        <div class="mt-20">
+          <h4>鍒跺害鍐呭</h4>
+          <div class="regulation-content">{{ currentRegulationDetail.content }}</div>
+        </div>
+        <!-- 濡傛灉tableData>0 鏄剧ず -->
+        <div style="margin: 10px 0;" v-if="tableData && tableData.length > 0" >
+          <el-button type="success" @click="resetForm(currentRegulationDetail)">纭鏌ョ湅</el-button>
+        </div>
+      </div>
+    </el-dialog>
+
+    <!-- 鐗堟湰鍘嗗彶瀵硅瘽妗� -->
+    <el-dialog v-model="showVersionHistoryDialog" title="鐗堟湰鍘嗗彶" width="800px">
+      <el-table :data="versionHistory" style="width: 100%;margin-bottom: 10px">
+        <el-table-column prop="version" label="鐗堟湰鍙�" width="100" />
+        <el-table-column prop="updateTime" label="鏇存柊鏃堕棿" width="180" />
+        <el-table-column prop="createUserName" label="鏇存柊浜�" width="120" />
+        <el-table-column prop="changeLog" label="鍙樻洿璇存槑">
+          <template #default="scope">
+            <el-tag :type="scope.row.status === 'active' ? 'success' : 'info'">
+              {{ scope.row.status === 'active' ? '鐢熸晥涓�' : '宸插簾姝�' }}
+            </el-tag>
+          </template>
+        </el-table-column>
+      </el-table>
+    </el-dialog>
+
+    <!-- 闃呰鐘舵�佸璇濇 -->
+    <el-dialog v-model="showReadStatusDialog" title="闃呰鐘舵��" width="800px">
+      <el-table :data="readStatusList" style="width: 100%;margin-bottom: 10px">
+        <el-table-column prop="employee" label="鍛樺伐濮撳悕" width="120" />
+        <el-table-column prop="department" label="鎵�灞為儴闂�" width="150" />
+        <el-table-column prop="createTime" label="闃呰鏃堕棿" width="180" />
+        <el-table-column prop="confirmTime" label="纭鏃堕棿" width="180" />
+        <el-table-column prop="status" label="鐘舵��" width="100">
+          <template #default="scope">
+            <el-tag :type="scope.row.status === 'confirmed' ? 'success' : 'warning'">
+              {{ scope.row.status === 'confirmed' ? '宸茬‘璁�' : '鏈‘璁�' }}
+            </el-tag>
+          </template>
+        </el-table-column>
+      </el-table>
+    </el-dialog>
+
+    <FileListDialog
+      ref="fileListDialogRef"
+      v-model="fileDialogVisible"
+      :show-upload-button="true"
+      :show-delete-button="true"
+      :delete-method="handleAttachmentDelete"
+      :rules-regulations-management-id="currentFileRuleId"
+      :name-column-label="'闄勪欢鍚嶇О'"
+      @upload="handleAttachmentUpload"
+    />
+  </div>
+</template>
+
+<script setup>
+import { ref, reactive, onMounted, getCurrentInstance } from 'vue'
+import { ElMessage, ElMessageBox } from 'element-plus'
+import { listRuleManagement,addRuleManagement,updateRuleManagement,delRuleManagement,getReadingStatusByRuleId,addReadingStatus,updateReadingStatus  } from '@/api/collaborativeApproval/sealManagement.js'
+import FileListDialog from '@/components/Dialog/FileListDialog.vue'
+import { listRuleFiles, delRuleFile, addRuleFile } from '@/api/collaborativeApproval/rulesRegulationsManagementFile.js'
+
+// 鍝嶅簲寮忔暟鎹�
+const operationType = ref('add')
+const tableData = ref([])
+const tableLoading = ref(false)
+// 鍒嗛〉鍙傛暟
+const page = reactive({
+  current: 1,
+  size: 10,
+  total: 0
+})
+// 闄勪欢寮圭獥
+const fileDialogVisible = ref(false)
+const fileListDialogRef = ref(null)
+const currentFileRuleId = ref(null)
+const filePage = reactive({
+  current: 1,
+  size: 10,
+  total: 0
+})
+// 瑙勭珷鍒跺害鐩稿叧
+const showRegulationDialog = ref(false)
+const showRegulationDetailDialog = ref(false)
+const showVersionHistoryDialog = ref(false)
+const showReadStatusDialog = ref(false)
+const currentRegulationDetail = ref(null)
+const regulationFormRef = ref()
+const regulationForm = reactive({
+  id: '',
+  regulationNum: '',
+  title: '',
+  category: '',
+  content: '',
+  version: '',
+  status: 'active',
+  readCount: 0,
+  effectiveTime: '',
+  scope: [],
+  requireConfirm: false
+})
+
+const readStatus = ref({
+  id: '',
+  ruleId: '',
+  employee: '',
+  department: '',
+  createTime: '',
+  confirmTime: '',
+  status: 'unconfirmed'
+})
+
+const regulationRules = {
+  title: [{ required: true, message: '璇疯緭鍏ュ埗搴︽爣棰�', trigger: 'blur' }],
+  category: [{ required: true, message: '璇烽�夋嫨鍒跺害鍒嗙被', trigger: 'change' }],
+  content: [{ required: true, message: '璇疯緭鍏ュ埗搴﹀唴瀹�', trigger: 'blur' }],
+  effectiveTime: [{ required: true, message: '璇烽�夋嫨鐢熸晥鏃堕棿', trigger: 'change' }],
+  scope: [{ required: true, message: '璇烽�夋嫨閫傜敤鑼冨洿', trigger: 'change' }]
+}
+
+const regulationSearchForm = reactive({
+  title: '',
+  category: ''
+})
+
+const regulations = ref([])
+
+const versionHistory = ref([])
+
+const readStatusList = ref([])
+  // { employee: '闄堝織寮�', department: '閿�鍞儴', readTime: '2025-01-11 10:30:00', confirmTime: '2025-01-11 10:35:00', status: 'confirmed' },
+  // { employee: '鍒橀泤濠�', department: '鎶�鏈儴', readTime: '2025-01-11 14:20:00', confirmTime: '', status: 'unconfirmed' },
+  // { employee: '鐜嬪缓鍥�', department: '璐㈠姟閮�', readTime: '2025-01-12 09:15:00', confirmTime: '2025-01-12 09:20:00', status: 'confirmed' }
+
+// 鍒跺害鍒嗙被
+const getCategoryText = (category) => {
+  const categoryMap = {
+    hr: '浜轰簨鍒跺害',
+    finance: '璐㈠姟鍒跺害',
+    safety: '瀹夊叏鍒跺害',
+    tech: '鎶�鏈埗搴�'
+  }
+  return categoryMap[category] || '鏈煡'
+}
+// 鎼滅储鍒跺害
+const searchRegulations = () => {
+  page.current=1
+  getRegulationList()
+}
+// 閲嶇疆鍒跺害鎼滅储
+const resetRegulationSearch = () => {
+  regulationSearchForm.title = ''
+  regulationSearchForm.category = ''
+  searchRegulations()
+}
+// 鏂板
+const handleAdd = () => {
+  operationType.value = 'add'
+  resetRegulationForm()
+  showRegulationDialog.value = true
+}
+
+// 缂栬緫
+const handleEdit = (row) => {
+  operationType.value = 'edit'
+  Object.assign(regulationForm, row)
+  showRegulationDialog.value = true
+}
+// 搴熷純
+const repealEdit = (row) => {
+  operationType.value = 'edit'
+  Object.assign(regulationForm, row)
+  regulationForm.status = 'repealed'
+  ElMessageBox.confirm('纭搴熷純璇ュ埗搴︼紵', '鎻愮ず', {
+    confirmButtonText: '纭畾',
+    cancelButtonText: '鍙栨秷',
+    type: 'warning'
+  }).then(() => {
+    updateRuleManagement(regulationForm).then(res => {
+      if(res.code == 200){
+        ElMessage.success('鍒跺害搴熷純鎴愬姛')
+        // showRegulationDialog.value = false
+        getRegulationList()
+        resetRegulationForm()
+      }
+    })
+  }).catch(() => {
+    ElMessage({
+      type: 'info',
+      message: '宸插彇娑堝簾寮�'
+    })
+  })
+}
+// 鍙戝竷鍒跺害
+const submitRegulation = async () => {
+  try {
+    await regulationFormRef.value.validate()
+    if(operationType.value == 'add'){
+      addRuleManagement(regulationForm).then(res => {
+        if(res.code == 200){
+          ElMessage.success('鍒跺害鍙戝竷鎴愬姛')
+          showRegulationDialog.value = false
+          getRegulationList()
+          resetRegulationForm()
+        }
+      })
+    }else{
+      updateRuleManagement(regulationForm).then(res => {
+        if(res.code == 200){
+          ElMessage.success('鍒跺害缂栬緫鎴愬姛')
+          showRegulationDialog.value = false
+          resetRegulationForm()
+          getRegulationList()
+      }})}
+  }catch(err){
+    ElMessage.error(err.msg)
+  }
+} 
+//閲嶇疆鍒跺害琛ㄥ崟
+const resetRegulationForm = () => {
+  Object.assign(regulationForm, {
+    id: '',
+    regulationNum: '',
+    title: '',
+    category: '',
+    content: '',
+    version: '',
+    status: 'active',
+    readCount: 0,
+    effectiveTime: '',
+    scope: [],
+    requireConfirm: false
+})
+}
+
+
+// 鏌ョ湅鍒跺害鐗堟湰鍘嗗彶
+const viewVersionHistory = (row) => {
+  showVersionHistoryDialog.value = true
+  const params = {
+
+    category: row.category
+  }
+  listRuleManagement(page,params).then(res => {
+    if(res.code == 200){
+      versionHistory.value = res.data.records
+    }
+  })
+}
+// 鏌ョ湅鍒跺害璇︽儏
+const viewRegulation = (row) => {
+  currentRegulationDetail.value = row
+  showRegulationDetailDialog.value = true
+  getReadingStatusByRuleId(row.id).then(res => {
+    if(res.code == 200){
+      readStatusList.value = res.data
+      if(readStatusList.value.length==0 && tableData.value.length>0){
+          const params = {
+          ruleId: row.id,
+          employee: tableData.value[0].staffName,
+          department: tableData.value[0].postJob,
+          status: 'unconfirmed'
+        }
+        addReadingStatus(params).then(res => {
+          if(res.code == 200){
+            ElMessage.success('鍒跺害闃呰鎴愬姛')
+          }
+        })
+      }
+    }
+  })
+  
+}
+// 鏌ョ湅鍒跺害闃呰鐘舵��
+const viewReadStatus = (row) => {
+  showReadStatusDialog.value = true
+  //鏌ョ湅闃呰鐘舵�佸垪琛�
+  getReadingStatusByRuleId(row.id).then(res => {
+    if(res.code == 200){
+      readStatusList.value = res.data
+    }
+  })
+}
+
+//纭鏌ョ湅
+const resetForm = (row) => {
+  console.log("row",row)
+  row.readCount = row.readCount + 1
+  
+  updateRuleManagement(row).then(res => {
+    if(res.code == 200){
+      ElMessage.success('鏌ョ湅鏁伴噺淇敼鎴愬姛')
+      //淇敼闃呰鐘舵��
+      //鏍规嵁鍒跺害id鍜屽綋鍓嶇櫥褰曠殑鍛樺伐寰楀埌闃呰鐘舵��
+      // let item = readStatusList.value.filter(item => item.employee == tableData.value[0].staffName )
+      // if(item.length>0){
+      //   item[0].status = 'confirmed',
+      //   item[0].confirmTime = new Date().toISOString().replace('T', ' ').split('.')[0];
+      // }
+      // 绛涢�夊綋鍓嶅憳宸ュ搴旇鍒跺害鐨勯槄璇荤姸鎬佽褰�
+      let statusItem = readStatusList.value.find(item => item.employee === tableData.value[0].staffName && item.ruleId === row.id);
+
+      if (statusItem) {
+        // 濡傛灉鎵惧埌璁板綍锛屾洿鏂扮姸鎬佸拰纭鏃堕棿
+        statusItem.status = 'confirmed';
+        // 鏍煎紡鍖栨椂闂翠负"YYYY-MM-DD HH:mm:ss"鏍煎紡
+        const now = new Date();
+        statusItem.confirmTime = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')} ${String(now.getHours()).padStart(2, '0')}:${String(now.getMinutes()).padStart(2, '0')}:${String(now.getSeconds()).padStart(2, '0')}`;
+        // statusItem.confirmTime = new Date().toISOString().replace('T', ' ').split('.')[0];
+        
+        updateReadingStatus(statusItem).then(res => {
+          if(res.code == 200){
+            ElMessage.success('鍒跺害闃呰鐘舵�佷慨鏀规垚鍔�')
+          }
+        })
+      }
+
+    }
+  })
+}
+
+// 瀵煎嚭瑙勭珷鍒跺害
+const { proxy } = getCurrentInstance()
+const handleExport = () => {
+  proxy.download('/rulesRegulationsManagement/export', { ...regulationSearchForm }, '瑙勭珷鍒跺害.xlsx')
+}
+
+// 闄勪欢锛氭煡璇�
+const fetchRuleFiles = async (rulesRegulationsManagementId) => {
+  const params = {
+    current: filePage.current,
+    size: filePage.size,
+    rulesRegulationsManagementId
+  }
+  const res = await listRuleFiles(params)
+  const records = res?.data?.records || []
+  filePage.total = res?.data?.total || records.length
+  const mapped = records.map(item => ({
+    id: item.id,
+    name: item.fileName || item.name,
+    url: item.fileUrl || item.url,
+    raw: item
+  }))
+  fileListDialogRef.value?.setList(mapped)
+}
+
+// 鎵撳紑闄勪欢寮圭獥
+const openFileDialog = async (row) => {
+  currentFileRuleId.value = row.id
+  fileDialogVisible.value = true
+  await fetchRuleFiles(row.id)
+}
+
+// 鍒锋柊闄勪欢鍒楄〃
+const refreshFileList = async () => {
+  if (!currentFileRuleId.value) return
+  await fetchRuleFiles(currentFileRuleId.value)
+}
+
+// 涓婁紶闄勪欢锛堢敱瀛愮粍浠惰Е鍙戯級
+const handleAttachmentUpload = async (filePayload) => {
+  if (!currentFileRuleId.value) return
+  const payload = {
+    name: filePayload?.fileName || filePayload?.name,
+    url: filePayload?.fileUrl || filePayload?.url,
+    rulesRegulationsManagementId: currentFileRuleId.value
+  }
+  await addRuleFile(payload)
+  ElMessage.success('鏂囦欢涓婁紶鎴愬姛')
+  await refreshFileList()
+}
+
+// 鍒犻櫎闄勪欢
+const handleAttachmentDelete = async (row) => {
+  if (!row?.id) return false
+  try {
+    await ElMessageBox.confirm('纭鍒犻櫎璇ラ檮浠讹紵', '鎻愮ず', { type: 'warning' })
+  } catch {
+    return false
+  }
+  await delRuleFile([row.id])
+  ElMessage.success('鍒犻櫎鎴愬姛')
+  await refreshFileList()
+}
+
+// 鑾峰彇瑙勭珷鍒跺害鍒楄〃鏁版嵁
+const getRegulationList = async () => {
+  tableLoading.value = true
+  listRuleManagement(page,regulationSearchForm)
+  .then(res => {
+
+    regulations.value = res.data.records
+    // 杩囨护鎺夊凡搴熷純鐨勫埗搴�
+    // regulations.value = res.data.records.filter(item => item.status !== 'repealed')
+    page.value.total = res.data.total;
+    tableLoading.value = false;
+
+  }).catch(err => {
+    tableLoading.value = false;
+  })
+}
+
+onMounted(() => {
+  // 鍒濆鍖�
+  getRegulationList()
+})
+</script>
+
+<style scoped>
+.app-container {
+  padding: 20px;
+}
+
+.card-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+}
+
+.tab-content {
+  padding: 20px 0;
+}
+
+.mb-20 {
+  margin-bottom: 20px;
+}
+
+.mt-20 {
+  margin-top: 20px;
+}
+
+.ml-10 {
+  margin-left: 10px;
+}
+
+.regulation-content {
+  background-color: #f5f5f5;
+  padding: 15px;
+  border-radius: 4px;
+  line-height: 1.6;
+  white-space: pre-wrap;
+  height: 200px;
+}
+
+.dialog-footer {
+  display: flex;
+  justify-content: flex-end;
+  gap: 10px;
+}
+</style>
diff --git a/src/views/collaborativeApproval/sealManagement/index.vue b/src/views/collaborativeApproval/sealManagement/index.vue
new file mode 100644
index 0000000..8e0d054
--- /dev/null
+++ b/src/views/collaborativeApproval/sealManagement/index.vue
@@ -0,0 +1,801 @@
+<template>
+  <div class="app-container">
+    <el-card class="box-card">
+      <template #header>
+        <div class="card-header">
+          <span>鐢ㄥ嵃绠$悊鍙戝竷</span>
+        </div>
+      </template>
+
+      
+   <!-- 鐢ㄥ嵃鐢宠绠$悊 -->
+        <div class="tab-content">
+            <el-row :gutter="20" class="mb-20 ">
+              <span class="ml-10">鐢ㄥ嵃鏍囬锛�</span>
+              <el-col :span="4">
+                <el-input v-model="sealSearchForm.title" placeholder="璇疯緭鍏ョ敵璇锋爣棰�" clearable />
+              </el-col>
+              <span class="ml-10">鐢ㄥ嵃缂栧彿锛�</span>
+              <el-col :span="4">
+                <el-input v-model="sealSearchForm.applicationNum" placeholder="璇疯緭鍏ョ敤鍗扮紪鍙�" clearable />
+              </el-col>
+              <span class="search_title">瀹℃壒鐘舵�侊細</span>
+              <el-col :span="4">
+                <el-select v-model="sealSearchForm.status" placeholder="瀹℃壒鐘舵��" clearable>
+                  <el-option label="寰呭鎵�" value="pending" />
+                  <el-option label="宸查�氳繃" value="approved" />
+                  <el-option label="宸叉嫆缁�" value="rejected" />
+                </el-select>
+              </el-col>
+              <el-col :span="8">
+                <el-button type="primary" @click="searchSealApplications">鎼滅储</el-button>
+                <el-button @click="resetSealSearch">閲嶇疆</el-button>
+                <el-button @click="handleExport">瀵煎嚭</el-button>
+                <el-button type="primary" @click="showSealApplyDialog = true">鐢宠鐢ㄥ嵃
+                </el-button>
+              </el-col>
+            </el-row>
+
+            <el-table :data="sealApplications" border v-loading="tableLoading" style="width: 100%">
+              <el-table-column prop="applicationNum" label="鐢宠缂栧彿" width="120" />
+              <el-table-column prop="title" label="鐢宠鏍囬" min-width="200" />
+              <el-table-column prop="createUserName" label="鐢宠浜�" width="120" />
+              <el-table-column prop="department" label="鎵�灞為儴闂�" width="150" />
+              <el-table-column prop="sealType" label="鐢ㄥ嵃绫诲瀷" width="120">
+                <template #default="scope">
+                  {{ getSealTypeText(scope.row.sealType) }}
+                </template>
+              </el-table-column>
+              <el-table-column prop="createTime" label="鐢宠鏃堕棿" width="180" />
+              <el-table-column prop="status" label="鐘舵��" width="100">
+                <template #default="scope">
+                  <el-tag :type="getStatusType(scope.row.status)">
+                    {{ getStatusText(scope.row.status) }}
+                  </el-tag>
+                </template>
+              </el-table-column>
+              <el-table-column label="鎿嶄綔" width="200" fixed="right">
+                <template #default="scope">
+                  <el-button link @click="viewSealDetail(scope.row)">鏌ョ湅</el-button>
+                  <el-button 
+                    v-if="scope.row.status === 'pending'"
+										link
+                    type="primary" 
+                    @click="approveSeal(scope.row)"
+                  >
+                    瀹℃壒
+                  </el-button>
+                  <el-button 
+                    v-if="scope.row.status === 'pending'"
+										link
+                    type="danger" 
+                    @click="rejectSeal(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-card>
+
+    <!-- 鐢ㄥ嵃鐢宠瀵硅瘽妗� -->
+    <el-dialog v-model="showSealApplyDialog" title="鐢宠鐢ㄥ嵃" width="600px">
+      <el-form :model="sealForm" :rules="sealRules" ref="sealFormRef" label-width="100px">
+        <el-form-item label="鐢宠缂栧彿" prop="applicationNum">
+          <el-input v-model="sealForm.applicationNum" placeholder="璇疯緭鍏ョ敵璇风紪鍙�" />
+        </el-form-item>
+        <el-form-item label="鐢宠鏍囬" prop="title">
+          <el-input v-model="sealForm.title" placeholder="璇疯緭鍏ョ敵璇锋爣棰�" />
+        </el-form-item>
+        <el-form-item label="鐢ㄥ嵃绫诲瀷" prop="sealType">
+          <el-select v-model="sealForm.sealType" placeholder="璇烽�夋嫨鐢ㄥ嵃绫诲瀷" style="width: 100%">
+            <el-option label="鍏珷" value="official" />
+            <el-option label="鍚堝悓涓撶敤绔�" value="contract" />
+            <el-option label="璐㈠姟涓撶敤绔�" value="finance" />
+            <el-option label="娉曚汉绔�" value="legal" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="鐢宠鍘熷洜" prop="reason">
+          <el-input v-model="sealForm.reason" type="textarea" :rows="4" placeholder="璇疯缁嗚鏄庣敤鍗板師鍥�" />
+        </el-form-item>
+        <el-form-item label="瀹℃壒浜�" prop="approveUserId">
+          <el-select v-model="sealForm.approveUserId" placeholder="璇烽�夋嫨瀹℃壒浜�" style="width: 100%" filterable>
+            <el-option
+                v-for="user in userList"
+                :key="user.userId"
+                :label="user.nickName"
+                :value="user.userId"
+            />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="绱ф�ョ▼搴�" prop="urgency">
+          <el-radio-group v-model="sealForm.urgency">
+            <el-radio label="normal">鏅��</el-radio>
+            <el-radio label="urgent">绱ф��</el-radio>
+            <el-radio label="very-urgent">鐗规��</el-radio>
+          </el-radio-group>
+        </el-form-item>
+      </el-form>
+      <template #footer>
+        <span class="dialog-footer">
+          <el-button @click="showSealApplyDialog = false">鍙栨秷</el-button>
+          <el-button type="primary" @click="submitSealApplication">鎻愪氦鐢宠</el-button>
+        </span>
+      </template>
+    </el-dialog>
+
+    <!-- 瑙勭珷鍒跺害鍙戝竷瀵硅瘽妗� -->
+    <!-- <el-dialog v-model="showRegulationDialog" :title="operationType === 'add' ? '鍙戝竷鍒跺害' : '缂栬緫鍒跺害'" width="800px">
+      <el-form :model="regulationForm" :rules="regulationRules" ref="regulationFormRef" label-width="100px">
+        <el-form-item label="鍒跺害缂栧彿" prop="regulationNum">
+          <el-input v-model="regulationForm.regulationNum" placeholder="璇疯緭鍏ュ埗搴︾紪鍙�" />
+        </el-form-item>
+        <el-form-item label="鍒跺害鏍囬" prop="title">
+          <el-input v-model="regulationForm.title" placeholder="璇疯緭鍏ュ埗搴︽爣棰�" />
+        </el-form-item>
+        <el-form-item label="鍒跺害鍒嗙被" prop="category">
+          <el-select v-model="regulationForm.category" placeholder="璇烽�夋嫨鍒跺害鍒嗙被" style="width: 100%">
+            <el-option label="浜轰簨鍒跺害" value="hr" />
+            <el-option label="璐㈠姟鍒跺害" value="finance" />
+            <el-option label="瀹夊叏鍒跺害" value="safety" />
+            <el-option label="鎶�鏈埗搴�" value="tech" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="鍒跺害鍐呭" prop="content">
+          <el-input v-model="regulationForm.content" type="textarea" :rows="10" placeholder="璇疯緭鍏ュ埗搴﹁缁嗗唴瀹�" />
+        </el-form-item>
+        <el-form-item label="鍒跺害鐗堟湰" prop="version">
+          <el-input v-model="regulationForm.version" placeholder="璇疯緭鍏ュ埗搴︾増鏈�" />
+        </el-form-item>
+        <el-form-item label="鐢熸晥鏃堕棿" prop="effectiveTime">
+          <el-date-picker v-model="regulationForm.effectiveTime" type="datetime" format="YYYY-MM-DD HH:mm:ss"
+             value-format="YYYY-MM-DD HH:mm:ss" placeholder="閫夋嫨鐢熸晥鏃堕棿" style="width: 100%" />
+        </el-form-item>
+        <el-form-item label="閫傜敤鑼冨洿" prop="scope">
+          <el-checkbox-group v-model="regulationForm.scope">
+            <el-checkbox label="all">鍏ㄤ綋鍛樺伐</el-checkbox>
+            <el-checkbox label="manager">绠$悊灞�</el-checkbox>
+            <el-checkbox label="hr">浜轰簨閮ㄩ棬</el-checkbox>
+            <el-checkbox label="finance">璐㈠姟閮ㄩ棬</el-checkbox>
+            <el-checkbox label="tech">鎶�鏈儴闂�</el-checkbox>
+          </el-checkbox-group>
+        </el-form-item>
+        <el-form-item label="鏄惁闇�瑕佺‘璁�" prop="requireConfirm">
+          <el-switch v-model="regulationForm.requireConfirm" />
+          <span class="ml-10">寮�鍚悗鍛樺伐闇�瑕侀槄璇荤‘璁�</span>
+        </el-form-item>
+      </el-form>
+      <template #footer>
+        <span class="dialog-footer">
+          <el-button @click="showRegulationDialog = false">鍙栨秷</el-button>
+          <el-button type="primary" @click="submitRegulation">鍙戝竷鍒跺害</el-button>
+        </span>
+      </template>
+    </el-dialog> -->
+
+    <!-- 鐢ㄥ嵃璇︽儏瀵硅瘽妗� -->
+    <el-dialog v-model="showSealDetailDialog" title="鐢ㄥ嵃鐢宠璇︽儏" width="700px">
+      <div v-if="currentSealDetail" class="mb10">
+        <el-descriptions :column="2" border>
+          <el-descriptions-item label="鐢宠缂栧彿">{{ currentSealDetail.id }}</el-descriptions-item>
+          <el-descriptions-item label="鐢宠鏍囬">{{ currentSealDetail.title }}</el-descriptions-item>
+          <el-descriptions-item label="鐢宠浜�">{{ currentSealDetail.createUserName }}</el-descriptions-item>
+          <el-descriptions-item label="鎵�灞為儴闂�">{{ currentSealDetail.department }}</el-descriptions-item>
+          <el-descriptions-item label="鐢ㄥ嵃绫诲瀷">{{ getSealTypeText(currentSealDetail.sealType) }}</el-descriptions-item>
+          <el-descriptions-item label="鐢宠鏃堕棿">{{ currentSealDetail.createTime }}</el-descriptions-item>
+          <el-descriptions-item label="鐘舵��">
+            <el-tag :type="getStatusType(currentSealDetail.status)">
+              {{ getStatusText(currentSealDetail.status) }}
+            </el-tag>
+          </el-descriptions-item>
+          <el-descriptions-item label="鐢宠鍘熷洜" :span="2">{{ currentSealDetail.reason }}</el-descriptions-item>
+        </el-descriptions>
+      </div>
+    </el-dialog>
+
+    <!-- 瑙勭珷鍒跺害璇︽儏瀵硅瘽妗� -->
+    <el-dialog v-model="showRegulationDetailDialog" title="瑙勭珷鍒跺害璇︽儏" width="800px">
+      <div v-if="currentRegulationDetail">
+        <el-descriptions :column="2" border>
+          <el-descriptions-item label="鍒跺害缂栧彿">{{ currentRegulationDetail.id }}</el-descriptions-item>
+          <el-descriptions-item label="鍒跺害鏍囬">{{ currentRegulationDetail.title }}</el-descriptions-item>
+          <el-descriptions-item label="鍒嗙被">{{ getCategoryText(currentRegulationDetail.category) }}</el-descriptions-item>
+          <el-descriptions-item label="鐗堟湰">{{ currentRegulationDetail.version }}</el-descriptions-item>
+          <el-descriptions-item label="鍙戝竷浜�">{{ currentRegulationDetail.createUserName }}</el-descriptions-item>
+          <el-descriptions-item label="鍙戝竷鏃堕棿">{{ currentRegulationDetail.createTime }}</el-descriptions-item>
+        </el-descriptions>
+        <div class="mt-20">
+          <h4>鍒跺害鍐呭</h4>
+          <div class="regulation-content">{{ currentRegulationDetail.content }}</div>
+        </div>
+        <!-- 濡傛灉tableData>0 鏄剧ず -->
+        <div style="margin: 10px 0;" v-if="tableData && tableData.length > 0" >
+          <el-button type="success" @click="resetForm(currentRegulationDetail)">纭鏌ョ湅</el-button>
+        </div>
+      </div>
+    </el-dialog>
+
+    <!-- 鐗堟湰鍘嗗彶瀵硅瘽妗� -->
+    <el-dialog v-model="showVersionHistoryDialog" title="鐗堟湰鍘嗗彶" width="800px">
+      <el-table :data="versionHistory" style="width: 100%;margin-bottom: 10px">
+        <el-table-column prop="version" label="鐗堟湰鍙�" width="100" />
+        <el-table-column prop="updateTime" label="鏇存柊鏃堕棿" width="180" />
+        <el-table-column prop="createUserName" label="鏇存柊浜�" width="120" />
+        <el-table-column prop="changeLog" label="鍙樻洿璇存槑">
+          <template #default="scope">
+            <el-tag :type="scope.row.status === 'active' ? 'success' : 'info'">
+              {{ scope.row.status === 'active' ? '鐢熸晥涓�' : '宸插簾姝�' }}
+            </el-tag>
+          </template>
+        </el-table-column>
+      </el-table>
+    </el-dialog>
+
+    <!-- 闃呰鐘舵�佸璇濇 -->
+    <el-dialog v-model="showReadStatusDialog" title="闃呰鐘舵��" width="800px">
+      <el-table :data="readStatusList" style="width: 100%;margin-bottom: 10px">
+        <el-table-column prop="employee" label="鍛樺伐濮撳悕" width="120" />
+        <el-table-column prop="department" label="鎵�灞為儴闂�" width="150" />
+        <el-table-column prop="createTime" label="闃呰鏃堕棿" width="180" />
+        <el-table-column prop="confirmTime" label="纭鏃堕棿" width="180" />
+        <el-table-column prop="status" label="鐘舵��" width="100">
+          <template #default="scope">
+            <el-tag :type="scope.row.status === 'confirmed' ? 'success' : 'warning'">
+              {{ scope.row.status === 'confirmed' ? '宸茬‘璁�' : '鏈‘璁�' }}
+            </el-tag>
+          </template>
+        </el-table-column>
+      </el-table>
+    </el-dialog>
+  </div>
+</template>
+
+<script setup>
+import { ref, reactive, onMounted, getCurrentInstance, watch } from 'vue'
+import { useRoute } from 'vue-router'
+import { ElMessage, ElMessageBox } from 'element-plus'
+import { Plus } from '@element-plus/icons-vue'
+import { listSealApplication, addSealApplication, updateSealApplication,listRuleManagement,addRuleManagement,updateRuleManagement,delRuleManagement,getReadingStatusByRuleId,getReadingStatusList,addReadingStatus,updateReadingStatus  } from '@/api/collaborativeApproval/sealManagement.js'
+import { el } from 'element-plus/es/locales.mjs'
+import { getUserProfile, userListNoPageByTenantId } from '@/api/system/user.js'
+import {staffJoinDel, staffJoinListPage} from "@/api/personnelManagement/onboarding.js";
+import useUserStore from '@/store/modules/user'
+import { userLoginFacotryList } from "@/api/system/user.js"
+
+// 鍝嶅簲寮忔暟鎹�
+const currentUser = ref(null)
+const activeTab = ref('seal')
+const operationType = ref('add')
+const tableData = ref([])
+// 鐢ㄥ嵃鐢宠鐩稿叧
+const userStore = useUserStore()
+const route = useRoute()
+const showSealApplyDialog = ref(false)
+const tableLoading = ref(false)
+const showSealDetailDialog = ref(false)
+const currentSealDetail = ref(null)
+const sealFormRef = ref()
+const userList = ref([])
+const sealForm = reactive({
+  applicationNum: '',
+  title: '',
+  sealType: '',
+  reason: '',
+  approveUserId: '',
+  urgency: 'normal',
+  status: 'pending'
+})
+
+const sealRules = {
+  applicationNum: [{ required: true, message: '璇疯緭鍏ョ敵璇风紪鍙�', trigger: 'blur' }],
+  title: [{ required: true, message: '璇疯緭鍏ョ敵璇锋爣棰�', trigger: 'blur' }],
+  sealType: [{ required: true, message: '璇烽�夋嫨鐢ㄥ嵃绫诲瀷', trigger: 'change' }],
+  reason: [{ required: true, message: '璇疯緭鍏ョ敵璇峰師鍥�', trigger: 'blur' }],
+  approveUserId: [{ required: true, message: '璇烽�夋嫨瀹℃壒浜�', trigger: 'change' }]
+}
+
+const sealSearchForm = reactive({
+  title: '',
+  status: '',
+  applicationNum: ''
+})
+// 鍒嗛〉鍙傛暟
+const page = reactive({
+  current: 1,
+  size: 100,
+  total: 0
+})
+// 瑙勭珷鍒跺害鐩稿叧
+const showRegulationDialog = ref(false)
+const showRegulationDetailDialog = ref(false)
+const showVersionHistoryDialog = ref(false)
+const showReadStatusDialog = ref(false)
+const currentRegulationDetail = ref(null)
+const regulationFormRef = ref()
+const regulationForm = reactive({
+  id: '',
+  regulationNum: '',
+  title: '',
+  category: '',
+  content: '',
+  version: '',
+  status: 'active',
+  readCount: 0,
+  effectiveTime: '',
+  scope: [],
+  requireConfirm: false
+})
+
+const readStatus = ref({
+  id: '',
+  ruleId: '',
+  employee: '',
+  department: '',
+  createTime: '',
+  confirmTime: '',
+  status: 'unconfirmed'
+})
+
+const regulationRules = {
+  title: [{ required: true, message: '璇疯緭鍏ュ埗搴︽爣棰�', trigger: 'blur' }],
+  category: [{ required: true, message: '璇烽�夋嫨鍒跺害鍒嗙被', trigger: 'change' }],
+  content: [{ required: true, message: '璇疯緭鍏ュ埗搴﹀唴瀹�', trigger: 'blur' }],
+  effectiveTime: [{ required: true, message: '璇烽�夋嫨鐢熸晥鏃堕棿', trigger: 'change' }],
+  scope: [{ required: true, message: '璇烽�夋嫨閫傜敤鑼冨洿', trigger: 'change' }]
+}
+
+const regulationSearchForm = reactive({
+  title: '',
+  category: ''
+})
+
+// 鍋囨暟鎹�
+const sealApplications = ref([])
+
+const regulations = ref([])
+
+const versionHistory = ref([])
+
+const readStatusList = ref([])
+  // { employee: '闄堝織寮�', department: '閿�鍞儴', readTime: '2025-01-11 10:30:00', confirmTime: '2025-01-11 10:35:00', status: 'confirmed' },
+  // { employee: '鍒橀泤濠�', department: '鎶�鏈儴', readTime: '2025-01-11 14:20:00', confirmTime: '', status: 'unconfirmed' },
+  // { employee: '鐜嬪缓鍥�', department: '璐㈠姟閮�', readTime: '2025-01-12 09:15:00', confirmTime: '2025-01-12 09:20:00', status: 'confirmed' }
+
+// 鐢ㄥ嵃鐢宠鐘舵��
+const getStatusType = (status) => {
+  const statusMap = {
+    pending: 'warning',
+    approved: 'success',
+    rejected: 'danger'
+  }
+  return statusMap[status] || 'info'
+}
+// 鍒跺害鐘舵��
+const getStatusText = (status) => {
+  const statusMap = {
+    pending: '寰呭鎵�',
+    approved: '宸查�氳繃',
+    rejected: '宸叉嫆缁�'
+  }
+  return statusMap[status] || '鏈煡'
+}
+// 鐢ㄥ嵃绫诲瀷
+const getSealTypeText = (sealType) => {
+  const sealTypeMap = {
+    official: '鍏珷',
+    contract: '鍚堝悓涓撶敤绔�',
+    finance: '璐㈠姟涓撶敤绔�',
+    tegal: '鎶�鏈笓鐢ㄧ珷'
+  }
+  return sealTypeMap[sealType] || '鏈煡'
+}
+// 鍒跺害鍒嗙被
+const getCategoryText = (category) => {
+  const categoryMap = {
+    hr: '浜轰簨鍒跺害',
+    finance: '璐㈠姟鍒跺害',
+    safety: '瀹夊叏鍒跺害',
+    tech: '鎶�鏈埗搴�'
+  }
+  return categoryMap[category] || '鏈煡'
+}
+// 鎼滅储鍗扮珷鐢宠
+const searchSealApplications = () => {
+  page.current=1
+  getSealApplicationList()
+
+  // ElMessage.success('鎼滅储瀹屾垚')
+}
+// 閲嶇疆鍗扮珷鐢宠鎼滅储
+const resetSealSearch = () => {
+  sealSearchForm.title = ''
+  sealSearchForm.status = ''
+  sealSearchForm.applicationNum = ''
+  searchSealApplications()
+}
+// 鎼滅储鍒跺害
+const searchRegulations = () => {
+  page.current=1
+  getRegulationList()
+}
+// 閲嶇疆鍒跺害鎼滅储
+const resetRegulationSearch = () => {
+  regulationSearchForm.title = ''
+  regulationSearchForm.category = ''
+  searchRegulations()
+}
+// 鎻愪氦鐢ㄥ嵃鐢宠
+const submitSealApplication = async () => {
+  try {
+    await sealFormRef.value.validate()
+    addSealApplication(sealForm).then(res => {
+      if(res.code == 200){
+        ElMessage.success('鐢宠鎻愪氦鎴愬姛')
+        showSealApplyDialog.value = false
+        getSealApplicationList()
+        Object.assign(sealForm, {
+        applicationNum: '',
+        title: '',
+        sealType: '',
+        reason: '',
+        approveUserId: '',
+        urgency: 'normal',
+        status: 'pending'
+      })
+      }
+    }).catch(err => {
+      ElMessage.error(err.msg)
+    })
+  
+  } catch (error) {
+    ElMessage.error('璇峰畬鍠勭敵璇蜂俊鎭�')
+  }
+}
+// 鏂板
+const handleAdd = () => {
+  operationType.value = 'add'
+  resetRegulationForm()
+  showRegulationDialog.value = true
+}
+
+// 缂栬緫
+const handleEdit = (row) => {
+  operationType.value = 'edit'
+  Object.assign(regulationForm, row)
+  showRegulationDialog.value = true
+}
+// 搴熷純
+const repealEdit = (row) => {
+  operationType.value = 'edit'
+  Object.assign(regulationForm, row)
+  regulationForm.status = 'repealed'
+  ElMessageBox.confirm('纭搴熷純璇ュ埗搴︼紵', '鎻愮ず', {
+    confirmButtonText: '纭畾',
+    cancelButtonText: '鍙栨秷',
+    type: 'warning'
+  }).then(() => {
+    updateRuleManagement(regulationForm).then(res => {
+      if(res.code == 200){
+        ElMessage.success('鍒跺害搴熷純鎴愬姛')
+        // showRegulationDialog.value = false
+        getRegulationList()
+        resetRegulationForm()
+      }
+    })
+  }).catch(() => {
+    ElMessage({
+      type: 'info',
+      message: '宸插彇娑堝簾寮�'
+    })
+  })
+}
+// 鍙戝竷鍒跺害
+const submitRegulation = async () => {
+  try {
+    await regulationFormRef.value.validate()
+    if(operationType.value == 'add'){
+      addRuleManagement(regulationForm).then(res => {
+        if(res.code == 200){
+          ElMessage.success('鍒跺害鍙戝竷鎴愬姛')
+          showRegulationDialog.value = false
+          getRegulationList()
+          resetRegulationForm()
+        }
+      })
+    }else{
+      updateRuleManagement(regulationForm).then(res => {
+        if(res.code == 200){
+          ElMessage.success('鍒跺害缂栬緫鎴愬姛')
+          showRegulationDialog.value = false
+          resetRegulationForm()
+          getRegulationList()
+      }})}
+  }catch(err){
+    ElMessage.error(err.msg)
+  }
+} 
+//閲嶇疆鍒跺害琛ㄥ崟
+const resetRegulationForm = () => {
+  Object.assign(regulationForm, {
+    id: '',
+    regulationNum: '',
+    title: '',
+    category: '',
+    content: '',
+    version: '',
+    status: 'active',
+    readCount: 0,
+    effectiveTime: '',
+    scope: [],
+    requireConfirm: false
+})
+}
+
+
+// 鏌ョ湅鐢ㄥ嵃鐢宠璇︽儏
+const viewSealDetail = (row) => {
+  currentSealDetail.value = row
+  showSealDetailDialog.value = true
+}
+// 瀹℃壒鐢ㄥ嵃鐢宠
+const approveSeal = (row) => {
+  console.log(row)
+  ElMessageBox.confirm('纭閫氳繃璇ョ敤鍗扮敵璇凤紵', '鎻愮ず', {
+    confirmButtonText: '纭畾',
+    cancelButtonText: '鍙栨秷',
+    type: 'warning'
+  }).then(() => {
+    row.status = 'approved'
+    updateSealApplication(row).then(res => {
+      if(res.code == 200){
+        ElMessage.success('瀹℃壒閫氳繃')
+      }
+    })
+  })
+}
+// 鎷掔粷鐢ㄥ嵃鐢宠
+const rejectSeal = (row) => {
+  ElMessageBox.prompt('璇疯緭鍏ユ嫆缁濆師鍥�', '鎻愮ず', {
+    confirmButtonText: '纭畾',
+    cancelButtonText: '鍙栨秷',
+    inputPattern: /\S+/,
+    inputErrorMessage: '鎷掔粷鍘熷洜涓嶈兘涓虹┖'
+  }).then(({ value }) => {
+    row.status = 'rejected'
+    updateSealApplication(row).then(res => {
+      if(res.code == 200){
+        ElMessage.success('瀹℃壒鎷掔粷')
+      }
+    })
+    ElMessage.success('宸叉嫆缁濈敵璇�')
+  })
+}
+// 鑾峰彇鍦ㄨ亴鍛樺伐鍒楄〃
+const getList = () => {
+  tableLoading.value = true;
+      //鑾峰彇褰撳墠鐧诲綍鐢ㄦ埛淇℃伅
+  getUserProfile().then(res => {
+    if(res.code == 200){
+      console.log(res.data.userName)
+      currentUser.value = res.data.userName
+    }
+  })
+  staffJoinListPage({staffState: 1, ...page}).then(res => {
+    tableLoading.value = false;
+    // tableData.value = res.data.records
+    // //绛涢�夊嚭鍜宑urrentUser鍚屽悕鐨勪汉鍛�
+    tableData.value = res.data.records.filter(item => item.staffName === currentUser.value)
+    page.total = res.data.total;
+      
+    if(tableData.value.length == 0){
+    ElMessage.error('褰撳墠鐢ㄦ埛鏈姞鍏ヤ换浣曢儴闂�')
+    }
+  }).catch(err => {
+    tableLoading.value = false;
+  })
+
+
+};
+
+// 鏌ョ湅鍒跺害鐗堟湰鍘嗗彶
+const viewVersionHistory = (row) => {
+  showVersionHistoryDialog.value = true
+  const params = {
+
+    category: row.category
+  }
+  listRuleManagement(page,params).then(res => {
+    if(res.code == 200){
+      versionHistory.value = res.data.records
+    }
+  })
+}
+// 鏌ョ湅鍒跺害璇︽儏
+const viewRegulation = (row) => {
+  getList()
+  currentRegulationDetail.value = row
+  showRegulationDetailDialog.value = true
+  getReadingStatusByRuleId(row.id).then(res => {
+    if(res.code == 200){
+      readStatusList.value = res.data
+      if(readStatusList.value.length==0 && tableData.value.length>0){
+          const params = {
+          ruleId: row.id,
+          employee: tableData.value[0].staffName,
+          department: tableData.value[0].postJob,
+          status: 'unconfirmed'
+        }
+        addReadingStatus(params).then(res => {
+          if(res.code == 200){
+            ElMessage.success('鍒跺害闃呰鎴愬姛')
+          }
+        })
+      }
+    }
+  })
+  
+}
+// 鏌ョ湅鍒跺害闃呰鐘舵��
+const viewReadStatus = (row) => {
+  showReadStatusDialog.value = true
+  //鏌ョ湅闃呰鐘舵�佸垪琛�
+  getReadingStatusByRuleId(row.id).then(res => {
+    if(res.code == 200){
+      readStatusList.value = res.data
+    }
+  })
+}
+
+//纭鏌ョ湅
+const resetForm = (row) => {
+  console.log("row",row)
+  row.readCount = row.readCount + 1
+  
+  updateRuleManagement(row).then(res => {
+    if(res.code == 200){
+      ElMessage.success('鏌ョ湅鏁伴噺淇敼鎴愬姛')
+      //淇敼闃呰鐘舵��
+      //鏍规嵁鍒跺害id鍜屽綋鍓嶇櫥褰曠殑鍛樺伐寰楀埌闃呰鐘舵��
+      // let item = readStatusList.value.filter(item => item.employee == tableData.value[0].staffName )
+      // if(item.length>0){
+      //   item[0].status = 'confirmed',
+      //   item[0].confirmTime = new Date().toISOString().replace('T', ' ').split('.')[0];
+      // }
+      // 绛涢�夊綋鍓嶅憳宸ュ搴旇鍒跺害鐨勯槄璇荤姸鎬佽褰�
+      let statusItem = readStatusList.value.find(item => item.employee === tableData.value[0].staffName && item.ruleId === row.id);
+
+      if (statusItem) {
+        // 濡傛灉鎵惧埌璁板綍锛屾洿鏂扮姸鎬佸拰纭鏃堕棿
+        statusItem.status = 'confirmed';
+        // 鏍煎紡鍖栨椂闂翠负"YYYY-MM-DD HH:mm:ss"鏍煎紡
+        const now = new Date();
+        statusItem.confirmTime = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')} ${String(now.getHours()).padStart(2, '0')}:${String(now.getMinutes()).padStart(2, '0')}:${String(now.getSeconds()).padStart(2, '0')}`;
+        // statusItem.confirmTime = new Date().toISOString().replace('T', ' ').split('.')[0];
+        
+        updateReadingStatus(statusItem).then(res => {
+          if(res.code == 200){
+            ElMessage.success('鍒跺害闃呰鐘舵�佷慨鏀规垚鍔�')
+          }
+        })
+      }
+
+    }
+  })
+}
+
+// 瀵煎嚭鐢ㄥ嵃鐢宠
+const { proxy } = getCurrentInstance()
+const handleExport = () => {
+  proxy.download('/sealApplicationManagement/export', { ...sealSearchForm }, '鐢ㄥ嵃鐢宠.xlsx')
+}
+
+// 鑾峰彇鍗扮珷鐢宠鍒楄〃鏁版嵁
+const getSealApplicationList = async () => {
+  tableLoading.value = true
+  listSealApplication(page,sealSearchForm)
+  .then(res => {
+    //鑾峰彇褰撳墠鐧诲綍鐨勯儴闂ㄤ俊鎭�
+// 鑾峰彇褰撳墠鐧诲綍鐨勯儴闂ㄤ俊鎭苟杩囨护鏁版嵁
+    const currentFactoryName = userStore.currentFactoryName
+    if (currentFactoryName) {
+      // 鏍规嵁currentFactoryName杩囨护鍑篸epartment鐩稿悓鐨勬暟鎹�
+      sealApplications.value = res.data.records.filter(item => item.department === currentFactoryName)
+      // 鏇存柊杩囨护鍚庣殑鎬绘暟
+      page.total = sealApplications.value.length
+    } else {
+      // 濡傛灉娌℃湁currentFactoryName锛屽垯鏄剧ず鎵�鏈夋暟鎹�
+      sealApplications.value = res.data.records
+      page.total = res.data.total
+    }
+    // sealApplications.value = res.data.records
+    // page.value.total = res.data.total;
+    tableLoading.value = false;
+
+  }).catch(err => {
+    tableLoading.value = false;
+  })
+}
+// 鑾峰彇瑙勭珷鍒跺害鍒楄〃鏁版嵁
+const getRegulationList = async () => {
+  tableLoading.value = true
+  listRuleManagement(page,regulationSearchForm)
+  .then(res => {
+
+    regulations.value = res.data.records
+    // 杩囨护鎺夊凡搴熷純鐨勫埗搴�
+    // regulations.value = res.data.records.filter(item => item.status !== 'repealed')
+    page.total = res.data.total;
+    tableLoading.value = false;
+
+  }).catch(err => {
+    tableLoading.value = false;
+  })
+}
+
+// 鐩戝惉瀵硅瘽妗嗘墦寮�锛岃幏鍙栫敤鎴峰垪琛�
+watch(showSealApplyDialog, (newVal) => {
+  if (newVal) {
+    userListNoPageByTenantId().then((res) => {
+      userList.value = res.data;
+    });
+  }
+});
+
+onMounted(() => {
+  // 璺敱鎼哄甫 applicationNum 鏃讹紝棰勫~骞舵煡璇�
+  if (route.query.applicationNum) {
+    sealSearchForm.applicationNum = String(route.query.applicationNum)
+    page.current = 1
+    getSealApplicationList()
+  } else {
+    getSealApplicationList()
+  }
+  getRegulationList()
+})
+</script>
+
+<style scoped>
+.app-container {
+  padding: 20px;
+}
+
+.card-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+}
+
+.tab-content {
+  padding: 20px 0;
+}
+
+.mb-20 {
+  margin-bottom: 20px;
+}
+
+.mt-20 {
+  margin-top: 20px;
+}
+
+.ml-10 {
+  margin-left: 10px;
+}
+
+.regulation-content {
+  background-color: #f5f5f5;
+  padding: 15px;
+  border-radius: 4px;
+  line-height: 1.6;
+  white-space: pre-wrap;
+  height: 200px;
+}
+
+.dialog-footer {
+  display: flex;
+  justify-content: flex-end;
+  gap: 10px;
+}
+</style>
diff --git a/src/views/collaborativeApproval/warningSystem/index.vue b/src/views/collaborativeApproval/warningSystem/index.vue
index b04c583..ddab6c0 100644
--- a/src/views/collaborativeApproval/warningSystem/index.vue
+++ b/src/views/collaborativeApproval/warningSystem/index.vue
@@ -33,7 +33,6 @@
             <th>绫诲瀷</th>
             <th>绛夌骇</th>
             <th>鐘舵��</th>
-            <th>璐d换浜�</th>
             <th>鎿嶄綔</th>
           </tr>
         </thead>
@@ -52,7 +51,6 @@
                 {{ warning.statusText }}
               </span>
             </td>
-            <td>{{ warning.responsible }}</td>
             <td>
               <button @click="viewDetail(warning)">鏌ョ湅璇︽儏</button>
             </td>
@@ -96,7 +94,7 @@
           levelText: '绾㈣壊棰勮',
           status: 'pending',
           statusText: '寰呭鐞�',
-          responsible: '寮犵粡鐞�',
+          responsible: '闄堝織寮�',
           description: 'A椤圭洰棰勭畻鎵ц鐜囧凡杈�95%锛岄璁″皢瓒呭嚭棰勭畻鑼冨洿銆�',
           impact: '褰卞搷椤圭洰鏁翠綋璐㈠姟鎸囨爣锛屽彲鑳藉鑷撮」鐩簭鎹�',
           suggestions: '鏆傚仠闈炲繀瑕佹敮鍑猴紝浼樺寲璧勬簮閰嶇疆锛岀敵璇烽绠楄皟鏁�'
@@ -148,7 +146,7 @@
           levelText: '绾㈣壊棰勮',
           status: 'pending',
           statusText: '寰呭鐞�',
-          responsible: '闄堟�荤洃',
+          responsible: '闄堝織寮�',
           description: '浜у搧D鍦ㄥ鎴风幇鍦哄嚭鐜拌川閲忛棶棰樸��',
           impact: '褰卞搷瀹㈡埛婊℃剰搴︼紝鍙兘閫犳垚缁忔祹鎹熷け',
           suggestions: '绔嬪嵆鍙洖闂浜у搧锛屽垎鏋愬師鍥狅紝鍒跺畾鏀硅繘鎺柦'
diff --git a/src/views/inventoryManagement/stockWarningLedger/index.vue b/src/views/inventoryManagement/stockWarningLedger/index.vue
new file mode 100644
index 0000000..067680c
--- /dev/null
+++ b/src/views/inventoryManagement/stockWarningLedger/index.vue
@@ -0,0 +1,360 @@
+<template>
+  <div class="app-container">
+    <div class="search_form">
+      <el-form :model="searchForm" :inline="true">
+        <el-form-item label="浜у搧澶х被锛�">
+          <el-input
+            v-model="searchForm.productCategory"
+            placeholder="璇疯緭鍏ヤ骇鍝佸ぇ绫�"
+            clearable
+            style="width: 200px"
+          />
+        </el-form-item>
+        <el-form-item label="瑙勬牸鍨嬪彿锛�">
+          <el-input
+            v-model="searchForm.specificationModel"
+            placeholder="璇疯緭鍏ヨ鏍煎瀷鍙�"
+            clearable
+            style="width: 200px"
+          />
+        </el-form-item>
+        <el-form-item label="棰勮绾у埆锛�">
+          <el-select
+            v-model="searchForm.warningLevel"
+            placeholder="璇烽�夋嫨棰勮绾у埆"
+            clearable
+            style="width: 150px"
+          >
+            <el-option label="绱ф��" value="绱ф��" />
+            <el-option label="閲嶈" value="閲嶈" />
+            <el-option label="涓�鑸�" value="涓�鑸�" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="棰勮鐘舵�侊細">
+          <el-select
+            v-model="searchForm.warningStatus"
+            placeholder="璇烽�夋嫨棰勮鐘舵��"
+            clearable
+            style="width: 150px"
+          >
+            <el-option label="宸查璀�" value="宸查璀�" />
+            <el-option label="姝e父" value="姝e父" />
+          </el-select>
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" @click="handleQuery">鎼滅储</el-button>
+          <el-button @click="resetQuery">閲嶇疆</el-button>
+        </el-form-item>
+      </el-form>
+    </div>
+
+    <div class="table_list">
+      <div class="actions"></div>
+      <el-table
+        :data="tableData"
+        border
+        v-loading="tableLoading"
+        style="width: 100%"
+        height="calc(100vh - 280px)"
+      >
+        <el-table-column align="center" label="搴忓彿" type="index" width="60" />
+        <el-table-column label="鎵规鍙�" prop="code" width="130" show-overflow-tooltip />
+        <el-table-column label="浜у搧澶х被" prop="productCategory" show-overflow-tooltip />
+        <el-table-column label="瑙勬牸鍨嬪彿" prop="specificationModel" show-overflow-tooltip />
+        <el-table-column label="褰撳墠搴撳瓨" prop="currentStock" width="120" show-overflow-tooltip>
+          <template #default="scope">
+            <span :class="getStockClass(scope.row)">{{ scope.row.currentStock || 0 }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column label="鏈�浣庡簱瀛�" prop="warnNum" width="120" show-overflow-tooltip />
+        <el-table-column label="棰勮绾у埆" prop="warningLevel" width="100" show-overflow-tooltip>
+          <template #default="scope">
+            <el-tag :type="getWarningLevelTag(scope.row.warningLevel)">
+              {{ scope.row.warningLevel || '-' }}
+            </el-tag>
+          </template>
+        </el-table-column>
+        <el-table-column label="棰勮鐘舵��" prop="warningStatus" width="100" show-overflow-tooltip>
+          <template #default="scope">
+            <el-tag :type="scope.row.warningStatus === '宸查璀�' ? 'danger' : 'success'">
+              {{ scope.row.warningStatus || '姝e父' }}
+            </el-tag>
+          </template>
+        </el-table-column>
+        <el-table-column label="棰勮鏃堕棿" prop="warningTime" width="150" show-overflow-tooltip />
+        <el-table-column label="棰勮缂鸿揣鏃堕棿" prop="expectedShortageTime" width="150" show-overflow-tooltip>
+          <template #default="scope">
+            <div v-if="scope.row.expectedShortageTime">
+              <div v-if="getCountdown(scope.row.expectedShortageTime).isExpired" class="countdown-expired">
+                <el-tag type="danger">宸茬己璐�</el-tag>
+              </div>
+              <div v-else class="countdown-timer">
+                <span :class="getCountdownClass(scope.row.expectedShortageTime)">
+                  {{ getCountdown(scope.row.expectedShortageTime).text }}
+                </span>
+              </div>
+            </div>
+            <span v-else>-</span>
+          </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>
+
+  </div>
+</template>
+
+<script setup>
+import { ref, reactive, onMounted } from 'vue'
+import { ElMessage } from 'element-plus'
+import pagination from '@/components/PIMTable/Pagination.vue'
+import {
+  getStockWarningLedgerPage
+} from '@/api/inventoryManagement/stockWarningLedger.js'
+
+// 鍝嶅簲寮忔暟鎹�
+const tableData = ref([])
+const tableLoading = ref(false)
+const total = ref(0)
+
+// 鍒嗛〉鍙傛暟
+const page = reactive({
+  current: 1,
+  size: 100
+})
+
+// 鎼滅储琛ㄥ崟
+const searchForm = reactive({
+  productCategory: '',
+  specificationModel: '',
+  warningLevel: '',
+  warningStatus: ''
+})
+
+// 鑾峰彇鍒楄〃鏁版嵁
+const getList = () => {
+  tableLoading.value = true
+  const params = {
+    ...page,
+    ...searchForm
+  }
+  getStockWarningLedgerPage(params)
+    .then(res => {
+      tableLoading.value = false
+      if (res.code === 200) {
+        tableData.value = res.data.records || []
+        total.value = res.data.total || 0
+        
+        // 璁$畻棰勮绾у埆鍜岀姸鎬�
+        tableData.value = tableData.value.map(item => {
+          const currentStock = parseFloat(item.inboundNum0 || item.currentStock || 0)
+          const warnNum = parseFloat(item.warnNum || 0)
+          const safetyStock = parseFloat(item.safetyStock || warnNum * 1.2)
+          
+          // 璁$畻棰勮绾у埆
+          if (currentStock <= 0) {
+            item.warningLevel = '绱ф��'
+            item.warningStatus = '宸查璀�'
+          } else if (currentStock < warnNum) {
+            item.warningLevel = '閲嶈'
+            item.warningStatus = '宸查璀�'
+          } else if (currentStock < safetyStock) {
+            item.warningLevel = '涓�鑸�'
+            item.warningStatus = '宸查璀�'
+          } else {
+            item.warningLevel = ''
+            item.warningStatus = '姝e父'
+          }
+          
+          // 璁$畻棰勮缂鸿揣鏃堕棿锛堝熀浜庢棩鍧囨秷鑰楅噺锛岃繖閲岀畝鍖栧鐞嗭級
+          if (item.warningStatus === '宸查璀�' && currentStock > 0 && warnNum > 0) {
+            const dailyConsumption = warnNum / 30 // 鍋囪30澶╂秷鑰楀畬鏈�浣庡簱瀛�
+            const daysRemaining = Math.floor(currentStock / dailyConsumption)
+            if (daysRemaining > 0) {
+              const date = new Date()
+              date.setDate(date.getDate() + daysRemaining)
+              item.expectedShortageTime = date.toISOString().split('T')[0]
+            }
+          }
+          
+          item.currentStock = currentStock
+          item.safetyStock = safetyStock
+          
+          return item
+        })
+      }
+    })
+    .catch(err => {
+      tableLoading.value = false
+      ElMessage.error(err.msg || '鑾峰彇鏁版嵁澶辫触')
+    })
+}
+
+// 鎼滅储
+const handleQuery = () => {
+  page.current = 1
+  getList()
+}
+
+// 閲嶇疆鎼滅储
+const resetQuery = () => {
+  Object.keys(searchForm).forEach(key => {
+    searchForm[key] = ''
+  })
+  handleQuery()
+}
+
+// 鍒嗛〉鍙樺寲
+const paginationChange = (obj) => {
+  page.current = obj.page
+  page.size = obj.limit
+  getList()
+}
+
+// 鑾峰彇搴撳瓨鏍峰紡绫�
+const getStockClass = (row) => {
+  const currentStock = parseFloat(row.currentStock || row.inboundNum0 || 0)
+  const warnNum = parseFloat(row.warnNum || 0)
+  
+  if (currentStock <= 0) {
+    return 'text-danger'
+  } else if (currentStock < warnNum) {
+    return 'text-warning'
+  }
+  return 'text-success'
+}
+
+// 鑾峰彇棰勮绾у埆鏍囩鏍峰紡
+const getWarningLevelTag = (level) => {
+  const levelMap = {
+    '绱ф��': 'danger',
+    '閲嶈': 'warning',
+    '涓�鑸�': 'info'
+  }
+  return levelMap[level] || 'info'
+}
+
+// 鑾峰彇鍊掕鏃朵俊鎭�
+const getCountdown = (expectedTime) => {
+  if (!expectedTime) return { text: '-', isExpired: false }
+
+  const now = new Date().getTime()
+  const expected = new Date(expectedTime).getTime()
+  const diff = expected - now
+
+  if (diff <= 0) {
+    return { text: '宸茬己璐�', isExpired: true }
+  }
+
+  const days = Math.floor(diff / (1000 * 60 * 60 * 24))
+  const hours = Math.floor((diff % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60))
+  const minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60))
+
+  if (days > 0) {
+    return { text: `${days}澶�${hours}灏忔椂`, isExpired: false }
+  } else if (hours > 0) {
+    return { text: `${hours}灏忔椂${minutes}鍒嗛挓`, isExpired: false }
+  } else {
+    return { text: `${minutes}鍒嗛挓`, isExpired: false }
+  }
+}
+
+// 鑾峰彇鍊掕鏃舵牱寮忕被
+const getCountdownClass = (expectedTime) => {
+  if (!expectedTime) return ''
+
+  const now = new Date().getTime()
+  const expected = new Date(expectedTime).getTime()
+  const diff = expected - now
+
+  if (diff <= 0) {
+    return 'countdown-expired'
+  } else if (diff <= 24 * 60 * 60 * 1000) { // 24灏忔椂鍐�
+    return 'countdown-urgent'
+  } else if (diff <= 7 * 24 * 60 * 60 * 1000) { // 7澶╁唴
+    return 'countdown-warning'
+  } else {
+    return 'countdown-normal'
+  }
+}
+
+// 椤甸潰鍔犺浇
+onMounted(() => {
+  getList()
+})
+</script>
+
+<style scoped lang="scss">
+.app-container {
+  padding: 20px;
+
+  .search_form {
+    background: #fff;
+    padding: 20px;
+    border-radius: 4px;
+    margin-bottom: 20px;
+  }
+
+  .table_list {
+    background: #fff;
+    border-radius: 4px;
+    padding: 20px;
+    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+
+    .actions {
+      display: flex;
+      justify-content: space-between;
+      margin-bottom: 20px;
+    }
+  }
+
+  .text-danger {
+    color: #f56c6c;
+    font-weight: bold;
+  }
+
+  .text-warning {
+    color: #e6a23c;
+    font-weight: bold;
+  }
+
+  .text-success {
+    color: #67c23a;
+    font-weight: bold;
+  }
+
+  .countdown-timer {
+    font-weight: bold;
+  }
+
+  .countdown-normal {
+    color: #67c23a;
+  }
+
+  .countdown-warning {
+    color: #e6a23c;
+  }
+
+  .countdown-urgent {
+    color: #f56c6c;
+    animation: blink 1s infinite;
+  }
+
+  .countdown-expired {
+    color: #f56c6c;
+    font-weight: bold;
+  }
+
+  @keyframes blink {
+    0%, 50% { opacity: 1; }
+    51%, 100% { opacity: 0.5; }
+  }
+}
+</style>
diff --git a/src/views/personnelManagement/payrollManagement/components/formDia.vue b/src/views/personnelManagement/payrollManagement/components/formDia.vue
index 6dbc326..e4cf0b3 100644
--- a/src/views/personnelManagement/payrollManagement/components/formDia.vue
+++ b/src/views/personnelManagement/payrollManagement/components/formDia.vue
@@ -2,7 +2,7 @@
   <div>
     <el-dialog
         v-model="dialogFormVisible"
-        :title="operationType === 'add' ? '鏂板鍏ヨ亴' : '缂栬緫浜哄憳'"
+        :title="operationType === 'add' ? '鏂板钖祫' : '缂栬緫钖祫'"
         width="50%"
         @close="closeDia"
     >
diff --git a/src/views/personnelManagement/payrollManagement/index.vue b/src/views/personnelManagement/payrollManagement/index.vue
index 1de23e4..24e3dd8 100644
--- a/src/views/personnelManagement/payrollManagement/index.vue
+++ b/src/views/personnelManagement/payrollManagement/index.vue
@@ -27,8 +27,8 @@
 				>
 			</div>
 			<div>
+				<el-button @click="handleExport" style="margin-right: 10px">瀵煎嚭</el-button>
 				<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>
@@ -51,7 +51,7 @@
 
 <script setup>
 import { Search } from "@element-plus/icons-vue";
-import {onMounted, ref} from "vue";
+import {onMounted, ref, reactive, toRefs, getCurrentInstance, nextTick} from "vue";
 import FormDia from "@/views/personnelManagement/payrollManagement/components/formDia.vue";
 import {staffJoinDel} from "@/api/personnelManagement/onboarding.js";
 import {ElMessageBox} from "element-plus";
@@ -283,6 +283,22 @@
 			proxy.$modal.msg("宸插彇娑�");
 		});
 };
+
+// 瀵煎嚭钖祫绠$悊
+const handleExport = () => {
+	ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚鍑猴紝鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
+		confirmButtonText: "纭",
+		cancelButtonText: "鍙栨秷",
+		type: "warning",
+	})
+		.then(() => {
+			proxy.download("/compensationPerformance/export", { ...searchForm.value, ...page }, "钖祫绠$悊.xlsx");
+		})
+		.catch(() => {
+			proxy.$modal.msg("宸插彇娑�");
+		});
+};
+
 onMounted(() => {
 	getList();
 });

--
Gitblit v1.9.3