yaowanxin
6 小时以前 94227d6729a9c489730435e406e3238354dec334
Merge remote-tracking branch 'origin/master' into dev

# Conflicts:
# .env.development
# .env.production
# .env.staging
# index.html
# package.json
# src/layout/components/Sidebar/Logo.vue
# src/main.js
# src/views/login.vue
# vite.config.js
已修改18个文件
已添加11个文件
4231 ■■■■■ 文件已修改
.env.development 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.env.production 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.env.staging 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
index.html 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
package.json 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
public/DHDCico.ico 补丁 | 查看 | 原始文档 | blame | 历史
src/api/collaborativeApproval/attendanceManagement.js 136 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/collaborativeApproval/knowledgeBase.js 55 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/collaborativeApproval/notificationManagement.js 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/collaborativeApproval/planTemplate.js 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/collaborativeApproval/rpaManagement.js 13 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/collaborativeApproval/sealManagement.js 116 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/inventoryManagement/stockWarning.js 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/personnelManagement/scheduling.js 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/personnelManagement/selfService.js 71 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/indexViews/DHDCLogo.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/indexViews/DHDCView.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/logo/敦煌鼎诚.png 补丁 | 查看 | 原始文档 | blame | 历史
src/layout/components/Sidebar/Logo.vue 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/collaborativeApproval/attendanceManagement/index.vue 509 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/collaborativeApproval/knowledgeBase/index.vue 216 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/collaborativeApproval/notificationManagement/index.vue 343 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/collaborativeApproval/planTemplate/index.vue 295 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/collaborativeApproval/rpaManagement/index.vue 205 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/collaborativeApproval/sealManagement/index.vue 519 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/inventoryManagement/stockWarning/index.vue 582 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/login.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/personnelManagement/scheduling/index.vue 483 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/personnelManagement/selfService/index.vue 486 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.env.development
@@ -1,8 +1,8 @@
# é¡µé¢æ ‡é¢˜
VITE_APP_TITLE = ä¸­å°ä¼ä¸šæ•°å­—化转型二级套餐包
VITE_APP_TITLE = æµ‹è¯•进销存管理系统
# å¼€å‘环境配置
VITE_APP_ENV = 'development'
# ä¸­å°ä¼ä¸šæ•°å­—化转型二级套餐包/开发环境
# æµ‹è¯•进销存管理系统/开发环境
VITE_APP_BASE_API = '/dev-api'
.env.production
@@ -1,11 +1,11 @@
# é¡µé¢æ ‡é¢˜
VITE_APP_TITLE = ä¸­å°ä¼ä¸šæ•°å­—化转型二级套餐包
VITE_APP_TITLE = æµ‹è¯•进销存管理系统
# ç”Ÿäº§çŽ¯å¢ƒé…ç½®
VITE_APP_ENV = 'production'
# ä¸­å°ä¼ä¸šæ•°å­—化转型二级套餐包/生产环境
# æµ‹è¯•进销存管理系统/生产环境
VITE_APP_BASE_API = '/prod-api'
# æ˜¯å¦åœ¨æ‰“包时开启压缩,支持 gzip å’Œ brotli
VITE_BUILD_COMPRESS = gzip
VITE_BUILD_COMPRESS = gzip
.env.staging
@@ -1,11 +1,11 @@
# é¡µé¢æ ‡é¢˜
VITE_APP_TITLE = ä¸­å°ä¼ä¸šæ•°å­—化转型二级套餐包
VITE_APP_TITLE = æµ‹è¯•进销存管理系统
# ç”Ÿäº§çŽ¯å¢ƒé…ç½®
VITE_APP_ENV = 'staging'
# ä¸­å°ä¼ä¸šæ•°å­—化转型二级套餐包/生产环境
# æµ‹è¯•进销存管理系统/生产环境
VITE_APP_BASE_API = '/stage-api'
# æ˜¯å¦åœ¨æ‰“包时开启压缩,支持 gzip å’Œ brotli
VITE_BUILD_COMPRESS = gzip
VITE_BUILD_COMPRESS = gzip
index.html
@@ -8,8 +8,8 @@
      name="viewport"
      content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"
    />
    <link rel="icon" href="/favicon.ico" />
    <title>中小企业数字化转型二级套餐包</title>
    <link rel="icon" href="/ZQHXico.ico" />
    <title>测试进销存管理系统</title>
    <!--[if lt IE 11
      ]><script>
        window.location.href = "/html/ie.html";
package.json
@@ -1,7 +1,7 @@
{
  "name": "ruoyi",
  "version": "3.8.9",
  "description": "中小企业数字化转型二级套餐包",
  "description": "测试进销存管理系统",
  "author": "若依",
  "license": "MIT",
  "type": "module",
public/DHDCico.ico
src/api/collaborativeApproval/attendanceManagement.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,136 @@
import request from "@/utils/request";
// æŸ¥è¯¢å‡æœŸè®¾ç½®åˆ—表
export function listHolidaySettings(query) {
  return request({
    url: "/holidaySettings/getList",
    method: "get",
    params: query,
  });
}
//查询年假规则列表
export function listAnnualLeaveSettingList(query) {
  return request({
    url: "/holidaySettings/getAnnualLeaveSettingList",
    method: "get",
    params: query,
  });
}
//查询加班规则列表
export function listOvertimeSettingList(query) {
  return request({
    url: "/holidaySettings/getOvertimeSettingList",
    method: "get",
    params: query,
  });
}
//查询工作时间规则列表
export function listWorkingHoursSettingList(query) {
  return request({
    url: "/holidaySettings/getWorkingHoursSettingList",
    method: "get",
    params: query,
  });
}
// æ–°å¢žå‡æœŸè®¾ç½®
export function addHolidaySettings(data) {
  return request({
    url: "/holidaySettings/add",
    method: "post",
    data: data,
  });
}
//新增年假规则
export function addAnnualLeaveSetting(data) {
  return request({
    url: "/holidaySettings/addAnnualLeaveSetting",
    method: "post",
    data: data,
  });
}
//新增加班规则
export function addOvertimeSetting(data) {
  return request({
    url: "/holidaySettings/addOvertimeSetting",
    method: "post",
    data: data,
  });
}
//新增工作时间规则
export function addWorkingHoursSetting(data) {
  return request({
    url: "/holidaySettings/addWorkingHoursSetting",
    method: "post",
    data: data,
  });
}
// ä¿®æ”¹å‡æœŸè®¾ç½®
export function updateHolidaySettings(data) {
  return request({
    url: "/holidaySettings/update",
    method: "post",
    data: data,
  });
}
// ä¿®æ”¹å¹´å‡è§„则
export function updateAnnualLeaveSetting(data) {
  return request({
    url: "/holidaySettings/updateAnnualLeaveSetting",
    method: "post",
    data: data,
  });
}
// ä¿®æ”¹åŠ ç­è§„åˆ™
export function updateOvertimeSetting(data) {
  return request({
    url: "/holidaySettings/updateOvertimeSetting",
    method: "post",
    data: data,
  });
}
// ä¿®æ”¹å·¥ä½œæ—¶é—´è§„则
export function updateWorkingHoursSetting(data) {
  return request({
    url: "/holidaySettings/updateWorkingHoursSetting",
    method: "post",
    data: data,
  });
}
// æ‰¹é‡åˆ é™¤å‡æœŸè®¾ç½®
export function delHolidaySettings(query) {
  return request({
    url: "/holidaySettings/delete",
    method: "delete",
    data: query,
  });
}
// æ‰¹é‡åˆ é™¤å¹´å‡è§„则
export function delAnnualLeaveSetting(query) {
  return request({
    url: "/holidaySettings/deleteAnnualLeaveSetting",
    method: "delete",
    data: query,
  });
}
// æ‰¹é‡åˆ é™¤åŠ ç­è§„åˆ™
export function delOvertimeSetting(query) {
  return request({
    url: "/holidaySettings/deleteOvertimeSetting",
    method: "delete",
    data: query,
  });
}
// æ‰¹é‡åˆ é™¤å·¥ä½œæ—¶é—´è§„则
export function delWorkingHoursSetting(query) {
  return request({
    url: "/holidaySettings/deleteWorkingHoursSetting",
    method: "delete",
    data: query,
  });
}
src/api/collaborativeApproval/knowledgeBase.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,55 @@
import request from "@/utils/request";
// æŸ¥è¯¢çŸ¥è¯†åº“列表
export function listKnowledgeBase(query) {
  return request({
    url: "/knowledgeBase/getList",
    method: "get",
    params: query,
  });
}
// æŸ¥è¯¢çŸ¥è¯†åº“详细
// export function getKnowledgeBase(knowledgeBaseId) {
//   return request({
//     url: "/collaborativeApproval/knowledgeBase/" + knowledgeBaseId,
//     method: "get",
//   });
// }
// æ–°å¢žçŸ¥è¯†åº“
export function addKnowledgeBase(data) {
  return request({
    url: "/knowledgeBase/add",
    method: "post",
    data: data,
  });
}
// ä¿®æ”¹çŸ¥è¯†åº“
export function updateKnowledgeBase(data) {
  return request({
    url: "/knowledgeBase/update",
    method: "post",
    data: data,
  });
}
// åˆ é™¤çŸ¥è¯†åº“
export function delKnowledgeBase(query) {
  return request({
    url: "/knowledgeBase/delete",
    method: "delete",
    data: query,
  });
}
// æ‰¹é‡åˆ é™¤çŸ¥è¯†åº“
export function delKnowledgeBaseBatch(knowledgeBaseIds) {
  return request({
    url: "/knowledgeBase/batch",
    method: "delete",
    data: knowledgeBaseIds,
  });
}
src/api/collaborativeApproval/notificationManagement.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,63 @@
import request from "@/utils/request";
// æŸ¥è¯¢é€šçŸ¥åˆ—表
export function listNotification(query) {
  return request({
    url: "/notificationManagement/getList",
    method: "get",
    params: query,
  });
}
// æ–°å¢žé€šçŸ¥
export function addNotification(data) {
  return request({
    url: "/notificationManagement/add",
    method: "post",
    data: data,
  });
}
//新增会议
export function addOnlineMeeting(data) {
  return request({
    url: "/notificationManagement/addOnlineMeeting",
    method: "post",
    data: data,
  });
}
//新增文件共享
export function addFileSharing(data) {
  return request({
    url: "/notificationManagement/addFileSharing",
    method: "post",
    data: data,
  });
}
// ä¿®æ”¹é€šçŸ¥
export function updateNotification(data) {
  return request({
    url: "/notificationManagement/update",
    method: "post",
    data: data,
  });
}
// æ‰¹é‡åˆ é™¤é€šçŸ¥
export function delNotification(query) {
  return request({
    url: "/notificationManagement/delete",
    method: "delete",
    data: query,
  });
}
// // æ‰¹é‡åˆ é™¤çŸ¥è¯†åº“
// export function delKnowledgeBaseBatch(knowledgeBaseIds) {
//   return request({
//     url: "/knowledgeBase/batch",
//     method: "delete",
//     data: knowledgeBaseIds,
//   });
// }
src/api/collaborativeApproval/planTemplate.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,64 @@
import request from "@/utils/request";
// æŸ¥è¯¢è®¡åˆ’列表
export function listDutyPlan(query) {
  return request({
    url: "/dutyPlan/getList",
    method: "get",
    params: query
  });
}
//数据
export function NumDutyPlan(query) {
  return request({
    url: "/dutyPlan/getNum",
    method: "get",
    params: query
  });
}
// æ–°å¢žè®¡åˆ’
export function addDutyPlan(data) {
  return request({
    url: "/dutyPlan/add",
    method: "post",
    data: data,
  });
}
// ä¿®æ”¹è®¡åˆ’
export function updateDutyPlan(data) {
  return request({
    url: "/dutyPlan/update",
    method: "post",
    data: data,
  });
}
// åˆ é™¤è®¡åˆ’
export function delDutyPlan(query) {
  return request({
    url: "/dutyPlan/delete",
    method: "delete",
    data: query,
  });
}
// å¯¼å‡ºè®¡åˆ’
export function exportDutyPlan(query) {
  return request({
    url: "/dutyPlan/export",
    method: "post",
    params: query,
  });
}
// // æ‰¹é‡åˆ é™¤è®¡åˆ’
// export function delDutyPlanBatch(dutyPlanIds) {
//   return request({
//     url: "/dutyPlan/batch",
//     method: "delete",
//     data: dutyPlanIds,
//   });
// }
src/api/collaborativeApproval/rpaManagement.js
@@ -3,7 +3,7 @@
// æŸ¥è¯¢RPA列表
export function listRpa(query) {
  return request({
    url: "/collaborativeApproval/rpa/list",
    url: "/rpaProcessAutomation/getList",
    method: "get",
    params: query,
  });
@@ -20,7 +20,7 @@
// æ–°å¢žRPA
export function addRpa(data) {
  return request({
    url: "/collaborativeApproval/rpa",
    url: "/rpaProcessAutomation/add",
    method: "post",
    data: data,
  });
@@ -29,17 +29,18 @@
// ä¿®æ”¹RPA
export function updateRpa(data) {
  return request({
    url: "/collaborativeApproval/rpa",
    method: "put",
    url: "/rpaProcessAutomation/update",
    method: "post",
    data: data,
  });
}
// åˆ é™¤RPA
export function delRpa(rpaId) {
export function delRpa(query) {
  return request({
    url: "/collaborativeApproval/rpa/" + rpaId,
    url: "/rpaProcessAutomation/delete",
    method: "delete",
    data: query,
  });
}
src/api/collaborativeApproval/sealManagement.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,116 @@
import request from "@/utils/request";
// æŸ¥è¯¢å°ç« ç”³è¯·åˆ—表
export function listSealApplication(page,query) {
  return request({
    url: "/sealApplicationManagement/getList",
    method: "get",
    params: {
      ...page,
      ...query},
  });
}
// æŸ¥è¯¢è§„章制度列表
export function listRuleManagement(page,query) {
  return request({
    url: "/rulesRegulationsManagement/getList",
    method: "get",
    params: {
      ...page,
      ...query},
  });
}
// æŸ¥è¯¢é˜…读状态列表
export function getReadingStatusList(page,query) {
  return request({
    url: "/rulesRegulationsManagement/getReadingStatusList",
    method: "get",
    params: {
      ...page,
      ...query},
  });
}
// æ ¹æ®è§„则id查询阅读状态列表
export function getReadingStatusByRuleId(id) {
  return request({
    url: "/rulesRegulationsManagement/getReadingStatusByRuleId/"+id,
    method: "get"
  });
}
// æ–°å¢žå°ç« ç”³è¯·
export function addSealApplication(data) {
  return request({
    url: "/sealApplicationManagement/add",
    method: "post",
    data: data,
  });
}
// æ–°å¢žè§„章制度
export function addRuleManagement(data) {
  return request({
    url: "/rulesRegulationsManagement/add",
    method: "post",
    data: data,
  });
}
// æ–°å¢žé˜…读状态
export function addReadingStatus(data) {
  return request({
    url: "/rulesRegulationsManagement/addReadingStatus",
    method: "post",
    data: data,
  });
}
// ä¿®æ”¹å°ç« ç”³è¯·
export function updateSealApplication(data) {
  return request({
    url: "/sealApplicationManagement/update",
    method: "post",
    data: data,
  });
}
// ä¿®æ”¹è§„章制度
export function updateRuleManagement(data) {
  return request({
    url: "/rulesRegulationsManagement/update",
    method: "post",
    data: data,
  });
}
// ä¿®æ”¹é˜…读状态
export function updateReadingStatus(data) {
  return request({
    url: "/rulesRegulationsManagement/updateReadingStatus",
    method: "post",
    data: data,
  });
}
// åˆ é™¤å°ç« ç”³è¯·
export function delSealApplication(query) {
  return request({
    url: "/sealApplicationManagement/delete",
    method: "delete",
    data: query,
  });
}
// åˆ é™¤è§„章制度
export function delRuleManagement(query) {
  return request({
    url: "/rulesRegulationsManagement/delete",
    method: "delete",
    data: query,
  });
}
// æ‰¹é‡åˆ é™¤çŸ¥è¯†åº“
export function delKnowledgeBaseBatch(knowledgeBaseIds) {
  return request({
    url: "/knowledgeBase/batch",
    method: "delete",
    data: knowledgeBaseIds,
  });
}
src/api/inventoryManagement/stockWarning.js
@@ -1,11 +1,14 @@
import request from "@/utils/request";
// æŸ¥è¯¢å‚¨æ°”罐预警列表
export const getStockWarningPage = (params) => {
export const getStockWarningPage = (page, params) => {
    return request({
        url: "/gasTankWarning/listPage",
        method: "get",
        params,
        params: {
            ...page,
            ...params
        },
    });
};
@@ -14,7 +17,7 @@
    return request({
        url: "/gasTankWarning/add",
        method: "post",
        data,
        data: data,
    });
};
@@ -22,8 +25,8 @@
export const updateStockWarning = (data) => {
    return request({
        url: "/gasTankWarning/update",
        method: "put",
        data,
        method: "post",
        data: data,
    });
};
@@ -32,7 +35,7 @@
    return request({
        url: "/gasTankWarning/delete",
        method: "delete",
        data: { ids },
        data: ids,
    });
};
src/api/personnelManagement/scheduling.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,32 @@
// æŽ’班管理
import request from "@/utils/request";
export function save(data) {
    return request({
        url: "/staff/staffScheduling/save",
        method: "post",
        data: data,
    });
}
export function del(id) {
    return request({
        url: "/staff/staffScheduling/del/"+id,
        method: "delete",
    });
}
export function delByIds(data) {
    return request({
        url: "/staff/staffScheduling/save",
        method: "post",
        data: data,
    });
}
export function listPage(data){
    return request({
        url: "/staff/staffScheduling/listPage",
        method: "post",
        data: data
    })
}
src/api/personnelManagement/selfService.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,71 @@
// è–ªé…¬ç®¡ç†
import request from "@/utils/request";
// æŸ¥è¯¢è€ƒå‹¤åˆ—表
export function personalAttendanceRecordsListPage(query) {
  return request({
    url: "/staff/personalAttendanceRecords/listPage",
    method: "get",
    params: query,
  });
}
// æŸ¥è¯¢å‡æœŸç”³è¯·åˆ—表
export function holidayApplicationListPage(query) {
  return request({
    url: "/staff/holidayApplication/listPage",
    method: "get",
    params: query,
  });
}
// æ–°å¢ž
export function personalAttendanceRecordsAdd(query) {
  return request({
    url: "/staff/personalAttendanceRecords/add",
    method: "post",
    data: query,
  });
}
// æ–°å¢žå‡æœŸç”³è¯·
export function holidayApplicationAdd(query) {
  return request({
    url: "/staff/holidayApplication/add",
    method: "post",
    data: query,
  });
}
// ä¿®æ”¹
export function personalAttendanceRecordsUpdate(query) {
  return request({
    url: "/staff/personalAttendanceRecords/update",
    method: "put",
    data: query,
  });
}
// ä¿®æ”¹å‡æœŸç”³è¯·
export function holidayApplicationUpdate(query) {
  return request({
    url: "/staff/holidayApplication/update",
    method: "post",
    data: query,
  });
}
// åˆ é™¤
export function personalAttendanceRecordsDelete(id) {
  return request({
    url: "/staff/personalAttendanceRecords/delete/"+id,
    method: "delete",
  });
}
// åˆ é™¤å‡æœŸç”³è¯·
export function holidayApplicationDelete(id) {
  return request({
    url: "/staff/holidayApplication/delete/"+id,
    method: "delete",
  });
}
// export function del(id) {
//     return request({
//         url: "/staff/staffScheduling/del/"+id,
//         method: "delete",
//     });
// }
src/assets/indexViews/DHDCLogo.png
src/assets/indexViews/DHDCView.png
src/assets/logo/¶Ø»Í¶¦³Ï.png
src/layout/components/Sidebar/Logo.vue
@@ -16,7 +16,7 @@
<script setup>
import { ref, computed, onMounted, watch } from 'vue'
import useUserStore from '@/store/modules/user'
import defaultLogo from '@/assets/indexViews/LCLogo.png' // å¯¼å…¥é»˜è®¤logo
import defaultLogo from '@/assets/indexViews/ZQHXLogo.png' // å¯¼å…¥é»˜è®¤logo
defineProps({
  collapse: {
@@ -126,4 +126,4 @@
    }
  }
}
</style>
</style>
src/views/collaborativeApproval/attendanceManagement/index.vue
@@ -5,7 +5,7 @@
      <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;">
            <el-table-column prop="name" label="假期名称" />
            <el-table-column prop="type" label="假期类型">
@@ -25,8 +25,8 @@
            </el-table-column>
            <el-table-column label="操作" fixed="right">
              <template #default="scope">
                <el-button type="primary" link @click="openDialog('holiday', 'edit', scope.row)">编辑</el-button>
                <el-button type="danger" link @click="deleteItem('holiday', scope.row)">删除</el-button>
                <el-button type="primary" size="small" @click="openDialog('holiday', 'edit', scope.row)">编辑</el-button>
                <el-button type="danger" size="small" @click="deleteItem('holiday', scope.row)">删除</el-button>
              </template>
            </el-table-column>
          </el-table>
@@ -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;">
            <el-table-column prop="employeeType" label="员工类型"/>
            <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" />
@@ -52,8 +56,8 @@
            </el-table-column>
            <el-table-column label="操作" fixed="right">
              <template #default="scope">
                <el-button type="primary" link @click="openDialog('annual', 'edit', scope.row)">编辑</el-button>
                <el-button type="danger" link @click="deleteItem('annual', scope.row)">删除</el-button>
                <el-button type="primary" size="small" @click="openDialog('annual', 'edit', scope.row)">编辑</el-button>
                <el-button type="danger" size="small" @click="deleteItem('annual', scope.row)">删除</el-button>
              </template>
            </el-table-column>
          </el-table>
@@ -64,7 +68,7 @@
      <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;">
            <el-table-column prop="name" label="规则名称" />
            <el-table-column prop="type" label="加班类型" >
@@ -84,8 +88,8 @@
            </el-table-column>
            <el-table-column label="操作" fixed="right">
              <template #default="scope">
                <el-button type="primary" link @click="openDialog('overtime', 'edit', scope.row)">编辑</el-button>
                <el-button type="danger" link @click="deleteItem('overtime', scope.row)">删除</el-button>
                <el-button type="primary" size="small" @click="openDialog('overtime', 'edit', scope.row)">编辑</el-button>
                <el-button type="danger" size="small" @click="deleteItem('overtime', scope.row)">删除</el-button>
              </template>
            </el-table-column>
          </el-table>
@@ -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;">
            <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>
@@ -118,8 +122,8 @@
            </el-table-column>
            <el-table-column label="操作" fixed="right">
              <template #default="scope">
                <el-button type="primary" link @click="openDialog('worktime', 'edit', scope.row)">编辑</el-button>
                <el-button type="danger" link @click="deleteItem('worktime', scope.row)">删除</el-button>
                <el-button type="primary" size="small" @click="openDialog('worktime', 'edit', scope.row)">编辑</el-button>
                <el-button type="danger" size="small" @click="deleteItem('worktime', scope.row)">删除</el-button>
              </template>
            </el-table-column>
          </el-table>
@@ -133,23 +137,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="正式员工" value="regular" />
            <!-- <el-option label="正式员工" 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 +201,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 +247,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 +268,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 +280,23 @@
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 form = reactive({
  name: '',
  type: '',
  dateRange: [],
  startDate: '',
  endDate: '',
  days: 0,
  employeeType: '',
  workYears: '',
@@ -300,9 +322,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 +334,9 @@
      }
    }
  }],
  endTime: [{
    required: true,
    message: '请选择结束时间',
  endTime: [{
    required: true,
    message: '请选择结束时间',
    trigger: 'change',
    validator: (rule, value, callback) => {
      if (!value) {
@@ -324,9 +346,9 @@
      }
    }
  }],
  workStartTime: [{
    required: true,
    message: '请选择上班时间',
  workStartTime: [{
    required: true,
    message: '请选择上班时间',
    trigger: 'change',
    validator: (rule, value, callback) => {
      if (!value) {
@@ -336,9 +358,9 @@
      }
    }
  }],
  workEndTime: [{
    required: true,
    message: '请选择下班时间',
  workEndTime: [{
    required: true,
    message: '请选择下班时间',
    trigger: 'change',
    validator: (rule, value, callback) => {
      if (!value) {
@@ -350,37 +372,12 @@
  }],
  rate: [{ required: true, message: '请输入倍率', trigger: 'blur' }]
}
// æ¨¡æ‹Ÿæ•°æ®
const holidayData = ref([
  { id: '1', name: '春节', type: 'legal', startDate: '2025-02-10', endDate: '2025-02-17', days: 8, status: 'active' },
  { id: '2', name: '清明节', type: 'legal', startDate: '2025-04-05', endDate: '2025-04-05', days: 1, status: 'active' },
  { id: '3', name: '劳动节', type: 'legal', startDate: '2025-05-01', endDate: '2025-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,7 +385,8 @@
const getTypeLabel = (type) => {
  const labelMap = {
    legal: '法定节假日', adjustment: '调休日', special: '特殊假期', company: '公司假期',
    weekday: '工作日加班', weekend: '周末加班', holiday: '节假日加班', night: '深夜加班'
    weekday: '工作日加班', weekend: '周末加班', holiday: '节假日加班', night: '深夜加班',
    regular: '正式员工', probation: '试用期员工', intern: '实习生'
  }
  return labelMap[type] || type
}
@@ -408,6 +406,12 @@
      { label: '节假日加班', value: 'holiday' },
      { label: '深夜加班', value: 'night' }
    ]
  } else if (currentType.value === 'annual') {
    return [
      { label: '正式员工', value: 'regular' },
      { label: '试用期员工', value: 'probation' },
      { label: '实习生', value: 'intern' }
    ]
  }
  return []
}
@@ -418,12 +422,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 +440,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 +470,7 @@
  try {
    currentType.value = type
    currentAction.value = action
    if (action === 'add') {
      dialogTitle.value = `新增${getTypeName(type)}`
      currentEditId.value = ''
@@ -474,7 +480,7 @@
      currentEditId.value = row.id
      fillForm(row)
    }
    dialogVisible.value = true
  } catch (error) {
    console.error('打开弹窗失败:', error)
@@ -497,6 +503,8 @@
    name: '',
    type: '',
    dateRange: [],
    startDate: '',
    endDate: '',
    days: 0,
    employeeType: '',
    workYears: '',
@@ -519,6 +527,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 +568,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,84 +586,190 @@
}
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
    //   }
    // }
  }
}
@@ -664,21 +780,114 @@
    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()
  console.log('考勤管理页面加载完成')
})
src/views/collaborativeApproval/knowledgeBase/index.vue
@@ -28,7 +28,7 @@
        <el-button type="danger" plain @click="handleDelete">删除</el-button>
      </div>
    </div>
    <div class="table_list">
      <PIMTable
        rowKey="id"
@@ -221,7 +221,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>
@@ -233,6 +233,7 @@
import { onMounted, ref, reactive, toRefs } from "vue";
import { ElMessage, ElMessageBox } from "element-plus";
import PIMTable from "@/components/PIMTable/PIMTable.vue";
import { listKnowledgeBase, delKnowledgeBaseBatch,addKnowledgeBase,updateKnowledgeBase } from "@/api/collaborativeApproval/knowledgeBase.js";
// è¡¨å•验证规则
const rules = {
@@ -259,7 +260,7 @@
  tableLoading: false,
  page: {
    current: 1,
    size: 100,
    size: 20,
    total: 0,
  },
  tableData: [],
@@ -268,7 +269,7 @@
    title: "",
    type: "",
    scenario: "",
    efficiency: "medium",
    efficiency: "",
    problem: "",
    solution: "",
    keyPoints: "",
@@ -282,11 +283,11 @@
  currentKnowledge: {}
});
const {
  searchForm,
  tableLoading,
  page,
  tableData,
const {
  searchForm,
  tableLoading,
  page,
  tableData,
  selectedIds,
  form,
  dialogVisible,
@@ -400,47 +401,47 @@
]);
// æ¨¡æ‹Ÿæ•°æ®
let mockData = [
  {
    id: "1",
    title: "特殊合同审批流程优化方案",
    type: "contract",
    scenario: "大额合同快速审批",
    efficiency: "high",
    problem: "大额合同审批流程复杂,审批时间长,影响业务进展",
    solution: "建立绿色通道,对符合条件的合同采用简化审批流程,由部门负责人直接审批,平均审批时间从3天缩短至1天",
    keyPoints: "绿色通道条件,简化流程,审批权限,时间控制",
    creator: "陈志强",
    usageCount: 15,
    createTime: "2025-01-15 10:30:00"
  },
  {
    id: "2",
    title: "跨部门协作审批经验总结",
    type: "experience",
    scenario: "多部门协作项目",
    efficiency: "medium",
    problem: "跨部门项目审批时,各部门意见不统一,审批进度缓慢",
    solution: "建立项目协调机制,指定项目负责人,定期召开协调会议,统一各方意见后再进行审批",
    keyPoints: "项目协调,定期会议,统一意见,负责人制度",
    creator: "李主管",
    usageCount: 8,
    createTime: "2025-01-14 15:20:00"
  },
  {
    id: "3",
    title: "紧急采购审批操作指南",
    type: "guide",
    scenario: "紧急采购需求",
    efficiency: "high",
    problem: "紧急采购时审批流程复杂,无法满足紧急需求",
    solution: "制定紧急采购审批标准,明确紧急程度分级,不同级别采用不同审批流程,确保紧急需求得到及时处理",
    keyPoints: "紧急分级,标准制定,流程简化,及时处理",
    creator: "王专员",
    usageCount: 12,
    createTime: "2025-01-13 09:15:00"
  }
];
// let mockData = [
//   {
//     id: "1",
//     title: "特殊合同审批流程优化方案",
//     type: "contract",
//     scenario: "大额合同快速审批",
//     efficiency: "high",
//     problem: "大额合同审批流程复杂,审批时间长,影响业务进展",
//     solution: "建立绿色通道,对符合条件的合同采用简化审批流程,由部门负责人直接审批,平均审批时间从3天缩短至1天",
//     keyPoints: "绿色通道条件,简化流程,审批权限,时间控制",
//     creator: "张经理",
//     usageCount: 15,
//     createTime: "2024-01-15 10:30:00"
//   },
//   {
//     id: "2",
//     title: "跨部门协作审批经验总结",
//     type: "experience",
//     scenario: "多部门协作项目",
//     efficiency: "medium",
//     problem: "跨部门项目审批时,各部门意见不统一,审批进度缓慢",
//     solution: "建立项目协调机制,指定项目负责人,定期召开协调会议,统一各方意见后再进行审批",
//     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 = [
@@ -472,13 +473,13 @@
  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,
@@ -488,19 +489,19 @@
    problem: `在${randomScenario}过程中遇到的问题描述...`,
    solution: `针对${randomScenario}的解决方案和操作步骤...`,
    keyPoints: "关键要点1,关键要点2,关键要点3,关键要点4",
          creator: ["陈志强", "刘雅婷", "王建国", "赵丽华"][Math.floor(Math.random() * 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}`);
};
@@ -526,24 +527,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 +559,7 @@
      title: "",
      type: "",
      scenario: "",
      efficiency: "medium",
      efficiency: "",
      problem: "",
      solution: "",
      keyPoints: "",
@@ -578,6 +569,7 @@
  } else if (type === "edit" && row) {
    dialogTitle.value = "编辑知识";
    Object.assign(form.value, {
      id: row.id,
      title: row.title,
      type: row.type,
      scenario: row.scenario,
@@ -665,15 +657,15 @@
// å¤åˆ¶çŸ¥è¯†
const copyKnowledge = () => {
  const knowledgeText = `
知识标题:${currentKnowledge.value.title}
知识类型:${getTypeLabel(currentKnowledge.value.type)}
适用场景:${currentKnowledge.value.scenario}
问题描述:${currentKnowledge.value.problem}
解决方案:${currentKnowledge.value.solution}
关键要点:${currentKnowledge.value.keyPoints}
创建人:${currentKnowledge.value.creator}
    çŸ¥è¯†æ ‡é¢˜ï¼š${currentKnowledge.value.title}
    çŸ¥è¯†ç±»åž‹ï¼š${getTypeLabel(currentKnowledge.value.type)}
    é€‚用场景:${currentKnowledge.value.scenario}
    é—®é¢˜æè¿°ï¼š${currentKnowledge.value.problem}
    è§£å†³æ–¹æ¡ˆï¼š${currentKnowledge.value.solution}
    å…³é”®è¦ç‚¹ï¼š${currentKnowledge.value.keyPoints}
    åˆ›å»ºäººï¼š${currentKnowledge.value.creator}
  `.trim();
  // å¤åˆ¶åˆ°å‰ªè´´æ¿
  navigator.clipboard.writeText(knowledgeText).then(() => {
    ElMessage.success("知识内容已复制到剪贴板");
@@ -690,7 +682,7 @@
    mockData[index].usageCount += 1;
    currentKnowledge.value.usageCount += 1;
  }
  ElMessage.success("已收藏,使用次数+1");
};
@@ -698,46 +690,28 @@
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,7 +723,7 @@
    ElMessage.warning("请选择要删除的知识");
    return;
  }
  ElMessageBox.confirm("选中的内容将被删除,是否确认删除?", "删除", {
    confirmButtonText: "确认",
    cancelButtonText: "取消",
@@ -762,7 +736,7 @@
        mockData.splice(index, 1);
      }
    });
    ElMessage.success("删除成功");
    selectedIds.value = [];
    getList();
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%"
              />
@@ -319,6 +323,8 @@
import PIMTable from "@/components/PIMTable/PIMTable.vue";
import { userListNoPageByTenantId } from "@/api/system/user.js";
import { staffOnJobListPage } from "@/api/personnelManagement/employeeRecord.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,
@@ -556,47 +562,6 @@
    ]
  }
]);
// æ¨¡æ‹Ÿæ•°æ®
let mockData = [
  {
    id: "1",
    title: "2024年春节放假通知",
    type: "holiday",
    priority: "high",
    status: "published",
    content: "根据国家规定,结合公司实际情况,现将2024年春节放假安排通知如下...",
    departments: ["技术部", "销售部", "人事部", "财务部", "运营部", "市场部", "客服部"],
    expireDate: "2025-02-15",
    syncMethods: ["wechat", "dingtalk", "email"],
    createTime: "2025-01-15 10:30:00"
  },
  {
    id: "2",
    title: "技术部周例会通知",
    type: "meeting",
    priority: "medium",
    status: "published",
    content: "技术部定于每周五下午2点召开周例会,请各位同事准时参加...",
    departments: ["技术部"],
    expireDate: "2025-01-20",
    syncMethods: ["wechat", "dingtalk"],
    createTime: "2025-01-14 15:20:00"
  },
  {
    id: "3",
    title: "员工行为规范处罚通知",
    type: "penalty",
    priority: "high",
    status: "draft",
    content: "为维护公司正常秩序,规范员工行为,现对违反公司规定的行为进行处罚...",
    departments: ["人事部", "技术部", "销售部"],
    expireDate: "2025-02-13",
    syncMethods: ["wechat", "email"],
    createTime: "2025-01-13 09:15:00"
  }
];
// é€šçŸ¥æ ‡é¢˜æ¨¡æ¿
const titleTemplates = [
  "关于{year}å¹´{holiday}放假安排的通知",
@@ -631,7 +596,7 @@
    employeesLoading.value = true;
    // ä¼˜å…ˆä½¿ç”¨ç³»ç»Ÿç”¨æˆ·æŽ¥å£ï¼ˆæŒ‰ç§Ÿæˆ·èŽ·å–ï¼‰
    const userResponse = await userListNoPageByTenantId();
    if (userResponse.data) {
      employees.value = userResponse.data.map(user => ({
        label: user.nickName || user.userName || '未知姓名',
@@ -643,12 +608,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 || '未知姓名',
@@ -664,9 +629,9 @@
    console.error('获取员工列表失败:', error);
    // å¦‚果接口都失败,使用默认数据
    employees.value = [
      { label: "陈志强", value: "001", dept: "技术部", phone: "13800138001", email: "chenzhiqiang@company.com", status: "0" },
      { label: "刘雅婷", value: "002", dept: "销售部", phone: "13800138002", email: "liuyating@company.com", status: "0" },
      { label: "王建国", value: "003", dept: "人事部", phone: "13800138003", email: "wangjianguo@company.com", status: "0" }
      { label: "张三", value: "001", dept: "技术部", phone: "13800138001", email: "zhangsan@company.com", status: "0" },
      { label: "李四", value: "002", dept: "销售部", phone: "13800138002", email: "lisi@company.com", status: "0" },
      { label: "王五", value: "003", dept: "人事部", phone: "13800138003", email: "wangwu@company.com", status: "0" }
    ];
  } finally {
    employeesLoading.value = false;
@@ -683,7 +648,7 @@
    }
    groups[dept].push(employee);
  });
  // æŒ‰éƒ¨é—¨åç§°æŽ’序,确保显示顺序一致
  return Object.keys(groups)
    .sort()
@@ -697,7 +662,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 +677,18 @@
const refreshEmployees = async () => {
  ElMessage.info("正在刷新员工列表...");
  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 +702,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 +741,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 +753,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 +774,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 +809,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 +838,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 +903,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 +936,7 @@
const createMeeting = async () => {
  try {
    await meetingFormRef.value.validate();
    // æ¨¡æ‹Ÿåˆ›å»ºä¼šè®®
    const meetingInfo = {
      title: meetingForm.value.title,
@@ -998,22 +944,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(`会议创建成功!会议ID: ${meetingInfo.meetingId},将通过${platformName}发送通知`);
    meetingDialogVisible.value = false;
         // èŽ·å–å‚ä¼šäººå‘˜ä¿¡æ¯
    // const platformName = meetingPlatforms.find(p => p.value === meetingForm.value.platform)?.label || "未知平台";
    // ElMessage.success(`会议创建成功!会议ID: ${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 +976,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 +1011,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 +1040,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(`文件共享成功!共享ID: ${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(`文件共享成功!共享ID: ${shareInfo.shareId},已通知相关部门`);
    // å°†æ–‡ä»¶å…±äº«ä¿¡æ¯æ·»åŠ åˆ°é€šçŸ¥åˆ—è¡¨
    const fileShareNotification = {
      id: (mockData.length + 1).toString(),
      title: `[文件共享] ${shareInfo.title}`,
      type: "temporary",
      priority: "medium",
@@ -1111,11 +1076,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 +1096,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(() => {
    // ç”¨æˆ·å–消
  });
src/views/collaborativeApproval/planTemplate/index.vue
@@ -18,6 +18,8 @@
          v-model="currentDate"
          :type="datePickerType"
          placeholder="选择日期"
          format="YYYY-MM-DD"
          value-format="YYYY-MM-DD"
          style="width: 180px; margin-left: 10px"
          @change="handleDateChange"
        />
@@ -25,7 +27,7 @@
      <div class="right-actions">
        <el-button type="primary" @click="handleAddPlan">新增计划</el-button>
        <el-button @click="handleExport">导出计划</el-button>
        <el-button @click="handleShare">共享计划</el-button>
        <!-- <el-button @click="handleShare">共享计划@</el-button> -->
      </div>
    </div>
@@ -107,7 +109,7 @@
            <span>{{ getCurrentLevelText() }} - {{ getCurrentPeriodText() }}</span>
            <div>
              <el-button size="small" @click="handleRefresh">刷新</el-button>
              <el-button size="small" @click="handleFilter">筛选</el-button>
              <!-- <el-button size="small" @click="handleFilter">筛选@</el-button> -->
            </div>
          </div>
        </template>
@@ -122,13 +124,13 @@
              <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="handleMoreAction">
                <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="share">共享@</el-dropdown-item> -->
                      <el-dropdown-item command="copy">复制</el-dropdown-item>
                      <el-dropdown-item command="delete" divided>删除</el-dropdown-item>
                    </el-dropdown-menu>
@@ -180,7 +182,7 @@
    <!-- æ–°å¢ž/编辑计划对话框 -->
    <el-dialog
      v-model="planDialogVisible"
      :title="dialogTitle"
      :title="operationType === 'add' ? '发布计划' : '编辑计划'"
      width="600px"
      @close="handleDialogClose"
    >
@@ -215,6 +217,8 @@
          <el-date-picker
            v-model="planForm.startDate"
            type="date"
            value-format="YYYY-MM-DD"
            format="YYYY-MM-DD"
            placeholder="选择开始时间"
            style="width: 100%"
          />
@@ -223,6 +227,8 @@
          <el-date-picker
            v-model="planForm.endDate"
            type="date"
            value-format="YYYY-MM-DD"
            format="YYYY-MM-DD"
            placeholder="选择结束时间"
            style="width: 100%"
          />
@@ -237,8 +243,48 @@
            <el-option label="低" value="low" />
          </el-select>
        </el-form-item>
        <el-form-item label="标签">
        <!-- <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>
@@ -248,12 +294,31 @@
        </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,
@@ -264,17 +329,22 @@
  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',
@@ -283,7 +353,9 @@
  endDate: '',
  assignee: '',
  priority: 'medium',
  tags: ''
  tags: [],
  status: '',
  progress: 0
})
// è¡¨å•验证规则
@@ -297,74 +369,17 @@
  assignee: [{ required: true, message: '请输入负责人', trigger: 'blur' }],
  priority: [{ required: true, message: '请选择优先级', trigger: 'change' }]
}
const departments = ["产品", "分析", "调研",'技术', '架构', '设计','市场', '推广', '营销'];
// æ¦‚览数据
const overviewData = reactive({
  personal: { total: 12, completion: 75 },
  group: { total: 8, completion: 60 },
  department: { total: 15, completion: 45 },
  company: { total: 6, completion: 30 }
  personal: { total: 0, completion: 0 },
  group: { total: 0, completion: 0 },
  department: { total: 0, completion: 0 },
  company: { total: 0, completion: 0 }
})
// è®¡åˆ’列表数据
const planList = ref([
  {
    id: 1,
    title: '产品需求分析',
    description: '对新产品进行详细的需求分析和市场调研,制定产品规划方案',
    level: 'personal',
    period: 'week',
    startDate: '2025-01-15',
    endDate: '2025-01-21',
    assignee: '陈志强',
    priority: 'high',
    status: 'in_progress',
    progress: 80,
    tags: ['产品', '分析', '调研']
  },
  {
    id: 2,
    title: '技术架构设计',
    description: '设计系统技术架构,包括数据库设计、接口设计等',
    level: 'group',
    period: 'month',
    startDate: '2025-01-01',
    endDate: '2025-01-31',
    assignee: '刘雅婷',
    priority: 'high',
    status: 'completed',
    progress: 100,
    tags: ['技术', '架构', '设计']
  },
  {
    id: 3,
    title: '市场推广计划',
    description: '制定年度市场推广策略和营销计划',
    level: 'department',
    period: 'year',
    startDate: '2025-01-01',
    endDate: '2025-12-31',
    assignee: '王建国',
    priority: 'medium',
    status: 'not_started',
    progress: 0,
    tags: ['市场', '推广', '营销']
  },
  {
    id: 4,
    title: '团队建设活动',
    description: '组织团队建设活动,提升团队凝聚力和协作效率',
    level: 'company',
    period: 'month',
    startDate: '2025-01-15',
    endDate: '2025-02-15',
    assignee: '赵丽华',
    priority: 'low',
    status: 'in_progress',
    progress: 30,
    tags: ['团队', '建设', '活动']
  }
])
const planList = ref([])
// è®¡ç®—属性
const datePickerType = computed(() => {
@@ -383,20 +398,24 @@
// æ–¹æ³•
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
  // é‡ç½®è¡¨å•
@@ -406,32 +425,61 @@
  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.keys(planForm).forEach(key => {
    if (key === 'tags') {
      planForm[key] = plan[key].join(', ')
    } else {
      planForm[key] = plan[key]
    }
  })
  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) => {
  ElMessage.info(`查看计划详情: ${plan.title}`)
  currentPlanDetail.value = plan
  showPlanDetailDialog.value = true
  // ElMessage.info(`查看计划详情: ${plan.title}`)
}
const handleMoreAction = (command) => {
const handleMoreAction = async(plan,command) => {
  let ids = [];
  ids.push(plan.id);
  console.log("ids",ids)
  switch (command) {
    case 'share':
      ElMessage.success('计划已共享')
      break
    case 'copy':
      ElMessage.success('计划已复制')
      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('确定要删除这个计划吗?', '提示', {
@@ -439,17 +487,40 @@
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        ElMessage.success('计划已删除')
        delDutyPlan(ids).then(res => {
          if (res.code === 200) {
            ElMessage.success('计划已删除')
            ids.value = [];
            getPlanList()
          }
        })
      })
      break
  }
}
//
const handleSavePlan = async () => {
  try {
    await planFormRef.value.validate()
    ElMessage.success('计划保存成功')
    planDialogVisible.value = false
    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)
  }
@@ -460,7 +531,8 @@
}
const handleRefresh = () => {
  ElMessage.success('数据已刷新')
  getPlanList()
  // ElMessage.success('数据已刷新')
}
const handleFilter = () => {
@@ -468,9 +540,21 @@
}
const handleExport = () => {
  ElMessage.success('计划已导出')
}
  ElMessageBox.confirm("是否确认导出?", "导出", {
    confirmButtonText: "确认",
    cancelButtonText: "取消",
    type: "warning",
  })
    .then(() => {
      // exportDutyPlan().then(res => {
      // })
      proxy.download("/dutyPlan/export", {}, "计划管理.xlsx");
    })
    .catch(() => {
      proxy.$modal.msg("已取消");
    });
};
const handleShare = () => {
  ElMessage.success('计划已共享')
}
@@ -527,8 +611,41 @@
  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>
src/views/collaborativeApproval/rpaManagement/index.vue
@@ -92,7 +92,7 @@
import { onMounted, ref, reactive, toRefs } 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 +100,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 +120,8 @@
// è¡¨å•引用
const formRef = ref();
// é€‰æ‹©çš„行数据
const selectedRows = ref([]);
// è¡¨å•验证规则
const rules = {
@@ -179,7 +178,7 @@
    label: "操作",
    align: "center",
    fixed: "right",
    width: 230,
    width: 150,
    operation: [
      {
        name: "编辑",
@@ -188,50 +187,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: "2025-01-15 10:30:00"
  },
  {
    id: "2",
    programName: "库存同步RPA",
    status: "stopped",
    description: "同步多个仓库的库存数据,确保数据一致性",
    createTime: "2025-01-14 15:20:00"
  },
  {
    id: "3",
    programName: "报表生成RPA",
    status: "error",
    description: "自动生成每日销售报表和库存报表",
    createTime: "2025-01-13 09:15:00"
  }
];
// ç”Ÿå‘½å‘¨æœŸ
onMounted(() => {
@@ -240,32 +215,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 +240,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 +259,38 @@
// æäº¤è¡¨å•
const submitForm = async () => {
  if (!formRef.value) return;
  try {
    await formRef.value.validate();
    if (dialogType.value === "add") {
      // æ·»åŠ æ–°RPA
      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,32 +329,30 @@
// åˆ é™¤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("已取消");
    });
};
</script>
src/views/collaborativeApproval/sealManagement/index.vue
@@ -17,7 +17,7 @@
          <div class="tab-content">
            <el-row :gutter="20" class="mb-20">
              <el-col :span="6">
                <el-input v-model="sealSearchForm.keyword" placeholder="请输入申请标题或申请人" clearable />
                <el-input v-model="sealSearchForm.title" placeholder="请输入申请标题" clearable />
              </el-col>
              <el-col :span="4">
                <el-select v-model="sealSearchForm.status" placeholder="审批状态" clearable>
@@ -32,13 +32,17 @@
              </el-col>
            </el-row>
            <el-table :data="sealApplications" style="width: 100%">
              <el-table-column prop="id" label="申请编号" width="120" />
            <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="applicant" label="申请人" width="120" />
              <el-table-column prop="createUserName" label="申请人" width="120" />
              <el-table-column prop="department" label="所属部门" width="150" />
              <el-table-column prop="sealType" label="用印类型" width="120" />
              <el-table-column prop="applyTime" label="申请时间" width="180" />
              <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)">
@@ -76,7 +80,7 @@
          <div class="tab-content">
            <el-row :gutter="20" class="mb-20">
              <el-col :span="6">
                <el-input v-model="regulationSearchForm.keyword" placeholder="请输入制度标题或发布人" clearable />
                <el-input v-model="regulationSearchForm.title" placeholder="请输入制度标题" clearable />
              </el-col>
              <el-col :span="4">
                <el-select v-model="regulationSearchForm.category" placeholder="制度分类" clearable>
@@ -89,14 +93,14 @@
              <el-col :span="8">
                <el-button type="primary" @click="searchRegulations">搜索</el-button>
                <el-button @click="resetRegulationSearch">重置</el-button>
                <el-button type="success" @click="showRegulationDialog = true">
                <el-button type="success" @click="handleAdd">
                  å‘布制度
                </el-button>
              </el-col>
            </el-row>
            <el-table :data="regulations" style="width: 100%">
              <el-table-column prop="id" label="制度编号" width="120" />
            <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="200" />
              <el-table-column prop="category" label="分类" width="120">
                <template #default="scope">
@@ -104,8 +108,8 @@
                </template>
              </el-table-column>
              <el-table-column prop="version" label="版本" width="80" />
              <el-table-column prop="publisher" label="发布人" width="120" />
              <el-table-column prop="publishTime" label="发布时间" width="180" />
              <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'">
@@ -117,12 +121,22 @@
              <el-table-column label="操作" width="250" fixed="right">
                <template #default="scope">
                  <el-button link @click="viewRegulation(scope.row)">查看</el-button>
                  <el-button link type="primary" @click="editRegulation(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>
                </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-tab-pane>
      </el-tabs>
@@ -131,6 +145,9 @@
    <!-- ç”¨å°ç”³è¯·å¯¹è¯æ¡† -->
    <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>
@@ -162,8 +179,11 @@
    </el-dialog>
    <!-- è§„章制度发布对话框 -->
    <el-dialog v-model="showRegulationDialog" title="发布规章制度" width="800px">
    <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>
@@ -178,8 +198,12 @@
        <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" placeholder="选择生效时间" style="width: 100%" />
          <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">
@@ -209,10 +233,10 @@
        <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.applicant }}</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="用印类型">{{ currentSealDetail.sealType }}</el-descriptions-item>
          <el-descriptions-item label="申请时间">{{ currentSealDetail.applyTime }}</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) }}
@@ -231,12 +255,16 @@
          <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.publisher }}</el-descriptions-item>
          <el-descriptions-item label="发布时间">{{ currentRegulationDetail.publishTime }}</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>
@@ -246,8 +274,14 @@
      <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="updater" label="更新人" width="120" />
        <el-table-column prop="changeLog" label="变更说明" />
        <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>
@@ -256,7 +290,7 @@
      <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="readTime" label="阅读时间" width="180" />
        <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">
@@ -274,33 +308,48 @@
import { ref, reactive, onMounted } from 'vue'
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 } from '@/api/system/user.js'
import {staffJoinDel, staffJoinListPage} from "@/api/personnelManagement/onboarding.js";
// å“åº”式数据
const currentUser = ref(null)
const activeTab = ref('seal')
const operationType = ref('add')
const tableData = ref([])
// ç”¨å°ç”³è¯·ç›¸å…³
const showSealApplyDialog = ref(false)
const tableLoading = ref(false)
const showSealDetailDialog = ref(false)
const currentSealDetail = ref(null)
const sealFormRef = ref()
const sealForm = reactive({
  applicationNum: '',
  title: '',
  sealType: '',
  reason: '',
  urgency: 'normal'
  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' }]
}
const sealSearchForm = reactive({
  keyword: '',
  title: '',
  status: ''
})
// åˆ†é¡µå‚æ•°
const page = reactive({
  current: 1,
  size: 10,
  total: 0
})
// è§„章制度相关
const showRegulationDialog = ref(false)
const showRegulationDetailDialog = ref(false)
@@ -309,12 +358,27 @@
const currentRegulationDetail = ref(null)
const regulationFormRef = ref()
const regulationForm = reactive({
  id: '',
  regulationNum: '',
  title: '',
  category: '',
  content: '',
  version: '',
  status: 'active',
  readCount: 0,
  effectiveTime: '',
  scope: [],
  requireConfirm: true
  requireConfirm: false
})
const readStatus = ref({
  id: '',
  ruleId: '',
  employee: '',
  department: '',
  createTime: '',
  confirmTime: '',
  status: 'unconfirmed'
})
const regulationRules = {
@@ -326,93 +390,23 @@
}
const regulationSearchForm = reactive({
  keyword: '',
  title: '',
  category: ''
})
// å‡æ•°æ®
const sealApplications = ref([
  {
    id: 'SEAL001',
    title: '合同用印申请',
    applicant: '陈志强',
    department: '销售部',
    sealType: '合同专用章',
    applyTime: '2025-01-15 10:30:00',
    status: 'pending',
    reason: '客户合同需要盖章'
  },
  {
    id: 'SEAL002',
    title: '财务报告用印',
    applicant: '王建国',
    department: '财务部',
    sealType: '财务专用章',
    applyTime: '2025-01-14 14:20:00',
    status: 'approved',
    reason: '季度财务报告需要盖章'
  },
  {
    id: 'SEAL003',
    title: '公司章程用印',
    applicant: '孙明华',
    department: '法务部',
    sealType: '公章',
    applyTime: '2025-01-13 09:15:00',
    status: 'rejected',
    reason: '公司章程修改需要盖章'
  }
])
const sealApplications = ref([])
const regulations = ref([
  {
    id: 'REG001',
    title: '员工考勤管理制度',
    category: 'hr',
    version: 'v2.1',
    publisher: '人事部',
    publishTime: '2025-01-10 09:00:00',
    status: 'active',
    readCount: 45,
    content: '为规范员工考勤管理,提高工作效率,特制定本制度...'
  },
  {
    id: 'REG002',
    title: '财务报销制度',
    category: 'finance',
    version: 'v1.5',
    publisher: '财务部',
    publishTime: '2025-01-08 14:30:00',
    status: 'active',
    readCount: 38,
    content: '为规范财务报销流程,加强财务管理,特制定本制度...'
  },
  {
    id: 'REG003',
    title: '安全生产管理制度',
    category: 'safety',
    version: 'v3.0',
    publisher: '安全部',
    publishTime: '2025-01-05 16:00:00',
    status: 'active',
    readCount: 52,
    content: '为确保员工人身安全,预防安全事故发生,特制定本制度...'
  }
])
const regulations = ref([])
const versionHistory = ref([
  { version: 'v2.1', updateTime: '2025-01-10 09:00:00', updater: '人事部', changeLog: '更新考勤时间规定' },
  { version: 'v2.0', updateTime: '2023-12-15 10:30:00', updater: '人事部', changeLog: '新增加班管理规定' },
  { version: 'v1.0', updateTime: '2023-11-01 14:00:00', updater: '人事部', changeLog: '首次发布' }
])
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 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',
@@ -421,7 +415,7 @@
  }
  return statusMap[status] || 'info'
}
// åˆ¶åº¦çŠ¶æ€
const getStatusText = (status) => {
  const statusMap = {
    pending: '待审批',
@@ -430,7 +424,17 @@
  }
  return statusMap[status] || '未知'
}
// ç”¨å°ç±»åž‹
const getSealTypeText = (sealType) => {
  const sealTypeMap = {
    official: '公章',
    contract: '合同专用章',
    finance: '财务专用章',
    tegal: '技术专用章'
  }
  return sealTypeMap[sealType] || '未知'
}
// åˆ¶åº¦åˆ†ç±»
const getCategoryText = (category) => {
  const categoryMap = {
    hr: '人事制度',
@@ -440,77 +444,159 @@
  }
  return categoryMap[category] || '未知'
}
// æœç´¢å°ç« ç”³è¯·
const searchSealApplications = () => {
  ElMessage.success('搜索完成')
}
  page.current=1
  getSealApplicationList()
  // ElMessage.success('搜索完成')
}
// é‡ç½®å°ç« ç”³è¯·æœç´¢
const resetSealSearch = () => {
  sealSearchForm.keyword = ''
  sealSearchForm.title = ''
  sealSearchForm.status = ''
  searchSealApplications()
}
// æœç´¢åˆ¶åº¦
const searchRegulations = () => {
  ElMessage.success('搜索完成')
  page.current=1
  getRegulationList()
}
// é‡ç½®åˆ¶åº¦æœç´¢
const resetRegulationSearch = () => {
  regulationSearchForm.keyword = ''
  regulationSearchForm.title = ''
  regulationSearchForm.category = ''
  searchRegulations()
}
// æäº¤ç”¨å°ç”³è¯·
const submitSealApplication = async () => {
  try {
    await sealFormRef.value.validate()
    ElMessage.success('申请提交成功')
    showSealApplyDialog.value = false
    Object.assign(sealForm, {
      title: '',
      sealType: '',
      reason: '',
      urgency: 'normal'
    addSealApplication(sealForm).then(res => {
      if(res.code == 200){
        ElMessage.success('申请提交成功')
        showSealApplyDialog.value = false
        getSealApplicationList()
        Object.assign(sealForm, {
        applicationNum: '',
        title: '',
        sealType: '',
        reason: '',
        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()
    ElMessage.success('制度发布成功')
    showRegulationDialog.value = false
    Object.assign(regulationForm, {
      title: '',
      category: '',
      content: '',
      effectiveTime: '',
      scope: [],
      requireConfirm: true
    })
  } catch (error) {
    ElMessage.error('请完善制度信息')
    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'
    ElMessage.success('审批通过')
    updateSealApplication(row).then(res => {
      if(res.code == 200){
        ElMessage.success('审批通过')
      }
    })
  })
}
// æ‹’绝用印申请
const rejectSeal = (row) => {
  ElMessageBox.prompt('请输入拒绝原因', '提示', {
    confirmButtonText: '确定',
@@ -519,29 +605,165 @@
    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}).then(res => {
    tableLoading.value = false;
    // tableData.value = res.data.records
    // //筛选出和currentUser同名的人员
    tableData.value = res.data.records.filter(item => item.staffName === currentUser.value)
    console.log("tableData",tableData.value)
    page.total = res.data.total;
    if(tableData.value.length == 0){
    ElMessage.error('当前用户未加入任何部门')
    }
  }).catch(err => {
    tableLoading.value = false;
  })
const viewRegulation = (row) => {
  currentRegulationDetail.value = row
  showRegulationDetailDialog.value = true
}
const editRegulation = (row) => {
  ElMessage.info('编辑功能开发中...')
}
};
// æŸ¥çœ‹åˆ¶åº¦ç‰ˆæœ¬åŽ†å²
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 getSealApplicationList = async () => {
  tableLoading.value = true
  listSealApplication(page,sealSearchForm)
  .then(res => {
    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.value.total = res.data.total;
    tableLoading.value = false;
  }).catch(err => {
    tableLoading.value = false;
  })
}
onMounted(() => {
  // åˆå§‹åŒ–
  getSealApplicationList()
  getRegulationList()
})
</script>
@@ -578,6 +800,7 @@
  border-radius: 4px;
  line-height: 1.6;
  white-space: pre-wrap;
  height: 200px;
}
.dialog-footer {
src/views/inventoryManagement/stockWarning/index.vue
@@ -41,27 +41,27 @@
      <!-- æ“ä½œæŒ‰é’® -->
      <div class="table-operations">
        <el-button type="primary" @click="handleAdd">新增预警规则</el-button>
        <el-button type="success" @click="handleBatchProcess">批量处理</el-button>
        <!-- <el-button type="success" @click="handleBatchProcess">批量处理@</el-button> -->
        <el-button @click="handleExport">导出</el-button>
      </div>
      <el-table
        :data="tableData"
        border
        v-loading="tableLoading"
      <el-table
        :data="tableData"
        border
        v-loading="tableLoading"
        @selection-change="handleSelectionChange"
        style="width: 100%"
        height="calc(100vh - 280px)"
      >
        <el-table-column align="center" type="selection" width="55" />
        <el-table-column align="center" label="序号" type="index" width="60" />
        <!-- åŸºç¡€ä¿¡æ¯å­—段 -->
        <el-table-column label="储气罐编码" prop="tankCode" width="120" show-overflow-tooltip />
        <el-table-column label="储气罐名称" prop="tankName" width="200" show-overflow-tooltip />
        <el-table-column label="储气罐类型" prop="tankType" width="120" show-overflow-tooltip />
        <el-table-column label="规格型号" prop="specificationModel" width="150" show-overflow-tooltip />
        <el-table-column label="容积(m³)" prop="volume" width="100" show-overflow-tooltip />
        <!-- åº“存相关字段 -->
        <el-table-column label="当前气体量" prop="currentGasLevel" width="120" show-overflow-tooltip>
          <template #default="scope">
@@ -72,7 +72,7 @@
        <el-table-column label="最低气体量" prop="minGasLevel" width="120" show-overflow-tooltip />
        <el-table-column label="最高气体量" prop="maxGasLevel" width="120" show-overflow-tooltip />
        <el-table-column label="当前压力(MPa)" prop="currentPressure" width="140" show-overflow-tooltip />
        <!-- é¢„警规则字段 -->
        <el-table-column label="预警类型" prop="warningType" width="100" show-overflow-tooltip>
          <template #default="scope">
@@ -94,7 +94,7 @@
            <el-switch v-model="scope.row.isEnabled" @change="handleEnableChange(scope.row)" />
          </template>
        </el-table-column>
        <!-- æ—¶é—´ç›¸å…³å­—段 -->
        <el-table-column label="预警时间" prop="warningTime" width="150" show-overflow-tooltip />
        <el-table-column label="预警持续天数" prop="warningDuration" width="120" show-overflow-tooltip />
@@ -115,32 +115,32 @@
            <span v-else>-</span>
          </template>
        </el-table-column>
        <!-- æ“ä½œåˆ— -->
        <el-table-column fixed="right" label="操作" width="200" align="center">
          <template #default="scope">
            <el-button link type="primary" size="small" @click="handleEdit(scope.row)">编辑</el-button>
            <el-button link type="success" size="small" @click="handleProcess(scope.row)">处理</el-button>
            <el-button link type="success" size="small" @click="handleProcess(scope.row)">处理@</el-button>
            <el-button link type="danger" size="small" @click="handleDelete(scope.row)">删除</el-button>
          </template>
        </el-table-column>
      </el-table>
      <!-- åˆ†é¡µ -->
      <pagination
        v-show="total > 0"
        :total="total"
      <pagination
        v-show="total > 0"
        :total="total"
        layout="total, sizes, prev, pager, next, jumper"
        :page="page.current"
        :limit="page.size"
        @pagination="paginationChange"
        :page="page.current"
        :limit="page.size"
        @pagination="paginationChange"
      />
    </div>
    <!-- æ–°å¢ž/编辑预警规则弹窗 -->
    <el-dialog
      v-model="dialogFormVisible"
      :title="operationType === 'add' ? '新增预警规则' : '编辑预警规则'"
    <el-dialog
      v-model="dialogFormVisible"
      :title="operationType === 'add' ? '新增预警规则' : '编辑预警规则'"
      width="50%"
      @close="closeDialog"
    >
@@ -158,7 +158,7 @@
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="储气罐类型:" prop="tankType">
@@ -176,7 +176,7 @@
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="容积(m³):" prop="volume">
@@ -189,7 +189,7 @@
            </el-form-item>
          </el-col>
        </el-row>
        <!-- åº“存相关 -->
        <el-row :gutter="20">
          <el-col :span="12">
@@ -203,7 +203,7 @@
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="最高气体量(%):" prop="maxGasLevel">
@@ -216,7 +216,7 @@
            </el-form-item>
          </el-col>
        </el-row>
        <!-- é¢„警规则 -->
        <el-row :gutter="20">
          <el-col :span="12">
@@ -239,7 +239,7 @@
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="预警阈值:" prop="warningThreshold">
@@ -252,15 +252,15 @@
            </el-form-item>
          </el-col>
        </el-row>
        <!-- æ—¶é—´ç›¸å…³ -->
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="预警时间:" prop="warningTime">
              <el-date-picker
                v-model="form.warningTime"
                type="datetime"
                placeholder="请选择预警时间"
              <el-date-picker
                v-model="form.warningTime"
                type="datetime"
                placeholder="请选择预警时间"
                style="width: 100%"
                value-format="YYYY-MM-DD HH:mm:ss"
              />
@@ -268,24 +268,24 @@
          </el-col>
          <el-col :span="12">
            <el-form-item label="预计充装时间:" prop="expectedRefillTime">
              <el-date-picker
                v-model="form.expectedRefillTime"
                type="datetime"
                placeholder="请选择预计充装时间"
              <el-date-picker
                v-model="form.expectedRefillTime"
                type="datetime"
                placeholder="请选择预计充装时间"
                style="width: 100%"
                value-format="YYYY-MM-DD HH:mm:ss"
              />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="预计缺气时间:" prop="expectedShortageTime">
              <el-date-picker
                v-model="form.expectedShortageTime"
                type="datetime"
                placeholder="请选择预计缺气时间"
              <el-date-picker
                v-model="form.expectedShortageTime"
                type="datetime"
                placeholder="请选择预计缺气时间"
                style="width: 100%"
                value-format="YYYY-MM-DD HH:mm:ss"
              />
@@ -293,17 +293,17 @@
          </el-col>
          <el-col :span="12">
            <el-form-item label="预警规则描述:" prop="warningRule">
              <el-input
                v-model="form.warningRule"
                type="textarea"
                :rows="3"
              <el-input
                v-model="form.warningRule"
                type="textarea"
                :rows="3"
                placeholder="请输入预警规则描述"
              />
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button @click="closeDialog">取消</el-button>
@@ -382,15 +382,15 @@
import { WarningFilled } from '@element-plus/icons-vue'
import pagination from '@/components/PIMTable/Pagination.vue'
// æ³¨é‡ŠæŽ‰API导入,使用假数据
// import {
//   getStockWarningPage,
//   addStockWarning,
//   updateStockWarning,
//   deleteStockWarning,
//   batchProcessStockWarning,
//   exportStockWarning,
//   toggleStockWarningStatus
// } from '@/api/inventoryManagement/stockWarning.js'
import {
  getStockWarningPage,
  addStockWarning,
  updateStockWarning,
  deleteStockWarning,
  batchProcessStockWarning,
  exportStockWarning,
  toggleStockWarningStatus
} from '@/api/inventoryManagement/stockWarning.js'
const { proxy } = getCurrentInstance()
@@ -410,7 +410,8 @@
// åˆ†é¡µå‚æ•°
const page = reactive({
  current: 1,
  size: 10
  size: 10,
  total: 0
})
// æœç´¢è¡¨å•
@@ -459,19 +460,19 @@
// èŽ·å–å€’è®¡æ—¶ä¿¡æ¯
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) {
@@ -484,11 +485,11 @@
// èŽ·å–å€’è®¡æ—¶æ ·å¼ç±»
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小时内
@@ -518,7 +519,7 @@
const showShortageWarning = (tank) => {
  currentWarningTank.value = tank
  shortageWarningVisible.value = true
  // æ’­æ”¾æç¤ºéŸ³ï¼ˆå¯é€‰ï¼‰
  // const audio = new Audio('/path/to/warning-sound.mp3')
  // audio.play()
@@ -537,236 +538,20 @@
  // è¿™é‡Œå¯ä»¥è°ƒç”¨å¤„理API
}
// ç”Ÿæˆå‡æ•°æ®
const generateMockData = () => {
  const mockData = [
    {
      id: 1,
      tankCode: 'TANK001',
      tankName: '液化气储罐A',
      tankType: '液化气储罐',
      specificationModel: 'LPG-5000L',
      volume: 5000,
      currentGasLevel: 15,
      safetyGasLevel: 30,
      minGasLevel: 10,
      maxGasLevel: 95,
      currentPressure: 2.5,
      warningType: '气体不足',
      warningLevel: '紧急',
      warningThreshold: 20,
      isEnabled: true,
      warningTime: '2025-01-15 08:30:00',
      warningDuration: 3,
      lastUpdateTime: '2025-01-15 10:00:00',
      expectedRefillTime: '2025-01-16 14:00:00',
      expectedShortageTime: '2025-01-15 18:30:00', // ä»Šå¤©ä¸‹åˆ6:30缺气
      warningRule: '当气体量低于20%时触发预警'
    },
    {
      id: 2,
      tankCode: 'TANK002',
      tankName: '压缩气储罐B',
      tankType: '压缩气储罐',
      specificationModel: 'COMP-3000L',
      volume: 3000,
      currentGasLevel: 45,
      safetyGasLevel: 25,
      minGasLevel: 15,
      maxGasLevel: 90,
      currentPressure: 8.2,
      warningType: '压力异常',
      warningLevel: '重要',
      warningThreshold: 10,
      isEnabled: true,
      warningTime: '2025-01-14 16:20:00',
      warningDuration: 2,
      lastUpdateTime: '2025-01-15 09:15:00',
      expectedRefillTime: '2025-01-17 09:00:00',
      expectedShortageTime: '2025-01-18 12:00:00', // 3天后缺气
      warningRule: '当压力超过8MPa时触发预警'
    },
    {
      id: 3,
      tankCode: 'TANK003',
      tankName: '天然气储罐C',
      tankType: '天然气储罐',
      specificationModel: 'NG-8000L',
      volume: 8000,
      currentGasLevel: 75,
      safetyGasLevel: 20,
      minGasLevel: 10,
      maxGasLevel: 95,
      currentPressure: 4.8,
      warningType: '温度异常',
      warningLevel: '一般',
      warningThreshold: 5,
      isEnabled: true,
      warningTime: '2025-01-13 11:45:00',
      warningDuration: 1,
      lastUpdateTime: '2025-01-15 08:45:00',
      expectedRefillTime: '2025-01-20 10:00:00',
      expectedShortageTime: '2025-01-22 15:30:00', // 7天后缺气
      warningRule: '当温度超过60°C时触发预警'
    },
    {
      id: 4,
      tankCode: 'TANK004',
      tankName: '氧气储罐D',
      tankType: '氧气储罐',
      specificationModel: 'O2-2000L',
      volume: 2000,
      currentGasLevel: 8,
      safetyGasLevel: 25,
      minGasLevel: 5,
      maxGasLevel: 90,
      currentPressure: 6.5,
      warningType: '泄漏预警',
      warningLevel: '紧急',
      warningThreshold: 15,
      isEnabled: true,
      warningTime: '2025-01-15 07:15:00',
      warningDuration: 4,
      lastUpdateTime: '2025-01-15 11:30:00',
      expectedRefillTime: '2025-01-15 16:00:00',
      expectedShortageTime: '2025-01-15 14:00:00', // ä»Šå¤©ä¸‹åˆ2点缺气
      warningRule: '当检测到气体泄漏时触发预警'
    },
    {
      id: 5,
      tankCode: 'TANK005',
      tankName: '液化气储罐E',
      tankType: '液化气储罐',
      specificationModel: 'LPG-6000L',
      volume: 6000,
      currentGasLevel: 35,
      safetyGasLevel: 30,
      minGasLevel: 15,
      maxGasLevel: 95,
      currentPressure: 3.2,
      warningType: '气体不足',
      warningLevel: '重要',
      warningThreshold: 20,
      isEnabled: false,
      warningTime: '2025-01-14 14:30:00',
      warningDuration: 2,
      lastUpdateTime: '2025-01-15 09:00:00',
      expectedRefillTime: '2025-01-19 08:00:00',
      expectedShortageTime: '2025-01-21 10:00:00', // 6天后缺气
      warningRule: '当气体量低于20%时触发预警'
    },
    {
      id: 6,
      tankCode: 'TANK006',
      tankName: '压缩气储罐F',
      tankType: '压缩气储罐',
      specificationModel: 'COMP-4000L',
      volume: 4000,
      currentGasLevel: 85,
      safetyGasLevel: 20,
      minGasLevel: 10,
      maxGasLevel: 90,
      currentPressure: 7.8,
      warningType: '压力异常',
      warningLevel: '一般',
      warningThreshold: 8,
      isEnabled: true,
      warningTime: '2025-01-12 09:20:00',
      warningDuration: 1,
      lastUpdateTime: '2025-01-15 08:30:00',
      expectedRefillTime: '2025-01-25 14:00:00',
      expectedShortageTime: '2025-01-28 16:00:00', // 13天后缺气
      warningRule: '当压力超过8MPa时触发预警'
    },
    {
      id: 7,
      tankCode: 'TANK007',
      tankName: '天然气储罐G',
      tankType: '天然气储罐',
      specificationModel: 'NG-10000L',
      volume: 10000,
      currentGasLevel: 92,
      safetyGasLevel: 15,
      minGasLevel: 8,
      maxGasLevel: 95,
      currentPressure: 5.2,
      warningType: '温度异常',
      warningLevel: '重要',
      warningThreshold: 6,
      isEnabled: true,
      warningTime: '2025-01-11 16:45:00',
      warningDuration: 1,
      lastUpdateTime: '2025-01-15 07:45:00',
      expectedRefillTime: '2025-01-30 09:00:00',
      expectedShortageTime: '2025-02-05 12:00:00', // 21天后缺气
      warningRule: '当温度超过60°C时触发预警'
    },
    {
      id: 8,
      tankCode: 'TANK008',
      tankName: '氧气储罐H',
      tankType: '氧气储罐',
      specificationModel: 'O2-1500L',
      volume: 1500,
      currentGasLevel: 12,
      safetyGasLevel: 30,
      minGasLevel: 8,
      maxGasLevel: 90,
      currentPressure: 4.5,
      warningType: '泄漏预警',
      warningLevel: '紧急',
      warningThreshold: 12,
      isEnabled: true,
      warningTime: '2025-01-15 06:30:00',
      warningDuration: 5,
      lastUpdateTime: '2025-01-15 12:15:00',
      expectedRefillTime: '2025-01-15 20:00:00',
      expectedShortageTime: '2025-01-15 17:30:00', // ä»Šå¤©ä¸‹åˆ5:30缺气
      warningRule: '当检测到气体泄漏时触发预警'
    }
  ]
  // æ ¹æ®æœç´¢æ¡ä»¶è¿‡æ»¤æ•°æ®
  let filteredData = mockData.filter(item => {
    if (searchForm.tankName && !item.tankName.includes(searchForm.tankName)) return false
    if (searchForm.tankType && item.tankType !== searchForm.tankType) return false
    if (searchForm.warningType && item.warningType !== searchForm.warningType) return false
    if (searchForm.warningLevel && item.warningLevel !== searchForm.warningLevel) return false
    return true
  })
  // åˆ†é¡µå¤„理
  const start = (page.current - 1) * page.size
  const end = start + page.size
  const paginatedData = filteredData.slice(start, end)
  return {
    records: paginatedData,
    total: filteredData.length
  }
}
// èŽ·å–åˆ—è¡¨æ•°æ®
const getList = async () => {
  tableLoading.value = true
  try {
    // æ¨¡æ‹Ÿç½‘络延迟
    await new Promise(resolve => setTimeout(resolve, 500))
    const result = generateMockData()
    tableData.value = result.records
    total.value = result.total
    // æ£€æŸ¥ç¼ºæ°”预警
  getStockWarningPage(page, searchForm)
  .then(res => {
    tableData.value = res.data.records
    page.value.total = res.data.total;
    tableLoading.value = false;
        // æ£€æŸ¥ç¼ºæ°”预警
    checkShortageWarnings()
  } catch (error) {
    console.error('获取列表失败:', error)
    ElMessage.error('获取列表失败')
  } finally {
    tableLoading.value = false
  }
  }).catch(err => {
    tableLoading.value = false;
  })
}
// æœç´¢
@@ -798,7 +583,7 @@
// æ–°å¢ž
const handleAdd = () => {
  operationType.value = 'add'
  resetForm()
  // resetForm()
  dialogFormVisible.value = true
}
@@ -815,7 +600,7 @@
    // æ¨¡æ‹ŸAPI调用延迟
    await new Promise(resolve => setTimeout(resolve, 300))
    ElMessage.success(`正在处理预警:${row.tankName}`)
    getList()
    // getList()
  } catch (error) {
    ElMessage.error('处理预警失败')
  }
@@ -829,11 +614,21 @@
      cancelButtonText: '取消',
      type: 'warning'
    })
    // æ¨¡æ‹ŸAPI调用延迟
    await new Promise(resolve => setTimeout(resolve, 300))
    ElMessage.success('删除成功')
    getList()
    let ids = [];
    ids.push(row.id);
    deleteStockWarning(ids).then(res => {
      if(res.code == 200){
        ElMessage.success("删除成功");
        ids.value = [];
        getList();
      }
    }).catch(err => {
      ElMessage.error(err.msg);
    })
    // // æ¨¡æ‹ŸAPI调用延迟
    // await new Promise(resolve => setTimeout(resolve, 300))
    // ElMessage.success('删除成功')
    // getList()
  } catch (error) {
    if (error !== 'cancel') {
      ElMessage.error('删除失败')
@@ -847,7 +642,7 @@
    ElMessage.warning('请选择要处理的预警')
    return
  }
  try {
    // æ¨¡æ‹ŸAPI调用延迟
    await new Promise(resolve => setTimeout(resolve, 500))
@@ -860,75 +655,65 @@
// å¯¼å‡º
const handleExport = async () => {
  try {
    // æ¨¡æ‹ŸAPI调用延迟
    await new Promise(resolve => setTimeout(resolve, 800))
    // ç”Ÿæˆå¯¼å‡ºæ•°æ®
    const exportData = generateMockData().records
    const csvContent = generateCSV(exportData)
    // åˆ›å»ºä¸‹è½½é“¾æŽ¥
    const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' })
    const url = window.URL.createObjectURL(blob)
    const link = document.createElement('a')
    link.href = url
    link.download = `储气罐预警数据_${new Date().getTime()}.csv`
    link.click()
    window.URL.revokeObjectURL(url)
    ElMessage.success('导出成功')
  } catch (error) {
    ElMessage.error('导出失败')
  }
  //   if (selectedRows.value.length === 0) {
  //     exportStockWarning().then(res => {
  //       // // åˆ›å»ºä¸‹è½½é“¾æŽ¥
  //       // const blob = new Blob([res.data], { type: 'text/csv;charset=utf-8;' })
  //       // const url = window.URL.createObjectURL(blob)
  //       // const link = document.createElement('a')
  //       // link.href = url
  //       // link.download = `储气罐预警数据_${new Date().getTime()}.csv`
  //       // link.click()
  //       // window.URL.revokeObjectURL(url)
  //     }).catch(err => {
  //       ElMessage.error(err.msg);
  //     })
  // }else{
  //     let ids = [];
  //     selectedRows.value.forEach(item => {
  //       ids.push(item.id);
  //     })
  //     exportStockWarning(ids).then(res => {
  //       // // åˆ›å»ºä¸‹è½½é“¾æŽ¥
  //       // const blob = new Blob([res.data], { type: 'text/csv;charset=utf-8;' })
  //       // const url = window.URL.createObjectURL(blob)
  //       // const link = document.createElement('a')
  //       // link.href = url
  //       // link.download = `储气罐预警数据_${new Date().getTime()}.csv`
  //       // link.click()
  //       // window.URL.revokeObjectURL(url)
  //     }).catch(err => {
  //       ElMessage.error(err.msg);
  //     })
  // }
    ElMessageBox.confirm("选中的内容将被导出,是否确认导出?", "导出", {
    confirmButtonText: "确认",
    cancelButtonText: "取消",
    type: "warning",
    })
    .then(() => {
      proxy.download("/gasTankWarning/export", {ids: selectedRows.value.map(item => item.id)}, "储气罐预警.xlsx");
    })
    .catch(() => {
      proxy.$modal.msg("已取消");
    });
}
// ç”ŸæˆCSV内容
const generateCSV = (data) => {
  const headers = [
    '储气罐编码', '储气罐名称', '储气罐类型', '规格型号', '容积(m³)',
    '当前气体量(%)', '安全气体量(%)', '最低气体量(%)', '最高气体量(%)',
    '当前压力(MPa)', '预警类型', '预警级别', '预警阈值', '是否启用',
    '预警时间', '预警持续天数', '最后更新时间', '预计充装时间', '预计缺气时间', '预警规则描述'
  ]
  const csvRows = [headers.join(',')]
  data.forEach(item => {
    const row = [
      item.tankCode,
      item.tankName,
      item.tankType,
      item.specificationModel,
      item.volume,
      item.currentGasLevel,
      item.safetyGasLevel,
      item.minGasLevel,
      item.maxGasLevel,
      item.currentPressure,
      item.warningType,
      item.warningLevel,
      item.warningThreshold,
      item.isEnabled ? '是' : '否',
      item.warningTime,
      item.warningDuration,
      item.lastUpdateTime,
      item.expectedRefillTime,
      item.expectedShortageTime,
      item.warningRule
    ]
    csvRows.push(row.join(','))
  })
  return csvRows.join('\n')
}
// å¯ç”¨çŠ¶æ€å˜åŒ–
// // å¯ç”¨çŠ¶æ€å˜åŒ–
const handleEnableChange = async (row) => {
  try {
    // æ¨¡æ‹ŸAPI调用延迟
    await new Promise(resolve => setTimeout(resolve, 200))
    ElMessage.success(`${row.tankName} çš„启用状态已更新`)
    updateStockWarning(row).then(res => {
      if(res.code == 200){
        ElMessage.success(`${row.tankName} çš„启用状态已更新`);
        getList();
      }
    }).catch(err => {
      ElMessage.error(err.msg);
    })
  } catch (error) {
    ElMessage.error('状态更新失败')
    // æ¢å¤åŽŸçŠ¶æ€
@@ -940,18 +725,39 @@
const submitForm = async () => {
  try {
    await proxy.$refs.formRef.validate()
    // æ¨¡æ‹ŸAPI调用延迟
    await new Promise(resolve => setTimeout(resolve, 500))
    // await new Promise(resolve => setTimeout(resolve, 500))
    if (operationType.value === 'add') {
      ElMessage.success('新增成功')
      addStockWarning(form).then(res => {
        if(res.code == 200){
          ElMessage.success("添加成功");
          dialogFormVisible.value = false
          getList()
          resetForm()
        }
      }).catch(err => {
        ElMessage.error(err.msg);
      })
      // ElMessage.success('新增成功')
    } else {
      ElMessage.success('编辑成功')
      updateStockWarning(form).then(res => {
        if(res.code == 200){
          ElMessage.success("更新成功");
          dialogFormVisible.value = false
          getList()
          resetForm()
        }
      }).catch(err => {
        ElMessage.error(err.msg);
      })
      // ElMessage.success('编辑成功')
    }
    closeDialog()
    getList()
    // closeDialog()
    // getList()
  } catch (error) {
    if (!error.errors) {
      ElMessage.error(operationType.value === 'add' ? '新增失败' : '编辑失败')
@@ -962,7 +768,7 @@
// å…³é—­å¼¹çª—
const closeDialog = () => {
  dialogFormVisible.value = false
  resetForm()
  // resetForm()
}
// é‡ç½®è¡¨å•
@@ -1040,89 +846,89 @@
<style scoped lang="scss">
.app-container {
  padding: 20px;
  .table-operations {
    text-align: right;
    margin-bottom: 20px;
    .el-button {
      margin-right: 10px;
    }
  }
  .table_list {
    background: #fff;
    border-radius: 4px;
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
  }
  .text-danger {
    color: #f56c6c;
    font-weight: bold;
  }
  .text-warning {
    color: #e6a23c;
    font-weight: bold;
  }
  .text-success {
    color: #67c23a;
    font-weight: bold;
  }
  .dialog-footer {
    text-align: right;
  }
  // å€’计时样式
  .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; }
  }
  // ç¼ºæ°”预警弹框样式
  .shortage-warning-content {
    text-align: center;
    padding: 20px 0;
    .warning-icon {
      margin-bottom: 20px;
    }
    .warning-message {
      h3 {
        color: #f56c6c;
        margin-bottom: 10px;
      }
      p {
        margin-bottom: 10px;
        color: #606266;
      }
      .warning-details {
        background: #f5f7fa;
        padding: 15px;
src/views/login.vue
@@ -181,7 +181,7 @@
<style lang='scss' scoped>
.login {
  height: 100%;
  background-image: url("../assets/indexViews/XYHBView.png");
  background-image: url("../assets/indexViews/JZYJView.png");
  background-size: cover;
  position: relative;
}
src/views/personnelManagement/scheduling/index.vue
@@ -5,43 +5,40 @@
      <el-form :inline="true" :model="filterForm" class="filter-form">
        <el-form-item label="员工姓名:">
          <el-input
            v-model="filterForm.employeeName"
            placeholder="请输入员工姓名"
            clearable
            style="width: 150px"
              v-model="filterForm.staffName"
              placeholder="请输入员工姓名"
              clearable
              style="width: 150px"
          />
        </el-form-item>
        <el-form-item label="班次类型:">
          <el-select v-model="filterForm.shiftType" placeholder="请选择班次" clearable style="width: 120px">
            <el-option label="早班" value="早班" />
            <el-option label="中班" value="中班" />
            <el-option label="晚班" value="晚班" />
            <el-option label="夜班" value="夜班" />
            <el-option v-for="item in shift_type" :label="item.label" :value="item.value" :key="item.value"/>
          </el-select>
        </el-form-item>
        <el-form-item label="日期范围:">
          <el-date-picker
            v-model="filterForm.dateRange"
            type="daterange"
            range-separator="至"
            start-placeholder="开始日期"
            end-placeholder="结束日期"
            format="YYYY-MM-DD"
            value-format="YYYY-MM-DD"
            style="width: 250px"
              v-model="filterForm.dateRange"
              type="daterange"
              range-separator="至"
              start-placeholder="开始日期"
              end-placeholder="结束日期"
              format="YYYY-MM-DD"
              value-format="YYYY-MM-DD"
              style="width: 250px"
          />
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="handleFilter">
            <el-icon><Search /></el-icon>
            <el-icon><Search/></el-icon>
            ç­›é€‰
          </el-button>
          <el-button @click="resetFilter">
            <el-icon><Refresh /></el-icon>
            <el-icon><Refresh/></el-icon>
            é‡ç½®
          </el-button>
          <el-button type="primary" @click="openScheduleDialog('add')">
          <el-icon><Plus /></el-icon>
          <el-icon><Plus/></el-icon>
          æ–°å¢žæŽ’班
        </el-button>
        </el-form-item>
@@ -51,27 +48,32 @@
    <!-- æŽ’班表格 -->
    <div class="table-section">
      <el-table
        :data="filteredScheduleList"
        border
        stripe
        style="width: 100%"
        height="calc(100vh - 18.5em)"
        @selection-change="handleSelectionChange"
          :data="scheduleList"
          border
          :loading="tableLoading"
          stripe
          style="width: 100%"
          height="calc(100vh - 18.5em)"
          @selection-change="handleSelectionChange"
      >
        <el-table-column type="selection" width="55" />
        <el-table-column prop="employeeName" label="员工姓名" width="120" />
        <el-table-column prop="employeeId" label="员工工号" width="100" />
        <el-table-column prop="department" label="部门" width="120" />
        <el-table-column type="selection" width="55"/>
        <el-table-column prop="staffName" label="员工姓名" width="120"/>
        <el-table-column prop="staffNo" label="员工工号" width="100"/>
        <el-table-column prop="department" label="部门" width="120">
          <template #default="scope">
              {{ (department_type.find(i => i.value === String(scope.row.department)) || {}).label }}
          </template>
        </el-table-column>
        <el-table-column prop="shiftType" label="班次类型" width="100">
          <template #default="scope">
            <el-tag :type="getShiftTagType(scope.row.shiftType)">
              {{ scope.row.shiftType }}
              {{ (shift_type.find(i => i.value === String(scope.row.shiftType)) || {}).label }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column prop="workDate" label="工作日期" width="120" />
        <el-table-column prop="startTime" label="开始时间" width="100" />
        <el-table-column prop="endTime" label="结束时间" width="100" />
        <el-table-column prop="workDate" label="工作日期" width="120"/>
        <el-table-column prop="startTime" label="开始时间" width="100"/>
        <el-table-column prop="endTime" label="结束时间" width="100"/>
        <el-table-column prop="workHours" label="工作时长" width="100">
          <template #default="scope">
            {{ scope.row.workHours }}小时
@@ -80,38 +82,45 @@
        <el-table-column prop="status" label="状态" width="100">
          <template #default="scope">
            <el-tag :type="getStatusTagType(scope.row.status)">
              {{ scope.row.status }}
              {{ (schedule_status.find(i => i.value === String(scope.row.status)) || {}).label }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column prop="remark" label="备注" min-width="150" />
        <el-table-column prop="remark" label="备注" min-width="150"/>
        <el-table-column label="操作" width="200" fixed="right">
          <template #default="scope">
            <el-button
              type="primary"
              size="small"
              @click="openScheduleDialog('edit', scope.row)"
                type="primary"
                size="small"
                @click="openScheduleDialog('edit', scope.row)"
            >
              ç¼–辑
            </el-button>
            <el-button
              type="danger"
              size="small"
              @click="handleDelete(scope.row)"
                type="danger"
                size="small"
                @click="handleDelete(scope.row)"
            >
              åˆ é™¤
            </el-button>
          </template>
        </el-table-column>
      </el-table>
        <pagination
            v-if="tableCount > 0"
            :total="tableCount"
            :page="filterForm.current"
            :limit="filterForm.size"
            @pagination="paginationChange"
        />
    </div>
    <!-- æ‰¹é‡æ“ä½œ -->
    <div class="batch-actions" v-if="selectedRows.length > 0">
      <el-button
        type="danger"
        @click="handleBatchDelete"
        :disabled="selectedRows.length === 0"
          type="danger"
          @click="handleBatchDelete"
          :disabled="selectedRows.length === 0"
      >
        æ‰¹é‡åˆ é™¤ ({{ selectedRows.length }})
      </el-button>
@@ -119,118 +128,111 @@
    <!-- æŽ’班新增/编辑对话框 -->
    <el-dialog
      v-model="scheduleDialog"
      :title="dialogType === 'add' ? '新增排班' : '编辑排班'"
      width="700px"
      @close="closeScheduleDialog"
        v-model="scheduleDialog"
        :title="dialogType === 'add' ? '新增排班' : '编辑排班'"
        width="700px"
        @close="closeScheduleDialog"
    >
      <el-form
        :model="scheduleForm"
        :rules="scheduleRules"
        ref="scheduleFormRef"
        label-width="120px"
          :model="scheduleForm"
          :rules="scheduleRules"
          ref="scheduleFormRef"
          label-width="120px"
      >
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="员工姓名:" prop="employeeName">
              <el-input v-model="scheduleForm.employeeName" placeholder="请输入员工姓名" />
            <el-form-item label="员工姓名:" prop="staffId">
              <el-select v-model="scheduleForm.staffId" placeholder="请输入员工姓名" style="width: 100%"
                         @change="handleSelectStaff">
                <el-option v-for="item in personList" :label="item.staffName" :value="item.id" :key="item.id"/>
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="员工工号:" prop="employeeId">
              <el-input v-model="scheduleForm.employeeId" placeholder="请输入员工工号" />
            <el-form-item label="员工工号:" prop="staffNo">
              <el-input :disabled="true" v-model="scheduleForm.staffNo" placeholder=""/>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="部门:" prop="department">
              <el-select v-model="scheduleForm.department" placeholder="请选择部门" style="width: 100%">
                <el-option label="技术部" value="技术部" />
                <el-option label="销售部" value="销售部" />
                <el-option label="人事部" value="人事部" />
                <el-option label="财务部" value="财务部" />
                <el-option label="生产部" value="生产部" />
                <el-option v-for="item in department_type" :label="item.label" :value="item.value" :key="item.value"/>
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="班次类型:" prop="shiftType">
              <el-select v-model="scheduleForm.shiftType" placeholder="请选择班次" style="width: 100%">
                <el-option label="早班" value="早班" />
                <el-option label="中班" value="中班" />
                <el-option label="晚班" value="晚班" />
                <el-option label="夜班" value="夜班" />
                <el-option v-for="item in shift_type" :label="item.label" :value="item.value" :key="item.value"/>
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="工作日期:" prop="workDate">
              <el-date-picker
                v-model="scheduleForm.workDate"
                type="date"
                placeholder="选择工作日期"
                style="width: 100%"
                format="YYYY-MM-DD"
                value-format="YYYY-MM-DD"
                  v-model="scheduleForm.workDate"
                  type="date"
                  placeholder="选择工作日期"
                  style="width: 100%"
                  format="YYYY-MM-DD"
                  value-format="YYYY-MM-DD"
              />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="状态:" prop="status">
              <el-select v-model="scheduleForm.status" placeholder="请选择状态" style="width: 100%">
                <el-option label="已安排" value="已安排" />
                <el-option label="已确认" value="已确认" />
                <el-option label="已完成" value="已完成" />
                <el-option label="已取消" value="已取消" />
                <el-option v-for="item in schedule_status" :label="item.label" :value="item.value" :key="item.value"/>
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="开始时间:" prop="startTime">
              <el-time-picker
                v-model="scheduleForm.startTime"
                placeholder="选择开始时间"
                style="width: 100%"
                format="HH:mm"
                value-format="HH:mm"
                  v-model="scheduleForm.startTime"
                  placeholder="选择开始时间"
                  style="width: 100%"
                  format="HH:mm"
                  value-format="HH:mm"
              />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="结束时间:" prop="endTime">
              <el-time-picker
                v-model="scheduleForm.endTime"
                placeholder="选择结束时间"
                style="width: 100%"
                format="HH:mm"
                value-format="HH:mm"
                  v-model="scheduleForm.endTime"
                  placeholder="选择结束时间"
                  style="width: 100%"
                  format="HH:mm"
                  value-format="HH:mm"
              />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col :span="24">
            <el-form-item label="备注:" prop="remark">
              <el-input
                v-model="scheduleForm.remark"
                type="textarea"
                :rows="3"
                placeholder="请输入备注信息"
                  v-model="scheduleForm.remark"
                  type="textarea"
                  :rows="3"
                  placeholder="请输入备注信息"
              />
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary" @click="submitScheduleForm">确认</el-button>
@@ -242,10 +244,16 @@
</template>
<script setup>
import { ref, reactive, computed, onMounted } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Plus, Download, Search, Refresh } from '@element-plus/icons-vue'
import {ref, reactive, computed, onMounted} from 'vue'
import {ElMessage, ElMessageBox} from 'element-plus'
import {useDict} from "@/utils/dict.js"
import {Plus, Download, Search, Refresh} from '@element-plus/icons-vue'
import {save, del, delByIds, listPage} from "@/api/personnelManagement/scheduling.js"
import {getStaffOnJob} from "@/api/personnelManagement/onboarding.js";
import dayjs from "dayjs";
import pagination from "@/components/PIMTable/Pagination.vue";
const tableCount = ref(0)
// å“åº”式数据
const scheduleDialog = ref(false)
const dialogType = ref('add')
@@ -254,137 +262,109 @@
// ç­›é€‰è¡¨å•
const filterForm = reactive({
  employeeName: '',
  staffName: '',
  shiftType: '',
  dateRange: []
  dateRange: [],
  current:1,
  size: 10
})
// æŽ’班表单
const scheduleForm = reactive({
  id: '',
  employeeName: '',
  employeeId: '',
  staffId: '',
  staffNo: '',
  department: '',
  shiftType: '',
  workDate: '',
  startTime: '',
  endTime: '',
  workStartTime: '',
  workEndTime: '',
  workHours: 0,
  status: '已安排',
  status: '',
  remark: ''
})
// è¡¨å•验证规则
const scheduleRules = reactive({
  employeeName: [{ required: true, message: '请输入员工姓名', trigger: 'blur' }],
  employeeId: [{ required: true, message: '请输入员工工号', trigger: 'blur' }],
  department: [{ required: true, message: '请选择部门', trigger: 'change' }],
  shiftType: [{ required: true, message: '请选择班次类型', trigger: 'change' }],
  workDate: [{ required: true, message: '请选择工作日期', trigger: 'change' }],
  startTime: [{ required: true, message: '请选择开始时间', trigger: 'change' }],
  endTime: [{ required: true, message: '请选择结束时间', trigger: 'change' }],
  status: [{ required: true, message: '请选择状态', trigger: 'change' }]
  staffId: [{required: true, message: '请选择员工', trigger: 'change'}],
  department: [{required: true, message: '请选择部门', trigger: 'change'}],
  shiftType: [{required: true, message: '请选择班次类型', trigger: 'change'}],
  workDate: [{required: true, message: '请选择工作日期', trigger: 'change'}],
  startTime: [{required: true, message: '请选择开始时间', trigger: 'change'}],
  endTime: [{required: true, message: '请选择结束时间', trigger: 'change'}],
  status: [{required: true, message: '请选择状态', trigger: 'change'}]
})
const tableLoading = ref(false)
//字典
const {department_type, schedule_status, shift_type} = useDict("department_type", "schedule_status", "shift_type")
// äººå‘˜åˆ—表
const personList = ref([]);
// æ¨¡æ‹ŸæŽ’班数据
const scheduleList = ref([
  {
    id: 1,
    employeeName: '张海洋',
    employeeId: 'EMP001',
    department: '技术部',
    shiftType: '早班',
    workDate: '2024-01-15',
    startTime: '08:00',
    endTime: '17:00',
    workHours: 9,
    status: '已安排',
    remark: '正常排班'
  },
  {
    id: 2,
    employeeName: '李超',
    employeeId: 'EMP002',
    department: '销售部',
    shiftType: '中班',
    workDate: '2024-01-15',
    startTime: '14:00',
    endTime: '22:00',
    workHours: 8,
    status: '已确认',
    remark: '客户会议'
  },
  {
    id: 3,
    employeeName: '王杰',
    employeeId: 'EMP003',
    department: '生产部',
    shiftType: '晚班',
    workDate: '2024-01-15',
    startTime: '22:00',
    endTime: '06:00',
    workHours: 8,
    status: '已安排',
    remark: '夜班生产'
  }
])
const scheduleList = ref([])
// è®¡ç®—属性:筛选后的排班列表
const filteredScheduleList = computed(() => {
  let result = scheduleList.value
  if (filterForm.employeeName) {
    result = result.filter(item =>
      item.employeeName.includes(filterForm.employeeName)
    )
  }
/**
 * èŽ·å–å½“å‰åœ¨èŒäººå‘˜åˆ—è¡¨
 */
const getPersonList = () => {
  getStaffOnJob().then(res => {
    personList.value = res.data
  })
};
const paginationChange = (obj) => {
  filterForm.current = obj.page;
  filterForm.size = obj.limit;
  handleFilter();
};
  if (filterForm.shiftType) {
    result = result.filter(item => item.shiftType === filterForm.shiftType)
  }
const handleSelectStaff = (val) => {
  let obj = personList.value.find(item => item.id === val)
  scheduleForm.staffNo = obj.staffNo
  if (filterForm.dateRange && filterForm.dateRange.length === 2) {
    result = result.filter(item => {
      const workDate = new Date(item.workDate)
      const startDate = new Date(filterForm.dateRange[0])
      const endDate = new Date(filterForm.dateRange[1])
      return workDate >= startDate && workDate <= endDate
    })
  }
  return result
})
}
// èŽ·å–ç­æ¬¡æ ‡ç­¾ç±»åž‹
const getShiftTagType = (shiftType) => {
  const typeMap = {
    '早班': 'success',
    '中班': 'warning',
    '晚班': 'info',
    '夜班': 'danger'
  }
  const typeMap = Object.fromEntries(shift_type.value.map(i => [i.value, i.elTagType]))
  return typeMap[shiftType] || 'info'
}
// èŽ·å–çŠ¶æ€æ ‡ç­¾ç±»åž‹
const getStatusTagType = (status) => {
  const typeMap = {
    '已安排': 'info',
    '已确认': 'warning',
    '已完成': 'success',
    '已取消': 'danger'
  }
  const typeMap = Object.fromEntries(schedule_status.value.map(i => [i.value, i.elTagType]))
  return typeMap[status] || 'info'
}
// ç­›é€‰
const handleFilter = () => {
  // ç­›é€‰é€»è¾‘已在计算属性中实现
const handleFilter = async () => {
  tableLoading.value = true
  let searchForm = {
    ...filterForm,
    ...(filterForm.dateRange.length > 0 && {
      startDate: filterForm.dateRange[0],
      endDate: filterForm.dateRange[1],
    })
  }
  let resp = await listPage(searchForm)
  tableCount.value = resp.data.total
  scheduleList.value = resp.data.records.map(it => {
    return {
      ...it,
      'startTime': dayjs(it.workStartTime).format('HH:mm'),
      'endTime': dayjs(it.workEndTime).format('HH:mm'),
    }
  })
  tableLoading.value = false
}
// é‡ç½®ç­›é€‰
const resetFilter = () => {
  filterForm.employeeName = ''
  filterForm.staffName = ''
  filterForm.shiftType = ''
  filterForm.dateRange = []
}
@@ -393,16 +373,16 @@
const openScheduleDialog = (type, data) => {
  dialogType.value = type
  scheduleDialog.value = true
  getPersonList()
  if (type === 'edit' && data) {
    // ç¼–辑模式,复制数据
    Object.assign(scheduleForm, { ...data })
    Object.assign(scheduleForm, {...data})
  } else {
    // æ–°å¢žæ¨¡å¼ï¼Œé‡ç½®è¡¨å•
    Object.keys(scheduleForm).forEach(key => {
      scheduleForm[key] = ''
    })
    scheduleForm.status = '已安排'
    // scheduleForm.status = '已安排'
    scheduleForm.workDate = new Date().toISOString().split('T')[0]
  }
}
@@ -415,66 +395,59 @@
// è®¡ç®—工作时长
const calculateWorkHours = () => {
  if (scheduleForm.startTime && scheduleForm.endTime) {
    const start = new Date(`2000-01-01 ${scheduleForm.startTime}`)
    const end = new Date(`2000-01-01 ${scheduleForm.endTime}`)
    if (end < start) {
      // è·¨å¤©çš„æƒ…况
      end.setDate(end.getDate() + 1)
  if (scheduleForm.workDate && scheduleForm.startTime && scheduleForm.endTime) {
    // ä½¿ç”¨ workDate ä¸Ž startTime å’Œ endTime ç»„合
    const startDateTime = new Date(`${scheduleForm.workDate} ${scheduleForm.startTime}`)
    const endDateTime = new Date(`${scheduleForm.workDate} ${scheduleForm.endTime}`)
    // å¤„理跨天情况(结束时间早于开始时间)
    if (endDateTime < startDateTime) {
      // è·¨å¤©ï¼Œå°†ç»“束日期加一天
      endDateTime.setDate(endDateTime.getDate() + 1)
    }
    const diffMs = end - start
    // è®¡ç®—工作时长(小时)
    const diffMs = endDateTime - startDateTime
    const diffHours = diffMs / (1000 * 60 * 60)
    scheduleForm.workHours = Math.round(diffHours * 100) / 100
    scheduleForm.workStartTime = dayjs(startDateTime).format("YYYY-MM-DD HH:mm:ss")
    scheduleForm.workEndTime = dayjs(endDateTime).format("YYYY-MM-DD HH:mm:ss")
  }
}
// æäº¤æŽ’班表单
const submitScheduleForm = () => {
  scheduleFormRef.value.validate((valid) => {
    if (valid) {
      // è®¡ç®—工作时长
      calculateWorkHours()
      if (dialogType.value === 'add') {
        // æ–°å¢ž
        const newSchedule = {
          ...scheduleForm,
          id: Date.now() // ä½¿ç”¨æ—¶é—´æˆ³ä½œä¸ºä¸´æ—¶ID
        }
        scheduleList.value.push(newSchedule)
        ElMessage.success('新增排班成功')
      } else {
        // ç¼–辑
        const index = scheduleList.value.findIndex(item => item.id === scheduleForm.id)
        if (index !== -1) {
          scheduleList.value[index] = { ...scheduleForm }
          ElMessage.success('编辑排班成功')
        }
      }
      closeScheduleDialog()
    }
  })
const submitScheduleForm = async () => {
  const valid = await scheduleFormRef.value.validate()
  if (!valid) return
  calculateWorkHours()
  const newSchedule = {...scheduleForm}
  try {
    await save(newSchedule)
    ElMessage.success('保存排班成功')
    handleFilter()
    closeScheduleDialog()
  } catch (err) {
    ElMessage.error('保存失败')
  }
}
// åˆ é™¤æŽ’班
const handleDelete = (row) => {
  ElMessageBox.confirm(
    `确定要删除 ${row.employeeName} çš„æŽ’班记录吗?`,
    '删除提示',
    {
      confirmButtonText: '确认',
      cancelButtonText: '取消',
      type: 'warning'
    }
      `确定要删除 ${row.staffName} çš„æŽ’班记录吗?`,
      '删除提示',
      {
        confirmButtonText: '确认',
        cancelButtonText: '取消',
        type: 'warning'
      }
  ).then(() => {
    const index = scheduleList.value.findIndex(item => item.id === row.id)
    if (index !== -1) {
      scheduleList.value.splice(index, 1)
      ElMessage.success('删除成功')
    }
    del(row.id)
    ElMessage.success('删除成功')
    handleFilter()
  }).catch(() => {
    ElMessage.info('已取消删除')
  })
@@ -486,19 +459,18 @@
    ElMessage.warning('请选择要删除的记录')
    return
  }
  ElMessageBox.confirm(
    `确定要删除选中的 ${selectedRows.value.length} æ¡æŽ’班记录吗?`,
    '批量删除提示',
    {
      confirmButtonText: '确认',
      cancelButtonText: '取消',
      type: 'warning'
    }
      `确定要删除选中的 ${selectedRows.value.length} æ¡æŽ’班记录吗?`,
      '批量删除提示',
      {
        confirmButtonText: '确认',
        cancelButtonText: '取消',
        type: 'warning'
      }
  ).then(() => {
    const selectedIds = selectedRows.value.map(row => row.id)
    scheduleList.value = scheduleList.value.filter(item => !selectedIds.includes(item.id))
    selectedRows.value = []
    delByIds(selectedRows.value.map(item => item.id))
    handleFilter()
    ElMessage.success('批量删除成功')
  }).catch(() => {
    ElMessage.info('已取消删除')
@@ -510,16 +482,11 @@
  selectedRows.value = selection
}
// ç›‘听时间变化,自动计算工作时长
const watchTimeChange = () => {
  if (scheduleForm.startTime && scheduleForm.endTime) {
    calculateWorkHours()
  }
}
// ç”Ÿå‘½å‘¨æœŸ
onMounted(() => {
  // é¡µé¢åˆå§‹åŒ–
  handleFilter()
})
</script>
@@ -611,15 +578,15 @@
  .scheduling-container {
    padding: 10px;
  }
  .page-header {
    padding: 15px;
  }
  .page-header h2 {
    font-size: 24px;
  }
  .header-controls {
    flex-direction: column;
    gap: 10px;
src/views/personnelManagement/selfService/index.vue
@@ -26,7 +26,7 @@
            <el-button type="primary" @click="addAttendanceRecord">新增记录</el-button>
          </div>
        </template>
        <el-table :data="attendanceData" style="width: 100%">
        <el-table :data="attendanceData" style="width: 100%" :loading="tableLoading">
          <el-table-column prop="date" label="日期"  />
          <el-table-column prop="checkIn" label="签到时间"  />
          <el-table-column prop="checkOut" label="签退时间"  />
@@ -41,7 +41,7 @@
          <el-table-column label="操作" width="150">
            <template #default="scope">
              <el-button size="small" @click="editAttendanceRecord(scope.row)">编辑</el-button>
              <el-button size="small" type="danger" @click="deleteAttendanceRecord(scope.$index)">删除</el-button>
              <el-button size="small" type="danger" @click="deleteAttendanceRecord(scope.row)">删除</el-button>
            </template>
          </el-table-column>
        </el-table>
@@ -52,15 +52,15 @@
        <template #header>
          <div class="card-header">
            <span>薪资单查询</span>
            <el-date-picker v-model="salaryMonth" type="month" placeholder="选择月份" />
            <el-date-picker v-model="payDateStr" type="month" placeholder="选择月份" value-format="YYYY-MM" format="YYYY-MM" @change="changMonth"/>
          </div>
        </template>
        <el-table :data="salaryData" style="width: 100%">
          <el-table-column prop="month" label="月份"  />
          <el-table-column prop="payDate" label="月份"  />
          <el-table-column prop="basicSalary" label="基本工资"  />
          <el-table-column prop="bonus" label="奖金"  />
          <el-table-column prop="deduction" label="扣款"  />
          <el-table-column prop="total" label="实发工资"  />
          <el-table-column prop="actualWages" label="实发工资"  />
          <el-table-column prop="status" label="状态" >
            <template #default="scope">
              <el-tag :type="scope.row.status === '已发放' ? 'success' : 'warning'">
@@ -76,7 +76,7 @@
        <template #header>
          <div class="card-header">
            <span>假期申请管理</span>
            <el-button type="primary" @click="showLeaveDialog = true">申请假期</el-button>
            <el-button type="primary" @click="openLeaveForm">申请假期</el-button>
          </div>
        </template>
        <el-table :data="leaveData" style="width: 100%">
@@ -95,7 +95,7 @@
          <el-table-column label="操作" width="150">
            <template #default="scope">
              <el-button size="small" @click="editLeaveRecord(scope.row)">编辑</el-button>
              <el-button size="small" type="danger" @click="deleteLeaveRecord(scope.$index)">删除</el-button>
              <el-button size="small" type="danger" @click="deleteLeaveRecord(scope.row)">删除</el-button>
            </template>
          </el-table-column>
        </el-table>
@@ -106,7 +106,7 @@
        <template #header>
          <div class="card-header">
            <span>个人信息维护</span>
            <el-button type="primary" @click="editProfile = true">编辑信息</el-button>
            <el-button type="primary" @click="editProfileForm">编辑信息</el-button>
          </div>
        </template>
        <el-descriptions :column="2" border>
@@ -117,13 +117,13 @@
          <el-descriptions-item label="入职日期">{{ profile.hireDate }}</el-descriptions-item>
          <el-descriptions-item label="联系电话">{{ profile.phone }}</el-descriptions-item>
          <el-descriptions-item label="邮箱">{{ profile.email }}</el-descriptions-item>
          <el-descriptions-item label="地址">{{ profile.address }}</el-descriptions-item>
          <el-descriptions-item label="地址">{{ profile.adress }}</el-descriptions-item>
        </el-descriptions>
      </el-card>
    </div>
    <!-- å‡æœŸç”³è¯·å¼¹çª— -->
    <el-dialog v-model="showLeaveDialog" title="申请假期" width="500px">
    <el-dialog v-model="showLeaveDialog" :title="leaveOperationType === 'add' ? '申请假期' : '编辑假期'" width="500px">
      <el-form :model="leaveForm" label-width="100px">
        <el-form-item label="假期类型">
          <el-select v-model="leaveForm.type" placeholder="请选择假期类型">
@@ -142,6 +142,13 @@
        <el-form-item label="申请原因">
          <el-input v-model="leaveForm.reason" type="textarea" rows="3" />
        </el-form-item>
        <!-- <el-form-item label="审批状态">
          <el-select v-model="leaveForm.status" placeholder="请选择审批状态">
            <el-option label="审批中" value="审批中" />
            <el-option label="已通过" value="已通过" />
            <el-option label="已拒绝" value="已拒绝" />
          </el-select>
        </el-form-item> -->
      </el-form>
      <template #footer>
        <el-button @click="showLeaveDialog = false">取消</el-button>
@@ -149,11 +156,11 @@
      </template>
    </el-dialog>
    <!-- æ–°å¢žè€ƒå‹¤è®°å½•弹窗 -->
    <el-dialog v-model="showAttendanceDialog" title="新增考勤记录" width="500px">
    <!-- æ–°å¢ž-编辑考勤记录弹窗 -->
    <el-dialog v-model="showAttendanceDialog" :title="operationType === 'add' ? '新增考勤记录' : '编辑考勤记录'" width="500px">
      <el-form :model="attendanceForm" :rules="attendanceRules" ref="attendanceFormRef" label-width="100px">
        <el-form-item label="日期" prop="date">
          <el-date-picker v-model="attendanceForm.date" type="date" placeholder="选择日期" />
          <el-date-picker v-model="attendanceForm.date" type="date" value-format="YYYY-MM-DD" format="YYYY-MM-DD" placeholder="选择日期" />
        </el-form-item>
        <el-form-item label="签到时间" prop="checkIn">
          <el-time-picker v-model="attendanceForm.checkIn" placeholder="选择签到时间" format="HH:mm" value-format="HH:mm" />
@@ -189,7 +196,7 @@
          <el-input v-model="profileForm.email" />
        </el-form-item>
        <el-form-item label="地址">
          <el-input v-model="profileForm.address" type="textarea" rows="2" />
          <el-input v-model="profileForm.adress" type="textarea" rows="2" />
        </el-form-item>
      </el-form>
      <template #footer>
@@ -201,14 +208,29 @@
</template>
<script setup>
import { ref, reactive, watch } from 'vue'
import { ElMessage } from 'element-plus'
import { ref, reactive, watch, onMounted } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { 
  Calendar, 
  Money, 
  Clock, 
  User
} from '@element-plus/icons-vue'
import { personalAttendanceRecordsListPage, personalAttendanceRecordsAdd, personalAttendanceRecordsUpdate, personalAttendanceRecordsDelete, holidayApplicationListPage, holidayApplicationAdd, holidayApplicationUpdate, holidayApplicationDelete } from '@/api/personnelManagement/selfService'
import { compensationListPage, compensationAdd, compensationUpdate, compensationDelete } from '@/api/personnelManagement/payrollManagement'
const { proxy } = getCurrentInstance()
import { getUserProfile } from '@/api/system/user.js'
import {staffJoinUpdate, staffJoinListPage} from "@/api/personnelManagement/onboarding.js";
import { fa, id } from 'element-plus/es/locales.mjs'
const tableLoading = ref(false)
// åˆ†é¡µå‚æ•°
const page = reactive({
  current: 1,
  size: 10,
  total: 0
})
// å½“前视图
const currentView = ref('attendance')
@@ -222,63 +244,84 @@
]
// è€ƒå‹¤æ•°æ®
const attendanceData = ref([
  { date: '2024-01-15', checkIn: '09:00', checkOut: '18:00', workHours: '9小时', status: '正常' },
  { date: '2024-01-16', checkIn: '08:55', checkOut: '18:05', workHours: '9小时10分', status: '正常' },
  { date: '2024-01-17', checkIn: '09:15', checkOut: '18:00', workHours: '8小时45分', status: '迟到' }
])
const attendanceData = ref([])
// è–ªèµ„数据
const salaryData = ref([
  { month: '2024-01', basicSalary: 8000, bonus: 1000, deduction: 200, total: 8800, status: '已发放' },
  { month: '2023-12', basicSalary: 8000, bonus: 800, deduction: 150, total: 8650, status: '已发放' }
])
const salaryData = ref([])
// å‡æœŸæ•°æ®
const leaveData = ref([
  { type: '年假', startDate: '2024-02-01', endDate: '2024-02-03', days: 3, reason: '春节回家', status: '已通过' },
  { type: '病假', startDate: '2024-01-20', endDate: '2024-01-21', days: 2, reason: '感冒发烧', status: '审批中' }
])
const leaveData = ref([])
const currentUser = ref()
const user= ref()
// ä¸ªäººä¿¡æ¯
const profile = ref({
  name: '张海洋',
  employeeId: 'EMP001',
  department: '技术部',
  position: '软件工程师',
  hireDate: '2023-03-01',
  phone: '13800138000',
  email: 'zhangsan@company.com',
  address: '北京市朝阳区xxx街道xxx号'
})
  id: '',
  name: '',
  employeeId: '',
  department: '',
  position: '',
  hireDate: '',
  phone: '',
  email: '',
  adress: ''
  })
// å¼¹çª—控制
const showLeaveDialog = ref(false)
const editProfile = ref(false)
const salaryMonth = ref('')
const payDateStr = ref('')
// è¡¨å•数据
const leaveForm = reactive({
  id: '',
  type: '',
  startDate: '',
  endDate: '',
  reason: ''
  days: 0,
  reason: '',
  status: ''
})
const profileForm = reactive({
  name: '',
  phone: '',
  email: '',
  address: ''
  name: "",
  email: "",
  adress: "",
  phone: "",
})
const joinForm = reactive({
  id: "",
  staffNo: "",
  staffName: "",
  email: "",
  adress: "",
  sex: "",
  nativePlace: "",
  postJob: "",
  firstStudy: "",
  profession: "",
  identityCard: "",
  age: 0,
  phone: "",
  emergencyContact: "",
  emergencyContactPhone: "",
  contractTerm: 0,
  contractStartTime: "",
  contractEndTime: "",
  staffState: 1,
})
// æ–°å¢žè€ƒå‹¤è®°å½•:弹窗与表单
const operationType = ref('add')
const leaveOperationType = ref('add')
const showAttendanceDialog = ref(false)
const attendanceFormRef = ref(null)
const attendanceForm = reactive({
  id: '',
  date: '',
  checkIn: '',
  checkOut: '',
  workHours: '',
  status: '正常'
})
const attendanceRules = {
@@ -305,6 +348,7 @@
// æ–°å¢žè€ƒå‹¤è®°å½•(打开弹窗并预填默认值)
const addAttendanceRecord = () => {
  operationType.value = 'add'
  attendanceForm.date = new Date().toISOString().split('T')[0]
  attendanceForm.checkIn = '09:00'
  attendanceForm.checkOut = '18:00'
@@ -324,11 +368,15 @@
  return m === 0 ? `${h}小时` : `${h}小时${m}分`
}
// æäº¤æ–°å¢žè€ƒå‹¤è®°å½•
// ç¼–辑考勤记录
const editAttendanceRecord = (row) => {
  operationType.value = 'edit'
  Object.assign(attendanceForm, row)
  showAttendanceDialog.value = true
}
// æäº¤æ–°å¢ž-编辑考勤记录
const submitAttendance = () => {
  if (!attendanceFormRef.value) return
  attendanceFormRef.value.validate((valid) => {
    if (!valid) return
  // if (!attendanceFormRef.value) return
    const workHours = computeWorkHours(attendanceForm.checkIn, attendanceForm.checkOut)
    const newRecord = {
      date: attendanceForm.date,
@@ -337,88 +385,320 @@
      workHours,
      status: attendanceForm.status
    }
    attendanceData.value.unshift(newRecord)
    showAttendanceDialog.value = false
    // é‡ç½®è¡¨å•
    attendanceForm.date = ''
    attendanceForm.checkIn = ''
    attendanceForm.checkOut = ''
    attendanceForm.status = '正常'
    ElMessage.success('考勤记录添加成功')
  if (operationType.value === 'add') {
    personalAttendanceRecordsAdd(newRecord)
    .then(res => {
      if (res.code === 200) {
        ElMessage.success('考勤记录添加成功')
        getPersonalAttendanceRecordsList()
        showAttendanceDialog.value = false
        // é‡ç½®è¡¨å•
        attendanceForm.date = ''
        attendanceForm.checkIn = ''
        attendanceForm.checkOut = ''
        attendanceForm.status = '正常'
      }
    }).catch(err => {
      ElMessage.error('考勤记录添加失败')
    })
  }else{
    attendanceForm.workHours = computeWorkHours(attendanceForm.checkIn, attendanceForm.checkOut)
    personalAttendanceRecordsUpdate(attendanceForm)
    .then(res => {
      if (res.code === 200) {
        ElMessage.success('考勤记录更新成功')
        getPersonalAttendanceRecordsList()
        showAttendanceDialog.value = false
        // é‡ç½®è¡¨å•
        attendanceForm.date = ''
        attendanceForm.checkIn = ''
        attendanceForm.checkOut = ''
        attendanceForm.status = '正常'
      }
    }).catch(err => {
      ElMessage.error('考勤记录更新失败')
    })
  }
  // attendanceFormRef.value.validate((valid) => {
  //   if (!valid) return
  // })
}
// åˆ é™¤è€ƒå‹¤è®°å½•
const deleteAttendanceRecord = (row) => {
  ElMessageBox.confirm('确定删除该考勤记录吗?', '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  }).then(() => {
    personalAttendanceRecordsDelete(row.id)
    .then(res => {
      if (res.code === 200) {
        ElMessage.success('考勤记录删除成功')
        getPersonalAttendanceRecordsList()
      }
    }).catch(err => {
      ElMessage.error('考勤记录删除失败')
    })
  }).catch(() => {
    ElMessage({
      type: 'info',
      message: '已取消删除'
    })
  })
}
// ç¼–辑考勤记录
const editAttendanceRecord = (row) => {
  ElMessage.info('编辑功能开发中...')
// ç”³è¯·å‡æœŸ
const openLeaveForm = () => {
  leaveOperationType.value = 'add'
  showLeaveDialog.value = true
  // leaveForm.type = ''
  // leaveForm.startDate = ''
  // leaveForm.endDate = ''
  // leaveForm.days = 0
  // leaveForm.reason = ''
  // leaveForm.status = 'warning'
}
// åˆ é™¤è€ƒå‹¤è®°å½•
const deleteAttendanceRecord = (index) => {
  attendanceData.value.splice(index, 1)
  ElMessage.success('考勤记录删除成功')
}
// ç¼–辑假期记录
const editLeaveRecord = (row) => {
  ElMessage.info('编辑功能开发中...')
  leaveOperationType.value = 'edit'
  showLeaveDialog.value = true
  Object.assign(leaveForm, row)
  // ElMessage.info('编辑功能开发中...')
}
// åˆ é™¤å‡æœŸè®°å½•
const deleteLeaveRecord = (index) => {
  leaveData.value.splice(index, 1)
  ElMessage.success('假期记录删除成功')
const deleteLeaveRecord = (row) => {
  ElMessageBox.confirm('确定删除该假期记录吗?', '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  }).then(() => {
    holidayApplicationDelete(row.id)
    .then(res => {
      if (res.code === 200) {
        ElMessage.success('假期记录删除成功')
        getHolidayApplicationList()
      }
    }).catch(err => {
      ElMessage.error('假期记录删除失败')
    })
  }).catch(() => {
    ElMessage({
      type: 'info',
      message: '已取消删除'
    })
  })
}
//计算假期天数
const calculateDays = () => {
  try {
    if (leaveForm.startDate && leaveForm.endDate) {
      const start = new Date(leaveForm.startDate)
      const end = new Date(leaveForm.endDate)
      leaveForm.startDate = start.toISOString().split('T')[0]
      leaveForm.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
      leaveForm.days = diffDays
    }
  } catch (error) {
    console.error('计算天数失败:', error)
  }
}
// æäº¤å‡æœŸç”³è¯·
const submitLeaveApplication = () => {
  if (!leaveForm.type || !leaveForm.startDate || !leaveForm.endDate || !leaveForm.reason) {
    ElMessage.warning('请填写完整信息')
    return
  }
  const newLeave = {
  if (leaveOperationType.value === 'add') {
    if (!leaveForm.type || !leaveForm.startDate || !leaveForm.endDate || !leaveForm.reason) {
      ElMessage.warning('请填写完整信息')
      return
    }
    calculateDays()
    const newLeave = {
    type: leaveForm.type,
    startDate: leaveForm.startDate,
    endDate: leaveForm.endDate,
    days: 3, // ç®€å•计算
    days: leaveForm.days, // ç®€å•计算
    reason: leaveForm.reason,
    status: '审批中'
    }
    holidayApplicationAdd(newLeave)
    .then(res => {
      if (res.code === 200) {
        ElMessage.success('假期申请提交成功')
        getHolidayApplicationList()
        showLeaveDialog.value = false
        // é‡ç½®è¡¨å•
        Object.keys(leaveForm).forEach(key => {
          leaveForm[key] = ''
        })
      }
    }).catch(err => {
      ElMessage.error('假期申请提交失败')
    })
  }else{
    calculateDays()
    holidayApplicationUpdate(leaveForm)
    .then(res => {
      if (res.code === 200) {
        ElMessage.success('假期申请更新成功')
        getHolidayApplicationList()
        showLeaveDialog.value = false
        // é‡ç½®è¡¨å•
        Object.keys(leaveForm).forEach(key => {
          leaveForm[key] = ''
        })
      }
    }).catch(err => {
      ElMessage.error('假期申请更新失败')
    })
  }
  leaveData.value.unshift(newLeave)
  showLeaveDialog.value = false
  // é‡ç½®è¡¨å•
  Object.keys(leaveForm).forEach(key => {
    leaveForm[key] = ''
}
// èŽ·å–ä¸ªäººä¿¡æ¯
const getProfile = () => {
  tableLoading.value = true;
  getUserProfile().then(res => {
    if (res.code === 200) {
      currentUser.value = res.data
      // console.log("----",currentUser.value)
        //得到人员列表
        staffJoinListPage({staffState: 1}).then(res => {
          //筛选出和currentUser同名的人员
          // let tableData = res.data.records
          user.value = res.data.records.find(item => item.staffName === currentUser.value.userName)
          // console.log("++++",user.value)
          if(user.value){
            profile.value.id=user.value.id
            profile.value.name=user.value.staffName
            profile.value.employeeId=user.value.staffNo
            profile.value.phone=user.value.phone
            profile.value.email=currentUser.value.email
            profile.value.adress=user.value.adress
            profile.value.position=user.value.postJob
            profile.value.hireDate=user.value.createTime
            profile.value.department=currentUser.value.deptNames
          }
          // console.log(profile.value)
          // tableLoading.value = false;
        }).catch(err => {})
    }
  }).catch(err => {
    tableLoading.value = false;
    ElMessage.error('获取个人信息失败')
  })
  ElMessage.success('假期申请提交成功')
}
// ä¿å­˜ä¸ªäººä¿¡æ¯
const saveProfile = () => {
  Object.assign(profile.value, profileForm)
  editProfile.value = false
  ElMessage.success('个人信息保存成功')
}
const saveProfile = async () => {
  tableLoading.value = true;
  try {
    const userRes = await getUserProfile();
    if (userRes.code === 200) {
      currentUser.value = userRes.data;
      const staffListRes = await staffJoinListPage({ staffState: 1 });
      user.value = staffListRes.data.records.find(item => item.staffName === currentUser.value.userName);
      // console.log("++++", user.value);
// åˆå§‹åŒ–个人信息表单
const initProfileForm = () => {
      Object.assign(joinForm, user.value);
      joinForm.staffName = profileForm.name;
      joinForm.phone = profileForm.phone;
      joinForm.email = profileForm.email;
      joinForm.adress = profileForm.adress;
      console.log(joinForm)
      // è°ƒç”¨æ›´æ–°ä¸ªäººä¿¡æ¯çš„æŽ¥å£
      staffJoinUpdate(joinForm).then(res => {
        if (res.code === 200) {
          ElMessage.success('个人信息保存成功');
          getProfile();
          editProfile.value = false;
        }
      }).catch(err => {
        ElMessage.error('个人信息保存失败');
      })
    }
  } catch (err) {
    ElMessage.error('获取个人信息失败');
  } finally {
    tableLoading.value = false;
  }
};
// ç¼–辑个人信息
const editProfileForm = () => {
  editProfile.value = true;
  Object.assign(profileForm, {
    name: profile.value.name,
    phone: profile.value.phone,
    email: profile.value.email,
    address: profile.value.address
    adress: profile.value.adress,
  });
};
//月份改变
const changMonth = () => {
  getCompensationList()
}
//获取考勤记录列表
const getPersonalAttendanceRecordsList = async () => {
  tableLoading.value = true
  personalAttendanceRecordsListPage(page)
  .then(res => {
    attendanceData.value = res.data.records
    page.value.total = res.data.total;
    tableLoading.value = false;
  }).catch(err => {
    tableLoading.value = false;
  })
}
//薪资单查询
const getCompensationList = async () => {
  tableLoading.value = true
  compensationListPage({...page,payDateStr:payDateStr.value})
  .then(res => {
    salaryData.value = res.data.records
    //过滤出当前月份的扣款合计
    salaryData.value.forEach(item => {
      item.deduction =0 + item.deductionAbsenteeism+item.sickLeaveDeductions+item.deductionPersonalLeave+item.forgetClockDeduct,
      item.bonus=0,
      item.status='已发放'
    })
// ç›‘听编辑个人信息弹窗
watch(editProfile, (val) => {
  if (val) {
    initProfileForm()
  }
    page.value.total = res.data.total;
    tableLoading.value = false;
  }).catch(err => {
    tableLoading.value = false;
  })
}
//获取假期申请列表
const getHolidayApplicationList = async () => {
  tableLoading.value = true
  holidayApplicationListPage(page)
  .then(res => {
    leaveData.value = res.data.records
    page.value.total = res.data.total;
    tableLoading.value = false;
  }).catch(err => {
    tableLoading.value = false;
  })
}
onMounted(() => {
  // åˆå§‹åŒ–
  getPersonalAttendanceRecordsList()
  getCompensationList()
  getHolidayApplicationList()
  getProfile()
})
</script>