From 828327d77032e40069a54da3803dd5aaa46aeba3 Mon Sep 17 00:00:00 2001
From: spring <2396852758@qq.com>
Date: 星期一, 10 三月 2025 16:28:34 +0800
Subject: [PATCH] 人员模块搬迁60%

---
 src/views/CNAS/personnel/personnelInfo/index.vue                                                    |  297 +
 src/views/CNAS/personnel/personnelInfo/Department/components/Records/control/Step/ConditionForm.vue |  145 
 src/views/CNAS/personnel/personnelInfo/Department/components/Records/dispose/Step/Fact.vue          |  108 
 src/views/CNAS/personnel/personnelInfo/Department/components/PersonnelCapacity/index.vue            |  567 +++
 src/views/CNAS/personnel/personalOverview/index.vue                                                 |  242 +
 src/views/CNAS/personnel/personnelInfo/Department/components/Communicate/Add.vue                    |  116 
 src/views/CNAS/personnel/personnelInfo/Department/components/Records/Add.vue                        |  234 +
 src/views/CNAS/personnel/personnelInfo/Department/components/Records/dispose/Step/Reason.vue        |  122 
 src/views/CNAS/personnel/personnelInfo/Department/components/Records/supervise/SuperviseForm.vue    |  201 +
 src/components/Editor/index.vue                                                                     |   36 
 src/views/CNAS/personnel/personnelInfo/Department/components/Plan/UploadExcel.vue                   |   44 
 src/views/CNAS/personnel/personnelInfo/Department/components/TrainingRecord/index.vue               |  285 +
 src/views/CNAS/personnel/personnelInfo/Department/components/Communicate/index.vue                  |  213 +
 src/views/CNAS/personnel/personnelInfo/Department/components/Records/control/Step/Inform.vue        |  103 
 src/components/materialOrder/filesLookVisible.vue                                                   |   54 
 src/views/CNAS/personnel/personnelInfo/Department/components/Records/index.vue                      |  406 ++
 src/views/CNAS/personnel/personnelInfo/Department/components/PersonnelList/index.vue                |  319 +
 src/views/CNAS/personnel/personnelInfo/Department/components/Records/dispose/Step/Measure.vue       |  121 
 src/api/cnas/personnel/personalOverview.js                                                          |   10 
 src/views/CNAS/personnel/personnelInfo/Department/components/Records/dispose/Step/Result.vue        |  111 
 src/views/structural/capabilityAndLaboratory/laboratory/index.vue                                   |    4 
 src/views/CNAS/personnel/personnelInfo/Department/components/Mandate/index.vue                      |  228 +
 src/views/CNAS/personnel/personnelInfo/Department/components/Mandate/Add.vue                        |  198 +
 src/views/CNAS/personnel/personnelInfo/Department/components/Records/dispose/index.vue              |  239 +
 src/views/CNAS/personnel/personnelInfo/Department/components/Records/supervise/ApproveForm.vue      |   84 
 src/api/cnas/personnel/personnelInfo.js                                                             |  819 ++++
 src/views/structural/capabilityAndLaboratory/capability/index.vue                                   |    8 
 src/components/Table/value-table.vue                                                                |   45 
 src/views/CNAS/personnel/personnelInfo/Department/components/PersonnelTraining/AddInDetail.vue      |  319 +
 src/components/ImageUpload/index.vue                                                                |   48 
 src/views/CNAS/personnel/personnelInfo/Department/components/Records/control/Step/RectifyForm.vue   |  101 
 src/views/CNAS/systemManagement/measuresDealRisks/components/hazardIdentificationRiskAssessment.vue |    1 
 src/views/CNAS/personnel/personnelInfo/Department/components/PersonnelInformation/index.vue         |  947 +++++
 src/views/CNAS/personnel/personnelInfo/Department/index.vue                                         |  156 
 src/views/CNAS/personnel/personnelInfo/Department/components/JobResponsibilities/index.vue          |  364 ++
 src/views/CNAS/personnel/personnelInfo/Department/components/rewardPunishmentRecord/index.vue       |  316 +
 src/views/CNAS/personnel/personnelInfo/Department/components/Records/control/index.vue              |  312 +
 src/views/CNAS/personnel/personnelInfo/Department/components/PersonnelTraining/Edit.vue             |  580 +++
 src/views/CNAS/personnel/personnelInfo/Department/components/Plan/Add.vue                           |  172 
 src/views/CNAS/personnel/personnelInfo/Department/components/trackRecord/index.vue                  |  298 +
 src/views/CNAS/personnel/personnelInfo/Department/components/PersonnelTraining/index.vue            | 1012 +++++
 src/assets/images/renyuan-title.svg                                                                 |   11 
 src/views/CNAS/personnel/personnelInfo/Department/components/Plan/index.vue                         |  484 ++
 src/views/CNAS/personnel/personnelInfo/Department/components/Records/control/Step/MeasureForm.vue   |  110 
 src/components/FileUpload/index.vue                                                                 |   20 
 45 files changed, 10,494 insertions(+), 116 deletions(-)

diff --git a/src/api/cnas/personnel/personalOverview.js b/src/api/cnas/personnel/personalOverview.js
new file mode 100644
index 0000000..e539973
--- /dev/null
+++ b/src/api/cnas/personnel/personalOverview.js
@@ -0,0 +1,10 @@
+import request from "@/utils/request";
+
+// 璧勬簮瑕佹眰-浜哄憳鎬昏
+export function selectPersonnelOverview(query) {
+  return request({
+    url: "/user/selectPersonnelOverview",
+    method: "get",
+    params: query,
+  });
+}
diff --git a/src/api/cnas/personnel/personnelInfo.js b/src/api/cnas/personnel/personnelInfo.js
new file mode 100644
index 0000000..9b0f117
--- /dev/null
+++ b/src/api/cnas/personnel/personnelInfo.js
@@ -0,0 +1,819 @@
+import request from "@/utils/request";
+
+//鍒犻櫎閮ㄩ棬
+export function delDepartmentLims(query) {
+  return request({
+    url: "/department/delDepartmentLims",
+    method: "delete",
+    params: query,
+  });
+}
+
+// 娣诲姞閮ㄩ棬
+export function addDepartmentLims(data) {
+  return request({
+    url: "/department/addDepartmentLims",
+    method: "post",
+    data: data,
+  });
+}
+
+// 鏌ヨCNAS浜哄憳渚ц竟鏍�
+export function selectCNSAPersonTree(query) {
+  return request({
+    url: "/personBasicInfo/selectCNSAPersonTree",
+    method: "get",
+    params: query,
+  });
+}
+
+// 瀵规帴浜哄憳骞冲彴 鑾峰彇鎵�鏈変汉鍛樹俊鎭�
+export function getEmployees(query) {
+  return request({
+    url: "/personBasicInfo/getEmployees",
+    method: "get",
+    params: query,
+  });
+}
+
+// 鑾峰彇浜哄憳鍒楄〃
+export function basicInformationOfPersonnelSelectPage(query) {
+  return request({
+    url: "/personBasicInfo/basicInformationOfPersonnelSelectPage",
+    method: "get",
+    params: query,
+  });
+}
+
+//鍒犻櫎浜哄憳鏄庣粏鎵�鍦ㄧ粍缁囨灦鏋�
+export function delUserDepardLimsId(query) {
+  return request({
+    url: "/user/delUserDepardLimsId",
+    method: "delete",
+    params: query,
+  });
+}
+
+// 淇敼浜哄憳鏄庣粏鎵�鍦ㄧ粍缁囨灦鏋�
+export function upUserDepardLimsId(data) {
+  return request({
+    url: "/user/upUserDepardLimsId",
+    method: "post",
+    data: data,
+  });
+}
+
+// 鏈俊鎭鍑�,浼犲弬绫讳技鍒嗛〉
+export function exportPersonBasicInfo(query) {
+  return request({
+    url: "/personBasicInfo/exportPersonBasicInfo",
+    method: "get",
+    responseType: "blob",
+    params: query,
+  });
+}
+
+// 鏈俊鎭鍑�,浼犲弬绫讳技鍒嗛〉
+export function exportPersonBasicInfoById(query) {
+  return request({
+    url: "/personBasicInfo/exportPersonBasicInfoById",
+    method: "get",
+    params: query,
+  });
+}
+
+/**
+ * @desc 娌熼�氳褰�
+ */
+
+// 娌熼�氳褰�-鍒楄〃
+export function personPersonCommunicationAbilityPage(query) {
+  return request({
+    url: "/personCommunicationAbility/personPersonCommunicationAbilityPage",
+    method: "get",
+    params: query,
+  });
+}
+
+//娌熼�氳褰�-鍒犻櫎
+export function deletePersonCommunicationAbility(query) {
+  return request({
+    url: "/personCommunicationAbility/deletePersonCommunicationAbility",
+    method: "delete",
+    params: query,
+  });
+}
+
+// 娌熼�氳褰�-瀵煎嚭
+export function exportPersonCommunicationAbility(query) {
+  return request({
+    url: "/personCommunicationAbility/exportPersonCommunicationAbility",
+    method: "get",
+    responseType: "blob",
+    params: query,
+  });
+}
+
+// 浜哄憳鍒楄〃
+export function selectUserList(query) {
+  return request({
+    url: "/deviceScope/selectUserList",
+    method: "get",
+    params: query,
+  });
+}
+
+// 娌熼�氳褰曟柊澧�-缂栬緫
+export function addOrUpdatePersonCommunicationAbility(data) {
+  return request({
+    url: "/personCommunicationAbility/addOrUpdatePersonCommunicationAbility",
+    method: "post",
+    data: data,
+  });
+}
+
+/**
+ * @desc 宀椾綅鑱岃矗
+ */
+
+// 鍒嗛〉鏌ヨ宀椾綅鑱岃矗
+export function personJobResponsibilitiesSelect(query) {
+  return request({
+    url: "/personJobResponsibilities/personJobResponsibilitiesSelect",
+    method: "get",
+    params: query,
+  });
+}
+
+// 鏂板宀椾綅鑱岃矗
+export function personJobResponsibilitiesSave(data) {
+  return request({
+    url: "/personJobResponsibilities/personJobResponsibilitiesSave",
+    method: "post",
+    data: data,
+  });
+}
+
+// 瀵煎嚭浜哄憳鑱岃矗,浼犲弬id
+export function exportPersonJobResponsibilities(query) {
+  return request({
+    url: "/personJobResponsibilities/exportPersonJobResponsibilities",
+    method: "get",
+    responseType: "blob",
+    params: query,
+  });
+}
+
+//鍒犻櫎宀椾綅鑱岃矗
+export function personJobResponsibilitiesDelete(query) {
+  return request({
+    url: "/personJobResponsibilities/personJobResponsibilitiesDelete",
+    method: "delete",
+    params: query,
+  });
+}
+
+/**
+ * @desc 浠昏亴鎺堟潈
+ */
+
+// 浠昏亴鎺堟潈璁板綍-鍒楄〃
+export function PersonPostAuthorizationRecordPage(query) {
+  return request({
+    url: "/personPostAuthorizationRecord/PersonPostAuthorizationRecordPage",
+    method: "get",
+    params: query,
+  });
+}
+
+//浠昏亴鎺堟潈璁板綍-鍒犻櫎
+export function deletePersonPostAuthorizationRecord(query) {
+  return request({
+    url: "/personPostAuthorizationRecord/deletePersonPostAuthorizationRecord",
+    method: "delete",
+    params: query,
+  });
+}
+
+// 瀵煎嚭浜哄憳鑱岃矗,浼犲弬id
+export function exportPersonPostAuthorizationRecord(query) {
+  return request({
+    url: "/personPostAuthorizationRecord/exportPersonPostAuthorizationRecord",
+    method: "get",
+    responseType: "blob",
+    params: query,
+  });
+}
+
+// 浠昏亴鎺堟潈璁板綍-鏂板
+export function addOrUpdatePersonPostAuthorizationRecord(data) {
+  return request({
+    url: "/personPostAuthorizationRecord/addOrUpdatePersonPostAuthorizationRecord",
+    method: "post",
+    data: data,
+  });
+}
+
+//鍒犻櫎鏂囦欢
+export function deleteCNASFile(query) {
+  return request({
+    url: "/personBasicInfo/deleteCNASFile",
+    method: "delete",
+    params: query,
+  });
+}
+
+/**
+ * @desc 浜哄憳鑳藉姏
+ */
+// 瀵煎嚭浜哄憳鑳藉姏
+export function exportPersonnelCapacity(query) {
+  return request({
+    url: "/personPersonnelCapacity/exportPersonnelCapacity",
+    method: "get",
+    responseType: "blob",
+    params: query,
+  });
+}
+
+// 鏌ヨ浜哄憳鑳藉姏
+export function personPersonnelCapacityPage(query) {
+  return request({
+    url: "/personPersonnelCapacity/personPersonnelCapacityPage",
+    method: "get",
+    params: query,
+  });
+}
+
+// 鏂板缂栬緫浜哄憳鑳藉姏
+export function addOrUpdatePersonPersonnelCapacity(data) {
+  return request({
+    url: "/personPersonnelCapacity/addOrUpdatePersonPersonnelCapacity",
+    method: "post",
+    data: data,
+  });
+}
+
+// 纭浜哄憳鑳藉姏
+export function confirmPersonnelCapability(data) {
+  return request({
+    url: "/personPersonnelCapacity/confirmPersonnelCapability",
+    method: "post",
+    data: data,
+  });
+}
+
+//鍒犻櫎浜哄憳鑳藉姏
+export function deletePersonPersonnelCapacity(query) {
+  return request({
+    url: "/personPersonnelCapacity/deletePersonPersonnelCapacity",
+    method: "delete",
+    params: query,
+  });
+}
+
+/**
+ * @desc 浜哄憳淇℃伅
+ */
+// 鑾峰彇闄勪欢
+export function getAnnex(query) {
+  return request({
+    url: "/personBasicInfo/getAnnex",
+    method: "get",
+    params: query,
+  });
+}
+
+// 鏇存柊闄勪欢
+export function updateAnnex(data) {
+  return request({
+    url: "/personBasicInfo/updateAnnex",
+    method: "post",
+    data: data,
+  });
+}
+
+//
+export function getAnnexByUserId(query) {
+  return request({
+    url: "/personBasicInfo/getAnnexByUserId",
+    method: "get",
+    params: query,
+  });
+}
+
+// 娣诲姞闄勪欢
+export function addAnnex(data) {
+  return request({
+    url: "/personBasicInfo/addAnnex",
+    method: "post",
+    data: data,
+  });
+}
+
+//鍒犻櫎闄勪欢
+export function deleteAnnex(query) {
+  return request({
+    url: "/personBasicInfo/deleteAnnex/" + query,
+    method: "delete",
+    // params: query,
+  });
+}
+
+//浜哄憳鍩烘湰淇℃伅鏌ヨ
+export function getCNASPersonnelInfo(query) {
+  return request({
+    url: "/personBasicInfo/getCNASPersonnelInfo",
+    method: "get",
+    params: query,
+  });
+}
+
+// 浜哄憳鍩烘湰淇℃伅淇濆瓨
+export function saveCNASPersonnelInfo(data) {
+  return request({
+    url: "/personBasicInfo/saveCNASPersonnelInfo",
+    method: "post",
+    data: data,
+  });
+}
+
+/**鍩硅璁″垝
+ */
+//骞村害璁″垝鏄庣粏琛� 鍒犻櫎
+export function deleteDetail(query) {
+  return request({
+    url: "/personTraining/deleteDetail",
+    method: "delete",
+    params: query,
+  });
+}
+
+//鏌ヨ浜哄憳鍩硅
+export function personTrainingSelect(query) {
+  return request({
+    url: "/personTraining/personTrainingSelect",
+    method: "get",
+    params: query,
+  });
+}
+
+//鏌ヨ鍩硅璁″垝骞村害璁″垝鏄庣粏琛�
+export function queryTheAnnualPlanDetailsTable(query) {
+  return request({
+    url: "/personTraining/queryTheAnnualPlanDetailsTable",
+    method: "get",
+    params: query,
+  });
+}
+
+//鍒犻櫎浜哄憳鍩硅淇℃伅
+export function personTrainingDelete(query) {
+  return request({
+    url: "/personTraining/personTrainingDelete",
+    method: "delete",
+    params: query,
+  });
+}
+
+// 瀹℃牳 骞村害浜哄憳鍩硅
+export function reviewAnnualPersonnelTraining(data) {
+  return request({
+    url: "/personTraining/reviewAnnualPersonnelTraining",
+    method: "post",
+    data: data,
+  });
+}
+
+// 鎵瑰噯 骞村害浜哄憳鍩硅
+export function approveAnnualPersonnelTraining(data) {
+  return request({
+    url: "/personTraining/approveAnnualPersonnelTraining",
+    method: "post",
+    data: data,
+  });
+}
+
+// 瀵煎嚭浜哄憳鍩硅涓庤�冩牳璁板綍
+export function exportPersonTrainingRecord(query) {
+  return request({
+    url: "/personTraining/exportPersonTrainingRecord",
+    method: "get",
+    responseType: "blob",
+    params: query,
+  });
+}
+
+// 瀵煎嚭/浜哄憳鍩硅
+export function exportPersonTraining(query) {
+  return request({
+    url: "/personTraining/exportPersonTraining",
+    method: "get",
+    responseType: "blob",
+    params: query,
+  });
+}
+
+// 璁ら/鍙栨秷璁ら
+export function claimOfTrainingAndAssessmentRecords(data) {
+  return request({
+    url: "/personTraining/claimOfTrainingAndAssessmentRecords",
+    method: "post",
+    data: data,
+  });
+}
+
+// 鎵归噺鍒犻櫎 骞村害璁″垝鏄庣粏琛�
+export function deleteAnnualPlanDetailTable(query) {
+  return request({
+    url: "/personTraining/deleteAnnualPlanDetailTable",
+    method: "delete",
+    params: query,
+  });
+}
+
+// 骞村害璁″垝鏄庣粏 鏂囦欢涓嬭浇
+export function fileDownLoad(query) {
+  return request({
+    url: "/personTraining/fileDownLoad",
+    method: "get",
+    responseType: "blob",
+    params: query,
+  });
+}
+
+// 鍒犻櫎鏌ヨ
+export function deleteFile(query) {
+  return request({
+    url: "/personTraining/deleteFile",
+    method: "delete",
+    params: query,
+  });
+}
+
+//闄勪欢鏌ヨ
+export function getFileData(query) {
+  return request({
+    url: "/personTraining/getFileData",
+    method: "get",
+    params: query,
+  });
+}
+
+//鍩硅涓庤�冩牳璁板綍 鏌ヨ
+export function trainingAndAssessmentRecordsPage(query) {
+  return request({
+    url: "/personTraining/trainingAndAssessmentRecordsPage",
+    method: "get",
+    params: query,
+  });
+}
+
+// 鍩硅涓庤�冩牳 澶辩劍鏇存柊
+export function outOfFocusPreservation(data) {
+  return request({
+    url: "/personTraining/outOfFocusPreservation",
+    method: "post",
+    data: data,
+  });
+}
+
+// 鍩硅涓庤�冩牳 鏂板浜哄憳
+export function newPersonnelAddedToTrainingRecords(data) {
+  return request({
+    url: "/personTraining/newPersonnelAddedToTrainingRecords",
+    method: "post",
+    data: data,
+  });
+}
+
+// 鍩硅涓庤�冩牳璁板綍 鎵归噺鍒犻櫎
+export function deleteTrainingAndAssessmentRecords(query) {
+  return request({
+    url: "/personTraining/deleteTrainingAndAssessmentRecords",
+    method: "delete",
+    params: query,
+  });
+}
+
+//  鍩硅涓庤�冩牳璁板綍 鎻愪氦
+export function trainingAndAssessmentRecordsAdded(data) {
+  return request({
+    url: "/personTraining/trainingAndAssessmentRecordsAdded",
+    method: "post",
+    data: data,
+  });
+}
+
+//鏌ヨ閮ㄩ棬
+export function selectDepartLims(query) {
+  return request({
+    url: "/personTraining/selectDepartLims",
+    method: "get",
+    params: query,
+  });
+}
+
+//  鏂板鍩硅璁″垝骞村害璁″垝鏄庣粏琛�
+export function addOrUpdatePersonTrainingDetailed(data) {
+  return request({
+    url: "/personTraining/addOrUpdatePersonTrainingDetailed",
+    method: "post",
+    data: data,
+  });
+}
+
+/**
+ * @desc 鐩戠潱璁″垝
+ */
+//骞村害璁″垝鍒楄〃
+export function yearPlanList(query) {
+  return request({
+    url: "/superVisePlan/yearPlanList",
+    method: "get",
+    params: query,
+  });
+}
+
+//骞村害璁″垝鏄庣粏
+export function yearPlanDetailList(query) {
+  return request({
+    url: "/superVisePlan/yearPlanDetailList",
+    method: "get",
+    params: query,
+  });
+}
+
+// 鍒犻櫎骞磋鍒�
+export function yearPlanDel(query) {
+  return request({
+    url: "/superVisePlan/yearPlanDel",
+    method: "delete",
+    params: query,
+  });
+}
+
+// 鍒犻櫎骞磋鍒掓槑缁�
+export function yearPlanDetailDel(query) {
+  return request({
+    url: "/superVisePlan/yearPlanDetailDel",
+    method: "delete",
+    params: query,
+  });
+}
+
+//  鎵瑰噯骞村害璁″垝
+export function yearPlanDetailApproval(data) {
+  return request({
+    url: "/superVisePlan/yearPlanDetailApproval",
+    method: "post",
+    data: data,
+  });
+}
+
+// 浜哄憳 鐩戠潱璁″垝瀵煎嚭
+export function exportSuperVisePlan(query) {
+  return request({
+    url: "/superVisePlan/exportSuperVisePlan",
+    method: "get",
+    responseType: "blob",
+    params: query,
+  });
+}
+
+//  鐩戠潱璁″垝瀵煎叆骞村害璁″垝
+export function yearPlanDetailImport(data) {
+  return request({
+    url: "/superVisePlan/yearPlanDetailImport",
+    method: "post",
+    headers: {
+      "Content-Type": "multipart/form-data;",
+    },
+    data: data,
+  });
+}
+
+//  鐩戠潱璁″垝-鏂板骞村害璁″垝
+export function yearPlanDetailAdd(data) {
+  return request({
+    url: "/superVisePlan/yearPlanDetailAdd",
+    method: "post",
+    data: data,
+  });
+}
+
+//  鐩戠潱璁″垝-缂栬緫骞村害璁″垝
+export function yearPlanDetailEdit(data) {
+  return request({
+    url: "/superVisePlan/yearPlanDetailEdit",
+    method: "post",
+    data: data,
+  });
+}
+
+/**
+ * @desc 鐩戠潱璁板綍
+ */
+//鏌ヨ
+export function personSupervisionRecordPage(query) {
+  return request({
+    url: "/personSupervisionRecord/personSupervisionRecordPage",
+    method: "get",
+    params: query,
+  });
+}
+
+// 鍒犻櫎 鐩戠潱璁板綍
+export function deletePersonSupervisionRecord(query) {
+  return request({
+    url: "/personSupervisionRecord/deletePersonSupervisionRecord",
+    method: "delete",
+    params: query,
+  });
+}
+
+// 鎺у埗鍗曞鍑�
+export function exportSupervisionControlSheet(query) {
+  return request({
+    url: "/personSupervisionRecord/exportSupervisionControlSheet",
+    method: "get",
+    responseType: "blob",
+    params: query,
+  });
+}
+
+// 澶勭悊鍗曞鍑�
+export function exportSupervisionProcessingSheet(query) {
+  return request({
+    url: "/personSupervisionRecord/exportSupervisionProcessingSheet",
+    method: "get",
+    responseType: "blob",
+    params: query,
+  });
+}
+
+// 鐩戠潱璁板綍瀵煎嚭
+export function exportPersonSupervisionRecord(query) {
+  return request({
+    url: "/personSupervisionRecord/exportPersonSupervisionRecord",
+    method: "get",
+    responseType: "blob",
+    params: query,
+  });
+}
+
+//  鏂板-缂栬緫 鐩戠潱璁板綍
+export function addOrUpdatePersonSupervisionRecord(data) {
+  return request({
+    url: "/personSupervisionRecord/addOrUpdatePersonSupervisionRecord",
+    method: "post",
+    data: data,
+  });
+}
+
+//鏌ヨ 鎺у埗鍗�
+export function personSupervisionControlSheetPage(query) {
+  return request({
+    url: "/personSupervisionRecord/personSupervisionControlSheetPage",
+    method: "get",
+    params: query,
+  });
+}
+
+//  鏂板-缂栬緫 鎺у埗鍗�
+export function addOrUpdatePersonSupervisionControl(data) {
+  return request({
+    url: "/personSupervisionRecord/addOrUpdatePersonSupervisionControl",
+    method: "post",
+    data: data,
+  });
+}
+
+//鏌ヨ 澶勭悊鍗�
+export function personSupervisionProcessingPage(query) {
+  return request({
+    url: "/personSupervisionRecord/personSupervisionProcessingPage",
+    method: "get",
+    params: query,
+  });
+}
+
+//  鏂板-缂栬緫 澶勭悊鍗�
+export function addOrUpdatePersonnelServiceProcessing(data) {
+  return request({
+    url: "/personSupervisionRecord/addOrUpdatePersonnelServiceProcessing",
+    method: "post",
+    data: data,
+  });
+}
+
+/**
+ * @desc 濂栨儵璁板綍
+ */
+//  濂栨儵璁板綍 鏂板/鏇存柊
+export function addOrUpdateRewardPunishment(data) {
+  return request({
+    url: "/personRewardPunishmentRecord/addOrUpdateRewardPunishment",
+    method: "post",
+    data: data,
+  });
+}
+
+// 浜哄憳 - 濂栨儵璁板綍 鍒犻櫎
+export function deleteRewardPunishment(query) {
+  return request({
+    url: "/personRewardPunishmentRecord/deleteRewardPunishment",
+    method: "delete",
+    params: query,
+  });
+}
+
+// 浜哄憳 - 濂栨儵璁板綍 鍒嗛〉鏌ヨ
+export function rewardPunishmentPage(query) {
+  return request({
+    url: "/personRewardPunishmentRecord/rewardPunishmentPage",
+    method: "get",
+    params: query,
+  });
+}
+
+/**
+ * @desc 宸ヤ綔灞ュ巻
+ */
+
+// 瀵煎嚭宸ヤ綔灞ュ巻
+export function personTrackRecordExport(query) {
+  return request({
+    url: "/personTrackRecord/personTrackRecordExport",
+    method: "get",
+    responseType: "blob",
+    params: query,
+  });
+}
+
+//  鏇存柊宸ヤ綔灞ュ巻
+export function personTrackRecordUpdate(data) {
+  return request({
+    url: "/personTrackRecord/personTrackRecordUpdate",
+    method: "post",
+    data: data,
+  });
+}
+
+//  鏂板宸ヤ綔灞ュ巻
+export function personTrackRecordSave(data) {
+  return request({
+    url: "/personTrackRecord/personTrackRecordSave",
+    method: "post",
+    data: data,
+  });
+}
+
+// 鍒犻櫎宸ヤ綔灞ュ巻
+export function personTrackRecordDelete(query) {
+  return request({
+    url: "/personTrackRecord/personTrackRecordDelete",
+    method: "delete",
+    params: query,
+  });
+}
+
+//鏌ヨ宸ヤ綔灞ュ巻
+export function personTrackRecordSelect(query) {
+  return request({
+    url: "/personTrackRecord/personTrackRecordSelect",
+    method: "get",
+    params: query,
+  });
+}
+
+/**
+ * @desc 鍩硅璁板綍
+ */
+// 瀵煎嚭鍩硅璁板綍
+export function exportTrainingRecord(query) {
+  return request({
+    url: "/personTrainingRecord/exportTrainingRecord",
+    method: "get",
+    responseType: "blob",
+    params: query,
+  });
+}
+
+//鏌ヨ浜哄憳 鍩硅璁板綍
+export function trainingSelectTrainingRecord(query) {
+  return request({
+    url: "/personTrainingRecord/trainingSelectTrainingRecord",
+    method: "get",
+    params: query,
+  });
+}
+
+//鏌ヨ浜哄憳鏄庣粏 鍩硅璁板綍
+export function queryPersonnelDetails(query) {
+  return request({
+    url: "/personTrainingRecord/queryPersonnelDetails",
+    method: "get",
+    params: query,
+  });
+}
diff --git a/src/assets/images/renyuan-title.svg b/src/assets/images/renyuan-title.svg
new file mode 100644
index 0000000..c69691f
--- /dev/null
+++ b/src/assets/images/renyuan-title.svg
@@ -0,0 +1,11 @@
+<svg width="148" height="21" viewBox="0 0 148 21" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path fill-rule="evenodd" clip-rule="evenodd" d="M7.00437 5.75531V0.0625L0.772461 5.75531H7.00437Z" fill="#B26F00"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M141.709 5.75531V0.0625L147.941 5.75531H141.709Z" fill="#B26F00"/>
+<path d="M6.97192 2.0625C6.97192 0.957931 7.86735 0.0625 8.97192 0.0625H139.676C140.781 0.0625 141.676 0.957931 141.676 2.0625V12.0625C141.676 16.4808 138.095 20.0625 133.676 20.0625H14.9719C10.5537 20.0625 6.97192 16.4808 6.97192 12.0625V2.0625Z" fill="url(#paint0_linear_2026_4)"/>
+<defs>
+<linearGradient id="paint0_linear_2026_4" x1="6.97192" y1="0.0625" x2="6.97192" y2="20.0625" gradientUnits="userSpaceOnUse">
+<stop stop-color="#F9C76F"/>
+<stop offset="1" stop-color="#FEB42F"/>
+</linearGradient>
+</defs>
+</svg>
diff --git a/src/components/Editor/index.vue b/src/components/Editor/index.vue
index 9323e53..1142802 100644
--- a/src/components/Editor/index.vue
+++ b/src/components/Editor/index.vue
@@ -1,17 +1,8 @@
 <template>
   <div>
-    <el-upload
-      :action="uploadUrl"
-      :before-upload="handleBeforeUpload"
-      :on-success="handleUploadSuccess"
-      :on-error="handleUploadError"
-      name="file"
-      :show-file-list="false"
-      :headers="headers"
-      style="display: none"
-      ref="upload"
-      v-if="this.type == 'url'"
-    >
+    <el-upload :action="uploadUrl" :before-upload="handleBeforeUpload" :on-success="handleUploadSuccess"
+      :on-error="handleUploadError" name="file" :show-file-list="false" :headers="uploadHeader" style="display: none"
+      ref="upload" v-if="this.type == 'url'">
     </el-upload>
     <div class="editor" ref="editor" :style="styles"></div>
   </div>
@@ -197,76 +188,95 @@
 </script>
 
 <style>
-.editor, .ql-toolbar {
+.editor,
+.ql-toolbar {
   white-space: pre-wrap !important;
   line-height: normal !important;
 }
+
 .quill-img {
   display: none;
 }
+
 .ql-snow .ql-tooltip[data-mode="link"]::before {
   content: "璇疯緭鍏ラ摼鎺ュ湴鍧�:";
 }
+
 .ql-snow .ql-tooltip.ql-editing a.ql-action::after {
   border-right: 0px;
   content: "淇濆瓨";
   padding-right: 0px;
 }
+
 .ql-snow .ql-tooltip[data-mode="video"]::before {
   content: "璇疯緭鍏ヨ棰戝湴鍧�:";
 }
+
 .ql-snow .ql-picker.ql-size .ql-picker-label::before,
 .ql-snow .ql-picker.ql-size .ql-picker-item::before {
   content: "14px";
 }
+
 .ql-snow .ql-picker.ql-size .ql-picker-label[data-value="small"]::before,
 .ql-snow .ql-picker.ql-size .ql-picker-item[data-value="small"]::before {
   content: "10px";
 }
+
 .ql-snow .ql-picker.ql-size .ql-picker-label[data-value="large"]::before,
 .ql-snow .ql-picker.ql-size .ql-picker-item[data-value="large"]::before {
   content: "18px";
 }
+
 .ql-snow .ql-picker.ql-size .ql-picker-label[data-value="huge"]::before,
 .ql-snow .ql-picker.ql-size .ql-picker-item[data-value="huge"]::before {
   content: "32px";
 }
+
 .ql-snow .ql-picker.ql-header .ql-picker-label::before,
 .ql-snow .ql-picker.ql-header .ql-picker-item::before {
   content: "鏂囨湰";
 }
+
 .ql-snow .ql-picker.ql-header .ql-picker-label[data-value="1"]::before,
 .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="1"]::before {
   content: "鏍囬1";
 }
+
 .ql-snow .ql-picker.ql-header .ql-picker-label[data-value="2"]::before,
 .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="2"]::before {
   content: "鏍囬2";
 }
+
 .ql-snow .ql-picker.ql-header .ql-picker-label[data-value="3"]::before,
 .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="3"]::before {
   content: "鏍囬3";
 }
+
 .ql-snow .ql-picker.ql-header .ql-picker-label[data-value="4"]::before,
 .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="4"]::before {
   content: "鏍囬4";
 }
+
 .ql-snow .ql-picker.ql-header .ql-picker-label[data-value="5"]::before,
 .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="5"]::before {
   content: "鏍囬5";
 }
+
 .ql-snow .ql-picker.ql-header .ql-picker-label[data-value="6"]::before,
 .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="6"]::before {
   content: "鏍囬6";
 }
+
 .ql-snow .ql-picker.ql-font .ql-picker-label::before,
 .ql-snow .ql-picker.ql-font .ql-picker-item::before {
   content: "鏍囧噯瀛椾綋";
 }
+
 .ql-snow .ql-picker.ql-font .ql-picker-label[data-value="serif"]::before,
 .ql-snow .ql-picker.ql-font .ql-picker-item[data-value="serif"]::before {
   content: "琛嚎瀛椾綋";
 }
+
 .ql-snow .ql-picker.ql-font .ql-picker-label[data-value="monospace"]::before,
 .ql-snow .ql-picker.ql-font .ql-picker-item[data-value="monospace"]::before {
   content: "绛夊瀛椾綋";
diff --git a/src/components/FileUpload/index.vue b/src/components/FileUpload/index.vue
index 12ad4ea..63a9f2e 100644
--- a/src/components/FileUpload/index.vue
+++ b/src/components/FileUpload/index.vue
@@ -1,19 +1,8 @@
 <template>
   <div class="upload-file">
-    <el-upload
-      multiple
-      :action="uploadFileUrl"
-      :before-upload="handleBeforeUpload"
-      :file-list="fileList"
-      :limit="limit"
-      :on-error="handleUploadError"
-      :on-exceed="handleExceed"
-      :on-success="handleUploadSuccess"
-      :show-file-list="false"
-      :headers="headers"
-      class="upload-file-uploader"
-      ref="fileUpload"
-    >
+    <el-upload multiple :action="uploadFileUrl" :before-upload="handleBeforeUpload" :file-list="fileList" :limit="limit"
+      :on-error="handleUploadError" :on-exceed="handleExceed" :on-success="handleUploadSuccess" :show-file-list="false"
+      :headers="uploadHeader" class="upload-file-uploader" ref="fileUpload">
       <!-- 涓婁紶鎸夐挳 -->
       <el-button size="mini" type="primary">閫夊彇鏂囦欢</el-button>
       <!-- 涓婁紶鎻愮ず -->
@@ -203,18 +192,21 @@
 .upload-file-uploader {
   margin-bottom: 5px;
 }
+
 .upload-file-list .el-upload-list__item {
   border: 1px solid #e4e7ed;
   line-height: 2;
   margin-bottom: 10px;
   position: relative;
 }
+
 .upload-file-list .ele-upload-list__item-content {
   display: flex;
   justify-content: space-between;
   align-items: center;
   color: inherit;
 }
+
 .ele-upload-list__item-content-action .el-link {
   margin-right: 10px;
 }
diff --git a/src/components/ImageUpload/index.vue b/src/components/ImageUpload/index.vue
index bf7e381..f8e4009 100644
--- a/src/components/ImageUpload/index.vue
+++ b/src/components/ImageUpload/index.vue
@@ -1,22 +1,9 @@
 <template>
   <div class="component-upload-image">
-    <el-upload
-      multiple
-      :action="uploadImgUrl"
-      list-type="picture-card"
-      :on-success="handleUploadSuccess"
-      :before-upload="handleBeforeUpload"
-      :limit="limit"
-      :on-error="handleUploadError"
-      :on-exceed="handleExceed"
-      ref="imageUpload"
-      :on-remove="handleDelete"
-      :show-file-list="true"
-      :headers="headers"
-      :file-list="fileList"
-      :on-preview="handlePictureCardPreview"
-      :class="{hide: this.fileList.length >= this.limit}"
-    >
+    <el-upload multiple :action="uploadImgUrl" list-type="picture-card" :on-success="handleUploadSuccess"
+      :before-upload="handleBeforeUpload" :limit="limit" :on-error="handleUploadError" :on-exceed="handleExceed"
+      ref="imageUpload" :on-remove="handleDelete" :show-file-list="true" :headers="uploadHeader" :file-list="fileList"
+      :on-preview="handlePictureCardPreview" :class="{ hide: this.fileList.length >= this.limit }">
       <i class="el-icon-plus"></i>
     </el-upload>
 
@@ -28,16 +15,8 @@
       鐨勬枃浠�
     </div>
 
-    <el-dialog
-      :visible.sync="dialogVisible"
-      title="棰勮"
-      width="800"
-      append-to-body
-    >
-      <img
-        :src="dialogImageUrl"
-        style="display: block; max-width: 100%; margin: 0 auto"
-      />
+    <el-dialog :visible.sync="dialogVisible" title="棰勮" width="800" append-to-body>
+      <img :src="dialogImageUrl" style="display: block; max-width: 100%; margin: 0 auto" />
     </el-dialog>
   </div>
 </template>
@@ -56,7 +35,7 @@
     },
     // 澶у皬闄愬埗(MB)
     fileSize: {
-       type: Number,
+      type: Number,
       default: 5,
     },
     // 鏂囦欢绫诲瀷, 渚嬪['png', 'jpg', 'jpeg']
@@ -95,9 +74,9 @@
           this.fileList = list.map(item => {
             if (typeof item === "string") {
               if (item.indexOf(this.baseUrl) === -1 && !isExternal(item)) {
-                  item = { name: this.baseUrl + item, url: this.baseUrl + item };
+                item = { name: this.baseUrl + item, url: this.baseUrl + item };
               } else {
-                  item = { name: item, url: item };
+                item = { name: item, url: item };
               }
             }
             return item;
@@ -215,17 +194,18 @@
 <style scoped lang="scss">
 // .el-upload--picture-card 鎺у埗鍔犲彿閮ㄥ垎
 ::v-deep.hide .el-upload--picture-card {
-    display: none;
+  display: none;
 }
+
 // 鍘绘帀鍔ㄧ敾鏁堟灉
 ::v-deep .el-list-enter-active,
 ::v-deep .el-list-leave-active {
-    transition: all 0s;
+  transition: all 0s;
 }
 
-::v-deep .el-list-enter, .el-list-leave-active {
+::v-deep .el-list-enter,
+.el-list-leave-active {
   opacity: 0;
   transform: translateY(0);
 }
 </style>
-
diff --git a/src/components/Table/value-table.vue b/src/components/Table/value-table.vue
index 34561e0..ec9f177 100644
--- a/src/components/Table/value-table.vue
+++ b/src/components/Table/value-table.vue
@@ -152,8 +152,8 @@
             <!-- 鍙搷浣滆杩涜鐐瑰嚮浜嬩欢 -->
             <span v-else-if="data.linkEvent && showLink(a.label, data.linkEvent)" style="color:#409EFF;cursor: pointer;"
               @click="handleLinkEvent(scope.row, data.linkEvent[a.label])">{{ scope.row[a.label] }}</span>
-            <img v-else-if="showUpload(a.label) && scope.row[a.label]" :src="javaApi + '/img/' + scope.row[a.label]" alt=""
-              style="width: 40px;height: 40px;margin-top: 10px;">
+            <img v-else-if="showUpload(a.label) && scope.row[a.label]" :src="javaApi + '/img/' + scope.row[a.label]"
+              alt="" style="width: 40px;height: 40px;margin-top: 10px;">
             <span v-else :class="{ red: getRedColor(a.label, scope.row) }">{{ scope.row[a.label] }}</span>
           </template>
         </el-table-column>
@@ -165,8 +165,9 @@
               <span v-if="a.type != 'upload'">{{ a.font }}</span>
               <el-upload v-else ref='upload' :accept='a.uploadConfig.accept'
                 :action="javaApi + a.uploadConfig.url + '?id=' + (a.uploadConfig.uploadIdFun ? a.uploadConfig.uploadIdFun(scope.row) : scope.row.id)"
-                :disabled="a.disabled ? a.disabled(scope.row, scope.$index) : false" :headers="token" :on-error="onError"
-                :on-success="handleSuccessUp" :show-file-list="false" name="file" style="background: transparent;">
+                :disabled="a.disabled ? a.disabled(scope.row, scope.$index) : false" :headers="uploadHeader"
+                :on-error="onError" :on-success="handleSuccessUp" :show-file-list="false" name="file"
+                style="background: transparent;">
                 <span>{{ a.font }}</span>
               </el-upload>
             </el-button>
@@ -189,7 +190,8 @@
               <span v-if="showUpReq(a.label)" class="required-span">* </span>{{ a.value }}锛�
             </el-col>
             <el-col :span="16 / data.row">
-              <el-input v-if="showType(a.label, data.selectField) == null && !showUpload(a.label) && !showCascader(a.label)"
+              <el-input
+                v-if="showType(a.label, data.selectField) == null && !showUpload(a.label) && !showCascader(a.label)"
                 v-model="upData[a.label]" :disabled="isDisabled(a.label)" :placeholder="`璇疯緭鍏�${a.value}`" clearable
                 size="small"></el-input>
               <el-select v-if="showType(a.label, data.selectField) != null" v-model="upData[a.label]"
@@ -201,8 +203,9 @@
                 </el-option>
               </el-select>
               <el-upload v-if="showUpload(a.label)" ref='upload' :accept='data.addUploadConfig.accept'
-                :action="javaApi + data.addUploadConfig.url" :headers="token" :multiple="false" :on-error="onError"
-                :on-success="m => handleSuccessUp(m, a.label)" :show-file-list="false" class="avatar-uploader" name="file"
+                :action="javaApi + data.addUploadConfig.url" :headers="uploadHeader" :multiple="false"
+                :on-error="onError" :on-success="m => handleSuccessUp(m, a.label)" :show-file-list="false"
+                class="avatar-uploader" name="file"
                 style="background: transparent;width: 80px;height: 80px;border: 1px solid #DCDFE6;border-radius: 6px;margin: 10px 0;">
                 <img v-if="upData[a.label]" :src="javaApi + '/img/' + upData[a.label]" class="avatar"
                   style="width: 80px;height: 80px;border-radius: 6px;">
@@ -221,7 +224,8 @@
               <span v-if="showUpReq(a.label)" class="required-span">* </span>{{ a.value }}锛�
             </el-col>
             <el-col :offset="1" :span="16">
-              <el-input v-if="showType(a.label, data.selectField) == null && !showUpload(a.label) && !showCascader(a.label)"
+              <el-input
+                v-if="showType(a.label, data.selectField) == null && !showUpload(a.label) && !showCascader(a.label)"
                 v-model="upData[a.label]" :disabled="isDisabled(a.label)" :placeholder="`璇疯緭鍏�${a.value}`" clearable
                 size="small"></el-input>
               <el-select v-if="showType(a.label, data.selectField) != null" v-model="upData[a.label]"
@@ -231,8 +235,9 @@
                   :value="b.value"></el-option>
               </el-select>
               <el-upload v-if="showUpload(a.label)" ref='upload' :accept='data.addUploadConfig.accept'
-                :action="javaApi + data.addUploadConfig.url" :headers="token" :multiple="false" :on-error="onError"
-                :on-success="m => handleSuccessUp(m, a.label)" :show-file-list="false" class="avatar-uploader" name="file"
+                :action="javaApi + data.addUploadConfig.url" :headers="uploadHeader" :multiple="false"
+                :on-error="onError" :on-success="m => handleSuccessUp(m, a.label)" :show-file-list="false"
+                class="avatar-uploader" name="file"
                 style="background: transparent;width: 80px;height: 80px;border: 1px solid #DCDFE6;border-radius: 6px;margin: 10px 0;">
                 <img v-if="upData[a.label]" :src="javaApi + '/img/' + upData[a.label]" class="avatar"
                   style="width: 80px;height: 80px;border-radius: 6px;">
@@ -260,7 +265,8 @@
                 class="required-span">*
               </span>{{ a.value }}锛�</el-col>
             <el-col :span="16 / data.row">
-              <el-input v-if="showType(a.label, data.selectField) == null && !showUpload(a.label) && !showCascader(a.label)"
+              <el-input
+                v-if="showType(a.label, data.selectField) == null && !showUpload(a.label) && !showCascader(a.label)"
                 v-model="upData[a.label]" :placeholder="`璇疯緭鍏�${a.value}`" clearable size="small"></el-input>
               <el-select v-if="showType(a.label, data.selectField) != null" v-model="upData[a.label]"
                 :multiple="data.selectField[a.label].choose" :placeholder="`璇烽�夋嫨${a.value}`" clearable filterable
@@ -269,8 +275,9 @@
                   :value="b.value"></el-option>
               </el-select>
               <el-upload v-if="showUpload(a.label)" ref='upload' :accept='data.addUploadConfig.accept'
-                :action="javaApi + data.addUploadConfig.url" :headers="token" :multiple="false" :on-error="onError"
-                :on-success="m => handleSuccessUp(m, a.label)" :show-file-list="false" class="avatar-uploader" name="file"
+                :action="javaApi + data.addUploadConfig.url" :headers="uploadHeader" :multiple="false"
+                :on-error="onError" :on-success="m => handleSuccessUp(m, a.label)" :show-file-list="false"
+                class="avatar-uploader" name="file"
                 style="background: transparent;width: 80px;height: 80px;border: 1px solid #DCDFE6;border-radius: 6px;margin: 10px 0;">
                 <img v-if="upData[a.label]" :src="javaApi + '/img/' + upData[a.label]" class="avatar"
                   style="width: 80px;height: 80px;border-radius: 6px;">
@@ -287,7 +294,8 @@
             <el-col :span="6" style="text-align: right;"><span v-if="showAddReq(a.label)" class="required-span">*
               </span>{{ a.value }}锛�</el-col>
             <el-col :offset="1" :span="16">
-              <el-input v-if="showType(a.label, data.selectField) == null && !showUpload(a.label) && !showCascader(a.label)"
+              <el-input
+                v-if="showType(a.label, data.selectField) == null && !showUpload(a.label) && !showCascader(a.label)"
                 v-model="upData[a.label]" :placeholder="`璇疯緭鍏�${a.value}`" clearable size="small"></el-input>
               <el-select v-if="showType(a.label, data.selectField) != null" v-model="upData[a.label]"
                 :multiple="data.selectField[a.label].choose" :placeholder="`璇烽�夋嫨${a.value}`" clearable size="small"
@@ -296,8 +304,9 @@
                   :value="b.value"></el-option>
               </el-select>
               <el-upload v-if="showUpload(a.label)" ref='upload' :accept='data.addUploadConfig.accept'
-                :action="javaApi + data.addUploadConfig.url" :headers="token" :multiple="false" :on-error="onError"
-                :on-success="m => handleSuccessUp(m, a.label)" :show-file-list="false" class="avatar-uploader" name="file"
+                :action="javaApi + data.addUploadConfig.url" :headers="uploadHeader" :multiple="false"
+                :on-error="onError" :on-success="m => handleSuccessUp(m, a.label)" :show-file-list="false"
+                class="avatar-uploader" name="file"
                 style="background: transparent;width: 80px;height: 80px;border: 1px solid #DCDFE6;border-radius: 6px;margin: 10px 0;">
                 <img v-if="upData[a.label]" :src="javaApi + '/img/' + upData[a.label]" class="avatar"
                   style="width: 80px;height: 80px;border-radius: 6px;">
@@ -328,8 +337,8 @@
     <el-dialog :visible.sync="uploadDia" title="鏁版嵁瀵煎叆" width="500px">
       <div style="margin: 0 auto;">
         <el-upload ref="upload" :accept="data.accept === undefined ? '.csv' : data.accept" :action="javaApi + inputUrl"
-          :auto-upload="false" :data="{ param: data.uploadStr }" :file-list="fileList" :headers="token" :limit="1"
-          :on-change="beforeUpload" :on-error="onError" :on-success="onSuccess" drag name="file">
+          :auto-upload="false" :data="{ param: data.uploadStr }" :file-list="fileList" :headers="uploadHeader"
+          :limit="1" :on-change="beforeUpload" :on-error="onError" :on-success="onSuccess" drag name="file">
           <i class="el-icon-upload"></i>
           <div class="el-upload__text">灏嗘枃浠舵嫋鍒版澶勶紝鎴�<em>鐐瑰嚮涓婁紶</em></div>
         </el-upload>
diff --git a/src/components/materialOrder/filesLookVisible.vue b/src/components/materialOrder/filesLookVisible.vue
index 2ab086f..1a44265 100644
--- a/src/components/materialOrder/filesLookVisible.vue
+++ b/src/components/materialOrder/filesLookVisible.vue
@@ -3,26 +3,20 @@
     <el-dialog title="闄勪欢鏌ョ湅" :visible.sync="isShow" width="80%" @closed="$emit('closeFilesLook')">
       <div style="display: flex;justify-content: space-between;">
         <ul class="tab">
-          <li v-for="(m,i) in dataVisibleTitle" :key="i" :class="{active:i===dataVisibleIndex}" @click="handleDataVisibleTab(m,i)">{{m.label}}</li>
+          <li v-for="(m, i) in dataVisibleTitle" :key="i" :class="{ active: i === dataVisibleIndex }"
+            @click="handleDataVisibleTab(m, i)">{{ m.label }}</li>
         </ul>
-        <el-upload :action="action"
-                   :auto-upload="true"
-                   :data="{orderId: dataVisibleIndex === 0 ? filesLookInfo.enterOrderId : filesLookInfo.quarterOrderId}"
-                   :on-success="handleSuccessUp" :show-file-list="false"
-                   accept='.jpg,.jpeg,.png,.gif,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.pdf,.zip,.rar' :headers="headers"
-                   :before-upload="beforeUpload"
-                   style="width: 80px !important;"
-                   :on-error="onError" ref='upload'>
+        <el-upload :action="action" :auto-upload="true"
+          :data="{ orderId: dataVisibleIndex === 0 ? filesLookInfo.enterOrderId : filesLookInfo.quarterOrderId }"
+          :on-success="handleSuccessUp" :show-file-list="false"
+          accept='.jpg,.jpeg,.png,.gif,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.pdf,.zip,.rar' :headers="uploadHeader"
+          :before-upload="beforeUpload" style="width: 80px !important;" :on-error="onError" ref='upload'>
           <el-button size="small" type="primary" style="height: 38px">闄勪欢涓婁紶</el-button>
         </el-upload>
       </div>
       <div style="height: 70vh;overflow-y: auto;" v-if="filesDialogVisible">
-        <ValueTable ref="fileList"
-                    :url="$api.insOrderPlan.getFileList"
-                    :delUrl="$api.insOrderPlan.delfile"
-                    class="value-table"
-                    :key="upIndex"
-                    :componentData="componentData"/>
+        <ValueTable ref="fileList" :url="$api.insOrderPlan.getFileList" :delUrl="$api.insOrderPlan.delfile"
+          class="value-table" :key="upIndex" :componentData="componentData" />
       </div>
     </el-dialog>
   </div>
@@ -35,7 +29,7 @@
 export default {
   name: "filesLookVisible",
   // import 寮曞叆鐨勭粍浠堕渶瑕佹敞鍏ュ埌瀵硅薄涓墠鑳戒娇鐢�
-  components: {ValueTable},
+  components: { ValueTable },
   props: {
     filesDialogVisible: {
       type: Boolean,
@@ -43,7 +37,7 @@
     },
     filesLookInfo: {
       type: Object,
-      default: () => {}
+      default: () => { }
     },
   },
   data() {
@@ -64,20 +58,20 @@
       dataVisibleIndex: 0, // tab鏍忛�夋嫨鍊�
       componentData: {
         entity: {
-          insOrderId:''
+          insOrderId: ''
         },
         isIndex: true,
         showSelect: false,
         select: false,
         sort: false,
-        init:false,
+        init: false,
         do: [
           {
             id: 'parent',
             font: '涓嬭浇',
             type: 'text',
             method: 'handleDown'
-          },{
+          }, {
             id: 'delete',
             font: '鍒犻櫎',
             type: 'text',
@@ -87,8 +81,8 @@
         isPage: false,
         linkEvent: {},
         tagField: {
-          type:{
-            select:[
+          type: {
+            select: [
               {
                 value: 1,
                 label: '鍥剧墖'
@@ -114,7 +108,7 @@
   // 鏂规硶闆嗗悎
   methods: {
     // 鍒囨崲鏁版嵁鏌ョ湅tab鏍�
-    handleDataVisibleTab (m, i) {
+    handleDataVisibleTab(m, i) {
       this.dataVisibleIndex = i
       this.refreshTable()
     },
@@ -129,17 +123,17 @@
         this.$refs['fileList'].selectList(e)
       })
     },
-    handleDown(row){
+    handleDown(row) {
       this.$axios.post(this.$api.insOrderPlan.downFile, {
         id: row.id,
       }).then(res => {
         if (res.code === 200) {
           let url = '';
-          if(res.data.type==1){
-            url = this.javaApi+'/img/'+res.data.fileUrl
-            file.downloadIamge(url,row.fileName)
-          }else{
-            url = this.javaApi+'/word/'+res.data.fileUrl
+          if (res.data.type == 1) {
+            url = this.javaApi + '/img/' + res.data.fileUrl
+            file.downloadIamge(url, row.fileName)
+          } else {
+            url = this.javaApi + '/word/' + res.data.fileUrl
             const link = document.createElement('a');
             link.href = url;
             link.download = row.fileName;
@@ -150,7 +144,7 @@
 
       })
     },
-    handleSuccessUp(response, ) {
+    handleSuccessUp(response,) {
       this.upLoading = false;
       if (response.code == 200) {
         this.$message.success('涓婁紶鎴愬姛');
diff --git a/src/views/CNAS/personnel/personalOverview/index.vue b/src/views/CNAS/personnel/personalOverview/index.vue
new file mode 100644
index 0000000..a227788
--- /dev/null
+++ b/src/views/CNAS/personnel/personalOverview/index.vue
@@ -0,0 +1,242 @@
+<style scoped>
+.search {
+  background-color: #fff;
+  height: 80px;
+  display: flex;
+  align-items: center;
+}
+
+.search_thing {
+  width: 350px;
+  display: flex;
+  align-items: center;
+}
+
+.search_label {
+  width: 110px;
+  font-size: 14px;
+  text-align: right;
+}
+
+.search_input {
+  width: calc(100% - 110px);
+}
+
+.table {
+  margin-top: 10px;
+  background-color: #fff;
+  width: calc(100% - 40px);
+  height: calc(100% - 60px - 80px - 10px - 40px);
+  padding: 20px;
+  overflow-y: auto;
+}
+
+.card {
+  list-style-type: none;
+  display: grid;
+  grid-template-columns: repeat(auto-fit, 320px);
+  /* justify-content: center; */
+  grid-gap: 16px;
+  min-height: 200px;
+}
+
+.card li {
+  width: 320px;
+  border-radius: 8px 8px 8px 8px;
+  box-shadow: 4px 4px 8px 0px rgba(51, 51, 51, 0.04);
+  border: 1px solid #EEEEEE;
+  margin: 0 !important;
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  box-sizing: border-box;
+  padding: 26px 16px 16px;
+  font-size: 14px;
+  position: relative;
+  overflow: show;
+}
+
+li .title {
+  width: 147px;
+  height: 20px;
+  background: url(../../../../assets/images/renyuan-title.svg) no-repeat;
+  position: absolute;
+  top: -6px;
+  left: 50%;
+  transform: translateX(-50%);
+  text-align: center;
+  line-height: 20px;
+  color: #fff;
+}
+</style>
+
+<template>
+  <div class="role_manage">
+    <div class="search">
+      <div class="search_thing">
+        <div class="search_label">浜哄憳鍚嶇О锛�</div>
+        <div class="search_input"><el-input size="small" placeholder="璇疯緭鍏�" clearable v-model="entity.name"></el-input>
+        </div>
+      </div>
+      <div class="search_thing" style="padding-left: 30px;">
+        <el-button size="small" @click="refresh()">閲� 缃�</el-button>
+        <el-button size="small" type="primary"
+          @click="currentPage = 1, list = [], finishLoding = false, keyMap = {}, refreshTable()">鏌� 璇�</el-button>
+      </div>
+    </div>
+    <div class="table" v-loading="loading">
+      <scroll-pagination @load="refreshTable" :finishLoding="finishLoding" :list="list"
+        v-if="list.length > 0 || loading">
+        <ul class="card" style="margin-top: 10px;">
+          <li v-for="(m, i) in list" :key="i">
+            <el-image style="width: 80px;
+            height: 112px;" :src="javaApi + '/img/' + m.pictureUrl">
+              <div slot="error" class="image-error" style="width: 79px;
+            height: 110px;
+            display: flex;
+            align-items: center;
+            justify-content: center;
+            border: 1px solid #EEEEEE;">
+                <i class="el-icon-picture-outline" style="font-size:30px;color:#666666;"></i>
+              </div>
+            </el-image>
+            <el-image style="width: 195px;
+            height: 112px;" :src="javaApi + '/img/' + m.signatureUrl">
+              <div slot="error" class="image-error" style="width: 194px;
+            height: 110px;
+            display: flex;
+            align-items: center;
+            justify-content: center;
+            border: 1px solid #EEEEEE;">
+                <i class="el-icon-picture-outline" style="font-size:30px;color:#666666;"></i>
+              </div>
+            </el-image>
+            <div class="title">{{ m.name }}</div>
+          </li>
+        </ul>
+      </scroll-pagination>
+      <div v-if="list.length < 1 && !loading" style="color:#909399;font-size:14px;text-align: center;margin-top:200px">
+        鏆傛棤鏁版嵁
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import ScrollPagination from '@/components/index/scroll-paging.vue'
+import {
+  selectPersonnelOverview
+} from '@/api/cnas/personnel/personalOverview'
+export default {
+  components: {
+    ScrollPagination
+  },
+  data() {
+    return {
+      entity: {
+        name: null,
+        state: 1,
+        orderBy: { field: "id", order: "asc" }
+      },
+      list: [],
+      currentPage: 1, // 褰撳墠椤�
+      pageSize: 16, // 涓�椤�16鏉�
+      total: '',
+      loading: true, // 缁勪欢loading鐨勫睍绀�,榛樿涓簍rue
+      finishLoding: false, // 鍔犺浇瀹屾垚锛屾樉绀哄凡缁忔病鏈夋洿澶氫簡
+      keyMap: {}
+    }
+  },
+  created() {
+    this.keyMap = {};
+    this.currentPage = 1;
+    this.list = [];
+    this.refreshTable();
+  },
+  methods: {
+    refreshTable() {
+      const key = `_${this.currentPage}`
+      const value = this.keyMap[key]
+      // 濡傛灉value瀛樺湪锛岃〃绀虹紦瀛樻湁鍊硷紝閭d箞闃绘璇锋眰
+      if (value) {
+        return
+      }
+      // value涓嶅瓨鍦紝琛ㄧず绗竴娆¤姹�,璁剧疆鍗犱綅
+      this.keyMap[key] = 'temp'
+      if (this.currentPage == 1) {
+        this.loading = true
+      }
+      selectPersonnelOverview({
+        current: this.currentPage,
+        size: this.pageSize,
+        ...this.entity
+      }).then(res => {
+        if (res.code == 200) {
+          this.total = res.data.body.total
+          let list = res.data.body.records;
+          if (list.length == 0) {
+            this.finishLoding = true;
+          } else {
+            if (list.length < this.pageSize) {
+              this.finishLoding = true;
+            }
+            this.list = this.list.concat(list)
+            if (this.total == this.list.length) {
+              this.finishLoding = true;
+            }
+            this.currentPage++;
+          }
+        }
+        this.loading = false
+      })
+    },
+    refresh() {
+      this.keyMap = {};
+      this.currentPage = 1;
+      this.list = [];
+      this.finishLoding = false;
+      this.entity = {
+        name: null,
+        state: 1,
+        orderBy: { field: "id", order: "asc" }
+      };
+      this.refreshTable()
+    },
+    // 婊氬姩瑙﹀簳鍔犺浇
+    scrollFn() {
+      let clientHeight = document.documentElement.clientHeight - 18; //鍙鍖哄煙
+      let scrollHeight = document.body.scrollHeight; // 婊氬姩鏂囨。楂樺害
+      let scrollTop = parseInt(document.documentElement.scrollTop); // 宸叉粴鍔ㄧ殑楂樺害
+      let height = 300;
+      if (
+        scrollTop + clientHeight >= scrollHeight - height &&
+        scrollHeight != 0
+      ) {
+        if (!this.finishLoding && this.currentPage * this.pageSize < this.total) {
+          this.currentPage = this.currentPage + 1;
+          this.refreshTable();
+        }
+      } else {
+        return false;
+      }
+    },
+    throttle(fn, wait) {
+      // 灏佽鍑芥暟杩涜鑺傛祦
+      var timer = null;
+      return function () {
+        var context = this;
+        var args = arguments;
+        if (!timer) {
+          timer = setTimeout(function () {
+            fn.apply(context, args);
+            timer = null;
+          }, wait);
+        }
+      };
+    },
+  },
+  destroyed() {
+    window.removeEventListener("scroll", this.throttle(), false);
+  },
+}
+</script>
diff --git a/src/views/CNAS/personnel/personnelInfo/Department/components/Communicate/Add.vue b/src/views/CNAS/personnel/personnelInfo/Department/components/Communicate/Add.vue
new file mode 100644
index 0000000..d22914f
--- /dev/null
+++ b/src/views/CNAS/personnel/personnelInfo/Department/components/Communicate/Add.vue
@@ -0,0 +1,116 @@
+<template>
+    <div class="add">
+        <el-dialog :title="isEdit ? '缂栬緫闄勪欢璧勬枡' : '鏂板闄勪欢璧勬枡'" :visible.sync="dialogVisible" width="40%">
+            <el-form :model="form" label-width="80px" size="small">
+                <el-form-item label="娌熼�氫汉">
+                    <el-select v-model="form.userId" placeholder="璇烽�夋嫨" style="width: 100%" multiple>
+                        <el-option v-for="(item, index) in userList" :key="index" :label="item.name"
+                            :value="item.id"></el-option>
+                    </el-select>
+                </el-form-item>
+                <el-form-item label="娌熼�氭椂闂�">
+                    <el-date-picker v-model="form.communicationTime" type="datetime" value-format="yyyy-MM-dd HH:mm:ss"
+                        placeholder="璇烽�夋嫨鏃ユ湡鏃堕棿" style="width: 100%">
+                    </el-date-picker>
+                </el-form-item>
+                <el-form-item label="娌熼�氬湴鐐�">
+                    <el-input v-model="form.communicationPlace" placeholder="璇烽�夋嫨"></el-input>
+                </el-form-item>
+                <el-form-item label="娌熼�氬唴瀹�">
+                    <el-input v-model="form.communicationContent" placeholder="璇烽�夋嫨"></el-input>
+                </el-form-item>
+            </el-form>
+            <div slot="footer" class="foot">
+                <el-button @click="dialogVisible = false">鍙� 娑�</el-button>
+                <el-button type="primary" :loading="loading" @click="submitForm">纭� 瀹�</el-button>
+            </div>
+        </el-dialog>
+    </div>
+</template>
+<script>
+import {
+    selectUserList,
+    addOrUpdatePersonCommunicationAbility
+} from '@/api/cnas/personnel/personnelInfo.js'
+export default {
+    data() {
+        return {
+            isEdit: false,
+            dialogVisible: false,
+            form: {
+                id: undefined,
+                userId: [],
+                communicationTime: undefined,
+                communicationPlace: undefined,
+                communicationContent: undefined
+            },
+            loading: false,
+            userList: []
+        }
+    },
+    methods: {
+        /**
+         * @desc 鏄剧ず妯℃�佹
+         * @param {*} row
+         * @param {*} type
+         */
+        openDialog(row, type) {
+            this.getUserList()
+            this.dialogVisible = true
+            if (type) {
+                this.isEdit = true
+                this.form.id = row.id
+                this.form.userId = row.userId.split(',').map(m => Number(m))
+                this.form.communicationTime = row.communicationTime
+                this.form.communicationPlace = row.communicationPlace
+                this.form.communicationContent = row.communicationContent
+            } else {
+                this.isEdit = false
+                this.form.id = undefined
+                this.form.userId = []
+                this.form.communicationTime = undefined
+                this.form.communicationPlace = undefined
+                this.form.communicationContent = undefined
+            }
+        },
+        /**
+         * @desc 鑾峰彇鐢ㄦ埛淇℃伅
+         */
+        async getUserList() {
+            const { code, data } = await selectUserList()
+            if (code == 200) {
+                this.userList = data
+            }
+        },
+        /**
+         * @desc 鎻愪氦琛ㄥ崟
+         */
+        async submitForm() {
+            this.loading = true
+            const { code, data } = await addOrUpdatePersonCommunicationAbility({
+                id: this.form.id,
+                userId: this.form.userId.join(','),
+                communicationTime: this.form.communicationTime,
+                communicationPlace: this.form.communicationPlace,
+                communicationContent: this.form.communicationContent,
+            })
+            if (code == 200) {
+                this.$emit('submit')
+                this.dialogVisible = false
+            } else {
+                this.$message.error(this.isEdit ? '缂栬緫澶辫触' : '鏂板澶辫触')
+            }
+            this.loading = false
+        }
+    }
+}
+</script>
+<style scoped>
+.foot {
+    width: 100%;
+}
+
+.add>>>.el-dialog__footer {
+    padding-right: 20px;
+}
+</style>
diff --git a/src/views/CNAS/personnel/personnelInfo/Department/components/Communicate/index.vue b/src/views/CNAS/personnel/personnelInfo/Department/components/Communicate/index.vue
new file mode 100644
index 0000000..086b96b
--- /dev/null
+++ b/src/views/CNAS/personnel/personnelInfo/Department/components/Communicate/index.vue
@@ -0,0 +1,213 @@
+<template>
+    <div class="flex_column">
+        <TableCard :showForm="isDepartment" title="娌熼�氳褰�">
+            <template v-slot:form>
+                <div v-if="isDepartment" class="w100 items_center justify_between">
+                    <div></div>
+                    <div>
+                        <el-button size="small" type="primary" @click="openDialog">鏂板</el-button>
+                    </div>
+                </div>
+            </template>
+            <template v-slot:table>
+                <limsTable :column="columnData" :height="'calc(100vh - 21em)'" :table-data="tableData"
+                    :table-loading="loading" style="margin-top: 18px; padding: 0 15px;" :page="page"
+                    @pagination="pagination"></limsTable>
+            </template>
+        </TableCard>
+        <Add ref="communicateModal" @submit="getTableData"></Add>
+    </div>
+</template>
+<script>
+import TableCard from '@/components/TableCard/index.vue';
+import limsTable from "@/components/Table/lims-table.vue";
+import Add from "./Add.vue"
+import {
+    personPersonCommunicationAbilityPage,
+    deletePersonCommunicationAbility,
+    exportPersonCommunicationAbility
+} from '@/api/cnas/personnel/personnelInfo.js'
+
+export default {
+    components: {
+        TableCard,
+        limsTable,
+        Add
+    },
+    props: {
+        departId: {
+            type: Number,
+            default: () => {
+                return null;
+            }
+        },
+        isDepartment: {
+            type: Boolean,
+            default: false
+        }
+    },
+    data() {
+        return {
+            // departId: 0,
+            columnData: [
+                {
+                    label: '搴忓彿',
+                    prop: 'id'
+                }, {
+                    label: '娌熼�氫汉',
+                    prop: 'userName'
+                }, {
+                    label: '娌熼�氭椂闂�',
+                    prop: 'communicationTime'
+                }, {
+                    label: '娌熼�氬湴鐐�',
+                    prop: 'communicationPlace'
+                }, {
+                    label: '娌熼�氬唴瀹�',
+                    prop: 'communicationContent'
+                }, {
+                    label: '鎿嶄綔',
+                    dataType: 'action',
+                    operation: [
+                        {
+                            name: '缂栬緫',
+                            type: 'text',
+                            clickFun: (row) => {
+                                this.openDialog(row, true)
+                            }
+                        }, {
+                            name: '瀵煎嚭',
+                            type: 'text',
+                            clickFun: (row) => {
+                                this.handleDown(row)
+                            }
+                        }, {
+                            name: '鍒犻櫎',
+                            type: 'text',
+                            color: '#f56c6c',
+                            clickFun: (row) => {
+                                this.delPerson(row.id)
+                            }
+                        }
+                    ]
+                },
+            ],
+            tableData: [],
+            page: {
+                current: 1,
+                pageSize: 20,
+                total: 0
+            },
+            loading: false
+        }
+    },
+    mounted() {
+        this.getTableData()
+    },
+    methods: {
+        openDialog(row, type = false) {
+            this.$refs.communicateModal.openDialog(row, type)
+        },
+        async getTableData() {
+            this.loading = true
+            const params = this.isDepartment ? {
+                departLimsId: this.departId,
+                current: this.page.current,
+                size: this.page.pageSize
+            } : {
+                userId: this.departId,
+                current: this.page.current,
+                size: this.page.pageSize
+            }
+            const { code, data } = await personPersonCommunicationAbilityPage(params)
+            if (code == 200) {
+                this.page.total = data.total
+                this.tableData = data.records
+                this.loading = false
+            }
+        },
+        pagination({ page, limit }) {
+            this.page.current = page;
+            this.page.size = limit;
+            this.getTableData();
+        },
+        /**
+         * @desc 鑾峰彇璁惧id
+         */
+        getDepart(id) {
+            this.departId = id
+            this.getTableData()
+        },
+        /**
+         * @desc 鍒犻櫎娌熼�氳褰�
+         */
+        delPerson(id) {
+            this.$confirm('姝ゆ搷浣滃皢姘镐箙鍒犻櫎璇ユ枃浠�, 鏄惁缁х画?', '鎻愮ず', {
+                confirmButtonText: '纭畾',
+                cancelButtonText: '鍙栨秷',
+                type: 'warning'
+            }).then(async () => {
+                let formData = new FormData()
+                formData.append('id', id)
+                const { code } = await deletePersonCommunicationAbility(formData)
+                if (code == 200) {
+                    this.$message({
+                        type: 'success',
+                        message: '鍒犻櫎鎴愬姛!'
+                    });
+                    this.getTableData()
+                }
+            })
+        },
+        async handleDown(row) {
+            exportPersonCommunicationAbility({ id: row.id }).then(res => {
+                if (res.code == 201) {
+                    this.$message.error(res.message)
+                    return
+                }
+                const blob = new Blob([res], { type: 'application/octet-stream' });
+                this.$download.saveAs(blob, row.userName + '-娌熼�氳褰�' + '.docx')
+            })
+        }
+    },
+    watch: {
+        departId: {
+            handler(newId, oldId) {
+                if (newId) {
+                    this.getTableData();
+                }
+            }
+        }
+    }
+}
+</script>
+<style scoped>
+.flex_column {
+    display: flex;
+    flex-direction: column;
+    justify-content: space-between;
+}
+
+.w100 {
+    width: 100%;
+}
+
+
+.items_center {
+    display: flex;
+    align-items: center;
+}
+
+.justify_between {
+    justify-content: space-between
+}
+
+.date_box {
+    margin: 0 5px;
+}
+
+.search {
+    width: 150px;
+    padding: 0 16px;
+}
+</style>
diff --git a/src/views/CNAS/personnel/personnelInfo/Department/components/JobResponsibilities/index.vue b/src/views/CNAS/personnel/personnelInfo/Department/components/JobResponsibilities/index.vue
new file mode 100644
index 0000000..ef784f1
--- /dev/null
+++ b/src/views/CNAS/personnel/personnelInfo/Department/components/JobResponsibilities/index.vue
@@ -0,0 +1,364 @@
+<!-- 宀椾綅鑱岃矗 -->
+<template>
+  <div class="view">
+    <div style="text-align: left; margin-bottom: 15px;padding: 0 10px">
+      <label>鍛樺伐锛�</label>
+      <el-input v-model="userName" clearable placeholder="璇疯緭鍏ュ憳宸�" size="small" style="width: 20vh;"></el-input>
+      <el-button size="small" type="primary" @click="refreshTable">鏌ヨ</el-button>
+      <div v-if="isDepartment" style="float: right;">
+        <el-button size="small" type="primary" @click="addPost">鏂板</el-button>
+        <!--        <el-button size="small" type="primary">瀵煎嚭excel</el-button>-->
+      </div>
+    </div>
+    <div class="table" style="padding: 0 10px">
+      <el-table :data="tableData" height="70vh" style="width: 100%">
+        <el-table-column label="搴忓彿" type="index" width="60"></el-table-column>
+        <el-table-column label="鍛樺伐缂栧彿" min-width="120" prop="account"></el-table-column>
+        <el-table-column label="宀椾綅鍚嶇О" min-width="180" prop="postName"></el-table-column>
+        <el-table-column label="鎵�灞為儴闂�" min-width="180" prop="departLimsName"></el-table-column>
+        <el-table-column label="宸ヤ綔鐩爣" min-width="180" prop="jobObjective"></el-table-column>
+        <el-table-column label="宀椾綅鑱岃矗" min-width="180" prop="jobResponsibilities"></el-table-column>
+        <el-table-column label="浠昏亴浜�" min-width="180" prop="incumbentName"></el-table-column>
+        <el-table-column label="浠昏亴浜哄鏍告棩鏈�" min-width="180" prop="incumbentDate"></el-table-column>
+        <el-table-column label="涓荤" min-width="180" prop="supervisorName"></el-table-column>
+        <el-table-column label="涓荤瀹℃牳鏃ユ湡" min-width="180" prop="supervisorDate"></el-table-column>
+        <el-table-column fixed="right" label="鎿嶄綔" width="140">
+          <template v-slot="scope">
+            <el-button v-if="!isDepartment || scope.row.currentState === '鍏抽棴'" size="small" type="text"
+              @click="handleViewClick(scope.row, 'view')">鏌ョ湅
+            </el-button>
+            <el-button v-if="isDepartment && scope.row.currentState !== '鍏抽棴'" size="small" type="text"
+              @click="handleViewClick(scope.row, 'edit')">缂栬緫
+            </el-button>
+            <el-button size="small" type="text" @click="downLoadPost(scope.row)">瀵煎嚭</el-button>
+            <el-button v-if="isDepartment" size="small" type="text" @click="deletePost(scope.row)">鍒犻櫎</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+      <el-pagination :current-page="1" :page-size="search.size" :page-sizes="[10, 20, 30, 50, 100]"
+        :total="search.total" layout="->,total, sizes, prev, pager, next, jumper" @size-change="handleSizeChange"
+        @current-change="handleCurrentChange">
+      </el-pagination>
+    </div>
+    <!-- 鏂板宀椾綅鑱岃矗 -->
+    <el-dialog :close-on-click-modal="false" :close-on-press-escape="false" :visible.sync="dialogVisible" title="鏂板宀椾綅鑱岃矗"
+      width="50%" @close="resetForm">
+      <el-steps :active="currentStep" align-center finish-status="success">
+        <el-step v-for="(v, i) in steps" :key="i" :title="v" style="cursor:pointer"
+          @click.native="choiceStep(i)"></el-step>
+      </el-steps>
+      <el-form ref="form" :model="form" :rules="rules" label-width="130px">
+        <div>
+          <el-card style="margin-top: 1em; height: 40vh; overflow-y: scroll;">
+            <!-- 鏂板璁惧浜嬭褰曞崱鐗� -->
+            <el-row>
+              <el-col :span="12">
+                <el-form-item label="宀椾綅鍚嶇О锛�" prop="postName">
+                  <el-input v-model="form.postName" :disabled="currentStep !== 0 || operationType === 'view'"
+                    size="small"></el-input>
+                </el-form-item>
+              </el-col>
+              <el-col :span="24">
+                <el-form-item label="宸ヤ綔鐩爣锛�" prop="jobObjective">
+                  <el-input v-model="form.jobObjective" :disabled="currentStep !== 0 || operationType === 'view'"
+                    size="small" type="textarea"></el-input>
+                </el-form-item>
+              </el-col>
+              <el-col :span="24">
+                <el-form-item label="宀椾綅鑱岃矗锛�" prop="jobResponsibilities">
+                  <el-input v-model="form.jobResponsibilities" :disabled="currentStep !== 0 || operationType === 'view'"
+                    size="small" type="textarea"></el-input>
+                </el-form-item>
+              </el-col>
+              <el-col v-if="currentStep === 0 || operationType === 'view'" :span="12">
+                <el-form-item :rules="[{ required: currentStep === 0, message: '璇烽�夋嫨浠昏亴浜�', trigger: 'change' }]"
+                  label="浠昏亴浜猴細" prop="incumbentId">
+                  <el-select v-model="form.incumbentId" :disabled="operationType === 'view'" clearable filterable
+                    placeholder="璇烽�夋嫨浠昏亴浜�" size="small" style="width: 100%;">
+                    <el-option v-for="item in responsibleOptions" :key="item.id" :label="item.name" :value="item.id">
+                    </el-option>
+                  </el-select>
+                </el-form-item>
+              </el-col>
+              <el-col v-if="currentStep === 1 || operationType === 'view'" :span="12">
+                <el-form-item :rules="[{ required: currentStep === 1, message: '璇烽�夋嫨涓荤', trigger: 'blur' }]" label="涓荤锛�"
+                  prop="supervisorId">
+                  <el-select v-model="form.supervisorId" :disabled="currentStep !== 1 || operationType === 'view'"
+                    clearable filterable placeholder="璇烽�夋嫨涓荤" size="small" style="width: 100%;">
+                    <el-option v-for="item in responsibleOptions" :key="item.id" :label="item.name" :value="item.id">
+                    </el-option>
+                  </el-select>
+                </el-form-item>
+              </el-col>
+            </el-row>
+          </el-card>
+          <el-row style="margin-top: 1em;">
+            <el-col :span="4">
+              鎿嶄綔浜猴細{{ form.submitPerson }}
+            </el-col>
+            <el-col :span="6">
+              鏃ユ湡锛歿{ form.submitDate }}
+            </el-col>
+          </el-row>
+        </div>
+      </el-form>
+      <span slot="footer" class="dialog-footer">
+        <el-button v-if="currentStep !== 0 && currentStep !== 3" @click="submitForm('3reject')">椹冲洖</el-button>
+        <el-button v-if="currentStep === 0" @click="submitForm('2save')">淇濆瓨</el-button>
+        <el-button v-if="currentStep !== 3" type="primary" @click="submitForm('1submit')">{{ currentStep === 0 ? '鎻愪氦' :
+          '閫氳繃'
+          }}</el-button>
+      </span>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { dateFormat } from '@/utils/date';
+import {
+  selectUserList,
+  personJobResponsibilitiesSelect,
+  personJobResponsibilitiesSave,
+  exportPersonJobResponsibilities,
+  personJobResponsibilitiesDelete,
+} from '@/api/cnas/personnel/personnelInfo.js'
+export default {
+  data() {
+    return {
+      userName: '',
+      tableData: [],
+      responsibleOptions: [],
+      search: {
+        size: 20,
+        current: 1,
+        total: 0
+      },
+      dialogVisible: false,
+      currentStep: 0, // 姝ラ鏉℃樉绀虹鍑犳
+      currentStepClick: 0, // 鐐瑰嚮姝ラ鏉″彉鍖�
+      operationType: '',
+      steps: ['鎻愪氦', '浠昏亴浜虹‘璁�', '涓荤纭'],
+      form: {
+        postName: '', // 宀椾綅鍚嶇О
+        jobObjective: '', // 宸ヤ綔鐩爣
+        jobResponsibilities: '', // 宀椾綅鑱岃矗
+        incumbentId: '', // 浠昏亴浜�
+        supervisorId: '' // 涓荤
+      },
+      rules: {
+        postName: [{ required: true, message: '璇疯緭鍏ュ矖浣嶅悕绉�', trigger: 'blur' }],
+        jobObjective: [{ required: true, message: '璇疯緭鍏ュ伐浣滅洰鏍�', trigger: 'blur' }],
+        jobResponsibilities: [{ required: true, message: '璇疯緭鍏ュ矖浣嶈亴璐�', trigger: 'blur' }],
+        incumbentId: [{ required: true, message: '璇烽�夋嫨浠昏亴浜�', trigger: 'change' }],
+        supervisorId: [{ required: true, message: '璇烽�夋嫨涓荤', trigger: 'change' }]
+      }
+      // departId: 0
+    };
+  },
+  props: {
+    departId: {
+      type: Number,
+      default: () => {
+        return null;
+      }
+    },
+    isDepartment: {
+      type: Boolean,
+      default: false
+    }
+  },
+  mounted() {
+    this.getPostList(this.departId);
+  },
+  methods: {
+    addPost() {
+      this.dialogVisible = true;
+      this.form = {
+        postName: '', // 宀椾綅鍚嶇О
+        jobObjective: '', // 宸ヤ綔鐩爣
+        jobResponsibilities: '', // 宀椾綅鑱岃矗
+        incumbentId: '', // 浠昏亴浜�
+        supervisorId: '', // 鎿嶄綔浜�
+        submitPerson: '', // 涓荤
+        submitDate: '', // 鏃ユ湡
+        currentStep: 0 // 鏃ユ湡
+      };
+      this.currentStep = 0;
+      this.getUserList();
+    },
+    // 鏌ヨ鍒楄〃淇℃伅
+    getPostList(userId) {
+      this.search.userId = userId;
+      const name = this.isDepartment ? 'departmentId' : 'userId';
+      personJobResponsibilitiesSelect({
+        userName: this.userName,
+        [name]: this.search.userId,
+        size: this.search.size,
+        current: this.search.current
+      }).then(res => {
+        if (res.code === 201) return;
+        this.tableData = res.data.records;
+        this.search.total = res.data.total;
+      });
+    },
+    //鎻愪氦琛ㄥ崟
+    async submitForm(saveState) {
+      this.$refs.form.validate((valid) => {
+        if (valid === true || saveState !== '1submit') {
+          // 缁欏綋鍓嶇幆鑺傝缃垱寤轰汉涓庢椂闂�
+          let user = JSON.parse(localStorage.getItem('user'));
+          const dateTime = dateFormat(new Date());
+          // 鑾峰彇褰撳墠鐜妭鎿嶄綔浜轰笌鏃ユ湡
+          switch (this.currentStep) {
+            case 0:
+              this.form.submittingOperator = user.name;
+              this.form.submittingDate = dateTime;
+              break;
+            case 1:
+              this.form.incumbentOperator = user.name;
+              this.form.incumbentDate = dateTime;
+              break;
+            case 2:
+              this.form.supervisorOperator = user.name;
+              this.form.supervisorDate = dateTime;
+              break;
+            default:
+              break;
+          }
+          // 鑾峰彇褰撳墠鐜妭璐熻矗浜�
+          switch (saveState === '3reject' ? this.currentStep - 1 : this.currentStep) {
+            case 1:
+              this.form.currentResponsible = this.form.submittingOperator;
+              break;
+            case 2:
+              this.form.currentResponsible = this.form.incumbentOperator;
+              break;
+            default:
+              break;
+          }
+          let currentStepAction;
+          // 璁剧疆璇ユ搷浣滃垽鏂槸鍚︿负鎻愪氦锛屼繚瀛橈紝椹冲洖锛岄�氳繃
+          switch (saveState) {
+            // 鎻愪氦锛岄�氳繃
+            case '1submit':
+              currentStepAction = this.currentStep + 1;
+              break;
+            // 淇濆瓨
+            case '2save':
+              currentStepAction = this.currentStep;
+              break;
+            // 椹冲洖
+            case '3reject':
+              currentStepAction = this.currentStep - 1;
+              break;
+            default:
+              break;
+          }
+          // 鑾峰彇褰撳墠鐘舵��
+          this.form.currentState = currentStepAction === 3 ? '鍏抽棴' : this.steps[currentStepAction];
+          personJobResponsibilitiesSave(this.form).then(res => {
+            if (res.code == 200) {
+              this.$message.success('鎻愪氦鎴愬姛');
+              this.getPostList(this.departId);
+              this.dialogVisible = false;
+            }
+          });
+        } else {
+          let step = this.steps[this.currentStep];
+          this.$message.warning(step + '  娴佺▼涓湁蹇呭~椤规湭濉紒');
+        }
+      });
+    },
+    // 缂栬緫
+    handleViewClick(row, type) {
+      this.operationType = type;
+      this.getUserList();
+      row.incumbentId = Number(row.incumbentId);
+      this.form = { ...row };
+      switch (row.currentState) {
+        case '鎻愪氦':
+          this.currentStep = 0;
+          break;
+        case '浠昏亴浜虹‘璁�':
+          this.currentStep = 1;
+          this.form.submitPerson = row.submittingOperator;
+          this.form.submitDate = row.submittingDate;
+          break;
+        case '涓荤纭':
+          this.currentStep = 2;
+          this.form.submitPerson = row.incumbentOperator;
+          this.form.submitDate = row.incumbentDate;
+          break;
+        case '鍏抽棴':
+          this.currentStep = 3;
+          this.form.submitPerson = row.supervisorOperator;
+          this.form.submitDate = row.supervisorDate;
+          break;
+        default:
+          break;
+      }
+      this.form.currentState = this.currentStep;
+      this.currentStepClick = this.currentStep === 3 ? 0 : this.currentStep
+      console.log('this.form---', this.form);
+      this.dialogVisible = true;
+    },
+    // 涓嬭浇宀椾綅鑱岃矗
+    downLoadPost(row) {
+      exportPersonJobResponsibilities({ id: row.id }).then(res => {
+        const blob = new Blob([res], { type: 'application/octet-stream' });
+        this.$download.saveAs(blob, row.incumbentName + '-宀椾綅鑱岃矗' + '.docx')
+      })
+    },
+    // 鍒犻櫎宀椾綅鑱岃矗
+    deletePost(row) {
+      this.$confirm('姝ゆ搷浣滃皢姘镐箙鍒犻櫎姝ゆ暟鎹�, 鏄惁缁х画?', '鎻愮ず', {
+        confirmButtonText: '纭畾',
+        cancelButtonText: '鍙栨秷',
+        type: 'warning'
+      }).then(() => {
+        personJobResponsibilitiesDelete({ id: row.id }).then(res => {
+          if (res.code == 200) {
+            this.$message.success('鍒犻櫎鎴愬姛');
+            this.getPostList(this.departId);
+          }
+        });
+      }).catch(() => {
+        this.$message.error('鍒犻櫎澶辫触');
+      });
+    },
+    resetForm() {
+      this.$refs.form.resetFields();
+    },
+    refreshTable() {
+      this.getPostList(this.departId);
+    },
+    // 鑾峰彇璐熻矗浜轰俊鎭帴鍙�
+    getUserList() {
+      selectUserList().then(res => {
+        if (res.code == 200) {
+          this.responsibleOptions = res.data;
+        }
+      });
+    },
+    choiceStep(index) {
+      this.currentStepClick = index;
+    },
+    handleSizeChange(val) {
+      this.search.size = val;
+      this.getPostList(this.departId);
+    },
+    handleCurrentChange(val) {
+      this.search.current = val;
+      this.getPostList(this.departId);
+    }
+  },
+  watch: {
+    departId: {
+      handler(newId, oldId) {
+        this.getPostList(newId);
+      }
+    }
+  }
+};
+</script>
+<style scoped></style>
diff --git a/src/views/CNAS/personnel/personnelInfo/Department/components/Mandate/Add.vue b/src/views/CNAS/personnel/personnelInfo/Department/components/Mandate/Add.vue
new file mode 100644
index 0000000..8741543
--- /dev/null
+++ b/src/views/CNAS/personnel/personnelInfo/Department/components/Mandate/Add.vue
@@ -0,0 +1,198 @@
+<template>
+    <div class="add">
+        <el-dialog :title="isEdit ? '缂栬緫闄勪欢璧勬枡' : '鏂板闄勪欢璧勬枡'" :visible.sync="dialogVisible" width="50%">
+            <el-form ref="ruleForm" :rules="rules" :model="form" label-width="100px" size="medium">
+                <el-form-item label="璇佷功缂栧彿" prop="certificateNumber">
+                    <el-input v-model="form.certificateNumber" placeholder="璇疯緭鍏�" style="width: 100%">
+                    </el-input>
+                </el-form-item>
+                <el-form-item label="琚换鑱屼汉鍛�" prop="userId">
+                    <el-select v-model="form.userId" placeholder="璇烽�夋嫨">
+                        <el-option v-for="(item, index) in userList" :key="index" :label="item.name"
+                            :value="item.id"></el-option>
+                    </el-select>
+                </el-form-item>
+                <el-form-item label="浠昏亴宀椾綅" prop="post">
+                    <el-input v-model="form.post" placeholder="璇疯緭鍏�"></el-input>
+                </el-form-item>
+                <el-form-item label="鐞嗚鑰冭瘯鎴愮哗" prop="num1">
+                    <el-input v-model="form.num1" placeholder="璇疯緭鍏�"></el-input>
+                </el-form-item>
+                <el-form-item label="鎿嶄綔鎶�鑳借�冭瘯鎴愮哗" prop="num2">
+                    <el-input v-model="form.num2" placeholder="璇疯緭鍏�"></el-input>
+                </el-form-item>
+                <el-form-item label="鎿嶄綔绫诲瀷" prop="operationType">
+                    <el-input v-model="form.operationType" placeholder="璇烽�夋嫨"></el-input>
+                </el-form-item>
+                <el-row>
+                    <el-col :span="20">
+                        <el-form-item label="涓婂矖璇佷功">
+                            <el-input v-model="form.systemFileName" size="small" disabled>
+                                <el-button slot="append" icon="el-icon-delete-solid"
+                                    @click="deleteFile(form.systemFileName)"></el-button>
+                            </el-input>
+                        </el-form-item>
+                    </el-col>
+                    <el-col :span="4">
+                        <el-upload ref="upload" style="float: left; margin: 0 12px 0 20px;" :action="action"
+                            :show-file-list="false" :on-success="onSuccess" :headers="uploadHeader">
+                            <el-button class="uploadFile" slot="trigger" size="small" type="primary">娴忚</el-button>
+                        </el-upload>
+                    </el-col>
+                </el-row>
+                <el-form-item label="澶囨敞">
+                    <el-input v-model="form.remarks" placeholder="璇烽�夋嫨"></el-input>
+                </el-form-item>
+            </el-form>
+            <div slot="footer" class="foot">
+                <el-button @click="dialogVisible = false">鍙� 娑�</el-button>
+                <el-button type="primary" :loading="loading" @click="submitForm">纭� 瀹�</el-button>
+            </div>
+        </el-dialog>
+    </div>
+</template>
+<script>
+import {
+    addOrUpdatePersonPostAuthorizationRecord,
+    selectUserList,
+    deleteCNASFile
+} from '@/api/cnas/personnel/personnelInfo.js'
+export default {
+    data() {
+        return {
+            isEdit: false,
+            dialogVisible: false,
+            form: {
+                id: undefined,
+                certificateNumber: undefined,
+                userId: undefined,
+                post: undefined,
+                operationType: undefined,
+                fileList: [],
+                fileName: undefined,
+                systemFileName: undefined,
+                remarks: undefined,
+                num2: undefined,
+                num1: undefined
+            },
+            rules: {
+                certificateNumber: [{ required: true, message: '璇疯緭鍏ヨ瘉涔︾紪鍙�', trigger: 'blur' }],
+                userId: [{ required: true, message: '璇烽�夋嫨琚换鑱屼汉鍛�', trigger: 'change' }],
+                post: [{ required: true, message: '浠昏亴宀椾綅', trigger: 'blur' }],
+                operationType: [{ required: true, message: '鎿嶄綔绫诲瀷', trigger: 'blur' }],
+
+            },
+            loading: false,
+            userList: []
+        }
+    },
+    mounted() {
+
+    },
+    computed: {
+        action() {
+            return this.javaApi + '/personBasicInfo/saveCNASFile'
+        }
+    },
+    methods: {
+        async onSuccess(response, file, fileList) {
+            this.$set(this.form, "systemFileName", response.data)
+        },
+        deleteFile(fileName) {
+            deleteCNASFile({ fileName }).then(res => {
+                this.$message.success('鍒犻櫎鎴愬姛锛�')
+                this.$set(this.form, "systemFileName", null)
+            })
+        },
+        async openDialog(row, type) {
+            await this.getUserList()
+            this.dialogVisible = true
+            if (type) {
+                this.isEdit = true
+                this.form.id = row.id
+                this.form.certificateNumber = row.certificateNumber
+                this.form.userId = Number(row.userId)
+                this.form.post = row.post
+                this.form.operationType = row.operationType
+                this.form.systemFileName = row.systemFileName
+                this.form.remarks = row.remarks
+                this.form.num1 = row.num1
+                this.form.num2 = row.num2
+            } else {
+                this.isEdit = false
+                this.form.id = undefined
+                this.form.certificateNumber = undefined
+                this.form.userId = undefined
+                this.form.post = undefined
+                this.form.operationType = undefined
+                this.form.fileList = []
+                this.form.fileName = undefined
+                this.form.systemFileName = undefined
+                this.form.remarks = undefined
+                this.form.num1 = undefined
+                this.form.num2 = undefined
+            }
+        },
+        closeDialog() {
+            this.dialogVisible = false
+        },
+        /**
+         * @desc 鑾峰彇鐢ㄦ埛淇℃伅
+         */
+        async getUserList() {
+            const { code, data } = await selectUserList()
+            if (code == 200) {
+                this.userList = data
+            }
+        },
+        /**
+         * @desc 鎻愪氦琛ㄥ崟
+         */
+        submitForm() {
+            this.$refs.ruleForm.validate(async (valid) => {
+                if (valid) {
+                    await this.submitFormData()
+                }
+            })
+        },
+        /**
+         * @desc 涓婁紶鏂囦欢
+         */
+        beforeUpload(file) {
+            this.form.fileList = [file]
+            this.form.fileName = file.name
+        },
+        /**
+         * @desc 鎻愪氦form琛ㄥ崟
+         */
+        async submitFormData() {
+            this.loading = true
+            const { code, data } = await addOrUpdatePersonPostAuthorizationRecord({
+                id: this.form.id,
+                certificateNumber: this.form.certificateNumber,
+                userId: this.form.userId,
+                post: this.form.post,
+                operationType: this.form.operationType,
+                systemFileName: this.form.systemFileName,
+                remarks: this.form.remarks,
+                num1: this.form.num1,
+                num2: this.form.num2
+            })
+            if (code == 200) {
+                this.closeDialog()
+                this.$emit('refresh')
+            }
+            this.loading = false
+        }
+    }
+}
+</script>
+<style scoped>
+.foot {
+    width: 100%;
+}
+
+.add>>>.el-dialog__footer {
+    padding-right: 20px;
+}
+</style>
diff --git a/src/views/CNAS/personnel/personnelInfo/Department/components/Mandate/index.vue b/src/views/CNAS/personnel/personnelInfo/Department/components/Mandate/index.vue
new file mode 100644
index 0000000..d6fa9a2
--- /dev/null
+++ b/src/views/CNAS/personnel/personnelInfo/Department/components/Mandate/index.vue
@@ -0,0 +1,228 @@
+<template>
+    <div class="flex_column">
+        <TableCard :showForm="isDepartment" title="浠昏亴鎺堟潈璁板綍">
+            <template v-slot:form>
+                <div v-if="isDepartment" class="w100 items_center justify_between">
+                    <div></div>
+                    <div>
+                        <el-button size="small" type="primary" @click="openDialog">鏂板</el-button>
+                    </div>
+                </div>
+            </template>
+            <template v-slot:table>
+                <limsTable :column="columnData" :height="'calc(100vh - 21em)'" :table-data="tableData"
+                    :table-loading="loading" style="margin-top: 18px; padding: 0 15px;" :page="page"
+                    @pagination="pagination"></limsTable>
+            </template>
+        </TableCard>
+        <Add ref="mandateModal" @refresh="getTableData"></Add>
+    </div>
+</template>
+<script>
+import TableCard from "@/components/TableCard/index.vue";
+import limsTable from "@/components/Table/lims-table.vue";
+import Add from "./Add.vue"
+import {
+    PersonPostAuthorizationRecordPage,
+    deletePersonPostAuthorizationRecord,
+    exportPersonPostAuthorizationRecord
+} from '@/api/cnas/personnel/personnelInfo.js'
+import { nextTick } from "vue";
+
+export default {
+    components: {
+        TableCard,
+        limsTable,
+        Add
+    },
+    props: {
+        departId: {
+            type: Number,
+            default: () => {
+                return null;
+            }
+        },
+        isDepartment: {
+            type: Boolean,
+            default: false
+        }
+    },
+    data() {
+        return {
+            // departId: 0,
+            columnData: [
+                {
+                    label: '搴忓彿',
+                    prop: 'id'
+                }, {
+                    label: '璇佷功缂栧彿',
+                    prop: 'certificateNumber'
+                }, {
+                    label: '琚换鑱屼汉鍛�',
+                    prop: 'userName'
+                }, {
+                    label: '浠昏亴宀椾綅',
+                    prop: 'post'
+                }, {
+                    label: '鐞嗚鑰冭瘯鎴愮哗',
+                    prop: 'num1'
+                }, {
+                    label: '鎿嶄綔鎶�鑳借�冭瘯鎴愮哗',
+                    prop: 'num2'
+                }, {
+                    label: '鎿嶄綔鏃堕棿',
+                    prop: 'updateTime'
+                }, {
+                    label: '澶囨敞',
+                    prop: 'remarks',
+                    width: 300
+                }, {
+                    label: '鎿嶄綔',
+                    dataType: 'action',
+                    width: 160,
+                    operation: [
+                        {
+                            name: '缂栬緫',
+                            type: 'text',
+                            clickFun: (row) => {
+                                this.openDialog(row, true)
+                            }
+                        }, {
+                            name: '涓嬭浇',
+                            type: 'text',
+                            clickFun: (row) => {
+                                this.handleDown(row)
+                            }
+                        }, {
+                            name: '鍒犻櫎',
+                            type: 'text',
+                            color: '#f56c6c',
+                            clickFun: (row) => {
+                                this.deleteNotify(row.id)
+                            }
+                        }
+                    ]
+                },
+            ],
+            tableData: [],
+            page: {
+                current: 1,
+                pageSize: 20,
+                total: 0
+            },
+            loading: false
+        }
+    },
+    mounted() {
+        this.getTableData()
+        console.log(this.departId)
+    },
+    methods: {
+        openDialog(row, type = false) {
+            this.$refs.mandateModal.openDialog(row, type)
+        },
+        /**
+         * @desc 鏌ヨ琛ㄦ牸鏁版嵁
+         */
+        async getTableData() {
+            this.loading = true
+            await nextTick()
+            const params = this.isDepartment ? {
+                departLimsId: this.departId,
+                current: this.page.current,
+                size: this.page.pageSize
+            } : {
+                userId: this.departId,
+                current: this.page.current,
+                size: this.page.pageSize
+            }
+            const { code, data } = await PersonPostAuthorizationRecordPage(params)
+            if (code == 200) {
+                this.page.total = data.total
+                this.tableData = data.records
+                this.loading = false
+            }
+        },
+        /**
+         * @desc 鍒嗛〉
+         */
+        pagination({ page, limit }) {
+            this.page.current = page;
+            this.page.size = limit;
+            this.getTableData();
+        },
+        /**
+         * @desc 鍒犻櫎浠昏亴璁板綍
+         */
+        deleteNotify(id) {
+            this.$confirm('姝ゆ搷浣滃皢姘镐箙鍒犻櫎璇ユ枃浠�, 鏄惁缁х画?', '鎻愮ず', {
+                confirmButtonText: '纭畾',
+                cancelButtonText: '鍙栨秷',
+                type: 'warning'
+            }).then(() => {
+                this.delMandate(id)
+            })
+        },
+        /**
+         * @desc api鍒犻櫎
+         */
+        async delMandate(id) {
+            const formData = new FormData()
+            formData.append('id', id)
+            const { code, data } = await deletePersonPostAuthorizationRecord(formData)
+            if (code == 200) {
+                this.$message({ message: '鍒犻櫎鎴愬姛', type: 'success' })
+                this.getTableData()
+            } else {
+                this.$message({ message: '鍒犻櫎澶辫触', type: 'error' })
+            }
+        },
+        /**
+         * @desc 鑾峰彇璁惧id
+         */
+        getDepart(id) {
+            this.departId = id
+            this.getTableData()
+        },
+        handleDown(row) {
+            exportPersonPostAuthorizationRecord({ id: row.id }).then(res => {
+                if (res.code == 201) {
+                    this.$message.error(res.message)
+                    return
+                }
+                const blob = new Blob([res], { type: 'application/octet-stream' });
+                this.$download.saveAs(blob, '浠昏亴鎺堟潈-' + row.certificateNumber + '-' + row.post + '.docx')
+            })
+        }
+    },
+    //   watch: {
+    //     departId: {
+    //       handler(newId, oldId) {
+    //         if (newId) {
+    //           this.getTableData();
+    //         }
+    //       }
+    //     }
+    //   }
+}
+</script>
+<style scoped>
+.flex_column {
+    display: flex;
+    flex-direction: column;
+    justify-content: space-between;
+}
+
+.w100 {
+    width: 100%;
+}
+
+.items_center {
+    display: flex;
+    align-items: center;
+}
+
+.justify_between {
+    justify-content: space-between
+}
+</style>
diff --git a/src/views/CNAS/personnel/personnelInfo/Department/components/PersonnelCapacity/index.vue b/src/views/CNAS/personnel/personnelInfo/Department/components/PersonnelCapacity/index.vue
new file mode 100644
index 0000000..49dd10d
--- /dev/null
+++ b/src/views/CNAS/personnel/personnelInfo/Department/components/PersonnelCapacity/index.vue
@@ -0,0 +1,567 @@
+<!-- 浜哄憳鑳藉姏 -->
+<template>
+  <div>
+    <div style="text-align: left; margin-bottom: 15px;padding: 0 16px">
+      <label>濮撳悕</label>
+      <el-input v-model="userName" placeholder="璇疯緭鍏ュ鍚�" size="small" style="width: 20vh;"></el-input>
+      <el-button size="small" type="primary" @click="refreshTable">鏌ヨ</el-button>
+      <div v-if="isDepartment" style="float: right;">
+        <el-button size="small" type="primary" @click="addAppointPost('add')">鏂板</el-button>
+      </div>
+    </div>
+    <div class="table">
+      <TableCard :showForm="false" :showTitle="false">
+        <template v-slot:table>
+          <limsTable :column="yearColumnData" :height="'calc(100vh - 20em)'" :table-data="tableData"
+            :table-loading="yearLoading" style="padding: 0 15px;margin-bottom: 16px" :page="search"
+            @pagination="pagination">
+            <div slot="jobResponsibilities" slot-scope="scope">
+              <div v-html="changeLine(scope.row.responsibilities)"></div>
+            </div>
+            <div slot="placeWorkSlot" slot-scope="scope">
+              <div v-html="changeLine(scope.row.placeWork)"></div>
+            </div>
+          </limsTable>
+        </template>
+      </TableCard>
+    </div>
+    <!--鏂板鑳藉姏璁ゅ畾寮规-->
+    <el-dialog :close-on-click-modal="false" :close-on-press-escape="false" :title="title" :visible.sync="dialogVisible"
+      width="80%" @close="resetForm">
+      <el-form v-if="dialogVisible" ref="infoForm" :model="form" :rules="rules">
+        <el-col :span="12">
+          <el-form-item label="浜哄憳锛�" label-width="110px" prop="userId">
+            <el-select v-model="form.userId" :disabled="operationType === 'view'" clearable filterable placeholder="璇烽�夋嫨"
+              size="small" style="width: 100%;">
+              <el-option v-for="item in responsibleOptions" :key="item.id" :label="item.name" :value="item.id">
+              </el-option>
+            </el-select>
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="鑱岀О锛�" label-width="110px" prop="technicalPost">
+            <el-input v-model="form.technicalPost" :disabled="operationType === 'view'" clearable size="small"
+              style="width: 100%;" />
+          </el-form-item>
+        </el-col>
+        <el-col :span="24">
+          <div style="display: flex;justify-content: space-evenly;font-weight: 600">
+            <span>鏌ユ牳缁撴灉</span>
+            <span>绗﹀悎涓庡惁</span>
+            <span>澶囨敞</span>
+          </div>
+        </el-col>
+        <el-col :span="8">
+          <el-form-item label="瀛﹀巻锛�" label-width="110px" prop="academicDegree">
+            <el-input v-model="form.academicDegree" :disabled="operationType === 'view'" size="small"></el-input>
+          </el-form-item>
+        </el-col>
+        <el-col :span="8">
+          <el-form-item class="radio-group" prop="academicConformNot" style="text-align: center">
+            <el-radio-group v-model="form.academicConformNot" :disabled="operationType === 'view'">
+              <el-radio :label="1">绗﹀悎</el-radio>
+              <el-radio :label="2">涓嶇鍚�</el-radio>
+              <el-radio :label="3">涓嶉�傜敤</el-radio>
+            </el-radio-group>
+          </el-form-item>
+        </el-col>
+        <el-col :span="8">
+          <el-form-item prop="academicRemarks">
+            <el-input v-model="form.academicRemarks" :disabled="operationType === 'view'" size="small"></el-input>
+          </el-form-item>
+        </el-col>
+        <el-col :span="8">
+          <el-form-item label="鐩稿叧骞撮檺锛�" label-width="110px" prop="relatedYears">
+            <el-input v-model="form.relatedYears" :disabled="operationType === 'view'" size="small"></el-input>
+          </el-form-item>
+        </el-col>
+        <el-col :span="8">
+          <el-form-item class="radio-group" prop="relatedYearsConformNot" style="text-align: center">
+            <el-radio-group v-model="form.relatedYearsConformNot" :disabled="operationType === 'view'">
+              <el-radio :label="1">绗﹀悎</el-radio>
+              <el-radio :label="2">涓嶇鍚�</el-radio>
+              <el-radio :label="3">涓嶉�傜敤</el-radio>
+            </el-radio-group>
+          </el-form-item>
+        </el-col>
+        <el-col :span="8">
+          <el-form-item prop="relatedYearsRemarks	">
+            <el-input v-model="form.relatedYearsRemarks" :disabled="operationType === 'view'" size="small"></el-input>
+          </el-form-item>
+        </el-col>
+        <el-col :span="8">
+          <el-form-item label="鐩稿叧鍩硅锛�" label-width="110px" prop="relatedTraining">
+            <el-input v-model="form.relatedTraining" :disabled="operationType === 'view'" size="small"></el-input>
+          </el-form-item>
+        </el-col>
+        <el-col :span="8">
+          <el-form-item class="radio-group" prop="relatedTrainingConformNot" style="text-align: center">
+            <el-radio-group v-model="form.relatedTrainingConformNot" :disabled="operationType === 'view'">
+              <el-radio :label="1">绗﹀悎</el-radio>
+              <el-radio :label="2">涓嶇鍚�</el-radio>
+              <el-radio :label="3">涓嶉�傜敤</el-radio>
+            </el-radio-group>
+          </el-form-item>
+        </el-col>
+        <el-col :span="8">
+          <el-form-item prop="relatedTrainingRemarks">
+            <el-input v-model="form.relatedTrainingRemarks" :disabled="operationType === 'view'"
+              size="small"></el-input>
+          </el-form-item>
+        </el-col>
+        <el-col :span="8">
+          <el-form-item label="鐩稿叧缁忛獙锛�" label-width="110px" prop="relevantExperience">
+            <el-input v-model="form.relevantExperience" :disabled="operationType === 'view'" size="small"></el-input>
+          </el-form-item>
+        </el-col>
+        <el-col :span="8">
+          <el-form-item class="radio-group" prop="relevantExperienceConformNot" style="text-align: center">
+            <el-radio-group v-model="form.relevantExperienceConformNot" :disabled="operationType === 'view'">
+              <el-radio :label="1">绗﹀悎</el-radio>
+              <el-radio :label="2">涓嶇鍚�</el-radio>
+              <el-radio :label="3">涓嶉�傜敤</el-radio>
+            </el-radio-group>
+          </el-form-item>
+        </el-col>
+        <el-col :span="8">
+          <el-form-item prop="relevantExperienceRemarks">
+            <el-input v-model="form.relevantExperienceRemarks" :disabled="operationType === 'view'"
+              size="small"></el-input>
+          </el-form-item>
+        </el-col>
+        <el-col :span="8">
+          <el-form-item label="涓婂矖璇侊細" label-width="110px" prop="workLicense">
+            <el-input v-model="form.workLicense" :disabled="operationType === 'view'" size="small" style="width: 100%">
+            </el-input>
+          </el-form-item>
+        </el-col>
+        <el-col :span="8">
+          <el-form-item class="radio-group" prop="workLicenseConformNot" style="text-align: center">
+            <el-radio-group v-model="form.workLicenseConformNot" :disabled="operationType === 'view'">
+              <el-radio :label="1">绗﹀悎</el-radio>
+              <el-radio :label="2">涓嶇鍚�</el-radio>
+              <el-radio :label="3">涓嶉�傜敤</el-radio>
+            </el-radio-group>
+          </el-form-item>
+        </el-col>
+        <el-col :span="8">
+          <el-form-item prop="workLicenseRemarks">
+            <el-input v-model="form.workLicenseRemarks" :disabled="operationType === 'view'" size="small"></el-input>
+          </el-form-item>
+        </el-col>
+        <el-col :span="8">
+          <el-form-item label="宀椾綅鑱岃矗锛�" label-width="110px" prop="jobResponsibilitiesTem" style="height: 450px">
+            <el-checkbox-group v-model="form.jobResponsibilitiesTem" :disabled="operationType === 'view'"
+              @change="selectResponsibilities">
+              <el-checkbox v-for="city in responsibilities" :key="city.value" :label="city.label"
+                :value="city.value"></el-checkbox>
+            </el-checkbox-group>
+          </el-form-item>
+        </el-col>
+        <el-col :span="8">
+          <el-form-item class="radio-group" prop="jobResponsibilitiesConformNot"
+            style="text-align: center;height: 420px">
+            <el-radio-group v-model="form.jobResponsibilitiesConformNot" :disabled="operationType === 'view'">
+              <el-radio :label="1">绗﹀悎</el-radio>
+              <el-radio :label="2">涓嶇鍚�</el-radio>
+              <el-radio :label="3">涓嶉�傜敤</el-radio>
+            </el-radio-group>
+          </el-form-item>
+        </el-col>
+        <el-col :span="8">
+          <el-form-item prop="jobResponsibilitiesRemarks" style="height: 420px">
+            <el-input v-model="form.jobResponsibilitiesRemarks" :disabled="operationType === 'view'"
+              size="small"></el-input>
+          </el-form-item>
+        </el-col>
+        <el-col :span="24">
+          <span style="padding-left: 110px;font-size: 14px">澶囨敞锛氬矖浣嶈亴璐h揪鍒�5椤瑰強5椤逛互涓婁负绗﹀悎</span>
+        </el-col>
+        <el-col :span="16">
+          <el-form-item label="缁煎悎璇勪环锛�" label-width="110px" prop="comprehensiveAssessment">
+            <el-radio-group v-model="form.comprehensiveAssessment" :disabled="operationType === 'view'">
+              <el-radio label="Qualified this position">鍙儨浠昏宀椾綅</el-radio>
+              <el-radio label="You can work while training">鍙竟鍩硅杈逛笂宀�</el-radio>
+              <el-radio label="Iconpetent for the position">涓嶈儨浠昏宀椾綅</el-radio>
+            </el-radio-group>
+          </el-form-item>
+        </el-col>
+      </el-form>
+      <span slot="footer" class="dialog-footer">
+        <el-button v-if="operationType !== 'view'" @click="resetForm">鍙栨秷</el-button>
+        <el-button v-if="operationType !== 'view'" type="primary" @click="submitForm">淇濆瓨</el-button>
+      </span>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import limsTable from "@/components/Table/lims-table.vue";
+import TableCard from '@/components/TableCard/index.vue';
+import {
+  exportPersonnelCapacity,
+  personPersonnelCapacityPage,
+  addOrUpdatePersonPersonnelCapacity,
+  confirmPersonnelCapability,
+  deletePersonPersonnelCapacity,
+  selectUserList,
+} from '@/api/cnas/personnel/personnelInfo.js'
+export default {
+  dicts: ['responsibilities_list'],
+  props: {
+    departId: {
+      type: Number,
+      default: () => {
+        return null;
+      }
+    },
+    isDepartment: {
+      type: Boolean,
+      default: false
+    }
+  },
+  components: {
+    limsTable,
+    TableCard
+  },
+  data() {
+    return {
+      userName: '',
+      tableData: [],
+      search: {
+        size: 20,
+        current: 1,
+        total: 0
+      },
+      title: '鏂板鑳藉姏璁ゅ畾',
+      operationType: '',
+      yearColumnData: [
+        {
+          label: '宀椾綅',
+          prop: 'postName',
+          minWidth: '100'
+        }, {
+          label: '濮撳悕',
+          prop: 'userName',
+          minWidth: '100'
+        }, {
+          label: '瀛﹀巻',
+          prop: 'academicDegree',
+          minWidth: '100'
+        }, {
+          label: '涓撲笟',
+          prop: 'major',
+          minWidth: '100'
+        }, {
+          label: '鑱岀О',
+          prop: 'technicalPost',
+          minWidth: '100'
+        }, {
+          dataType: 'slot',
+          label: '宸ヤ綔缁忓巻',
+          prop: 'placeWork',
+          minWidth: '100',
+          slot: 'placeWorkSlot'
+        }, {
+          dataType: 'slot',
+          label: '宀椾綅鑱岃矗',
+          prop: 'jobResponsibilities',
+          minWidth: '200px',
+          slot: 'jobResponsibilities'
+        }, {
+          dataType: 'tag',
+          label: '缁煎悎璇勪环',
+          minWidth: '140px',
+          prop: 'comprehensiveAssessment',
+          formatData: (params) => {
+            if (params == 'Qualified this position') {
+              return '鍙儨浠昏宀椾綅';
+            } else if (params == 'You can work while training') {
+              return '鍙竟鍩硅杈逛笂宀�';
+            } else {
+              return '涓嶈儨浠昏宀椾綅';
+            }
+          },
+          formatType: (params) => {
+            if (params == 'Qualified this position') {
+              return 'success';
+            } else if (params == 'You can work while training') {
+              return 'warning';
+            } else {
+              return 'danger';
+            }
+          }
+        }, {
+          label: '纭浜�',
+          prop: 'confirmOperatingPersonnelId',
+          minWidth: '100'
+        }, {
+          label: '纭鏃ユ湡',
+          prop: 'confirmDate',
+          minWidth: '160'
+        }, {
+          dataType: 'action',
+          minWidth: '220',
+          label: '鎿嶄綔',
+          fixed: 'right',
+          operation: [
+            {
+              name: '缂栬緫',
+              type: 'text',
+              clickFun: (row) => {
+                this.handleViewClick('edit', row);
+              },
+              showHide: (row) => {
+                if (this.isDepartment) {
+                  return true;
+                } else {
+                  return false;
+                }
+              }
+            },
+            {
+              name: '鏌ョ湅',
+              type: 'text',
+              clickFun: (row) => {
+                this.handleViewClick('view', row);
+              }
+            },
+            {
+              name: '瀵煎嚭',
+              type: 'text',
+              clickFun: (row) => {
+                this.downLoadPost(row);
+              }
+            },
+            {
+              name: '纭',
+              type: 'text',
+              clickFun: (row) => {
+                this.verifyGet(row.id);
+              }
+            },
+            {
+              name: '鍒犻櫎',
+              type: 'text',
+              color: '#f56c6c',
+              clickFun: (row) => {
+                this.deletePost(row.id);
+              },
+              showHide: (row) => {
+                if (this.isDepartment) {
+                  return true;
+                } else {
+                  return false;
+                }
+              }
+            }
+          ]
+        }],
+      yearLoading: false,
+      dialogVisible: false,
+      form: {
+        jobResponsibilitiesTem: []
+      },
+      responsibleOptions: [],
+      rules: {
+        userId: [{ required: true, message: '璇烽�夋嫨浜哄憳', trigger: 'change' }],
+        academicDegree: [{ required: true, message: '璇疯緭鍏ュ鍘嗘煡鏍哥粨鏋�', trigger: 'blur' }],
+        academicConformNot: [{ required: true, message: '璇烽�夋嫨瀛﹀巻绗﹀悎涓庡惁', trigger: 'change' }],
+        relatedYears: [{ required: true, message: '璇疯緭鍏ョ浉鍏冲勾闄愭煡鏍哥粨鏋�', trigger: 'blur' }],
+        relatedYearsConformNot: [{ required: true, message: '璇烽�夋嫨鐩稿叧骞撮檺绗﹀悎涓庡惁', trigger: 'change' }],
+        relatedTraining: [{ required: true, message: '璇疯緭鍏ョ浉鍩硅闄愭煡鏍哥粨鏋�', trigger: 'blur' }],
+        relatedTrainingConformNot: [{ required: true, message: '璇烽�夋嫨鐩稿叧鍩硅绗﹀悎涓庡惁', trigger: 'change' }],
+        relevantExperience: [{ required: true, message: '璇疯緭鍏ョ浉鍏崇粡楠屾煡鏍哥粨鏋�', trigger: 'blur' }],
+        relevantExperienceConformNot: [{ required: true, message: '璇烽�夋嫨鐩稿叧缁忛獙绗﹀悎涓庡惁', trigger: 'change' }],
+        workLicense: [{ required: true, message: '璇疯緭鍏ヤ笂宀楄瘉鏌ユ牳缁撴灉', trigger: 'blur' }],
+        workLicenseConformNot: [{ required: true, message: '璇烽�夋嫨涓婂矖璇佺鍚堜笌鍚�', trigger: 'change' }],
+        jobResponsibilitiesTem: [{ required: true, message: '璇烽�夋嫨宀椾綅鑱岃矗鏌ユ牳缁撴灉', trigger: 'change' }],
+        jobResponsibilitiesConformNot: [{ required: true, message: '璇烽�夋嫨宀椾綅鑱岃矗绗﹀悎涓庡惁', trigger: 'change' }],
+        comprehensiveAssessment: [{ required: true, message: '璇烽�夋嫨缁煎悎璇勪环', trigger: 'change' }]
+      },
+      responsibilities: []
+    };
+  },
+  mounted() {
+    this.getList(this.departId);
+  },
+  methods: {
+    // 涓嬭浇
+    downLoadPost(row) {
+      exportPersonnelCapacity({ id: row.id }).then(res => {
+        this.outLoading = false
+        const blob = new Blob([res], { type: 'application/msword' });
+        this.$download.saveAs(blob, "浜哄憳鑳藉姏瀵煎嚭" + '.docx')
+      })
+    },
+    // 鏌ヨ
+    refreshTable() {
+      this.getList(this.departId);
+    },
+    // 鑾峰彇浜哄憳鑳藉姏鍒楄〃淇℃伅
+    getList(userId) {
+      this.search.userId = userId;
+      const name = this.isDepartment ? 'departmentId' : 'userId';
+      this.yearLoading = true
+      personPersonnelCapacityPage({
+        userName: this.userName,
+        [name]: this.search.userId,
+        size: this.search.size,
+        current: this.search.current
+      }).then(res => {
+        this.yearLoading = false
+        if (res.code === 201) return;
+        this.tableData = res.data.records;
+        this.search.total = res.data.total;
+      }).catch(err => {
+        console.log(err);
+        this.yearLoading = false
+      })
+    },
+    selectResponsibilities(arr) {
+      let arrTem = [];
+      arr.map(val => {
+        const index = this.responsibilities.findIndex(item => item.label === val);
+        if (index > -1) {
+          arrTem.push(this.responsibilities[index].value);
+        }
+      });
+      this.form.jobResponsibilities = arrTem.join(',');
+    },
+    getResponsibilities() {
+      this.responsibilities = this.dict.type.responsibilities_list;
+    },
+    changeLine(val) {
+      if (val) {
+        return val.replace(/,/g, '<br>')
+      } else {
+        return
+      }
+    },
+    // 鏂板
+    addAppointPost(type) {
+      this.operationType = type;
+      this.title = '鏂板鑳藉姏璁ゅ畾'
+      this.dialogVisible = true;
+      this.form = {
+        jobResponsibilitiesTem: []
+      }
+      this.getUserList();
+      this.getResponsibilities();
+
+    },
+    // 缂栬緫/鏌ョ湅
+    handleViewClick(type, row) {
+      this.operationType = type;
+      this.title = this.operationType === 'edit' ? '淇敼鑳藉姏璁ゅ畾' : '鏌ョ湅鑳藉姏璁ゅ畾'
+      this.dialogVisible = true;
+      this.form = { ...row }
+      if (this.form.responsibilities) {
+        this.$set(this.form, 'jobResponsibilitiesTem', this.form.responsibilities.split(","))
+      } else {
+        this.$set(this.form, 'jobResponsibilitiesTem', [])
+      }
+      this.getUserList();
+      this.getResponsibilities();
+    },
+    submitForm() {
+      this.$refs.infoForm.validate((valid) => {
+        if (valid) {
+          addOrUpdatePersonPersonnelCapacity(this.form).then(res => {
+            if (res.code == 200) {
+              this.$message.success('鎻愪氦鎴愬姛');
+              this.getList(this.departId);
+              this.form.id = null;
+              this.dialogVisible = false;
+            }
+          });
+        }
+      });
+    },
+    verifyGet(id) {
+      this.$confirm('鏄惁纭鏈潯淇℃伅?', '鎻愮ず', {
+        confirmButtonText: '纭畾',
+        cancelButtonText: '鍙栨秷',
+        type: 'warning'
+      }).then(() => {
+        confirmPersonnelCapability({ id }).then(res => {
+          if (res.code == 200) {
+            this.$message.success('纭鎴愬姛');
+            this.getList(this.departId);
+          }
+        });
+      }).catch((err) => {
+        console.log('err---', err);
+        this.$message.info('宸插彇娑�')
+      });
+    },
+    // 鍒犻櫎宀椾綅鑱岃矗
+    deletePost(id) {
+      this.$confirm('姝ゆ搷浣滃皢姘镐箙鍒犻櫎姝ゆ暟鎹�, 鏄惁缁х画?', '鎻愮ず', {
+        confirmButtonText: '纭畾',
+        cancelButtonText: '鍙栨秷',
+        type: 'warning'
+      }).then(() => {
+        deletePersonPersonnelCapacity({ id }).then(res => {
+          if (res.code == 200) {
+            this.$message.success('鍒犻櫎鎴愬姛');
+            this.getList(this.departId);
+          }
+        });
+      }).catch(() => {
+        this.$message.error('鍒犻櫎澶辫触');
+      });
+    },
+    resetForm() {
+      this.$refs.infoForm.resetFields();
+      this.dialogVisible = false;
+    },
+    // 鑾峰彇璐熻矗浜轰俊鎭帴鍙�
+    getUserList() {
+      selectUserList().then(res => {
+        if (res.code == 200) {
+          this.responsibleOptions = res.data;
+        }
+      });
+    },
+    pagination({ page, limit }) {
+      this.search.current = page;
+      this.search.size = limit;
+      this.getList();
+    },
+  },
+  watch: {
+    // 鐩戝惉鐐瑰嚮el-tree鐨勬暟鎹紝杩涜鏁版嵁鍒锋柊
+    departId: {
+      handler(newId, oldId) {
+        this.getList(newId);
+      }
+    },
+    // 鐩戝惉鐐瑰嚮el-tree鐨勬暟鎹紝杩涜鏁版嵁鍒锋柊
+    isDepartment: {
+      handler(newId, oldId) {
+        this.getList(this.departId);
+      }
+    },
+  }
+};
+</script>
+<style scoped>
+>>>.el-dialog {
+  margin: 6vh auto 50px !important;
+}
+
+>>>.el-dialog__body {
+  max-height: 70vh;
+  overflow-y: auto;
+}
+
+.radio-group>>>.el-form-item__error {
+  padding-left: 38px;
+}
+
+>>>.el-checkbox__label {
+  width: 212px;
+  white-space: pre-wrap;
+}
+</style>
diff --git a/src/views/CNAS/personnel/personnelInfo/Department/components/PersonnelInformation/index.vue b/src/views/CNAS/personnel/personnelInfo/Department/components/PersonnelInformation/index.vue
new file mode 100644
index 0000000..7b60dff
--- /dev/null
+++ b/src/views/CNAS/personnel/personnelInfo/Department/components/PersonnelInformation/index.vue
@@ -0,0 +1,947 @@
+<template>
+  <div>
+    <div style="text-align: right;margin-bottom: 10px">
+      <!--       <el-button size="small" @click="$emit('goBackList')">杩斿洖</el-button>-->
+      <el-button size="small" type="primary" @click="synchronous" :loading="synchronousLoading">鍚屾绗笁鏂逛俊鎭�</el-button>
+      <el-button size="small" type="primary" @click="dialogVisible = true">浜哄憳鍒嗙被</el-button>
+      <el-button :loading="saveLoading" size="small" type="primary" @click="save">淇濆瓨</el-button>
+    </div>
+    <div>
+      <div style="display: flex;flex-direction: row;">
+        <div style="width: 12em">
+          <el-image :src="javaApi + '/img/' + form.pictureUrl" fit="fill"
+            style="width: 180px;height: 300px;border: 1px solid #000;border-radius: 10px;margin-left: 6px;margin-top: 10px;">
+            <div slot="error" class="image-slot">
+              <i class="el-icon-picture-outline" style="font-size: 40px;"></i>
+            </div>
+          </el-image>
+          <el-image :src="javaApi + '/img/' + form.signatureUrl" fit="fill"
+            style="width:80%;height: 50px;border: 1px solid #000;border-radius: 10px;margin-left: 22px;margin-top: 20px;">
+            <div slot="error" class="image-slot">
+              <i class="el-icon-picture-outline" style="font-size: 40px;"></i>
+            </div>
+          </el-image>
+        </div>
+        <div style="height: calc(100vh - 14em);overflow-y: auto">
+          <el-form ref="form" :model="form" label-width="110px">
+            <el-row>
+              <el-col :span="8">
+                <el-form-item label="濮撳悕">
+                  <el-input v-model="form.name" clearable size="small"></el-input>
+                </el-form-item>
+              </el-col>
+              <el-col :span="8">
+                <el-form-item label="鐧诲綍璐﹀彿">
+                  <el-input v-model="form.account" clearable size="small"></el-input>
+                </el-form-item>
+              </el-col>
+              <el-col :span="8">
+                <el-form-item label="褰撳墠鐘舵��">
+                  <el-radio-group v-model="form.currentState">
+                    <el-radio label="1formal" size="mini">姝e紡</el-radio>
+                    <el-radio label="2intern" size="mini">瀹炰範</el-radio>
+                    <el-radio label="3leaveOffice" size="mini">绂昏亴</el-radio>
+                  </el-radio-group>
+                </el-form-item>
+              </el-col>
+            </el-row>
+            <el-row>
+              <el-col :span="8">
+                <el-form-item label="宸ュ彿">
+                  <el-input v-model="form.jobNumber" clearable size="small"></el-input>
+                </el-form-item>
+              </el-col>
+              <el-col :span="8">
+                <el-form-item label="鍛樺伐瀛愮紪鍙�">
+                  <el-input v-model="form.subordinateNumber" clearable size="small"></el-input>
+                </el-form-item>
+              </el-col>
+              <el-col :span="8">
+                <el-form-item label="鎬у埆">
+                  <el-radio-group v-model="form.sex">
+                    <el-radio label="1" size="mini">鐢�</el-radio>
+                    <el-radio label="0" size="mini">濂�</el-radio>
+                  </el-radio-group>
+                </el-form-item>
+              </el-col>
+              <!-- <el-col :span="8">
+                              <el-form-item label="鍏ヨ亴鏃堕棿">
+                                  <el-date-picker v-model="form.entryTime" type="date" placeholder="閫夋嫨鏃ユ湡" size="small"
+                                      style="width: 99%;" format="yyyy-MM-dd" value-format="yyyy-MM-dd HH:mm:ss">
+                                  </el-date-picker>
+                              </el-form-item>
+                          </el-col> -->
+              <!-- <el-col :span="8">
+                              <el-form-item label="褰撳墠鑱屽姟">
+                                  <el-input v-model="form.currentPosition" size="small" clearable></el-input>
+                              </el-form-item>
+                          </el-col> -->
+            </el-row>
+            <el-row>
+              <el-col :span="8">
+                <el-form-item label="鍏徃鍚嶇О">
+                  <el-input v-model="form.corporateName" clearable size="small"></el-input>
+                </el-form-item>
+              </el-col>
+              <el-col :span="8">
+                <el-form-item label="閮ㄩ棬缂栧彿">
+                  <el-input v-model="form.departmentCode" clearable size="small"></el-input>
+                </el-form-item>
+              </el-col>
+              <el-col :span="8">
+                <el-form-item label="鎵�灞為儴闂�">
+                  <el-cascader v-model="form.departLimsId" :options="department"
+                    :props="{ label: 'name', value: 'id', checkStrictly: true }" filterable
+                    style="width: 100%;"></el-cascader>
+                </el-form-item>
+              </el-col>
+            </el-row>
+            <el-row>
+              <el-col :span="8">
+                <el-form-item label="宀椾綅绫诲埆">
+                  <el-input v-model="form.postType" clearable size="small"></el-input>
+                </el-form-item>
+              </el-col>
+              <el-col :span="8">
+                <el-form-item label="宀椾綅缂栧彿">
+                  <el-input v-model="form.postCode" clearable size="small"></el-input>
+                </el-form-item>
+              </el-col>
+              <el-col :span="8">
+                <el-form-item label="宀椾綅鍚嶇О">
+                  <el-input v-model="form.postName" clearable size="small"></el-input>
+                </el-form-item>
+              </el-col>
+            </el-row>
+            <el-row>
+              <el-col :span="8">
+                <el-form-item label="鍏ラ泦鍥㈡椂闂�">
+                  <el-date-picker v-model="form.groupTime" format="yyyy-MM-dd" placeholder="閫夋嫨鏃ユ湡" size="small"
+                    style="width: 99%;" type="date" value-format="yyyy-MM-dd">
+                  </el-date-picker>
+                </el-form-item>
+              </el-col>
+              <el-col :span="8">
+                <el-form-item label="鍏ュ崟浣嶆椂闂�">
+                  <el-date-picker v-model="form.unitTime" format="yyyy-MM-dd" placeholder="閫夋嫨鏃ユ湡" size="small"
+                    style="width: 99%;" type="date" value-format="yyyy-MM-dd">
+                  </el-date-picker>
+                </el-form-item>
+              </el-col>
+              <el-col :span="8">
+                <el-form-item label="鐩存帴涓婄骇">
+                  <el-input v-model="form.reportingTo" clearable size="small"></el-input>
+                </el-form-item>
+              </el-col>
+            </el-row>
+            <el-row>
+              <el-col :span="8">
+                <el-form-item label="鍔冲姩鍏崇郴">
+                  <el-radio-group v-model="form.laborRelations">
+                    <el-radio label="鍚堝悓宸�" size="mini">鍚堝悓宸�</el-radio>
+                    <el-radio label="姝e紡宸�" size="mini">姝e紡宸�</el-radio>
+                  </el-radio-group>
+                </el-form-item>
+              </el-col>
+              <el-col :span="8">
+                <el-form-item label="璇曠敤寮�濮嬫椂闂�">
+                  <el-date-picker v-model="form.trialStartTime" format="yyyy-MM-dd" placeholder="閫夋嫨鏃ユ湡" size="small"
+                    style="width: 99%;" type="date" value-format="yyyy-MM-dd">
+                  </el-date-picker>
+                </el-form-item>
+              </el-col>
+              <el-col :span="8">
+                <el-form-item label="璇曠敤缁撴潫鏃堕棿">
+                  <el-date-picker v-model="form.trialEndTime" format="yyyy-MM-dd" placeholder="閫夋嫨鏃ユ湡" size="small"
+                    style="width: 99%;" type="date" value-format="yyyy-MM-dd">
+                  </el-date-picker>
+                </el-form-item>
+              </el-col>
+            </el-row>
+            <el-row>
+              <el-col :span="24" style="text-align: left;">
+                <el-form-item label="浜哄憳鍒嗙被">
+                  <span style="color: #000;">{{ form.personnelClassification }}</span>
+                </el-form-item>
+              </el-col>
+            </el-row>
+            <el-row>
+              <el-col :span="8">
+                <el-form-item label="鍑虹敓鏃ユ湡">
+                  <el-date-picker v-model="form.dateBirth" format="yyyy-MM-dd" placeholder="閫夋嫨鏃ユ湡" size="small"
+                    style="width: 99%;" type="date" value-format="yyyy-MM-dd">
+                  </el-date-picker>
+                </el-form-item>
+              </el-col>
+              <el-col :span="8">
+                <el-form-item label="绫嶈疮">
+                  <el-input v-model="form.nativePlace" clearable size="small"></el-input>
+                </el-form-item>
+              </el-col>
+              <el-col :span="8">
+                <el-form-item label="姘戞棌">
+                  <el-input v-model="form.nation" clearable size="small"></el-input>
+                </el-form-item>
+              </el-col>
+            </el-row>
+            <el-row>
+              <el-col :span="8">
+                <el-form-item label="璇佷欢绫诲瀷">
+                  <el-input v-model="form.idType" clearable size="small"></el-input>
+                </el-form-item>
+              </el-col>
+              <el-col :span="8">
+                <el-form-item label="韬唤璇佸彿">
+                  <el-input v-model="form.identityCard" clearable size="small"></el-input>
+                </el-form-item>
+              </el-col>
+              <el-col :span="8">
+                <el-form-item label="骞撮緞">
+                  <el-input-number v-model="form.personBasicInfoAge" :max="130" :min="1" controls-position="right"
+                    size="small" style="width: 99%;"></el-input-number>
+                </el-form-item>
+              </el-col>
+            </el-row>
+            <el-row>
+              <el-col :span="8">
+                <el-form-item label="璇佷欢鏈夋晥鏈�">
+                  <el-date-picker v-model="form.validityPeriod" format="yyyy-MM-dd" placeholder="閫夋嫨鏃ユ湡" size="small"
+                    style="width: 99%;" type="date" value-format="yyyy-MM-dd">
+                  </el-date-picker>
+                </el-form-item>
+              </el-col>
+              <el-col :span="8">
+                <el-form-item label="濠氬Щ鐘跺喌">
+                  <el-radio-group v-model="form.maritalStatus">
+                    <el-radio label='宸插' size="mini">宸插</el-radio>
+                    <el-radio label='鏈' size="mini">鏈</el-radio>
+                  </el-radio-group>
+                </el-form-item>
+              </el-col>
+              <el-col :span="8">
+                <el-form-item label="璇佷欢鍦板潃">
+                  <el-input v-model="form.idAddress" clearable size="small"></el-input>
+                </el-form-item>
+              </el-col>
+            </el-row>
+            <el-row>
+              <el-col :span="8">
+                <el-form-item label="璇佷欢璇︾粏鍦板潃">
+                  <el-input v-model="form.idDetailAddress" clearable size="small"></el-input>
+                </el-form-item>
+              </el-col>
+              <el-col :span="8">
+                <el-form-item label="鐜板眳鍦板潃">
+                  <el-input v-model="form.currentAddress" clearable size="small"></el-input>
+                </el-form-item>
+              </el-col>
+              <el-col :span="8">
+                <el-form-item label="鐜板眳璇︾粏鍦板潃">
+                  <el-input v-model="form.currentDetailAddress" clearable size="small"></el-input>
+                </el-form-item>
+              </el-col>
+            </el-row>
+            <el-row>
+              <el-col :span="8">
+                <el-form-item label="閫佽揪鍦板潃">
+                  <el-input v-model="form.serviceAddress" clearable size="small"></el-input>
+                </el-form-item>
+              </el-col>
+              <el-col :span="8">
+                <el-form-item label="閫佽揪璇︾粏鍦板潃">
+                  <el-input v-model="form.serviceDetailAddress" clearable size="small"></el-input>
+                </el-form-item>
+              </el-col>
+              <el-col :span="8">
+                <el-form-item label="鏄惁閫�浼嶅啗浜�">
+                  <el-radio-group v-model="form.retiredSoldiers">
+                    <el-radio label='鏄�' size="mini">鏄�</el-radio>
+                    <el-radio label='鍚�' size="mini">鍚�</el-radio>
+                  </el-radio-group>
+                </el-form-item>
+              </el-col>
+            </el-row>
+            <el-row>
+              <el-col :span="8">
+                <el-form-item label="鏀挎不闈㈣矊">
+                  <el-input v-model="form.politicalStatus" clearable size="small"></el-input>
+                </el-form-item>
+              </el-col>
+              <el-col :span="8">
+                <el-form-item label="鍏ュ厷/鍥㈡椂闂�">
+                  <el-date-picker v-model="form.dumplingTime" format="yyyy-MM-dd" placeholder="閫夋嫨鏃ユ湡" size="small"
+                    style="width: 99%;" type="date" value-format="yyyy-MM-dd">
+                  </el-date-picker>
+                </el-form-item>
+              </el-col>
+              <el-col :span="8">
+                <el-form-item label="鎵嬫満鍙�">
+                  <el-input v-model="form.telephone" clearable size="small"></el-input>
+                </el-form-item>
+              </el-col>
+            </el-row>
+            <el-row>
+              <el-col :span="8">
+                <el-form-item label="鐭彿">
+                  <el-input v-model="form.cornet" clearable size="small"></el-input>
+                </el-form-item>
+              </el-col>
+              <el-col :span="8">
+                <el-form-item label="鍔炲叕鐢佃瘽">
+                  <el-input v-model="form.officePhone" clearable size="small"></el-input>
+                </el-form-item>
+              </el-col>
+              <el-col :span="8">
+                <el-form-item label="鍏徃閭">
+                  <el-input v-model="form.companyEmail" clearable size="small"></el-input>
+                </el-form-item>
+              </el-col>
+            </el-row>
+            <el-row>
+              <el-col :span="8">
+                <el-form-item label="璁$畻鏈虹瓑绾�">
+                  <el-input v-model="form.ncre" clearable size="small"></el-input>
+                </el-form-item>
+              </el-col>
+              <el-col :span="8">
+                <el-form-item label="鏈�楂樺鍘�">
+                  <el-input v-model="form.officialAcademicRedentials" clearable size="small"></el-input>
+                </el-form-item>
+              </el-col>
+              <el-col :span="8">
+                <el-form-item label="鏈�楂樺浣�">
+                  <el-input v-model="form.highestDegree" clearable size="small"></el-input>
+                </el-form-item>
+              </el-col>
+            </el-row>
+            <el-row>
+              <el-col :span="8">
+                <el-form-item label="姣曚笟闄㈡牎1">
+                  <el-input v-model="form.graduatedInstitutions1" clearable size="small"></el-input>
+                </el-form-item>
+              </el-col>
+              <el-col :span="8">
+                <el-form-item label="涓撲笟1">
+                  <el-input v-model="form.major1" clearable size="small"></el-input>
+                </el-form-item>
+              </el-col>
+              <el-col :span="8">
+                <el-form-item label="姣曚笟鏃堕棿1">
+                  <el-date-picker v-model="form.graduationTime1" format="yyyy-MM-dd" placeholder="閫夋嫨鏃ユ湡" size="small"
+                    style="width: 99%;" type="date" value-format="yyyy-MM-dd">
+                  </el-date-picker>
+                </el-form-item>
+              </el-col>
+            </el-row>
+            <el-row>
+              <el-col :span="8">
+                <el-form-item label="姣曚笟闄㈡牎2">
+                  <el-input v-model="form.graduatedInstitutions2" clearable size="small"></el-input>
+                </el-form-item>
+              </el-col>
+              <el-col :span="8">
+                <el-form-item label="涓撲笟2">
+                  <el-input v-model="form.major2" clearable size="small"></el-input>
+                </el-form-item>
+              </el-col>
+              <el-col :span="8">
+                <el-form-item label="姣曚笟鏃堕棿2">
+                  <el-date-picker v-model="form.graduationTime2" format="yyyy-MM-dd" placeholder="閫夋嫨鏃ユ湡" size="small"
+                    style="width: 99%;" type="date" value-format="yyyy-MM-dd">
+                  </el-date-picker>
+                </el-form-item>
+              </el-col>
+            </el-row>
+            <el-row>
+              <el-col :span="8">
+                <el-form-item label="鏄惁鍏ㄦ棩鍒�">
+                  <el-radio-group v-model="form.fullTime">
+                    <el-radio :label="1" size="mini">鏄�</el-radio>
+                    <el-radio :label="0" size="mini">鍚�</el-radio>
+                  </el-radio-group>
+                </el-form-item>
+              </el-col>
+              <el-col :span="8">
+                <el-form-item label="鏄惁灞炰簬涓ぉ">
+                  <el-radio-group v-model="form.enroll">
+                    <el-radio :label=1 size="mini">鏄�</el-radio>
+                    <el-radio :label=0 size="mini">鍚�</el-radio>
+                  </el-radio-group>
+                </el-form-item>
+              </el-col>
+              <el-col :span="8">
+                <el-form-item label="XX灞婂ぇ瀛︾敓">
+                  <el-input v-model="form.collegeStudents" clearable size="small"></el-input>
+                </el-form-item>
+              </el-col>
+            </el-row>
+            <el-row>
+              <el-col :span="8">
+                <el-form-item label="绱ф�ヨ仈绯讳汉">
+                  <el-input v-model="form.emergencyContact" clearable size="small"></el-input>
+                </el-form-item>
+              </el-col>
+              <el-col :span="8">
+                <el-form-item label="绱ф�ヨ仈绯荤數璇�">
+                  <el-input v-model="form.emergencyContactPhone" clearable size="small"></el-input>
+                </el-form-item>
+              </el-col>
+              <el-col :span="8">
+                <el-form-item label="鏈�鍚庢洿鏂版椂闂�">
+                  <el-date-picker v-model="form.lastUpdateTime" format="yyyy-MM-dd" placeholder="閫夋嫨鏃ユ湡" size="small"
+                    style="width: 99%;" type="date" value-format="yyyy-MM-dd">
+                  </el-date-picker>
+                </el-form-item>
+              </el-col>
+            </el-row>
+            <el-row>
+              <el-col :span="18">
+                <el-form-item label="涓汉鐓х墖">
+                  <el-input v-model="form.pictureUrl" disabled size="small">
+                    <el-button v-if="form.pictureUrl" slot="append" icon="el-icon-delete-solid"
+                      @click="deleteFile(form.pictureUrl, 'pictureUrl')"></el-button>
+                  </el-input>
+                </el-form-item>
+              </el-col>
+              <el-col :span="6">
+                <el-upload ref="upload" :action="action" :headers="uploadHeader"
+                  :on-success="(response, file, fileList) => onSuccess(response, file, fileList, 'pictureUrl')"
+                  :show-file-list="false" style="float: left; margin: 0 10px 0 10px;">
+                  <el-button slot="trigger" class="uploadFile" size="mini" type="primary">涓婁紶</el-button>
+                </el-upload>
+                <el-button v-if="form.pictureUrl" class="uploadFile" size="mini" type="primary"
+                  @click="downloadFile(form.pictureUrl)">涓嬭浇</el-button>
+              </el-col>
+            </el-row>
+            <el-row>
+              <el-col :span="18">
+                <el-form-item label="鐢靛瓙绛惧悕">
+                  <el-input v-model="form.signatureUrl" disabled size="small">
+                    <el-button v-if="form.signatureUrl" slot="append" icon="el-icon-delete-solid"
+                      @click="deleteFile(form.signatureUrl, 'signatureUrl')"></el-button>
+                  </el-input>
+                </el-form-item>
+              </el-col>
+              <el-col :span="6">
+                <el-upload ref="upload" :action="action" :headers="uploadHeader"
+                  :on-success="(response, file, fileList) => onSuccess(response, file, fileList, 'signatureUrl')"
+                  :show-file-list="false" style="float: left; margin: 0 10px 0 10px;">
+                  <el-button slot="trigger" class="uploadFile" size="small" type="primary">涓婁紶</el-button>
+                </el-upload>
+                <el-button v-if="form.signatureUrl" class="uploadFile" size="small" type="primary"
+                  @click="downloadFile(form.signatureUrl)">涓嬭浇</el-button>
+              </el-col>
+            </el-row>
+            <!-- <el-row>
+                          <el-col :span="20">
+                              <el-form-item label="闄勪欢璧勬枡">
+                                  <el-input v-model="form.attachmentInformation" size="small" disabled>
+                                      <el-button v-if="form.attachmentInformation" slot="append"
+                                          icon="el-icon-delete-solid"
+                                          @click="deleteFile(form.attachmentInformation, 'attachmentInformation')"></el-button>
+                                  </el-input>
+                              </el-form-item>
+                          </el-col>
+                          <el-col :span="4">
+                              <el-upload ref="upload" style="float: left; margin: 0 20px;" :action="action"
+                                  :show-file-list="false"
+                                  :on-success="(response, file, fileList) => onSuccess(response, file, fileList, 'attachmentInformation')">
+                                  <el-button class="uploadFile" slot="trigger" size="mini" type="primary">娴忚</el-button>
+                              </el-upload>
+                              <el-button class="uploadFile" size="mini" type="primary" @click="downloadFile(form.attachmentInformation)">涓嬭浇</el-button>
+                          </el-col>
+                      </el-row> -->
+
+            <el-row>
+              <el-col :span="20">
+                <el-form-item label="闄勪欢璧勬枡">
+                </el-form-item>
+              </el-col>
+              <el-col :span="4">
+                <el-button size="mini" style="float: right;margin-right: 25px" type="primary"
+                  @click="annexAdd(0)">鏂板</el-button>
+              </el-col>
+            </el-row>
+            <el-table :data="annexList" border height="200" style="width: 96%;">
+              <el-table-column label="搴忓彿" type="index" width="80px">
+              </el-table-column>
+              <el-table-column label="璇佷欢鍙�" prop="idNumber" width="150px">
+              </el-table-column>
+              <el-table-column label="鍙戣瘉鍗曚綅" prop="issueUnit" width="150px">
+              </el-table-column>
+              <el-table-column label="鏂囦欢鍚嶇О" prop="fileName" show-overflow-tooltip width="200px">
+              </el-table-column>
+              <el-table-column label="绾у埆" prop="level" width="150px">
+              </el-table-column>
+              <el-table-column label="鏈夋晥鏈�" prop="periodValidity" width="150px">
+              </el-table-column>
+              <el-table-column label="娣诲姞鏃堕棿" prop="createTime" width="150px">
+              </el-table-column>
+              <el-table-column fixed="right" label="鎿嶄綔" width="150px">
+                <template slot-scope="scope">
+                  <el-button size="mini" type="text" @click="downloadFile(scope.row.fileName)">涓嬭浇</el-button>
+                  <el-button size="mini" type="text" @click="annexAdd(1, scope.row)">缂栬緫</el-button>
+                  <el-button size="mini" type="text" @click="deleteAnnex(scope.row)">鍒犻櫎</el-button>
+                </template>
+              </el-table-column>
+            </el-table>
+          </el-form>
+          <el-row>
+          </el-row>
+        </div>
+      </div>
+    </div>
+    <!-- 浜哄憳鍒嗙被寮规 -->
+    <el-dialog :visible.sync="dialogVisible" title="鎻愮ず" width="40%" @open="getComparisonList">
+      <div style="height: 30vh;">
+        <el-row>
+          <el-col :span="4">
+            浜哄憳鍒嗙被锛�
+          </el-col>
+          <el-col :span="20" style="text-align: left;">
+            <el-checkbox-group v-model="checkList">
+              <el-checkbox v-for="v in personnelClassification" :key="v.value" :label="v.value"></el-checkbox>
+            </el-checkbox-group>
+          </el-col>
+        </el-row>
+      </div>
+      <span slot="footer" class="dialog-footer">
+        <el-button @click="dialogVisible = false">鍙� 娑�</el-button>
+        <el-button type="primary" @click="clickPersonnelClassificationSure">纭� 瀹�</el-button>
+      </span>
+    </el-dialog>
+
+    <!-- 鏂板闄勪欢璧勬枡 -->
+    <el-dialog :before-close="handleClose" :title="title" :visible.sync="dialogVisible1" width="40%"
+      @open="getComparisonList">
+      <el-form ref="annex" :model="annex" :rules="rules" label-width="100px">
+        <el-row>
+          <el-col :span="16">
+            <el-form-item label="璇佷欢鍙�" prop="idNumber">
+              <el-input v-model="annex.idNumber" clearable size="small" style="width: 100%;"></el-input>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row style="margin-top: 15px">
+          <el-col :span="16">
+            <el-form-item label="鍙戣瘉鍗曚綅" prop="issueUnit">
+              <el-input v-model="annex.issueUnit" clearable size="small"></el-input>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row style="margin-top: 15px">
+          <el-col :span="16">
+            <el-form-item label="绾у埆" prop="level">
+              <el-input v-model="annex.level" clearable size="small"></el-input>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row style="margin-top: 15px">
+          <el-col :span="16">
+            <el-form-item label="鏈夋晥鏈�" prop="periodValidity">
+              <el-date-picker v-model="annex.periodValidity" format="yyyy-MM-dd" placeholder="閫夋嫨鏃ユ湡" size="small"
+                style="width: 99%;" type="date" value-format="yyyy-MM-dd">
+              </el-date-picker>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row style="margin-top: 15px">
+          <el-col :span="16">
+            <el-form-item label="澶嶅嵃浠�" prop="copy">
+              <el-input v-model="annex.copy" clearable size="small"></el-input>
+            </el-form-item>
+          </el-col>
+        </el-row>
+
+        <el-row style="margin-top: 15px">
+          <el-col :span="16">
+            <el-form-item label="鍘熶欢" prop="original">
+              <el-input v-model="annex.original" clearable size="small"></el-input>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row style="margin-top: 15px">
+          <el-col :span="16">
+            <el-form-item label="鏂囦欢">
+              <el-upload :action="action" :headers="uploadHeader" :before-upload="beforeAvatarUpload"
+                :on-success="(response, file, fileList) => onSuccess(response, file, fileList, 'fileName')"
+                :show-file-list="false">
+                <img v-if="imageUrl" :src="imageUrl" class="avatar">
+                <i v-else class="el-icon-upload avatar-uploader-icon"></i>
+              </el-upload>
+            </el-form-item>
+          </el-col>
+        </el-row>
+      </el-form>
+      <span slot="footer" class="dialog-footer">
+        <el-button @click="cancellation">鍙� 娑�</el-button>
+        <el-button type="primary" @click="submitForm('annex')">纭� 瀹�</el-button>
+      </span>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import {
+  getEmployees,
+  getAnnex,
+  updateAnnex,
+  getAnnexByUserId,
+  addAnnex,
+  deleteAnnex,
+  getCNASPersonnelInfo,
+  saveCNASPersonnelInfo,
+  deleteCNASFile
+} from '@/api/cnas/personnel/personnelInfo.js'
+export default {
+  dicts: ['personnl_type'],
+  props: {
+    clickNodeVal: {
+      type: Object,
+      default: () => { return {} }
+    },
+  },
+  data() {
+    return {
+      synchronousLoading: false,
+      addOrupdate: null,
+      title: '',
+      annexList: [],
+      imageUrl: '',
+      annex: {
+        userId: '',
+        idNumber: '',
+        issueUnit: '',
+        level: '',
+        periodValidity: '',
+        copy: '',
+        original: '',
+        fileName: ''
+      },
+      rules: {
+        idNumber: [
+          { required: true, message: '璇疯緭鍏ヨ瘉浠跺彿', trigger: 'blur' }
+        ],
+        issueUnit: [
+          { required: true, message: '璇疯緭鍏ュ彂璇佸崟浣�', trigger: 'blur' }
+        ],
+        periodValidity: [
+          { required: true, message: '璇烽�夋嫨鏈夋晥鏈�', trigger: 'blur' }
+        ]
+      },
+      dialogVisible1: false,
+      form: {
+        userId: '',
+        name: '',
+        account: '',
+        currentState: '',
+        jobNumber: '',
+        subordinateNumber: '',
+        sex: '',
+        corporateName: '',
+        department: '',
+        departLimsId: [],
+        postType: '',
+        postCode: '',
+        postName: '',
+        groupTime: '',
+        unitTime: '',
+        reportingTo: '',
+        laborRelations: '',
+        trialStartTime: '',
+        trialEndTime: '',
+        personnelClassification: '',
+        dateBirth: '',
+        nativePlace: '',
+        nation: '',
+        idType: '',
+        identityCard: '',
+        age: '',
+        validityPeriod: '',
+        maritalStatus: '',
+        idAddress: '',
+        idDetailAddress: '',
+        currentAddress: '',
+        currentDetailAddress: '',
+        serviceAddress: '',
+        serviceDetailAddress: '',
+        retiredSoldiers: '',
+        politicalStatus: '',
+        dumplingTime: '',
+        telephone: '',
+        cornet: '',
+        officePhone: '',
+        email: '',
+        ncre: '',
+        officialAcademicRedentials: '',
+        highestDegree: '',
+        graduatedInstitutions1: '',
+        major1: '',
+        graduationTime1: '',
+        graduatedInstitutions2: '',
+        major2: '',
+        graduationTime2: '',
+        fullTime: '',
+        enroll: '',
+        collegeStudents: '',
+        emergencyContact: '',
+        emergencyContactPhone: '',
+        lastUpdateTime: '',
+        pictureUrl: '',
+        signatureUrl: '',
+      },
+      department: [],
+      saveLoading: false,
+      dialogVisible: false,
+      personnelClassification: [],
+      checkList: [],
+      successFileList: [], // 闃叉鍚庣鍑虹幇鑴忔暟鎹�
+      isSave: false,
+    }
+  },
+  created() {
+    this.init()
+  },
+  computed: {
+    action() {
+      return this.javaApi + '/personBasicInfo/saveCNASFile'
+    }
+  },
+  methods: {
+    synchronous() {
+      console.log('鍩烘湰淇℃伅', this.clickNodeVal);
+      this.synchronousLoading = true
+      getEmployees({ userId: this.clickNodeVal.userId }).then(res => {
+        this.synchronousLoading = false
+        this.getUserBasisInfo(this.clickNodeVal.userId)
+        this.$message.success("鍚屾鎴愬姛")
+
+      })
+    },
+    annexAdd(type, row) {
+      if (type === 1) {
+        this.title = '缂栬緫闄勪欢璧勬枡'
+        this.addOrupdate = 1
+        getAnnex({ id: row.id }).then(res => {
+          this.annex = res.data
+          this.imageUrl = this.javaApi + '/img/' + res.data.fileName
+        })
+      } else {
+        this.title = '鏂板闄勪欢璧勬枡'
+        this.addOrupdate = 2
+      }
+      this.dialogVisible1 = true
+    },
+    submitForm(formName) {
+      this.$refs[formName].validate((valid) => {
+        if (valid) {
+          this.addAnnex()
+        } else {
+          return false
+        }
+      })
+    },
+    addAnnex() {
+      if (this.annex.fileName == "" || this.annex.fileName == null || this.annex.fileName == undefined) {
+        this.$message.error("璇蜂笂浼犳枃浠�")
+        return
+      }
+      this.annex.userId = this.clickNodeVal.userId
+      if (this.addOrupdate === 1) {
+        updateAnnex(this.annex).then(res => {
+          if (res.code == 200) {
+            getAnnexByUserId({ userId: this.clickNodeVal.userId }).then(res => {
+              this.dialogVisible1 = false
+              this.imageUrl = ''
+              this.resetForm('annex')
+              this.annexList = res.data
+              this.$message.success('鏇存柊鎴愬姛锛�')
+            })
+          }
+        })
+      } else {
+        this.annex.id = null
+        addAnnex(this.annex).then(res => {
+          if (res.code == 200) {
+            getAnnexByUserId({ userId: this.clickNodeVal.userId }).then(res => {
+              this.dialogVisible1 = false
+              this.imageUrl = ''
+              this.resetForm('annex')
+              this.annexList = res.data
+              this.$message.success('淇濆瓨鎴愬姛')
+            })
+          }
+        })
+      }
+    },
+    deleteAnnex(row) {
+      this.$confirm('姝ゆ搷浣滃皢姘镐箙鍒犻櫎璇ユ枃浠�, 鏄惁缁х画?', '鎻愮ず', {
+        confirmButtonText: '纭畾',
+        cancelButtonText: '鍙栨秷',
+        type: 'warning'
+      }).then(() => {
+        deleteAnnex(row.id).then(res => {
+          this.$message.success('鍒犻櫎鎴愬姛锛�')
+          this.annexList = this.annexList.filter(item => item.id != row.id)
+        })
+      })
+    },
+    beforeAvatarUpload(file) {
+      const isJPGorPNG = file.type === 'image/jpeg' || file.type === 'image/png' || file.type === 'image/gif';
+      const isLt2MB = file.size / 1024 / 1024 < 2;
+      if (!isJPGorPNG) {
+        this.$message.error('涓婁紶鍥剧墖鍙兘鏄� JPG/PNG 鏍煎紡!');
+        return false;
+      }
+      // if (!isLt2MB) {
+      //   this.$message.error('涓婁紶鍥剧墖澶у皬涓嶈兘瓒呰繃 2MB!');
+      // }
+      // 鏍¢獙閫氳繃鎵嶈繑鍥� true锛屽厑璁告枃浠朵笂浼�
+      return isJPGorPNG && isLt2MB;
+    },
+    downloadFile(fileName) {
+      this.$download.saveAs(fileName, fileName)
+    },
+    async onSuccess(response, file, fileList, entityVal) {
+      if (entityVal == 'fileName') {
+        this.annex.fileName = response.data
+        this.imageUrl = this.javaApi + '/img/' + response.data
+      }
+      // 鍦ㄤ繚瀛樿祴鍊兼柊鏂囦欢
+      this.successFileList.push(response.data)
+      this.$set(this.form, entityVal, response.data)
+    },
+    // 鍒濆鍖栬皟鐢�
+    init() {
+      if (!this.clickNodeVal.userId) {
+        let user = JSON.parse(localStorage.getItem('user'))
+        this.getUserBasisInfo(user.userId)
+        this.clickNodeVal.userId = user.userId
+      } else {
+        this.getUserBasisInfo(this.clickNodeVal.userId)
+      }
+    },
+    getUserBasisInfo(userId) {
+      getCNASPersonnelInfo({ userId }).then(res => {
+        this.form = res.data.PersonBasicInfoDto
+        this.department = res.data.department
+        this.annexList = res.data.annexList
+        this.form.departLimsId = res.data.PersonBasicInfoDto.departLimsId.split(',').filter(a => a != "").map(Number)
+        console.log('res.data', res);
+      })
+    },
+    async save() {
+      this.saveLoading = true
+      this.form.userId = this.clickNodeVal.userId
+      if (Array.isArray(this.form.departLimsId)) {
+        if (this.form.departLimsId.length > 0) {
+          this.form.departLimsId = this.form.departLimsId.join(',').trim() + ','
+        } else {
+          this.form.departLimsId = ''
+        }
+      }
+      saveCNASPersonnelInfo(this.form).then(res => {
+        this.saveLoading = false
+        this.isSave = true
+        this.getUserBasisInfo(this.clickNodeVal.userId)
+        this.$message.success('淇濆瓨鎴愬姛锛�')
+      })
+    },
+    // 鍙栦汉鍛樺垎绫荤殑瀛楀吀
+    getComparisonList() {
+      tthis.personnelClassification = this.dict.type.personnl_type;
+      this.checkList = this.form.personnelClassification.split('锛�')
+    },
+    clickPersonnelClassificationSure() {
+      this.dialogVisible = false
+      this.form.personnelClassification = this.checkList.filter(m => m).join('锛�')
+    },
+    async deleteFile(fileName, entityVal) {
+      await deleteCNASFile({ fileName }).then(res => {
+        this.$message.success('鍒犻櫎鎴愬姛锛�')
+        this.$set(this.form, entityVal, null)
+        let index = this.successFileList.indexOf(fileName)
+        if (index != -1) {
+          this.successFileList.splice(index, 1)
+        }
+      })
+    },
+    validateFileSize(rule, value, callback) {
+      if (!value) {
+        return callback(new Error('璇蜂笂浼犳枃浠�'));
+      } else {
+        callback();
+      }
+    },
+    cancellation() {
+      this.dialogVisible1 = false
+      this.imageUrl = ''
+      this.resetForm('annex')
+    },
+    handleClose(done) {
+      this.imageUrl = ''
+      this.annex = {
+        userId: '',
+        idNumber: '',
+        issueUnit: '',
+        level: '',
+        periodValidity: '',
+        copy: '',
+        original: '',
+        fileName: ''
+      }
+      done();
+    },
+    resetForm(formName) {
+      this.$refs[formName].resetFields();
+    }
+  },
+  watch: {
+    // 鐩戝惉鐐瑰嚮el-tree鐨勬暟鎹紝杩涜鏁版嵁鍒锋柊
+    clickNodeVal: {
+      handler(newVal, oldVal) {
+        if (newVal.userId) {
+          this.getUserBasisInfo(newVal.userId)
+        }
+      },
+    }
+  }
+}
+</script>
+
+<style scoped>
+>>>.el-form-item {
+  margin-bottom: 3px;
+}
+
+.el-input {
+  border-radius: 15px;
+}
+
+.el-icon-picture-outline {
+  position: absolute;
+  left: 50%;
+  top: 50%;
+  transform: translate(-50%, -50%);
+}
+
+.uploadFile {
+  margin-top: 2px;
+  float: left;
+}
+
+.avatar-uploader-icon {
+  font-size: 28px;
+  color: #0f8bf1;
+  width: 178px;
+  height: 50px;
+  text-align: center;
+  border: 1px solid #d9d9d9;
+}
+
+.avatar {
+  width: 178px;
+  height: 178px;
+  display: block;
+}
+</style>
diff --git a/src/views/CNAS/personnel/personnelInfo/Department/components/PersonnelList/index.vue b/src/views/CNAS/personnel/personnelInfo/Department/components/PersonnelList/index.vue
new file mode 100644
index 0000000..4aa3298
--- /dev/null
+++ b/src/views/CNAS/personnel/personnelInfo/Department/components/PersonnelList/index.vue
@@ -0,0 +1,319 @@
+<template>
+  <div>
+    <div class="search-list">
+      <span class="search-input">
+        <span class="search-label">
+          <span style="width: 120px;font-size: 14px;line-height: 32px">浜哄憳鍚嶇О锛�</span>
+          <el-input v-model="entity.name" clearable placeholder="璇疯緭鍏�" size="small" style="width: 100%;"
+            @keyup.enter.native="refreshTable()">
+          </el-input>
+        </span>
+        <el-button size="small" style="margin-left: 10px" @click="refresh()">閲� 缃�</el-button>
+        <el-button size="small" type="primary" @click="refreshTable()">鏌� 璇�</el-button>
+      </span>
+      <span>
+        <el-button :loading="synchronousLoading" size="small" type="primary" @click="synchronous"
+          :v-show="departId">鍚屾绗笁鏂逛汉鍛樹俊鎭�</el-button>
+        <el-button :loading="outLoading" size="small" type="primary" @click="handleDown">瀵煎嚭</el-button>
+        <el-button size="small" type="primary" @click="selectUserDia = true">鏂板缓</el-button>
+      </span>
+    </div>
+    <div class="search-table">
+      <el-table v-loading="tableLoading" :data="tableData" border height="calc(100vh - 20em)" style="width: 100%;">
+        <el-table-column align="center" label="搴忓彿" width="60">
+          <template v-slot="scope">
+            <span>{{ (page.current - 1) * page.size + scope.$index + 1 }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column label="鍛樺伐缂栧彿" prop="account" width="150"></el-table-column>
+        <el-table-column label="濮撳悕" prop="name" width="120"></el-table-column>
+        <el-table-column label="鍏ラ泦鍥㈡椂闂�" prop="groupTime" width="120"></el-table-column>
+        <el-table-column label="绫嶈疮" prop="nativePlace" width="120"></el-table-column>
+        <el-table-column label="璇佷欢鍙风爜" prop="identityCard" show-overflow-tooltip width="300"></el-table-column>
+        <el-table-column label="璇佷欢鍦板潃" prop="idAddress" show-overflow-tooltip width="100"></el-table-column>
+        <el-table-column label="鎵嬫満鍙�" prop="telephone" show-overflow-tooltip width="100"></el-table-column>
+        <el-table-column label="姣曚笟闄㈡牎" prop="graduatedInstitutions1" width="100"></el-table-column>
+        <el-table-column label="鎵�瀛︿笓涓�" prop="major1" width="100"></el-table-column>
+        <el-table-column label="姣曚笟鏃堕棿" prop="graduationTime1" width="100"></el-table-column>
+        <el-table-column label="鏈�楂樺鍘�" prop="officialAcademicRedentials" width="100"></el-table-column>
+        <el-table-column label="鏈�楂樺浣�" prop="highestDegree" width="100"></el-table-column>
+        <el-table-column label="鑱岀О" prop="professionalTitle" width="100"></el-table-column>
+        <el-table-column label="绱ф�ヨ仈绯讳汉" prop="emergencyContact" width="120"></el-table-column>
+        <el-table-column label="绱ф�ヨ仈绯荤數璇�" prop="emergencyContactPhone" width="120"></el-table-column>
+        <el-table-column fixed="right" label="鎿嶄綔" width="140">
+          <template slot-scope="scope">
+            <el-button size="small" type="text" @click="downPerson(scope.row)">涓嬭浇</el-button>
+            <el-button size="small" type="text" @click="$emit('updatePerson', scope.row)">缂栬緫
+            </el-button>
+            <el-button size="small" type="text" @click="deletePerson(scope.row)">鍒犻櫎
+            </el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+      <el-pagination :current-page="1" :current-page.sync="page.current" :page-size="page.size"
+        :page-sizes="[10, 20, 30, 50, 100]" :total="page.total" layout="->,total, sizes, prev, pager, next, jumper"
+        style="margin-top: 16px" @size-change="handleSizeChange" @current-change="handleCurrentChange">
+      </el-pagination>
+    </div>
+    <el-dialog :visible.sync="selectUserDia" title="閫夋嫨鐢ㄦ埛" width="70%">
+      <div class="search" style="margin-bottom: 9px;">
+        <div class="search_thing">
+          <div class="search_label">鐢ㄦ埛鍚嶏細</div>
+          <div class="search_input">
+            <el-input v-model="addUserTableInfo.entity.name" clearable placeholder="璇疯緭鍏�" size="small"
+              @keyup.enter.native="$refs.ValueTable.selectList()"></el-input>
+          </div>
+        </div>
+      </div>
+      <div v-if="selectUserDia" class="body" style="height: 60vh;">
+        <ValueTable ref="ValueTable" :componentData="addUserTableInfo" :url="$api.user.selectUserList" />
+      </div>
+      <span slot="footer" class="dialog-footer">
+        <el-button @click="selectUserDia = false">鍙� 娑�</el-button>
+        <el-button type="primary" @click="selectUser">纭� 瀹�</el-button>
+      </span>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import ValueTable from '@/components/Table/value-table.vue';
+import {
+  getEmployees,
+  basicInformationOfPersonnelSelectPage,
+  delUserDepardLimsId,
+  upUserDepardLimsId,
+  exportPersonBasicInfo,
+  exportPersonBasicInfoById,
+} from '@/api/cnas/personnel/personnelInfo.js'
+export default {
+  name: 'PersonnelList',
+  // import 寮曞叆鐨勭粍浠堕渶瑕佹敞鍏ュ埌瀵硅薄涓墠鑳戒娇鐢�
+  components: { ValueTable },
+  props: {
+    departId: {
+      type: Number,
+      default: () => {
+        return null;
+      }
+    },
+    isDepartment: {
+      type: Boolean,
+      default: false
+    },
+    currentCompaniesList: {
+      type: Array,
+      default: []
+    }
+  },
+  data() {
+    // 杩欓噷瀛樻斁鏁版嵁
+    return {
+      synchronousLoading: false,
+      page: {
+        size: 20,
+        current: 1,
+      },
+      outLoading: false,
+      tableLoading: false,
+      tableData: [], // 浜哄憳鎬诲垪琛ㄦ暟鎹�
+      selectUserDia: false, // 娣诲姞浜哄憳寮规
+      entity: {
+        name: '',
+        orderBy: {
+          field: 'id',
+          order: 'asc'
+        }
+      },
+      addUserTableInfo: {
+        name: null,
+        entity: {
+          isCustom: 0,
+          orderBy: {
+            field: 'id',
+            order: 'asc'
+          }
+        },
+        isIndex: true,
+        showSelect: true,
+        select: true,
+        do: [],
+        tagField: {
+          state: {
+            select: [
+              {
+                value: 1,
+                type: 'success',
+                label: '鍚敤'
+              },
+              {
+                value: 0,
+                type: 'danger',
+                label: '鍋滅敤'
+              }
+            ]
+          }
+        },
+        selectField: {},
+        upUserDepardLimsIdPower: true
+      },
+    };
+  },
+  mounted() {
+    this.refreshTable();
+  },
+  // 鏂规硶闆嗗悎
+  methods: {
+    synchronous() {
+      console.log('departId', this.departId);
+      this.$message.warning("姝e湪鍚屾锛岃绋嶅悗...")
+      this.synchronousLoading = true
+      getEmployees({ departId: this.departId }).then(res => {
+        this.synchronousLoading = false
+        this.$message.success("鍚屾鎴愬姛")
+      })
+    },
+    /**
+     * @desc 鑾峰彇璁惧id
+     */
+    // 閲嶇疆
+    refresh() {
+      this.page = {
+        size: 20,
+        current: 1,
+      };
+      this.entity.name = ''
+      this.refreshTable();
+    },
+    // 鏌ヨ浜哄憳鍒楄〃鏁版嵁
+    refreshTable(entity, type) {
+      try {
+        this.tableLoading = true;
+        this.entity.departLimsId = this.departId;
+        basicInformationOfPersonnelSelectPage({ ...this.page, ...this.entit }).then(res => {
+          this.tableLoading = false;
+          if (res.code === 201) {
+            return;
+          }
+          this.page.total = res.data.total;
+          this.tableData = res.data.records;
+        });
+      } catch (e) {
+        this.tableLoading = false;
+      }
+    },
+    // 鍒犻櫎浜哄憳
+    deletePerson(row) {
+      this.$confirm('鏄惁鍒犻櫎褰撳墠鏁版嵁?', '璀﹀憡', {
+        confirmButtonText: '纭畾',
+        cancelButtonText: '鍙栨秷',
+        type: 'warning'
+      })
+        .then(() => {
+          delUserDepardLimsId({ id: row.id }).then(res => {
+            if (res.code === 201) {
+              return;
+            }
+            this.$message.success('鍒犻櫎鎴愬姛');
+            this.refreshTable();
+          })
+            .catch(e => {
+              this.$message.error('鍒犻櫎澶辫触');
+            });
+        })
+        .catch(() => {
+        });
+    },
+    handleSizeChange(val) {
+      this.page.size = val;
+      this.refreshTable();
+    },
+    handleCurrentChange(val) {
+      this.page.current = val;
+      this.refreshTable();
+    },
+    selectUser() {
+      if (!this.currentCompaniesList.length > 0) {
+        this.$message.warning("璇烽�夋嫨閮ㄩ棬锛�")
+        return;
+      }
+      let selects = this.$refs.ValueTable.multipleSelection;
+      if (selects.length == 0) {
+        this.$message.error('鏈�夋嫨鏁版嵁');
+        return;
+      }
+      let ids = [];
+      selects.forEach(a => {
+        ids.push(a.id);
+      });
+      let str = '';
+      this.currentCompaniesList.forEach(a => {
+        if (a) {
+          str += a + ',';
+        }
+      });
+      this.selectUserDia = false;
+      upUserDepardLimsId({
+        ids: JSON.stringify(ids),
+        id: str
+      }).then(res => {
+        if (res.code === 201) {
+          return;
+        }
+        this.$message.success('娣诲姞鎴愬姛');
+        this.refreshTable();
+      });
+      this.$emit('refreshTree')
+    },
+    handleDown() {
+      this.outLoading = true;
+      let entity = this.HaveJson(this.entity)
+      delete entity.orderBy;
+      exportPersonBasicInfo(entity).then(res => {
+        this.outLoading = false;
+        if (res.code === 201) {
+          return;
+        }
+        const blob = new Blob([res], { type: 'application/octet-stream' });
+        this.$download.saveAs(blob, '浜哄憳淇℃伅.xlsx')
+      });
+    },
+    downPerson(row) {
+      exportPersonBasicInfoById({ id: row.userId }).then(res => {
+        this.$download.saveAs(res.data, res.data)
+        this.$message.success('涓嬭浇鎴愬姛')
+      });
+    }
+  },
+  watch: {
+    departId: {
+      handler(newId, oldId) {
+        if (newId) {
+          this.page.current = 1
+          this.refreshTable();
+        }
+      }
+    }
+  }
+};
+</script>
+
+<style scoped>
+.search-list {
+  padding: 0 16px 16px;
+  display: flex;
+  justify-content: space-between;
+}
+
+.search-table {
+  padding: 0 16px;
+}
+
+.search-input {
+  display: flex;
+}
+
+.search-label {
+  display: flex;
+}
+</style>
diff --git a/src/views/CNAS/personnel/personnelInfo/Department/components/PersonnelTraining/AddInDetail.vue b/src/views/CNAS/personnel/personnelInfo/Department/components/PersonnelTraining/AddInDetail.vue
new file mode 100644
index 0000000..38bb4b4
--- /dev/null
+++ b/src/views/CNAS/personnel/personnelInfo/Department/components/PersonnelTraining/AddInDetail.vue
@@ -0,0 +1,319 @@
+<template>
+  <div>
+    <el-dialog :visible.sync="addTrainingPlanDia" :show="currshowlist" @close="$emit('update:currshowlist', false)"
+      title="鏂板鍩硅璁″垝" width="50%">
+      <div class="body">
+        <el-form ref="trainingPlan" :model="trainingPlan" label-position="right" label-width="90px"
+          :rules="trainingPlanRules">
+          <el-row>
+            <el-col :span="12">
+              <!-- <el-form-item label="鍩硅鏃ユ湡:" prop="trainingDate">
+                <el-date-picker v-model="trainingPlan.trainingDate" format="yyyy-MM-dd"
+                                placeholder="閫夋嫨鏃ユ湡" size="small" value-format="yyyy-MM-dd"
+                                type="date" style="width: 100%"></el-date-picker>
+              </el-form-item> -->
+              <el-form-item label="鍩硅鏈堜唤:" prop="trainingDate">
+                <el-select v-model="trainingPlan.trainingDate">
+                  <el-option v-for="(v, i) in months" :key="i" :label="v.label" :value="v.value"></el-option>
+                </el-select>
+              </el-form-item>
+            </el-col>
+            <el-col :span="12">
+              <el-form-item label="鍩硅鏃ユ湡:" prop="trainingDateTwo">
+                <el-date-picker v-model="trainingPlan.trainingDateTwo" type="date" value-format="yyyy-MM-dd"
+                  placeholder="閫夋嫨鏃ユ湡">
+                </el-date-picker>
+              </el-form-item>
+            </el-col>
+            <el-col :span="12">
+              <el-form-item label="寮�濮嬫椂闂�:" prop="openingTime">
+                <el-time-picker v-model="trainingPlan.openingTime" placeholder="閫夋嫨鏃堕棿" size="small" style="width: 100%"
+                  value-format="HH:mm:ss"></el-time-picker>
+              </el-form-item>
+            </el-col>
+            <el-col :span="12">
+              <el-form-item label="缁撴潫鏃堕棿:" prop="endTime">
+                <el-time-picker v-model="trainingPlan.endTime" placeholder="閫夋嫨鏃堕棿" size="small" style="width: 100%"
+                  value-format="HH:mm:ss"></el-time-picker>
+              </el-form-item>
+            </el-col>
+            <el-col :span="12">
+              <el-form-item label="鍩硅鐩爣:">
+                <el-input v-model="trainingPlan.trainingObjectives" placeholder="璇疯緭鍏�" size="small"></el-input>
+              </el-form-item>
+            </el-col>
+            <el-col :span="12">
+              <el-form-item label="鍙傚姞瀵硅薄:">
+                <el-input v-model="trainingPlan.participants" placeholder="璇疯緭鍏�" size="small"></el-input>
+              </el-form-item>
+            </el-col>
+            <el-col :span="12">
+              <el-form-item label="鍩硅鍐呭:" prop="trainingContent">
+                <el-input v-model="trainingPlan.trainingContent" placeholder="璇疯緭鍏�" size="small"></el-input>
+              </el-form-item>
+            </el-col>
+            <el-col :span="12">
+              <el-form-item label="鍩硅璁插笀:" prop="trainingLecturerId">
+                <el-select v-model="trainingPlan.trainingLecturerId" multiple clearable filterable placeholder="璇烽�夋嫨"
+                  size="small" style="width: 100%">
+                  <el-option v-for="item in responsibleOptions" :key="item.id" :label="item.name" :value="item.name">
+                  </el-option>
+                </el-select>
+              </el-form-item>
+            </el-col>
+            <el-col :span="12">
+              <el-form-item label="璇鹃瀛﹀垎:">
+                <el-input type="number" v-model="trainingPlan.projectCredits" label="鎻忚堪鏂囧瓧" size="small"></el-input>
+              </el-form-item>
+            </el-col>
+            <el-col :span="12">
+              <el-form-item label="鍩硅鍦扮偣:">
+                <el-input v-model="trainingPlan.placeTraining" placeholder="璇疯緭鍏�" size="small"></el-input>
+              </el-form-item>
+            </el-col>
+            <el-col :span="12">
+              <el-form-item label="鍩硅鏂瑰紡:">
+                <el-input v-model="trainingPlan.trainingMode" placeholder="璇疯緭鍏�" size="small"></el-input>
+              </el-form-item>
+            </el-col>
+            <el-col :span="12">
+              <el-form-item label="涓惧姙閮ㄩ棬:">
+                <el-select v-model="trainingPlan.holdingDepartment" placeholder="璇烽�夋嫨">
+                  <el-option v-for="(v, i) in departLims" :key="i" :label="v.name" :value="v.id"></el-option>
+                </el-select>
+                <!--
+                <el-input
+                  v-model="trainingPlan.holdingDepartment"
+                  placeholder="璇疯緭鍏�"
+                  size="small"
+                ></el-input> -->
+              </el-form-item>
+            </el-col>
+            <el-col :span="12">
+              <el-form-item label="璇炬椂:">
+                <el-input type="number" v-model="trainingPlan.classHour" label="鎻忚堪鏂囧瓧" size="small"></el-input>
+              </el-form-item>
+            </el-col>
+          </el-row>
+        </el-form>
+      </div>
+      <span slot="footer" class="dialog-footer">
+        <el-button @click="closeAdd">鍙� 娑�</el-button>
+        <el-button type="primary" @click="submitAdd">纭� 瀹�</el-button>
+      </span>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import {
+  selectDepartLims,
+  addOrUpdatePersonTrainingDetailed,
+} from '@/api/cnas/personnel/personnelInfo.js'
+import { selectUserCondition } from "@/api/system/user";
+export default {
+  props: {
+    currshowlist: {
+      type: Boolean,
+      default: false,
+    },
+    currentChangeRow: {
+      type: Object,
+      default: () => {
+        return {};
+      },
+    },
+  },
+  name: "Add",
+  // import 寮曞叆鐨勭粍浠堕渶瑕佹敞鍏ュ埌瀵硅薄涓墠鑳戒娇鐢�
+  components: {},
+  data() {
+    var trainingLecturerIdValidate = (rule, value, callback) => {
+      if (typeof value !== "undefined" && value.length == 0) {
+        callback(new Error("璇烽�夋嫨璁插笀"));
+      } else {
+        callback();
+      }
+    };
+    // 杩欓噷瀛樻斁鏁版嵁
+    return {
+      departLims: [],
+      months: [
+        { label: "1鏈�", value: "1鏈�" },
+        { label: "2鏈�", value: "2鏈�" },
+        { label: "3鏈�", value: "3鏈�" },
+        { label: "4鏈�", value: "4鏈�" },
+        { label: "5鏈�", value: "5鏈�" },
+        { label: "6鏈�", value: "6鏈�" },
+        { label: "7鏈�", value: "7鏈�" },
+        { label: "8鏈�", value: "8鏈�" },
+        { label: "9鏈�", value: "9鏈�" },
+        { label: "10鏈�", value: "10鏈�" },
+        { label: "11鏈�", value: "11鏈�" },
+        { label: "12鏈�", value: "12鏈�" },
+      ],
+      addTrainingPlanDia: false,
+      trainingPlan: {
+        id: "",
+        planId: "",
+        trainingDate: "",
+        trainingDateTwo: "",
+        classHour: "",
+        openingTime: "",
+        endTime: "",
+        trainingObjectives: "",
+        participants: "",
+        trainingContent: "",
+        trainingLecturerId: undefined,
+        projectCredits: "",
+        placeTraining: "",
+        trainingMode: "",
+        holdingDepartment: "",
+      },
+      trainingPlanRules: {
+        trainingDate: [
+          { required: true, message: "璇烽�夋嫨鍩硅鏃ユ湡", trigger: "change" },
+        ],
+        trainingDateTwo: [
+          { required: true, message: "璇烽�夋嫨鍩硅鏃ユ湡", trigger: "change" },
+        ],
+        openingTime: [
+          { required: true, message: "璇烽�夋嫨寮�濮嬫椂闂�", trigger: "change" },
+        ],
+        endTime: [
+          { required: true, message: "璇烽�夋嫨缁撴潫鏃堕棿", trigger: "change" },
+        ],
+        trainingContent: [
+          { required: true, message: "璇疯緭鍏ュ煿璁唴瀹�", trigger: "blur" },
+        ],
+        trainingLecturerId: [
+          {
+            required: true,
+            validator: trainingLecturerIdValidate,
+            trigger: "change",
+          },
+        ],
+      },
+      responsibleOptions: [],
+    };
+  },
+  created() {
+    this.departLims = [];
+    selectDepartLims().then((res) => {
+      this.departLims = res.data;
+    });
+  },
+  // 鏂规硶闆嗗悎
+  methods: {
+    showDialog(id) {
+      this.trainingPlan.planId = id;
+      this.getUserList();
+      // this.addTrainingPlanDia = true;
+    },
+    showEditDialog(row) {
+      this.getUserList();
+      let data = JSON.parse(JSON.stringify(row));
+
+      console.log(data.trainingLecturerId);
+      let list = data.trainingLecturerId.split(/銆亅锛寍,|\\s+/);
+      this.$set(this.trainingPlan, "trainingLecturerId", list);
+      this.$set(this.trainingPlan, "id", data.id);
+      this.$set(this.trainingPlan, "trainingDate", data.trainingDate);
+      this.$set(this.trainingPlan, "trainingDateTwo", data.trainingDateTwo);
+      this.$set(this.trainingPlan, "classHour", data.classHour);
+      this.$set(this.trainingPlan, "openingTime", data.openingTime);
+      this.$set(this.trainingPlan, "endTime", data.endTime);
+      this.$set(
+        this.trainingPlan,
+        "trainingObjectives",
+        data.trainingObjectives
+      );
+      this.$set(this.trainingPlan, "participants", data.participants);
+      this.$set(this.trainingPlan, "projectCredits", data.projectCredits);
+      this.$set(this.trainingPlan, "placeTraining", data.placeTraining);
+      this.$set(this.trainingPlan, "trainingContent", data.trainingContent);
+      this.$set(this.trainingPlan, "trainingMode", data.trainingMode);
+      this.$set(this.trainingPlan, "holdingDepartment", data.holdingDepartment);
+      this.$set(this.trainingPlan, "planId", data.planId);
+
+      console.log("222", this.trainingPlan);
+    },
+    // 鎻愪氦鏂板
+    submitAdd() {
+      this.$refs.trainingPlan.validate((valid) => {
+        if (valid) {
+          // 灏嗗煿璁甯堝�煎皝瑁�
+          this.trainingPlan.trainingLecturerId =
+            this.trainingPlan.trainingLecturerId.join(",");
+          console.log(
+            "this.trainingPlan.trainingLecturerId",
+            this.trainingPlan.trainingLecturerId
+          );
+          const personTrainingDetailed = this.trainingPlan;
+          console.log("personTrainingDetailed", personTrainingDetailed);
+          addOrUpdatePersonTrainingDetailed(personTrainingDetailed).then((res) => {
+            if (res.code == 200) {
+              this.$message.success("鎻愪氦鎴愬姛");
+              this.closeAdd();
+              this.dialogVisible = false;
+            }
+          });
+        }
+      });
+    },
+    // 鍏抽棴寮规
+    closeAdd() {
+      this.$refs.trainingPlan.resetFields();
+      this.$emit("search");
+      this.$emit("searchPlan");
+      this.addTrainingPlanDia = false;
+    },
+    // 鑾峰彇璐熻矗浜轰俊鎭帴鍙�
+    getUserList() {
+      selectUserCondition().then((res) => {
+        if (res.code == 200) {
+          this.responsibleOptions = res.data;
+        }
+      });
+    },
+  },
+  watch: {
+    // addTrainingPlanDia(newVal) {
+    //   if (newVal) {
+    //     this.trainingPlan.planId = null;
+    //   }
+    // },
+    currshowlist(newValue) {
+      this.addTrainingPlanDia = this.currshowlist;
+      if (!newValue) {
+        this.closeAdd();
+        this.trainingPlan = {
+          id: "",
+          planId: "",
+          trainingDate: "",
+          classHour: "",
+          openingTime: "",
+          endTime: "",
+          trainingObjectives: "",
+          participants: "",
+          trainingContent: "",
+          trainingLecturerId: undefined,
+          projectCredits: "",
+          placeTraining: "",
+          trainingMode: "",
+          holdingDepartment: "",
+        };
+      }
+      if (this.currshowlist) {
+        this.$nextTick(() => {
+          if (this.trainingPlan.trainingLecturerId.length == 0) {
+            this.trainingPlan.trainingLecturerId = undefined;
+          }
+        });
+      }
+    },
+  },
+};
+</script>
+
+<style scoped></style>
diff --git a/src/views/CNAS/personnel/personnelInfo/Department/components/PersonnelTraining/Edit.vue b/src/views/CNAS/personnel/personnelInfo/Department/components/PersonnelTraining/Edit.vue
new file mode 100644
index 0000000..1953d01
--- /dev/null
+++ b/src/views/CNAS/personnel/personnelInfo/Department/components/PersonnelTraining/Edit.vue
@@ -0,0 +1,580 @@
+<template>
+  <div>
+    <div class="page-header">
+      <h4><span class="line"></span><span>鍩硅涓庤�冩牳璁板綍</span></h4>
+      <div class="btns">
+        <el-button size="small" type="primary" @click="submitForm" :disabled="![1, 4].includes(currentRow.state)">{{
+          currentRow.assessmentUserId ? '淇濆瓨' : '鎻愪氦' }}</el-button>
+        <el-button size="small" @click="$emit('goBack')">杩斿洖</el-button>
+      </div>
+    </div>
+    <div class="form_title">
+      <el-row>
+        <el-col :span="5">
+          <span class="form_label">璇剧▼缂栧彿锛�</span>
+          <span> {{ trainingForm.courseCode }} </span>
+        </el-col>
+        <el-col :span="6">
+          <span class="form_label">鍩硅鍐呭锛�</span>
+          <span> {{ trainingForm.trainingContent }} </span>
+        </el-col>
+        <el-col :span="4">
+          <span class="form_label">鐘舵�侊細</span>
+          <el-tag v-if="trainingForm.state === 1" type="success">宸插畬鎴�</el-tag>
+          <el-tag v-if="trainingForm.state === 2" type="warning">杩涜涓�</el-tag>
+          <el-tag v-if="trainingForm.state === 3" type="primary">鏈紑濮�</el-tag>
+          <el-tag v-if="trainingForm.state === 4" type="info">宸茬粨鏉�</el-tag>
+        </el-col>
+        <el-col :span="4">
+          <span class="form_label">鍩硅璁插笀锛�</span>
+          <span> {{ trainingForm.trainingLecturerId }} </span>
+        </el-col>
+        <el-col :span="4">
+          <span class="form_label">鍩硅鏃ユ湡锛�</span>
+          <span> {{ trainingForm.trainingDate }} </span>
+        </el-col>
+      </el-row>
+      <el-row style="margin: 15px 0">
+        <el-form>
+          <el-col :span="12">
+            <el-form-item label="鑰冩牳鏂瑰紡">
+              <el-input v-model="trainingForm.assessmentMethod"
+                :disabled="currentRow.state == 1 || currentRow.assessmentUserId" :rows="2" placeholder="璇疯緭鍏�"
+                size="small" style="width: 79%" type="textarea"></el-input>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="鏈鍩硅缁煎悎璇勪环">
+              <el-input v-model="trainingForm.comprehensiveAssessment"
+                :disabled="currentRow.state == 1 || ((currentRow.assessmentUserId !== user.userId) && ![35, 16, 36].includes(user.userId)) || !currentRow.assessmentUserId"
+                :rows="2" placeholder="璇疯緭鍏�" size="small" style="width: 68%" type="textarea"></el-input>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="璇勪环浜�">
+              <el-select v-model="trainingForm.assessmentUserId"
+                :disabled="currentRow.state == 1 || currentRow.assessmentUserId" placeholder="璇烽�夋嫨" size="small"
+                style="width: 68%">
+                <el-option v-for="item in userList" :key="item.id" :label="item.name" :value="item.id"></el-option>
+              </el-select>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="璇勪环鏃堕棿">
+              <el-date-picker v-model="trainingForm.assessmentDate"
+                :disabled="currentRow.state == 1 || ((currentRow.assessmentUserId !== user.userId) && ![35, 16, 36].includes(user.userId)) || !currentRow.assessmentUserId"
+                style="width:40%" type="date" format="yyyy-MM-dd" value-format="yyyy-MM-dd" size="small"
+                placeholder="閫夋嫨鏃ユ湡">
+              </el-date-picker>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="鍩硅鎽樿">
+              <el-input v-model="trainingForm.trainingAbstract"
+                :disabled="currentRow.state == 1 || currentRow.assessmentUserId" :rows="2" placeholder="璇疯緭鍏�"
+                size="small" style="width: 79%" type="textarea"></el-input>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item>
+              <!-- <el-upload
+                ref="upload"
+                :action="action"
+                :before-upload="beforeUpload"
+                :on-error="onError"
+                :data="uploadData"
+                :headers="uploadHeader"
+                :on-success="attachmentUpload"
+                >
+                <el-button size="small" type="primary">鐐瑰嚮涓婁紶</el-button>
+              </el-upload> -->
+              <el-button type="primary" size="small" @click="attachmentFrame = true">闄勪欢</el-button>
+            </el-form-item>
+          </el-col>
+          <!-- <el-col :span="12" :offset="12">
+            <el-image
+              v-if="currentRow.url"
+              style="width: 70%; height: 100px"
+              :src="javaApi + '/img/' + currentRow.url">
+              </el-image>
+          </el-col> -->
+        </el-form>
+      </el-row>
+    </div>
+    <!-- 鏂囦欢棰勮 -->
+    <el-dialog :visible.sync="lookDialogVisible" fullscreen title="鏌ョ湅闄勪欢" width="800px">
+      <filePreview v-if="lookDialogVisible" :currentFile="{}" :fileUrl="previewFile"
+        style="height: 90vh;overflow-y: auto;top: 0" />
+    </el-dialog>
+    <!-- 闄勪欢寮规 -->
+    <el-dialog title="闄勪欢" :visible.sync="attachmentFrame" width="70%" border :before-close="handleClose">
+      <el-upload ref="upload" :action="action" :before-upload="beforeUpload" :on-error="onError" :data="uploadData"
+        :headers="uploadHeader" :on-success="attachmentUpload" style="margin-bottom: 10px">
+        <el-button size="small" type="primary" :disabled="currentRow.state == 1">涓婁紶闄勪欢</el-button>
+      </el-upload>
+      <el-table ref="fileData" :data="fileData" height="400px">
+        <el-table-column label="搴忓彿" type="index" width="100" header-align="center" align="center">
+        </el-table-column>
+        <el-table-column label="鏂囦欢鍚嶇О" prop="fileName" header-align="center" align="center">
+        </el-table-column>
+        <el-table-column label="鎿嶄綔" fixed="right" width="200px" header-align="center" align="center">
+          <template slot-scope="scope">
+            <el-button type="text" size="small" @click="preview(scope.row)">棰勮</el-button>
+            <el-button type="text" size="small" @click="download(scope.row)">涓嬭浇</el-button>
+            <el-button type="text" style="color: red;" size="small" @click="deleteFile(scope.row)">鍒犻櫎</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+      <span slot="footer" class="dialog-footer">
+        <el-button @click="attachmentFrame = false">鍙� 娑�</el-button>
+        <el-button type="primary" @click="attachmentFrame = false">纭� 瀹�</el-button>
+      </span>
+    </el-dialog>
+
+
+    <el-divider>浜哄憳璇︽儏</el-divider>
+    <div>
+      <div class="items_center">
+        <span>濮撳悕</span>
+        <el-input v-model="userName" class="search" placeholder="璇疯緭鍏�" size="small"></el-input>
+        <el-button size="small" type="primary" @click="getInfo">鏌ヨ</el-button>
+      </div>
+      <div class="items_btn">
+        <el-button :disabled="currentRow.state === 1" size="small" type="primary" @click="addPerson">鏂板浜哄憳</el-button>
+        <el-button :disabled="currentRow.state === 1" size="small" @click="batchDelete">鎵归噺鍒犻櫎</el-button>
+      </div>
+      <el-table :data="trainingTableData" height="calc(100vh - 30em)" stripe style="width: 100%"
+        @selection-change="handleSelectionChange">
+        <el-table-column type="selection" width="55"></el-table-column>
+        <el-table-column label="搴忓彿" type="index" width="60"></el-table-column>
+        <el-table-column label="濮撳悕" prop="userName"></el-table-column>
+        <el-table-column label="宸ュ彿" prop="account"></el-table-column>
+        <el-table-column label="瑙掕壊" prop="roleName"></el-table-column>
+        <el-table-column label="鐢佃瘽鍙风爜" prop="phone"></el-table-column>
+        <el-table-column label="鑰冩牳缁撴灉" prop="examinationResults">
+          <template v-slot="scope">
+            <el-select v-model="scope.row.examinationResults" :disabled="currentRow.state === 1" size="small"
+              style="width: 100%" @change="updatePersonResult(scope.row)">
+              <el-option label="鍚堟牸" value="鍚堟牸"></el-option>
+              <el-option label="涓嶅悎鏍�" value="涓嶅悎鏍�"></el-option>
+            </el-select>
+          </template>
+        </el-table-column>
+      </el-table>
+    </div>
+    <el-dialog :visible.sync="selectUserDia" title="閫夋嫨鐢ㄦ埛" width="70%">
+      <div class="search" style="margin-bottom: 9px;">
+        <div class="search_thing">
+          <div class="search_label">鐢ㄦ埛鍚嶏細</div>
+          <div class="search_input">
+            <el-input v-model="addUserTableInfo.entity.name" clearable placeholder="璇疯緭鍏�" size="small"
+              @keyup.enter.native="$refs.ValueTable.selectList()"></el-input>
+          </div>
+        </div>
+      </div>
+      <div v-if="selectUserDia" class="body" style="height: 60vh;">
+        <ValueTable ref="ValueTable" :componentData="addUserTableInfo" :isSelectedList="isSelectedList"
+          :url="$api.user.selectUserList" />
+      </div>
+      <span slot="footer" class="dialog-footer">
+        <el-button @click="selectUserDia = false">鍙� 娑�</el-button>
+        <el-button type="primary" @click="selectUser">纭� 瀹�</el-button>
+      </span>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import TableCard from '@/components/TableCard/index.vue';
+import limsTable from "@/components/Table/lims-table.vue";
+import ValueTable from '@/components/Table/value-table.vue';
+import filePreview from "@/components/Preview/filePreview.vue";
+import {
+  fileDownLoad,
+  deleteFile,
+  getFileData,
+  trainingAndAssessmentRecordsPage,
+  outOfFocusPreservation,
+  newPersonnelAddedToTrainingRecords,
+  deleteTrainingAndAssessmentRecords,
+  trainingAndAssessmentRecordsAdded,
+} from '@/api/cnas/personnel/personnelInfo.js'
+import { selectUserCondition } from "@/api/system/user";
+import { mapGetters } from "vuex";
+export default {
+  name: 'Edit',
+  // import 寮曞叆鐨勭粍浠堕渶瑕佹敞鍏ュ埌瀵硅薄涓墠鑳戒娇鐢�
+  components: { ValueTable, limsTable, TableCard, filePreview },
+  props: {
+    currentRow: {
+      type: Object,
+      default: () => {
+        return {}
+      }
+    },
+  },
+  data() {
+    // 杩欓噷瀛樻斁鏁版嵁
+    return {
+      previewFile: '',
+      lookDialogVisible: false,
+      user: {},
+      fileData: [],
+      attachmentFrame: false,
+      isSelectedList: [], // 绂佺敤鐨勫閫�
+      userName: undefined,
+      trainingForm: {
+        code: '111111',
+        date: '2024-10-10',
+      },
+      uploadData: {},
+      trainingColumn: [
+        {
+          label: '濮撳悕',
+          prop: 'userName'
+        },
+        {
+          label: '宸ュ彿',
+          prop: 'account'
+        },
+        {
+          label: '瑙掕壊',
+          prop: 'roleName'
+        },
+        {
+          label: '鐢佃瘽鍙风爜',
+          prop: 'phone'
+        },
+        {
+          label: '鑰冩牳缁撴灉',
+          prop: 'result'
+        }
+      ],
+      trainingTableData: [],
+      trainingLoading: false,
+      selectUserDia: false, // 娣诲姞浜哄憳寮规
+      addUserTableInfo: {
+        name: null,
+        entity: {
+          departLimsId: '1',
+          orderBy: {
+            field: 'id',
+            order: 'asc'
+          }
+        },
+        isIndex: true,
+        showSelect: true,
+        select: true,
+        do: [],
+        tagField: {
+          state: {
+            select: [
+              {
+                value: 1,
+                type: 'success',
+                label: '鍚敤'
+              },
+              {
+                value: 0,
+                type: 'danger',
+                label: '鍋滅敤'
+              }
+            ]
+          }
+        },
+        selectField: {},
+        upUserDepardLimsIdPower: true
+      },
+      multipleSelection: [],
+      userList: [],
+    };
+  },
+  computed: {
+    action() {
+      return this.javaApi + '/personTraining/fileUpload';
+    },
+    ...mapGetters(["userId"]),
+  },
+  mounted() {
+    this.trainingForm = JSON.parse(JSON.stringify(this.currentRow))
+    this.getInfo()
+    this.getUserList()
+    this.getFileData(this.trainingForm.id)
+    // 鑾峰彇褰撳墠鐧诲綍浜轰俊鎭�
+    this.loginPerson();
+  },
+  // 鏂规硶闆嗗悎
+  methods: {
+    // 闄勪欢棰勮
+    preview(row) {
+      let folder = '';
+      if (row.fileUrl.includes('xls')) {
+        folder = 'excel'
+      } else if (row.fileUrl.includes('docx')) {
+        folder = 'word'
+      } else {
+        folder = 'img'
+      }
+      this.previewFile = this.javaApi + folder + row.fileUrl
+      this.$nextTick(() => {
+        this.lookDialogVisible = true
+      })
+    },
+    // 涓嬭浇
+    download(row) {
+      fileDownLoad({ id: row.id }).then(res => {
+        console.log('2123');
+        const blob = new Blob([res], { type: row.mime });
+        this.$download.saveAs(blob, row.fileName)
+      })
+    },
+
+    // 鍒犻櫎
+    deleteFile(row) {
+      this.$confirm('姝ゆ搷浣滃皢姘镐箙鍒犻櫎璇ユ枃浠�, 鏄惁缁х画?', '鎻愮ず', {
+        confirmButtonText: '纭畾',
+        cancelButtonText: '鍙栨秷',
+        type: 'warning'
+      }).then(() => {
+        deleteFile({ id: row.id }).then(res => {
+          this.$message({
+            type: 'success',
+            message: '鍒犻櫎鎴愬姛!'
+          });
+          this.getFileData(this.trainingForm.id);
+        })
+      })
+
+    },
+    // 鏌ヨ
+    getFileData(id) {
+      getFileData({ detailedId: id }).then(res => {
+        this.fileData = res.data
+      })
+    },
+    // 闄勪欢涓婁紶 鎴愬姛鐨勯挬瀛�
+    attachmentUpload(res, file, fileList) {
+      // 缁欏浘鐗囪矾寰勮祴鍊�
+      this.$message.success('涓婁紶鎴愬姛')
+      this.currentRow.url = res.data.url
+      this.$refs.upload.clearFiles();
+      this.getFileData(this.trainingForm.id);
+    },
+    // 澶辫触鐨勯挬瀛�
+    onError(err, file, fileList) {
+      this.$message.error('涓婁紶澶辫触')
+    },
+    // 涓婁紶鍓嶇殑閽╁瓙
+    beforeUpload(file) {
+      // 缁欎紶閫掔殑鍙傛暟璧嬪��
+      this.$set(this.uploadData, "id", this.currentRow.id)
+    },
+    // 褰撳墠鐧诲綍浜轰俊鎭� 
+    loginPerson() {
+      this.user = {
+        userId: this.userId
+      }
+    },
+    // 鑾峰彇褰撳墠鏁版嵁
+    async getInfo() {
+      this.trainingLoading = true
+      trainingAndAssessmentRecordsPage({
+        trainingDetailedId: this.currentRow.id,
+        userName: this.userName
+      }).then(res => {
+        if (res.code === 200) {
+          this.trainingTableData = res.data
+        }
+        this.trainingLoading = false
+      })
+    },
+    async updatePersonResult(row) {
+      const { code } = await outOfFocusPreservation(row)
+      if (code === 200) {
+        this.$message.success("鎿嶄綔鎴愬姛锛�")
+      }
+    },
+    addPerson() {
+      this.isSelectedList = this.trainingTableData.map(item => item.userId)
+      this.selectUserDia = true;
+    },
+    selectUser() {
+      let selects = this.$refs.ValueTable.multipleSelection;
+      if (selects.length == 0) {
+        this.$message.error('鏈�夋嫨鏁版嵁');
+        return;
+      }
+      let list = []
+      selects.forEach(a => {
+        const obj = {
+          courseId: this.currentRow.id,
+          examinationResults: "",
+          userId: a.id
+        }
+        list.push(obj)
+        // this.trainingTableData.push(obj);
+      });
+      newPersonnelAddedToTrainingRecords(list).then(res => {
+        this.isSelectedList = []
+        this.selectUserDia = false;
+        this.getInfo()
+      })
+    },
+    // 鎵归噺鍒犻櫎
+    handleSelectionChange(list) {
+      this.multipleSelection = list
+    },
+    batchDelete() {
+      console.log('鎵归噺鍒犻櫎', this.multipleSelection)
+      if (this.multipleSelection.length > 0) {
+        let ids = this.multipleSelection.map(item => item.trainingRecordId)
+        this.$confirm('鏄惁纭鍒犻櫎鎵�閫夋嫨鐨勬暟鎹�?', '鎻愮ず', {
+          confirmButtonText: '纭畾',
+          cancelButtonText: '鍙栨秷',
+          type: 'warning'
+        }).then(() => {
+          let formData = new FormData()
+          formData.append('ids', ids)
+          deleteTrainingAndAssessmentRecords(formData)
+            .then(res => {
+              if (res.code == 200) {
+                this.$message.success('鍒犻櫎鎴愬姛');
+                this.getInfo()
+              }
+            });
+        }).catch(() => {
+          this.$message.warning('鍙栨秷鍒犻櫎');
+        });
+      } else {
+        this.$message.warning('璇烽�夋嫨闇�瑕佸垹闄ょ殑鏁版嵁')
+      }
+    },
+    handleSizeChange(val) {
+      this.search.size = val;
+      this.getInfo();
+    },
+    handleCurrentChange(val) {
+      this.search.current = val;
+      this.getInfo();
+    },
+    /**
+     * @desc 鎻愪氦琛ㄥ崟
+     */
+    async submitForm() {
+      console.log('this.currentRow.state', this.currentRow.state);
+      if (this.currentRow.state !== 4 && this.currentRow.state !== 1) {
+        this.$message.warning("褰撳墠鐘舵�佹棤娉曟彁浜�/鎾ら攢锛�")
+        return
+      }
+      // 濡傛灉绛変簬4 琛ㄧず璇ョ姸鎬佷负宸茬粨鏉燂紝1 琛ㄧず宸插畬鎴�
+      let state = 4
+      if (this.currentRow.assessmentUserId == this.user.userId) {
+        state = 1
+      }
+      let data = {
+        assessmentMethod: this.trainingForm.assessmentMethod,
+        comprehensiveAssessment: this.trainingForm.comprehensiveAssessment,
+        trainingDetailedId: this.trainingForm.id,
+        assessmentUserId: this.currentRow.assessmentUserId ? this.currentRow.assessmentUserId : this.trainingForm.assessmentUserId,
+        assessmentDate: this.trainingForm.assessmentDate,
+        state: state,
+        trainingAbstract: this.trainingForm.trainingAbstract
+      }
+      const { code } = await trainingAndAssessmentRecordsAdded(data)
+      if (code === 200) {
+        this.currentRow.state = state
+        this.$message.success("鎿嶄綔鎴愬姛")
+        // this.$emit('refresh',this.currentRow.id)
+      }
+    },
+    getUserList() {
+      selectUserCondition().then(res => {
+        if (res.code === 201) {
+          return
+        }
+        this.userList = res.data
+      })
+    },
+    handleClose() {
+      this.attachmentFrame = false;
+    },
+  }
+};
+</script>
+
+<style scoped>
+.page-header {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  padding: 0 20px;
+  margin-bottom: 10px;
+}
+
+h4 {
+  display: flex;
+  align-items: center;
+}
+
+h4 .line {
+  display: inline-block;
+  width: 3px;
+  height: 16px;
+  background: #3A7BFA;
+  margin-right: 4px;
+}
+
+.form_title {
+  font-size: 14px;
+  padding: 0 20px;
+  margin-bottom: 10px;
+}
+
+.el-divider {
+  margin: 0 1em 1em 0;
+}
+
+.form__input_label {
+  width: 90px;
+  margin-right: 6px;
+  color: #606266;
+}
+
+.form__input_label2 {
+  width: 210px;
+  margin-right: 6px;
+  color: #606266;
+}
+
+.search_thing {
+  display: flex;
+  align-items: center
+}
+
+.search_label {
+  width: 120px;
+}
+
+.pagination {
+  display: flex;
+  justify-content: space-between
+}
+
+.items_center {
+  float: left;
+  width: 50%;
+  text-align: left;
+}
+
+.items_btn {
+  text-align: right;
+  width: 50%;
+  float: right;
+  margin-bottom: 1em;
+}
+
+.search {
+  width: 180px;
+  padding: 0 16px;
+}
+</style>
diff --git a/src/views/CNAS/personnel/personnelInfo/Department/components/PersonnelTraining/index.vue b/src/views/CNAS/personnel/personnelInfo/Department/components/PersonnelTraining/index.vue
new file mode 100644
index 0000000..9467953
--- /dev/null
+++ b/src/views/CNAS/personnel/personnelInfo/Department/components/PersonnelTraining/index.vue
@@ -0,0 +1,1012 @@
+<!-- 浜哄憳鍩硅 -->
+<template>
+  <div class="flex_column">
+    <div v-if="!editPlanShow && isDepartment && flag">
+      <TableCard title="骞村害璁″垝琛�">
+        <template v-slot:form>
+          <div class="items_center">
+            <span>鍒涘缓浜�</span>
+            <el-input v-model="pagination.compilerName" class="search" placeholder="璇疯緭鍏�" size="mini"></el-input>
+            <el-button size="mini" type="primary" @click="getYearPlanList(departId)">鏌ヨ</el-button>
+          </div>
+          <div>
+            <el-button size="mini" type="primary" @click="uploadDia = true">瀵煎叆</el-button>
+          </div>
+        </template>
+        <template v-slot:table>
+          <limsTable :column="yearPlanColumn" :currentChange="currentChange" :height="'130'"
+            :table-data="yearPlanTableData" :table-loading="yearLoading" highlightCurrentRow style="padding: 0 15px"
+            :page="pagination" @pagination="paginationMetod">
+          </limsTable>
+        </template>
+      </TableCard>
+    </div>
+    <div v-if="!editPlanShow" class="table">
+      <TableCard title="骞村害璁″垝鏄庣粏琛�">
+        <template v-slot:form>
+          <div class="items_center">
+            <span>鍩硅璁插笀</span>
+            <el-input v-model="inDetailForm.trainingLecturerName" class="search" clearable placeholder="璇疯緭鍏�"
+              size="mini"></el-input>
+            <!-- <span>璇剧▼缂栧彿</span>
+            <el-input v-model="inDetailForm.courseCode" class="search" clearable placeholder="璇疯緭鍏�" size="small"></el-input> -->
+            <span style="margin-right: 4px">鍩硅鏃ユ湡</span>
+            <el-date-picker v-model="inDetailForm.trainingDate" clearable format="yyyy-MM-dd" placeholder="閫夋嫨鏃ユ湡"
+              size="mini" type="date" value-format="yyyy-MM-dd"></el-date-picker>
+            <el-button size="mini" style="margin-left: 10px" type="primary" @click="searchTable">鏌ヨ</el-button>
+          </div>
+          <div style="display: flex; align-items: center">
+            <el-button v-if="isDepartment && currentChangeRow && isOperation && flag" size="mini"
+              @click="batchDelete">鎵归噺鍒犻櫎</el-button>
+            <el-button v-if="isDepartment && currentChangeRow && isOperation && flag" size="mini" type="primary"
+              @click="addTrainingPlan">鏂板</el-button>
+          </div>
+        </template>
+        <template v-slot:table>
+          <el-tabs v-model="activeName" style="margin-left: 15px">
+            <el-tab-pane label="鏈煿璁�" name="first">
+              <limsTable :column="inDetailPlanColumn" :handleSelectionChange="handleSelectionChange"
+                :height="tableHeight + ''" :isSelection="true" :table-data="inDetailPlanTableData"
+                :table-loading="yearLoading" style="padding: 0 15px" :page="inDetailPagination"
+                @pagination="paginationmethod0">
+              </limsTable>
+            </el-tab-pane>
+            <el-tab-pane label="宸茬粨鏉�" name="second">
+              <limsTable :column="inDetailPlanColumn" :handleSelectionChange="handleSelectionChange"
+                :height="tableHeight + ''" :isSelection="true" :table-data="inDetailPlanTableData"
+                :table-loading="yearLoading" style="padding: 0 15px" :page="inDetailPagination"
+                @pagination="paginationmethod0">
+              </limsTable>
+            </el-tab-pane>
+          </el-tabs>
+        </template>
+      </TableCard>
+    </div>
+    <Add ref="addPlan" :currshowlist.sync="addInDetail" :currentChangeRow="currentChangeRow"
+      @search="getInDetailPlan(currentRowId, departId)" @searchPlan="refreshYearPlanList(departId2)"></Add>
+    <Edit v-if="editPlanShow" ref="editPlan" :currentRow="currentRow" :key="editKey" @refresh="refresh"
+      @del="getInDetailPlan(currentRowId, departId)" @goBack="goBack"></Edit>
+    <el-dialog :visible.sync="reviewDialog" title="瀹℃牳" width="30%" @close="reviewRemarks = ''">
+      <span>
+        瀹℃牳澶囨敞锛�
+        <el-input v-model="reviewRemarks" type="textarea"></el-input>
+      </span>
+      <span slot="footer" class="dialog-footer">
+        <el-button :loading="reviewLoading" @click="handleReview(2)">涓嶉�氳繃</el-button>
+        <el-button :loading="reviewLoading" type="primary" @click="handleReview(1)">閫� 杩�</el-button>
+      </span>
+    </el-dialog>
+    <el-dialog :visible.sync="approvalDialog" title="鎵瑰噯" width="30%" @close="approvalRemarks = ''">
+      <span>
+        鎵瑰噯澶囨敞锛�
+        <el-input v-model="approvalRemarks" type="textarea"></el-input>
+      </span>
+      <span slot="footer" class="dialog-footer">
+        <el-button :loading="approvalLoading" @click="handleApproval(2)">涓嶆壒鍑�</el-button>
+        <el-button :loading="reviewLoading" type="primary" @click="handleApproval(1)">鎵� 鍑�</el-button>
+      </span>
+    </el-dialog>
+    <el-dialog :visible.sync="uploadDia" title="鏁版嵁瀵煎叆" width="500px">
+      <div style="margin: 0 auto">
+        <el-upload ref="upload" :action="javaApi + '/personTraining/personTrainingImport'" :auto-upload="false"
+          :before-upload="beforeUpload" :file-list="fileList" :headers="uploadHeader" :limit="1" :on-error="onError"
+          :on-success="onSuccess" accept=".xlsx" drag name="file">
+          <i class="el-icon-upload"></i>
+          <div class="el-upload__text">灏嗘枃浠舵嫋鍒版澶勶紝鎴�<em>鐐瑰嚮涓婁紶</em></div>
+        </el-upload>
+      </div>
+      <span slot="footer" class="dialog-footer">
+        <el-button @click="uploadDia = false">鍙� 娑�</el-button>
+        <el-button :loading="uploading" type="primary" @click="submitUpload()">涓� 浼�</el-button>
+      </span>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import TableCard from '@/components/TableCard/index.vue';
+import limsTable from "@/components/Table/lims-table.vue";
+import Add from "./AddInDetail.vue";
+import Edit from "./Edit.vue";
+import {
+  deleteDetail,
+  personTrainingSelect,
+  queryTheAnnualPlanDetailsTable,
+  personTrainingDelete,
+  reviewAnnualPersonnelTraining,
+  approveAnnualPersonnelTraining,
+  exportPersonTrainingRecord,
+  claimOfTrainingAndAssessmentRecords,
+  exportPersonTraining,
+  deleteAnnualPlanDetailTable,
+} from '@/api/cnas/personnel/personnelInfo.js'
+
+export default {
+  name: "PersonnelTraining",
+  components: { Add, limsTable, TableCard, Edit },
+  props: {
+    flag: {
+      type: Boolean,
+      default: false,
+    },
+    departId: {
+      type: Number,
+      default: () => {
+        return null;
+      },
+    },
+    isDepartment: {
+      type: Boolean,
+      default: false,
+    },
+  },
+  data() {
+    return {
+      currentPlanId: null,
+      activeName: "first",
+      addInDetail: false,
+      departId2: null,
+      editKey: 1,
+      search: {},
+      superviseForm: {},
+      inDetailForm: {
+        trainingLecturerName: "",
+        courseCode: "",
+        trainingDate: "",
+      },
+      yearLoading: false,
+      yearPlanTableData: [], // 骞村害璁″垝琛ㄦ暟鎹�
+      yearPlanColumn: [
+        {
+          label: "鏂囦欢鍚嶇О",
+          width: "160px",
+          minWidth: "160px",
+          prop: "fileName",
+          showOverflowTooltip: true,
+        },
+        {
+          label: "鍒涘缓鏃堕棿",
+          width: "160px",
+          prop: "createTime",
+        },
+        {
+          label: "鍒涘缓浜�",
+          prop: "createUserName",
+        },
+        {
+          label: "缂栧埗浜�",
+          prop: "compilerName",
+        },
+        {
+          label: "缂栧埗鏃ユ湡",
+          width: "160px",
+          prop: "compilationDate",
+        },
+        {
+          label: "瀹℃牳浜�",
+          prop: "reviewerName",
+          minWidth: "100px",
+        },
+        {
+          dataType: "tag",
+          label: "瀹℃牳鐘舵��",
+          prop: "reviewerStatus",
+          width: "100px",
+          formatData: (params) => {
+            if (params == 1) {
+              return "閫氳繃";
+            } else if (params == 2) {
+              return "涓嶉�氳繃";
+            } else {
+              return null;
+            }
+          },
+          formatType: (params) => {
+            if (params == 1) {
+              return "success";
+            } else if (params == 2) {
+              return "danger";
+            } else {
+              return null;
+            }
+          },
+        },
+        {
+          label: "瀹℃牳澶囨敞",
+          prop: "auditRemarks",
+          minWidth: "100px",
+        },
+        {
+          label: "瀹℃牳鏃ユ湡",
+          width: "160px",
+          prop: "auditDate",
+        },
+        {
+          label: "鎵瑰噯浜�",
+          prop: "approverName",
+          minWidth: "100px",
+        },
+        {
+          label: "鎵瑰噯澶囨敞",
+          prop: "approvalRemarks",
+          minWidth: "100px",
+        },
+        {
+          dataType: "tag",
+          label: "鎵瑰噯鐘舵��",
+          minWidth: "100px",
+          prop: "approvalStatus",
+          formatData: (params) => {
+            if (params == 1) {
+              return "鎵瑰噯";
+            } else if (params == 2) {
+              return "涓嶆壒鍑�";
+            } else {
+              return null;
+            }
+          },
+          formatType: (params) => {
+            if (params == 1) {
+              return "success";
+            } else if (params == 2) {
+              return "danger";
+            } else {
+              return null;
+            }
+          },
+        },
+        {
+          label: "鎵瑰噯鏃ユ湡",
+          width: "160px",
+          prop: "approvalDate",
+        },
+        {
+          dataType: "action",
+          width: "180px",
+          label: "鎿嶄綔",
+          fixed: "right",
+          operation: [
+            {
+              name: "瀵煎嚭",
+              type: "text",
+              disabled: (row) => {
+                if (row.approvalStatus === 1 && row.reviewerStatus === 1) {
+                  return false;
+                } else {
+                  return true;
+                }
+              },
+              clickFun: (row) => {
+                this.downLoadPost(row);
+              },
+            },
+            {
+              name: "瀹℃牳",
+              type: "text",
+              disabled: (row) => {
+                if (row.reviewerStatus === 1 || (row.departId == 18 && row.currentId != 10 && row.currentId != 16) || (row.departId == 19 && row.currentId != 35 && row.currentId != 16)) {
+                  return true;
+                } else {
+                  return false;
+                }
+              },
+              clickFun: (row) => {
+                this.handleCheck(row.id);
+              },
+            },
+            {
+              name: "鎵瑰噯",
+              type: "text",
+              disabled: (row) => {
+                if (row.approvalStatus === 1 || (row.currentId != 11 && row.currentId != 16)) {
+                  return true;
+                } else {
+                  return false;
+                }
+              },
+              clickFun: (row) => {
+                this.handleApprove(row.id);
+              },
+            },
+            {
+              name: "鍒犻櫎",
+              type: "text",
+              color: "#f56c6c",
+              clickFun: (row) => {
+                this.deleteFun(row.id);
+              },
+            },
+          ],
+        },
+      ],
+      inDetailPlanTableData: [], // 骞村害璁″垝鏄庣粏琛ㄨ〃鏁版嵁
+      inDetailPlanColumn: [
+        // {
+        //   label: '璇剧▼缂栧彿',
+        //   prop: 'courseCode',
+        //   width: '130px',
+        // },
+        {
+          dataType: "tag",
+          label: "鎶ュ悕鐘舵��",
+          width: "100px",
+          prop: "whetherClaim",
+          isShow: this.flag,
+          formatData: (params) => {
+            if (params === true) {
+              return "宸叉姤鍚�";
+            } else {
+              return "鏈姤鍚�";
+            }
+          },
+          formatType: (params) => {
+            if (params === true) {
+              return "success";
+            } else {
+              return "info";
+            }
+          },
+        },
+        {
+          label: "鎶ュ悕浜烘暟",
+          prop: "enrollment",
+          width: "100px",
+          isShow: !this.flag,
+        },
+        {
+          label: "鍩硅鐩爣",
+          prop: "trainingObjectives",
+          width: "160px",
+          minWidth: "160px",
+          showOverflowTooltip: true,
+        },
+        {
+          label: "鍩硅鍐呭",
+          prop: "trainingContent",
+          width: "160px",
+          minWidth: "160px",
+          showOverflowTooltip: true,
+        },
+        {
+          label: "鍩硅鏂瑰紡",
+          prop: "trainingMode",
+          width: "140px",
+          minWidth: "140px",
+          showOverflowTooltip: true,
+        },
+        {
+          dataType: "tag",
+          label: "璇剧▼鐘舵��",
+          width: "100px",
+          prop: "state",
+          formatData: (params) => {
+            if (params == 1) {
+              return "宸插畬鎴�";
+            } else if (params == 2) {
+              return "杩涜涓�";
+            } else if (params == 3) {
+              return "鏈紑濮�";
+            } else if (params == 4) {
+              return "宸茬粨鏉�";
+            } else {
+              return null;
+            }
+          },
+          formatType: (params) => {
+            if (params == 1) {
+              return "success";
+            } else if (params == 2) {
+              return "warning";
+            } else if (params == 3) {
+              return "primary";
+            } else if (params == 4) {
+              return "info";
+            } else {
+              return null;
+            }
+          },
+        },
+        {
+          label: "鍙傚姞瀵硅薄",
+          prop: "participants",
+          width: "140px",
+          minWidth: "140px",
+          showOverflowTooltip: true,
+        },
+        {
+          label: "涓惧姙閮ㄩ棬",
+          prop: "holdingDepartmentName",
+          width: "140px",
+          minWidth: "140px",
+          showOverflowTooltip: true,
+        },
+        {
+          label: "鍩硅鍦扮偣",
+          prop: "placeTraining",
+          width: "160px",
+          minWidth: "160px",
+          showOverflowTooltip: true,
+        },
+        {
+          label: "鍩硅璁插笀",
+          prop: "trainingLecturerId",
+          width: "120px",
+          minWidth: "120px",
+          showOverflowTooltip: true,
+        },
+        {
+          label: "鍩硅鏃ユ湡",
+          prop: "trainingDateTwo",
+          width: "140px",
+        },
+        {
+          label: "寮�濮嬫椂闂�",
+          prop: "openingTime",
+          width: "120px",
+        },
+        {
+          label: "璇炬椂",
+          prop: "classHour",
+          width: "100px",
+        },
+        {
+          label: "澶囨敞",
+          prop: "remarks",
+          width: "120px",
+          minWidth: "120px",
+          showOverflowTooltip: true,
+        },
+        {
+          dataType: "action",
+          width: "240",
+          label: "鎿嶄綔",
+          fixed: "right",
+          operation: [
+            // 瓒呰繃浼氳寮�濮嬫椂闂村氨涓嶈兘璁ら浜�
+            {
+              name: "鎶ュ悕",
+              type: "text",
+              clickFun: (row) => {
+                this.handleClaim(row);
+              },
+              disabled: (row) => {
+                if (
+                  row.whetherClaim === true ||
+                  row.trainingDateTwo < this.$moment().format("YYYY-MM-DD")
+                ) {
+                  return true;
+                } else {
+                  return false;
+                }
+              },
+            },
+            {
+              name: "缁撴灉鏄庣粏",
+              type: "text",
+              clickFun: (row) => {
+                this.editInDetail(row);
+              },
+              showHide: (row) => {
+                if (row.isDisabled == 1) {
+                  return true;
+                } else {
+                  return false;
+                }
+              },
+            },
+            {
+              name: "瀵煎嚭",
+              type: "text",
+              clickFun: (row) => {
+                this.downLoadInDetail(row);
+              },
+            },
+            {
+              name: "鍒犻櫎",
+              type: "text",
+              color: "#f56c6c",
+              clickFun: (row) => {
+                this.deleteDetail(row);
+              },
+              showHide: (row) => {
+                if (row.isDisabled == 1) {
+                  return true;
+                } else {
+                  return false;
+                }
+              },
+            },
+            {
+              name: "缂栬緫",
+              type: "text",
+              clickFun: (row) => {
+                this.editDetail(row);
+              },
+              showHide: (row) => {
+                if (row.isDisabled == 1) {
+                  return true;
+                } else {
+                  return false;
+                }
+              },
+            },
+          ],
+        },
+      ],
+      pagination: {
+        size: 20,
+        current: 1,
+        total: 0,
+        compilerName: "",
+      },
+      inDetailPagination: {
+        size: 20,
+        current: 1,
+        total: 0,
+      },
+      editPlanShow: false,
+      currentRow: {},
+      currentRowId: null, // 褰撳墠閫変腑鏁版嵁鐨刬d
+      reviewRemarks: "", // 瀹℃牳澶囨敞
+      reviewDialog: false, // 瀹℃牳寮规
+      reviewLoading: false, // 瀹℃牳鎻愪氦鎸夐挳
+      approvalRemarks: "", // 瀹℃牳澶囨敞
+      approvalDialog: false, // 瀹℃牳寮规
+      approvalLoading: false, // 瀹℃牳鎻愪氦鎸夐挳
+      multipleSelection: [], // 骞村害鏄庣粏琛ㄩ�変腑鐨勬暟鎹�
+      uploadDia: false,
+      uploading: false,
+      isOperation: false,
+      token: null,
+      fileList: [],
+      currentChangeRow: {},
+      tableHeight: 0,
+    };
+  },
+  beforeDestroy() {
+    window.removeEventListener("resize", this.getTableHeight);
+  },
+  created() {
+    this.getTableHeight();
+  },
+  mounted() {
+    window.addEventListener("resize", this.getTableHeight);
+    this.token = {
+      token: sessionStorage.getItem("token"),
+    };
+    if (this.isDepartment) {
+      this.getYearPlanList(this.departId);
+    } else {
+      this.getInDetailPlan("", this.departId);
+    }
+    console.log("this.flag", this.flag);
+  },
+  methods: {
+    //鍔ㄦ�佽幏鍙栬〃鏍奸珮搴�
+    getTableHeight() {
+      const otherHeight = 548; // 鍏朵綑楂樺害
+      const tableH = 50; // 璺濈椤甸潰涓嬫柟鐨勯珮搴�
+      const tableHeightDetil = window.innerHeight - tableH;
+      if (tableHeightDetil <= 300) {
+        this.tableHeight = 200;
+      } else {
+        this.tableHeight = window.innerHeight - tableH - otherHeight;
+      }
+    },
+    // 缂栬緫鏄庣粏
+    editDetail(row) {
+      this.addInDetail = true;
+      this.$nextTick(() => {
+        this.$refs.addPlan.showEditDialog(row);
+      });
+    },
+    // 鍒犻櫎鏄庣粏
+    deleteDetail(row) {
+      this.$confirm("鏄惁鍒犻櫎?", "鎻愮ず", {
+        confirmButtonText: "纭畾",
+        cancelButtonText: "鍙栨秷",
+        type: "warning",
+      }).then(() => {
+        deleteDetail({ id: row.id }).then((res) => {
+          this.$message.success("鍒犻櫎鎴愬姛");
+          this.searchTable();
+        });
+      });
+    },
+    searchTable() {
+      // 灏嗛〉鐮佽涓�
+      this.inDetailPagination.current = 1
+      this.getInDetailPlan(this.currentRowId);
+    },
+    // 鏌ヨ-骞村害璁″垝琛�
+    getYearPlanList(userId) {
+      const name = this.isDepartment ? "departmentId" : "userId";
+      personTrainingSelect({
+        [name]: userId,
+        size: this.pagination.size,
+        current: this.pagination.current,
+        compilerName: this.pagination.compilerName
+      }).then((res) => {
+        if (res.code === 201) return;
+        let data = {};
+        this.yearPlanTableData = res.data.records;
+        this.pagination.total = res.data.total;
+        if (this.yearPlanTableData.length > 0) {
+          this.currentRowId = this.yearPlanTableData[0].id;
+          if (this.currentPlanId) {
+            let filterData = this.yearPlanTableData.filter(
+              (item) => item.id == this.currentPlanId
+            );
+            if (filterData.length > 0) {
+              data = filterData[0];
+            }
+          } else {
+            data = this.yearPlanTableData[0];
+          }
+          this.currentChange(data);
+        } else {
+          this.inDetailPlanTableData = [];
+        }
+      });
+    },
+    refreshYearPlanList(departmentId) {
+      console.log("鍒锋柊涓昏〃", departmentId);
+      personTrainingSelect({
+        departmentId: departmentId,
+        size: this.pagination.size,
+        current: this.pagination.current,
+        compilerName: this.pagination.compilerName
+      }).then((res) => {
+        if (res.code === 201) return;
+        this.yearPlanTableData = res.data.records;
+        this.pagination.total = res.data.total;
+      });
+    },
+    currentChange(row) {
+      const now = new Date();
+      const currentYear = now.getFullYear();
+      this.currentChangeRow = row;
+      this.currentRowId = row.id;
+      if (row.createTime.slice(0, 4) == currentYear) {
+        this.isOperation = true;
+      } else {
+        this.isOperation = false;
+      }
+      this.currentPlanId = row.id;
+      this.getInDetailPlan(row.id);
+    },
+    getInDetailPlan(id) {
+      if (this.inDetailForm.trainingDate === null) {
+        this.inDetailForm.trainingDate = "";
+      }
+      let state = 3;
+      if (this.activeName != "first") {
+        state = -1;
+      }
+      const userId = this.isDepartment ? "" : this.departId;
+      if (this.currentPlanId) {
+        id = this.currentPlanId;
+      }
+      queryTheAnnualPlanDetailsTable({
+        userId,
+        size: this.inDetailPagination.size,
+        current: this.inDetailPagination.current,
+        trainingLecturerName: this.inDetailForm.trainingLecturerName,
+        trainingDate: this.inDetailForm.trainingDate,
+        courseCode: this.inDetailForm.courseCode,
+        departId: this.departId,
+        state
+      }).then((res) => {
+        if (res.code === 201) return;
+        this.inDetailPlanTableData = res.data.records;
+        this.inDetailPagination.total = res.data.total;
+        this.departId2 = res.data.records[0].departId;
+      });
+    },
+    // 鏂板骞村害璁″垝鏄庣粏琛�
+    addTrainingPlan() {
+      if (!this.currentRowId) {
+        this.$message.warning("璇烽�夋嫨涓�鏉¤鍒掕繘琛屾柊澧�");
+        return;
+      }
+      this.addInDetail = true;
+      this.$nextTick(() => {
+        this.$refs.addPlan.showDialog(this.currentRowId);
+      });
+    },
+    // 骞村害璁″垝琛�-鍒犻櫎
+    deleteFun(id) {
+      this.$confirm("姝ゆ搷浣滃皢姘镐箙鍒犻櫎璇ユ暟鎹�, 鏄惁缁х画?", "鎻愮ず", {
+        confirmButtonText: "纭畾",
+        cancelButtonText: "鍙栨秷",
+        type: "warning",
+      })
+        .then(() => {
+          personTrainingDelete({ id }).then((res) => {
+            this.$message.success("鍒犻櫎鎴愬姛锛�");
+            this.getYearPlanList(this.departId);
+          });
+        })
+        .catch(() => {
+          this.$message({
+            type: "info",
+            message: "宸插彇娑堝垹闄�",
+          });
+        });
+    },
+    // 骞村害璁″垝琛�-瀹℃牳
+    handleCheck(id) {
+      this.currentRowId = id;
+      this.reviewDialog = true;
+    },
+    handleReview(status) {
+      const personTrainingUpdateDto = {
+        id: this.currentRowId,
+        remarks: this.reviewRemarks,
+        status: status,
+      };
+      this.reviewLoading = true;
+      reviewAnnualPersonnelTraining(personTrainingUpdateDto).then((res) => {
+        if (res.code === 200) {
+          this.$message.success("鎻愪氦鎴愬姛锛�");
+          this.reviewDialog = false;
+          this.getYearPlanList(this.departId);
+        }
+        this.reviewLoading = false;
+      })
+        .catch(() => {
+          this.reviewLoading = false;
+        });
+    },
+    // 骞村害璁″垝琛�-鎵瑰噯
+    handleApprove(id) {
+      this.currentRowId = id;
+      this.approvalDialog = true;
+    },
+    handleApproval(status) {
+      const personTrainingUpdateDto = {
+        id: this.currentRowId,
+        remarks: this.approvalRemarks,
+        status: status,
+      };
+      this.approvalLoading = true;
+      approveAnnualPersonnelTraining(personTrainingUpdateDto).then((res) => {
+        if (res.code === 200) {
+          this.$message.success("鎻愪氦鎴愬姛锛�");
+          this.approvalDialog = false;
+          this.getYearPlanList(this.departId);
+        }
+        this.approvalLoading = false;
+      })
+        .catch(() => {
+          this.approvalLoading = false;
+        });
+    },
+    // 骞村害璁″垝琛�-涓嬭浇
+    downLoadPost(row) {
+      exportPersonTraining({ id: row.id }).then((res) => {
+        this.outLoading = false;
+        const blob = new Blob([res], { type: "application/msword" });
+        this.$download.saveAs(blob, row.fileName + ".docx")
+      });
+    },
+    // 骞村害璁″垝-瀵煎叆
+    submitUpload() {
+      if (this.$refs.upload.uploadFiles.length == 0) {
+        this.$message.error("鏈�夋嫨鏂囦欢");
+        return;
+      }
+      this.uploading = true;
+      this.$refs.upload.submit();
+      this.uploading = false;
+    },
+    onSuccess(response, file, fileList) {
+      this.$refs.upload.clearFiles();
+      this.uploadDia = false;
+      this.uploading = false;
+      if (response.code == 201) {
+        this.$message.error(response.message);
+        return;
+      }
+      this.$message.success("涓婁紶鎴愬姛");
+      this.standardList = [];
+      this.productList = [];
+      this.getYearPlanList(this.departId);
+    },
+    onError(err, file, fileList) {
+      this.$message.error("涓婁紶澶辫触");
+      this.$refs.upload.clearFiles();
+      this.uploading = false;
+    },
+    beforeUpload(file, fileList) {
+      if (
+        file.type !=
+        "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
+      ) {
+        this.$message.error("涓婁紶鏂囦欢鏍煎紡涓嶆纭�");
+        this.$refs.upload.clearFiles();
+        return false;
+      }
+    },
+    // 骞村害璁″垝鍒嗛〉
+    paginationMetod({ page, limit }) {
+      this.pagination.current = page;
+      this.pagination.size = limit;
+      this.getYearPlanList();
+    },
+    // 骞村害璁″垝鏄庣粏琛�-璁ら銆佸彇娑堣棰�
+    handleClaim(row) {
+      this.$confirm("鏄惁纭鎶ュ悕璇ヨ绋�?", "鎻愮ず", {
+        confirmButtonText: "鎶ュ悕",
+        cancelButtonText: "鍙栨秷鎶ュ悕",
+        type: "warning",
+      })
+        .then(() => {
+          this.handleClaimFun(true, row.id);
+        })
+        .catch(() => {
+          this.handleClaimFun(false, row.id);
+        });
+    },
+    handleClaimFun(claimAndClaim, rowId) {
+      claimOfTrainingAndAssessmentRecords({
+        claimAndClaim,
+        rowId
+      }).then((res) => {
+        this.getInDetailPlan(this.currentChangeRow.id);
+      });
+    },
+    // 骞村害璁″垝鏄庣粏琛�-缂栬緫
+    editInDetail(row) {
+      this.editPlanShow = true;
+      this.currentRow = row;
+    },
+    //
+    goBack() {
+      this.editPlanShow = false;
+      this.getInDetailPlan(this.currentRowId);
+    },
+    refresh(id) {
+      if (this.inDetailForm.trainingDate === null) {
+        this.inDetailForm.trainingDate = "";
+      }
+      const userId = this.isDepartment ? "" : this.departId;
+      queryTheAnnualPlanDetailsTable({
+        userId,
+        size: this.inDetailPagination.size,
+        current: this.inDetailPagination.current,
+        trainingLecturerName: this.inDetailForm.trainingLecturerName,
+        id,
+        trainingDate: this.inDetailForm.trainingDate,
+        courseCode: this.inDetailForm.courseCode,
+        departId: this.departId
+      }).then((res) => {
+        if (res.code === 201) return;
+        this.inDetailPlanTableData = res.data.records;
+        this.inDetailPagination.total = res.data.total;
+        this.currentRow = this.inDetailPlanTableData.find(
+          (item) => item.id == id
+        );
+        this.editKey += 1;
+      });
+      console.log("鍒锋柊", this.currentRow);
+    },
+    refresh(id) {
+      if (this.inDetailForm.trainingDate === null) {
+        this.inDetailForm.trainingDate = "";
+      }
+      const userId = this.isDepartment ? "" : this.departId;
+      queryTheAnnualPlanDetailsTable({
+        userId,
+        size: this.inDetailPagination.size,
+        current: this.inDetailPagination.current,
+        id,
+        trainingLecturerName: this.inDetailForm.trainingLecturerName,
+        trainingDate: this.inDetailForm.trainingDate,
+        courseCode: this.inDetailForm.courseCode,
+        departId: this.departId
+      }).then((res) => {
+        if (res.code === 201) return;
+        this.inDetailPlanTableData = res.data.records;
+        this.inDetailPagination.total = res.data.total;
+        this.currentRow = this.inDetailPlanTableData.find(
+          (item) => item.id == id
+        );
+        this.editKey += 1;
+      });
+      console.log("鍒锋柊", this.currentRow);
+    },
+    // 骞村害璁″垝鏄庣粏琛�-涓嬭浇
+    downLoadInDetail(row) {
+      exportPersonTrainingRecord({ id: row.id }).then((res) => {
+        this.outLoading = false;
+        const blob = new Blob([res], { type: "application/msword" });
+        this.$download.saveAs(blob, row.courseCode + "浜哄憳鍩硅涓庤�冩牳璁板綍" + ".docx")
+      });
+    },
+    // 骞村害璁″垝鏄庣粏琛�-澶氶��
+    handleSelectionChange(list) {
+      this.multipleSelection = list;
+    },
+    // 骞村害鏄庣粏琛�-鍒犻櫎
+    batchDelete() {
+      if (this.multipleSelection.length > 0) {
+        let ids = [];
+        this.multipleSelection.forEach((item) => {
+          ids.push(item.id);
+        });
+        this.$confirm("鏄惁纭鍒犻櫎鎵�閫夋嫨鐨勬暟鎹�?", "鎻愮ず", {
+          confirmButtonText: "纭畾",
+          cancelButtonText: "鍙栨秷",
+          type: "warning",
+        })
+          .then(() => {
+            deleteAnnualPlanDetailTable({ ids: ids.join(",") }).then((res) => {
+              if (res.code == 200) {
+                this.$message.success("鍒犻櫎鎴愬姛");
+                this.getInDetailPlan(this.currentRowId);
+              }
+            });
+          })
+          .catch(() => {
+            this.$message.warning("鍙栨秷鍒犻櫎");
+          });
+      } else {
+        this.$message.warning("璇烽�夋嫨闇�瑕佸垹闄ょ殑鏁版嵁");
+      }
+    },
+    paginationmethod0({ page, limit }) {
+      this.inDetailPagination.current = page;
+      this.inDetailPagination.size = limit;
+      this.getYearPlanList(this.departId);
+    },
+  },
+  watch: {
+    // 鐩戝惉鐐瑰嚮el-tree鐨勬暟鎹紝杩涜鏁版嵁鍒锋柊
+    departId: {
+      handler(newId, oldId) {
+        this.currentPlanId = null;
+        if (this.isDepartment) {
+          console.log("涓�");
+          this.getYearPlanList(newId);
+        } else {
+          this.getInDetailPlan("");
+        }
+      },
+    },
+    activeName: {
+      handler(newValue, oldValue) {
+        this.getInDetailPlan(this.currentRowId);
+      },
+    },
+  },
+};
+</script>
+<style scoped>
+.flex_column {
+  display: flex;
+  height: 80vh;
+  flex-direction: column;
+  overflow: auto;
+  justify-content: space-between;
+}
+
+.pagination {
+  display: flex;
+  justify-content: space-between;
+}
+
+.items_center {
+  display: flex;
+  align-items: center;
+}
+
+.date_box {
+  margin: 0 5px;
+}
+
+.search {
+  width: 150px;
+  margin: 0 16px;
+}
+</style>
diff --git a/src/views/CNAS/personnel/personnelInfo/Department/components/Plan/Add.vue b/src/views/CNAS/personnel/personnelInfo/Department/components/Plan/Add.vue
new file mode 100644
index 0000000..44d9244
--- /dev/null
+++ b/src/views/CNAS/personnel/personnelInfo/Department/components/Plan/Add.vue
@@ -0,0 +1,172 @@
+<template>
+    <div class="add">
+        <el-dialog :title="isEdit ? '缂栬緫鐩戠潱璁″垝鏄庣粏' : '鏂板鐩戠潱璁″垝鏄庣粏'" :visible.sync="dialogVisible" width="800px">
+            <el-form ref="formRef" :model="ruleForm" :rules="rules" label-width="100px">
+                <el-col :span="12">
+                    <el-form-item label="鐩戠潱鏃ユ湡" prop="superviseDate">
+                        <el-date-picker v-model="ruleForm.superviseDate" format="yyyy-MM-dd" placeholder="閫夋嫨鏃ユ湡"
+                            style="width: 100%;" type="date" value-format="yyyy-MM-dd"></el-date-picker>
+                    </el-form-item>
+                </el-col>
+                <el-col :span="12">
+                    <el-form-item label="鐩戠潱鐩殑" prop="superviseDes">
+                        <el-input v-model="ruleForm.superviseDes"></el-input>
+                    </el-form-item>
+                </el-col>
+                <el-col :span="12">
+                    <el-form-item label="鐩戠潱椤圭洰" prop="superviseProject">
+                        <el-input v-model="ruleForm.superviseProject"></el-input>
+                    </el-form-item>
+                </el-col>
+                <el-col :span="12">
+                    <el-form-item label="琚洃鐫d汉" prop="supervisePerson">
+                        <el-input v-model="ruleForm.supervisePerson"></el-input>
+                    </el-form-item>
+                </el-col>
+                <el-col :span="24">
+                    <el-form-item label="鐩戠潱鍘熷洜" prop="superviseReason">
+                        <el-input v-model="ruleForm.superviseReason"></el-input>
+                    </el-form-item>
+                </el-col>
+                <el-col :span="24">
+                    <el-form-item label="澶囨敞" prop="remarks">
+                        <el-input v-model="ruleForm.remarks"></el-input>
+                    </el-form-item>
+                </el-col>
+            </el-form>
+            <div slot="footer" class="foot">
+                <el-button @click="dialogVisible = false">鍙� 娑�</el-button>
+                <el-button :loading="loading" type="primary" @click="submitForm">纭� 瀹�</el-button>
+            </div>
+        </el-dialog>
+    </div>
+</template>
+<script>
+import {
+    yearPlanDetailAdd,
+    yearPlanDetailEdit
+} from '@/api/cnas/personnel/personnelInfo.js'
+export default {
+    props: {
+        planId: {
+            type: Number,
+            default: undefined
+        }
+    },
+    data() {
+        return {
+            loading: false,
+            isEdit: false,
+            dialogVisible: false,
+            ruleForm: {
+                id: undefined,
+                superviseDate: undefined, // 鐩戠潱鏃ユ湡
+                superviseDes: undefined, // 鐩戠潱鐩殑
+                superviseProject: undefined, // 鐩戠潱椤圭洰
+                supervisePerson: undefined, // 琚洃鐫d汉
+                superviseReason: undefined, // 鐩戠潱鍘熷洜
+                remarks: undefined, // 澶囨敞
+            },
+            rules: {
+                superviseDate: [{ required: true, message: '璇烽�夋嫨鏃ユ湡', trigger: 'change' }],
+                superviseDes: [{ required: true, message: '璇疯緭鍏ョ洃鐫g洰鐨�', trigger: 'blur' }],
+                superviseProject: [{ required: true, message: '璇疯緭鍏ョ洃鐫i」鐩�', trigger: 'blur' }],
+                supervisePerson: [{ required: true, message: '璇疯緭鍏ヨ鐩戠潱浜�', trigger: 'blur' }],
+                superviseReason: [{ required: true, message: '璇疯緭鍏ョ洃鐫e師鍥�', trigger: 'blur' }],
+            }
+        }
+    },
+    methods: {
+        formatForm(row) {
+            this.ruleForm.id = undefined
+            this.ruleForm.planId = row.planId
+            this.ruleForm.superviseDate = undefined
+            this.ruleForm.superviseDes = undefined
+            this.ruleForm.superviseProject = undefined
+            this.ruleForm.supervisePerson = undefined
+            this.ruleForm.superviseReason = undefined
+            this.ruleForm.remarks = undefined
+        },
+        renderForm(row) {
+            this.ruleForm.id = row.id
+            this.ruleForm.superviseDate = row.superviseDate
+            this.ruleForm.superviseDes = row.superviseDes
+            this.ruleForm.superviseProject = row.superviseProject
+            this.ruleForm.supervisePerson = row.supervisePerson
+            this.ruleForm.superviseReason = row.superviseReason
+            this.ruleForm.remarks = row.remarks
+        },
+        showDialog(row, type) {
+            console.log(row)
+            if (type) {
+                this.isEdit = true
+                this.renderForm(row)
+            } else {
+                this.formatForm(row)
+                this.isEdit = false
+            }
+            this.dialogVisible = true
+        },
+        closeDialog() {
+            this.dialogVisible = false
+        },
+        async addYearDetail() {
+            const { code, data } = await yearPlanDetailAdd(this.ruleForm)
+            this.loading = false
+            if (code == 200) {
+                this.$message({
+                    type: 'success',
+                    message: '鏂板鎴愬姛'
+                })
+                this.closeDialog()
+                this.$emit('submit')
+            } else {
+                this.$message({
+                    type: 'error',
+                    message: '鏂板澶辫触'
+                })
+            }
+        },
+        async editYearDetail() {
+            const { code, data } = await yearPlanDetailEdit(this.ruleForm)
+            this.loading = false
+            if (code == 200) {
+                this.$message({
+                    type: 'success',
+                    message: '缂栬緫鎴愬姛'
+                })
+                this.closeDialog()
+                this.$emit('submit')
+            } else {
+                this.$message({
+                    type: 'error',
+                    message: '缂栬緫澶辫触'
+                })
+            }
+        },
+        submitForm() {
+            this.$refs.formRef.validate((valid) => {
+                if (valid) {
+                    this.loading = true
+                    if (this.isEdit) {
+                        this.editYearDetail()
+                    } else {
+                        this.addYearDetail()
+                    }
+                } else {
+                    return false;
+                }
+            })
+        },
+    }
+}
+</script>
+<style scoped>
+.foot {
+    width: 100%;
+}
+
+.add>>>.el-dialog__footer {
+    padding-right: 20px;
+}
+</style>
diff --git a/src/views/CNAS/personnel/personnelInfo/Department/components/Plan/UploadExcel.vue b/src/views/CNAS/personnel/personnelInfo/Department/components/Plan/UploadExcel.vue
new file mode 100644
index 0000000..dec71b7
--- /dev/null
+++ b/src/views/CNAS/personnel/personnelInfo/Department/components/Plan/UploadExcel.vue
@@ -0,0 +1,44 @@
+<template>
+    <div>
+        <el-upload ref="upload" action="#" :before-upload="beforeUpload" :http-request="uploadFile"
+            :file-list="fileList" :on-success="uploadFileSuccess" accept=".xls, .xlsx" :limit="1" :auto-upload="true"
+            :show-file-list="false">
+            <el-button size="small" type="primary">瀵煎叆</el-button>
+        </el-upload>
+    </div>
+</template>
+<script>
+import {
+    yearPlanDetailImport
+} from '@/api/cnas/personnel/personnelInfo.js'
+export default {
+    data() {
+        return {
+            fileList: []
+        }
+    },
+    methods: {
+        /**
+         * @desc 涓婁紶鏂囦欢
+         */
+        beforeUpload(file) {
+            this.fileList = [file]
+        },
+        /**
+         * @desc 涓婁紶鑷虫湇鍔″櫒
+         */
+        async uploadFile() {
+            console.log('鏂囦欢', this.fileList[0])
+            let formData = new FormData()
+            formData.append('file', this.fileList[0])
+            const { code, data } = await yearPlanDetailImport(formData)
+            if (code == 200) {
+                this.$emit('upload')
+            }
+        },
+        uploadFileSuccess() {
+            this.$refs.upload.clearFiles()
+        }
+    }
+}
+</script>
\ No newline at end of file
diff --git a/src/views/CNAS/personnel/personnelInfo/Department/components/Plan/index.vue b/src/views/CNAS/personnel/personnelInfo/Department/components/Plan/index.vue
new file mode 100644
index 0000000..6ef1c26
--- /dev/null
+++ b/src/views/CNAS/personnel/personnelInfo/Department/components/Plan/index.vue
@@ -0,0 +1,484 @@
+<template>
+    <div class="flex_column">
+        <div>
+            <TableCard title="骞村害璁″垝琛�">
+                <template v-slot:form>
+                    <div class="items_center">
+                        <span>缂栧埗浜�</span>
+                        <el-input v-model="yearForm.organizationPerson" class="search" placeholder="璇疯緭鍏�"
+                            size="small"></el-input>
+                        <el-button size="small" type="primary" @click="getYearPlanList">鏌ヨ</el-button>
+                        <el-button size="small" @click="clearYear">娓呯┖</el-button>
+                    </div>
+                    <!-- <UploadExcel v-if="isShowButton" @upload="getYearPlanList"></UploadExcel> -->
+                    <el-upload ref="upload" v-if="isShowButton" :action="action" :data="uploadData"
+                        :headers="uploadHeader" :before-upload="beforeUpload" :on-success="onSuccess">
+                        <el-button size="small" type="primary">瀵煎叆</el-button>
+                    </el-upload>
+
+
+
+
+                </template>
+                <template v-slot:table>
+                    <limsTable ref="yearTable" :column="yearColumnData" :height="'calc(100vh - 38em)'"
+                        :highlightCurrentRow="true" :rowClick="rowClick" :table-data="yearTableData"
+                        :table-loading="yearLoading" style="margin-top: 0.5em;
+                        padding: 0 15px;" :page="yearPage" @pagination="yearPagination">
+                    </limsTable>
+                </template>
+            </TableCard>
+        </div>
+        <div style="width: 100%; height: 0.5em; background-color: #f5f7fb;"></div>
+        <div>
+            <TableCard title="骞村害璁″垝鏄庣粏琛�">
+                <template v-slot:form>
+                    <div class="items_center">
+                        <span>鐩戠潱鏃ユ湡</span>
+                        <el-date-picker v-model="yearDetailForm.date" class="date_box" format="yyyy-MM-dd"
+                            placeholder="閫夋嫨鏃ユ湡" size="small" type="date" value-format="yyyy-MM-dd">
+                        </el-date-picker>
+                        <span>鐩戠潱椤圭洰</span>
+                        <el-input v-model="yearDetailForm.project" class="search" placeholder="璇疯緭鍏�"
+                            size="small"></el-input>
+                        <el-button size="small" type="primary" @click="getYearDetailPlanList">鏌ヨ</el-button>
+                        <el-button size="small" @click="clearDetail">娓呯┖</el-button>
+                    </div>
+                    <div>
+                        <el-button v-if="isOperation" size="small" type="primary"
+                            @click="showDialog('add')">鏂板</el-button>
+                    </div>
+                </template>
+                <template v-slot:table>
+                    <limsTable :column="yearDetailColumnData" :height="'calc(100vh - 38em)'"
+                        :table-data="yearDetailTableData" :table-loading="yearDetailLoading"
+                        style="margin-top: 18px; padding: 0 15px;" :page="yearDeatilPage"
+                        @pagination="yearDeatilPagination">
+                    </limsTable>
+                </template>
+            </TableCard>
+        </div>
+        <PlanAdd ref="planModal" :planId="planId" @submit="handleForm"></PlanAdd>
+    </div>
+</template>
+<script>
+import TableCard from '@/components/TableCard/index.vue';
+import PlanAdd from "./Add.vue"
+import limsTable from "@/components/Table/lims-table.vue";
+import UploadExcel from "./UploadExcel.vue"
+import {
+    yearPlanList,
+    yearPlanDetailList,
+    yearPlanDel,
+    yearPlanDetailDel,
+    yearPlanDetailApproval,
+    exportSuperVisePlan
+} from '@/api/cnas/personnel/personnelInfo.js'
+
+export default {
+    props: {
+        departId: {
+            type: Number,
+            default: null
+        }
+    },
+
+
+    components: {
+        TableCard,
+        PlanAdd,
+        limsTable,
+        UploadExcel
+    },
+    data() {
+        return {
+            uploadData: {},
+            isShowButton: false,
+            planId: undefined,
+            yearForm: {
+                organizationPerson: undefined,
+            },
+            yearTableData: [],  // 骞磋〃
+            yearPage: {
+                curent: 1,
+                pageSize: 20,
+                total: 0
+            },
+            yearColumnData: [
+                {
+                    label: '鏂囦欢鍚嶇О',
+                    prop: 'fileName',
+                    minWidth: '150px'
+                }, {
+                    label: '缂栧埗浜�',
+                    prop: 'organizationPersonName',
+                    minWidth: '100'
+                }, {
+                    label: '缂栧埗鏃ユ湡',
+                    prop: 'organizationDate',
+                    minWidth: '160'
+                }, {
+                    label: '鎵瑰噯浜�',
+                    prop: 'approvalName',
+                    minWidth: '100'
+                }, {
+                    label: '鎵瑰噯鏃ユ湡',
+                    prop: 'approvalDate',
+                    minWidth: '160'
+                }, {
+                    label: '瀹℃牳浜�',
+                    prop: 'examine'
+                }, {
+                    dataType: 'tag',
+                    label: '鎵瑰噯鐘舵��',
+                    prop: 'approvalStatus',
+                    minWidth: '130',
+                    formatData: (params) => {
+                        if (params == 1) {
+                            return '鎵瑰噯'
+                        } else {
+                            return '涓嶆壒鍑�'
+                        }
+                    },
+                    formatType: (params) => {
+                        if (params == 1) {
+                            return 'success'
+                        } else {
+                            return 'danger'
+                        }
+                    }
+                }, {
+                    label: '鍒涘缓鏃ユ湡',
+                    prop: 'createTime',
+                    minWidth: '160'
+                }, {
+                    label: '鍒涘缓浜�',
+                    prop: 'createName',
+                    minWidth: '100'
+                }, {
+                    dataType: 'action',
+                    minWidth: '160',
+                    label: '鎿嶄綔',
+                    fixed: 'right',
+                    operation: [
+                        {
+                            name: '瀵煎嚭',
+                            type: 'text',
+                            clickFun: (row) => {
+                                this.downLoadPost(row)
+                            }
+                        },
+                        {
+                            name: '鎵瑰噯',
+                            type: 'text',
+                            disabled: (row) => {
+                                if (row.approvalStatus == 1 || (row.departId == 18 && ![12, 11, 16].includes(row.currentId)) || (row.departId == 19 && ![35, 41, 16].includes(row.currentId))) {
+                                    return true
+                                } else {
+                                    return false
+                                }
+                            },
+                            clickFun: (row) => {
+                                this.approvalYearPlan(row)
+                            }
+                        },
+                        {
+                            name: '鍒犻櫎',
+                            type: 'text',
+                            color: '#f56c6c',
+                            clickFun: (row) => {
+                                this.delYearPlan(row.id)
+                            }
+                        }
+                    ]
+                }],
+            yearLoading: false,
+            yearDetailForm: {
+                date: undefined,
+                project: undefined
+            },
+            yearDetailTableData: [],    // 骞存槑缁嗚〃
+            yearDeatilPage: {
+                curent: 1,
+                pageSize: 20,
+                total: 0
+            },
+            yearDetailColumnData: [
+                {
+                    label: '鐩戠潱鏃ユ湡',
+                    prop: 'superviseDate'
+                }, {
+                    label: '鐩戠潱鐩殑',
+                    prop: 'superviseDes'
+                }, {
+                    label: '琚洃鐫d汉鍛�',
+                    prop: 'supervisePerson'
+                }, {
+                    label: '澶囨敞',
+                    prop: 'remarks'
+                }, {
+                    label: '鍩硅鏃ユ湡',
+                    prop: 'trainDate'
+                }, {
+                    label: '鍒涘缓',
+                    prop: 'createBy'
+                }, {
+                    dataType: 'action',
+                    width: '180',
+                    label: '鎿嶄綔',
+                    operation: [
+                        {
+                            name: '缂栬緫',
+                            type: 'text',
+                            clickFun: (row) => {
+                                this.$refs.planModal.showDialog(row, true)
+                            }
+                        },
+                        {
+                            name: '鍒犻櫎',
+                            type: 'text',
+                            color: '#f56c6c',
+                            clickFun: (row) => {
+                                this.delYearPlanDetail(row.id)
+                            }
+                        }
+                    ]
+                }
+            ],
+            yearDetailLoading: false,
+            isOperation: false,
+        }
+    },
+    mounted() {
+        this.getYearPlanList()
+        // this.getPower()
+        // this.getYearDetailPlanList()
+
+    },
+    computed: {
+        action() {
+            return this.javaApi + '/superVisePlan/yearPlanDetailImport'
+        },
+    },
+    watch: {
+        departId(newValue, oldValue) {
+            this.getYearPlanList();
+        }
+    },
+    methods: {
+        // 涓婁紶鍓嶇殑閽╁瓙
+        beforeUpload(file) {
+            let list = file.name.split(".")
+            let fileName = list[list.length - 1]
+            this.$set(this.uploadData, "suffix", fileName)
+        },
+        // 鎴愬姛涔嬪悗鐨勯挬瀛�
+        onSuccess(response, file, fileList) {
+            this.getYearPlanList();
+            this.$message.success("瀵煎叆鎴愬姛")
+            this.$refs.upload.clearFiles()
+        },
+        getPower() {
+            let power = JSON.parse(sessionStorage.getItem('power'))
+            let up = false
+            for (var i = 0; i < power.length; i++) {
+                if (power[i].menuMethod == 'yearPlanDetailImport') {
+                    up = true
+                }
+            }
+            if (!up) {
+                this.isShowButton = false
+            } else {
+                this.isShowButton = true
+            }
+        },
+        /**
+         * @desc 鏌ヨ骞村害璁″垝鍒楄〃
+         */
+        async getYearPlanList() {
+            this.yearLoading = true
+            const { code, data } = await yearPlanList({
+                current: this.yearPage.curent,
+                size: this.yearPage.pageSize,
+                organizationPerson: this.yearForm.organizationPerson,
+                departId: this.departId
+            })
+            if (code == 200) {
+                this.yearTableData = data.records
+                this.yearPage.total = data.total
+                if (this.yearTableData.length > 0) {
+                    this.rowClick(this.yearTableData[0])
+                } else {
+                    this.yearDetailTableData = []
+                }
+            }
+            console.log('涓昏〃鏁版嵁', this.yearTableData);
+            this.yearLoading = false
+        },
+        // 骞磋鍒掑垎椤�
+        yearPagination({ page, limit }) {
+            this.yearPage.current = page;
+            this.yearPage.size = limit;
+            this.getYearPlanList();
+        },
+        // 骞村害璁″垝琛ㄦ牸锛岀偣鍑昏鏁版嵁鍚庡埛鏂拌鎯�
+        rowClick(row) {
+            const now = new Date();
+            const currentYear = now.getFullYear();
+            if (row.createTime.slice(0, 4) == currentYear) {
+                this.isOperation = true;
+            } else {
+                this.isOperation = false;
+            }
+            this.planId = row.id
+            this.getYearDetailPlanList()
+        },
+        // 鏂板|缂栬緫瀹屾垚鍚庡仛浠�涔�
+        handleForm() {
+            this.getYearDetailPlanList()
+        },
+        // 娓呴櫎骞�
+        clearYear() {
+            this.$refs.yearTable.setCurrent()
+            this.yearForm.organizationPerson = undefined
+            this.getYearPlanList()
+        },
+        // 娓呴櫎鏄庣粏
+        clearDetail() {
+            this.yearDetailForm.date = undefined
+            this.yearDetailForm.project = undefined
+            this.getYearDetailPlanList()
+        },
+
+        /**
+         * @desc 鏌ヨ骞村害璁″垝鏄庣粏
+         */
+        async getYearDetailPlanList() {
+            this.yearDetailLoading = true
+            const { code, data } = await yearPlanDetailList({
+                planId: this.planId,
+                current: this.yearDeatilPage.curent,
+                size: this.yearDeatilPage.pageSize,
+                date: this.yearDetailForm.date,
+                project: this.yearDetailForm.project
+            })
+            if (code == 200) {
+                this.yearDetailTableData = data.records
+                this.yearDeatilPage.total = data.total
+            }
+            this.yearDetailLoading = false
+        },
+        showDialog(operationType, row, type = false) {
+            if (operationType === 'add') {
+                if (!this.planId) {
+                    this.$message.warning('璇烽�夋嫨涓�鏉¤鍒掕繘琛屾柊澧�')
+                    return
+                }
+            }
+            this.$refs.planModal.showDialog({ planId: this.planId, ...row }, type)
+        },
+
+
+
+        // 骞存槑缁嗚鍒掑垎椤�
+        yearDeatilPagination({ page, limit }) {
+            this.yearDeatilPage.current = page;
+            this.yearDeatilPage.size = limit;
+            this.getYearDetailPlanList();
+        },
+        // 鍒犻櫎骞磋鍒�
+        delYearPlan(id) {
+            this.$confirm('姝ゆ搷浣滃皢姘镐箙鍒犻櫎璇ユ枃浠�, 鏄惁缁х画?', '鎻愮ず', {
+                confirmButtonText: '纭畾',
+                cancelButtonText: '鍙栨秷',
+                type: 'warning'
+            }).then(async () => {
+                const { code } = await yearPlanDel({ id })
+                if (code == 200) {
+                    this.$message.success('鍒犻櫎鎴愬姛')
+                    this.getYearPlanList()
+                    this.getYearDetailPlanList()
+                } else {
+                    this.$message.error('鍒犻櫎澶辫触')
+                }
+            })
+        },
+        // 鍒犻櫎骞磋鍒掓槑缁�
+        delYearPlanDetail(id) {
+            this.$confirm('姝ゆ搷浣滃皢姘镐箙鍒犻櫎璇ユ枃浠�, 鏄惁缁х画?', '鎻愮ず', {
+                confirmButtonText: '纭畾',
+                cancelButtonText: '鍙栨秷',
+                type: 'warning'
+            }).then(async () => {
+                const { code } = await yearPlanDetailDel({ id })
+                if (code == 200) {
+                    this.$message.success('鍒犻櫎鎴愬姛')
+                    this.getYearDetailPlanList()
+                } else {
+                    this.$message.error('鍒犻櫎澶辫触')
+                }
+            })
+        },
+        // 鎵瑰噯骞村害璁″垝
+        approvalYearPlan(row) {
+            this.$confirm('纭鎵瑰噯璇ュ勾搴﹁鍒�?', '鎻愮ず', {
+                confirmButtonText: '鎵瑰噯',
+                cancelButtonText: '涓嶆壒鍑�',
+                type: 'info'
+            }).then(() => {
+                this.approvalYearPlanFun(1, row.id)
+            }).catch(action => {
+                this.approvalYearPlanFun(0, row.id)
+            })
+        },
+        // 骞村害璁″垝琛�-涓嬭浇
+        downLoadPost(row) {
+            exportSuperVisePlan({ id: row.id }).then(res => {
+                this.outLoading = false
+                const blob = new Blob([res], { type: 'application/msword' });
+                this.$download.saveAs(blob, row.fileName + '.docx')
+            })
+        },
+        async approvalYearPlanFun(approvalStatus, rowId) {
+            const { code } = await yearPlanDetailApproval({
+                id: rowId,
+                approvalStatus: approvalStatus
+            })
+            if (code == 200) {
+                this.$message.success('鎿嶄綔鎴愬姛锛�')
+                this.getYearPlanList()
+            } else {
+                this.$message.error('鎿嶄綔鎴愬姛锛�')
+            }
+        }
+    }
+}
+</script>
+<style scoped>
+.flex_column {
+    display: flex;
+    height: 80vh;
+    flex-direction: column;
+    overflow: auto;
+    justify-content: space-between;
+}
+
+.pagination {
+    display: flex;
+    justify-content: space-between
+}
+
+.items_center {
+    display: flex;
+    align-items: center;
+}
+
+.date_box {
+    margin: 0 5px;
+}
+
+.search {
+    width: 150px;
+    padding: 0 16px;
+}
+</style>
diff --git a/src/views/CNAS/personnel/personnelInfo/Department/components/Records/Add.vue b/src/views/CNAS/personnel/personnelInfo/Department/components/Records/Add.vue
new file mode 100644
index 0000000..0919282
--- /dev/null
+++ b/src/views/CNAS/personnel/personnelInfo/Department/components/Records/Add.vue
@@ -0,0 +1,234 @@
+<template>
+    <div class="add">
+        <el-dialog :isEdit="isEdit" :title="isEdit ? '缂栬緫宸ヤ綔鐩戠潱璁板綍' : '鏂板宸ヤ綔鐩戠潱璁板綍'" :visible.sync="dialogVisible" width="800">
+            <el-steps v-if="isEdit" :active="active" :align-center="true" finish-status="success">
+                <el-step style="cursor: pointer;" title="妫�娴�" @click.native="setStep(0)"></el-step>
+                <el-step style="cursor: pointer;" title="瀹℃壒" @click.native="setStep(1)"></el-step>
+            </el-steps>
+            <SuperviseForm v-show="pageStatus == 0" ref="superviseFormRef" :disabled="active != 0" :departId="departId"
+                :isEdit="isEdit" :superviseForm.sync="mainForm.superviseForm" :userList="userList" @addData="addData"
+                @close="closeDialog" @submit="submit"></SuperviseForm>
+            <ApproveForm v-show="pageStatus == 1" ref="approveFormRef" :approveForm.sync="mainForm.approveForm"
+                :disabled="active != 1" :departId="departId" :isEdit="isEdit" :userList="userList" @close="toClose"
+                @submit="submit"></ApproveForm>
+            <el-result v-show="pageStatus == 2" icon="success" subTitle="澶勭悊瀹屾垚" title="瀹℃牳瀹屾垚">
+            </el-result>
+        </el-dialog>
+    </div>
+</template>
+<script>
+import SuperviseForm from './supervise/SuperviseForm.vue'
+import ApproveForm from './supervise/ApproveForm.vue'
+import {
+    selectUserList,
+    addOrUpdatePersonSupervisionRecord
+} from '@/api/cnas/personnel/personnelInfo.js'
+import { dateFormat } from '@/utils/date.js'
+
+export default {
+    props: {
+        departId: {
+            type: Number,
+            default: null
+        }
+    },
+
+    components: {
+        SuperviseForm,
+        ApproveForm
+    },
+    data() {
+        return {
+            active: 0,
+            pageStatus: 0,
+            isEdit: false,
+            dialogVisible: false,
+            userList: [],
+            id: undefined,
+            mainForm: {
+                superviseForm: {
+                    testerId: undefined,
+                    supervisorId: undefined,
+                    testItem: undefined,
+                    sampleNumber: undefined,
+                    detectionDate: undefined,
+                    personnel: [],
+                    instrumentEquipment: undefined,
+                    workingEnvironment: undefined,
+                    sampleCollection: undefined,
+                    samplePreparation: undefined,
+                    testMethod: undefined,
+                    testingRecords: undefined,
+                    testReport: undefined,
+                    evaluationSupervisionSituation: undefined,
+                    doNotMeetTheHandlingOpinions: undefined,
+                },
+                approveForm: {
+                    technicalDirector: undefined
+                }
+            }
+        }
+    },
+    methods: {
+        async openDialog(row, type = false) {
+            this.dialogVisible = true
+            this.isEdit = type
+            console.log('type', this.isEdit);
+            await this.getUserList()
+            if (this.isEdit) {
+                // 缂栬緫
+                this.loadForm(row)
+                this.id = row.id
+                console.log(1111);
+            } else {
+                // 鏂板
+                this.resetForm(row)
+                this.id = undefined
+                console.log(22222);
+            }
+            console.log('this.id', this.id);
+        },
+        /**
+         * @desc 鍔犺浇琛ㄥ崟
+         */
+        loadForm(row) {
+            if (row.currentState) {
+                this.active = Number(row.currentState)
+                this.pageStatus = Number(row.currentState === '2' ? 0 : row.currentState)
+            }
+            // 绗�1姝�
+            this.mainForm.superviseForm.testerId = row.testerId
+            this.mainForm.superviseForm.supervisorId = row.supervisorId
+            this.mainForm.superviseForm.testItem = row.testItem
+            this.mainForm.superviseForm.sampleNumber = row.sampleNumber
+            this.mainForm.superviseForm.detectionDate = row.detectionDate
+            // let personList = row.personnel.split(',')
+            // this.mainForm.superviseForm.personnel = personList.map(item => {
+            //     return Number(item)
+            // });
+            this.mainForm.superviseForm.personnel = row.personnel
+            this.mainForm.superviseForm.instrumentEquipment = row.instrumentEquipment
+            this.mainForm.superviseForm.workingEnvironment = row.workingEnvironment
+            this.mainForm.superviseForm.sampleCollection = row.sampleCollection
+            this.mainForm.superviseForm.samplePreparation = row.samplePreparation
+            this.mainForm.superviseForm.testMethod = row.testMethod
+            this.mainForm.superviseForm.testingRecords = row.testingRecords
+            this.mainForm.superviseForm.testReport = row.testReport
+            this.mainForm.superviseForm.evaluationSupervisionSituation = row.evaluationSupervisionSituation
+            this.mainForm.superviseForm.doNotMeetTheHandlingOpinions = row.doNotMeetTheHandlingOpinions
+            // 绗�2姝�
+            this.mainForm.approveForm.technicalDirector = row.technicalDirector
+        },
+        /**
+         * @desc 閲嶇疆琛ㄥ崟
+         */
+        resetForm(row) {
+            console.log(row)
+            this.active = 0
+            this.pageStatus = 0
+            // 绗�1涓�
+            this.mainForm.superviseForm.currentState = undefined
+            this.mainForm.superviseForm.testerId = undefined
+            this.mainForm.superviseForm.supervisorId = undefined
+            this.mainForm.superviseForm.testItem = undefined
+            this.mainForm.superviseForm.sampleNumber = undefined
+            this.mainForm.superviseForm.detectionDate = undefined
+            this.mainForm.superviseForm.personnel = undefined
+            this.mainForm.superviseForm.instrumentEquipment = undefined
+            this.mainForm.superviseForm.workingEnvironment = undefined
+            this.mainForm.superviseForm.sampleCollection = undefined
+            this.mainForm.superviseForm.samplePreparation = undefined
+            this.mainForm.superviseForm.testMethod = undefined
+            this.mainForm.superviseForm.testingRecords = undefined
+            this.mainForm.superviseForm.testReport = undefined
+            this.mainForm.superviseForm.evaluationSupervisionSituation = undefined
+            this.mainForm.superviseForm.doNotMeetTheHandlingOpinions = undefined
+            // 绗�2涓�
+            this.mainForm.approveForm.technicalDirector = undefined
+            console.log('鏂板', this.mainForm);
+
+
+        },
+        closeDialog() {
+            this.dialogVisible = false
+        },
+        /**
+         * @desc 鑾峰彇鐢ㄦ埛淇℃伅
+         */
+        async getUserList() {
+            const { code, data } = await selectUserList()
+            if (code == 200) {
+                this.userList = data
+            }
+        },
+        /**
+         * @desc 椹冲洖
+         */
+        toClose() {
+            this.submitFormApi({
+                id: this.id,
+                currentState: 0,
+            })
+        },
+        /**
+         * @desc 鏂板
+         */
+        addData(step) {
+            let data = this.setParams(step)
+            this.submitFormApi(data)
+        },
+        /**
+         * @desc 缂栬緫
+         */
+        submit(step) {
+            let data = this.setParams(step)
+            data.id = this.id
+            this.submitFormApi(data)
+        },
+        // 璁剧疆鍙傛暟
+        setParams(step) {
+            if (step == 1) {
+                let result = this.mainForm.superviseForm
+                result.currentState = this.active + 1
+                result.technicalDirectorDate = dateFormat(new Date(), 'YYYY-MM-DD HH:mm:ss')
+                return result
+            }
+            if (step == 2) {
+                let result = this.mainForm.approveForm
+                result.currentState = this.active + 1
+                return result
+            }
+        },
+        // 鍚戞湇鍔″櫒鍙戦�佽〃鍗�
+        async submitFormApi(data) {
+            console.log('鎺ュ彛琛ㄥ崟', data)
+            // 灏嗛儴闂ㄥ甫鍏�
+            if (data.id == null) {
+                data.departLimsId = this.departId
+            }
+            const { code } = await addOrUpdatePersonSupervisionRecord(data)
+            if (code == 200) {
+                this.$message.success('鎿嶄綔鎴愬姛')
+                this.dialogVisible = false
+                this.$emit('submit')
+            }
+        },
+        setStep(e) {
+            this.pageStatus = e
+        }
+    }
+}
+</script>
+<style scoped>
+.foot {
+    width: 100%;
+}
+
+.add>>>.el-dialog__footer {
+    padding-right: 20px;
+}
+
+.main_right {
+    text-align: left;
+}
+</style>
diff --git a/src/views/CNAS/personnel/personnelInfo/Department/components/Records/control/Step/ConditionForm.vue b/src/views/CNAS/personnel/personnelInfo/Department/components/Records/control/Step/ConditionForm.vue
new file mode 100644
index 0000000..42a1e7b
--- /dev/null
+++ b/src/views/CNAS/personnel/personnelInfo/Department/components/Records/control/Step/ConditionForm.vue
@@ -0,0 +1,145 @@
+<template>
+    <el-form label-width="160px" :model="form" :disabled="disabled" style="position: relative;" size="small">
+        <el-card :body-style="{ height: '350px', overflow: 'auto' }">
+            <el-form-item label="閮ㄩ棬璐熻矗浜�">
+                <el-select v-model="form.departmentHeadId" placeholder="璇烽�夋嫨" style="width: 100%">
+                    <el-option v-for="(item, index) in userList" :key="index" :label="item.name"
+                        :value="item.id"></el-option>
+                </el-select>
+            </el-form-item>
+            <el-form-item label="琚洃鐫d汉">
+                <el-select v-model="form.supervisedPersonId" placeholder="璇烽�夋嫨" style="width: 100%">
+                    <el-option v-for="(item, index) in userList" :key="index" :label="item.name"
+                        :value="item.id"></el-option>
+                </el-select>
+            </el-form-item>
+            <el-form-item label="涓嶇鍚堝伐浣滃彂鐜伴�斿緞">
+                <el-checkbox-group v-model="form.discoveryApproach">
+                    <el-checkbox v-for="(item, index) in checkbox" :key="index" :label="item.value" name="type">{{
+                        item.label }}
+                    </el-checkbox>
+                </el-checkbox-group>
+            </el-form-item>
+            <el-form-item label="涓嶇鍚堝伐浣滅殑璇︾粏璁板綍">
+                <el-input v-model="form.notConformDetails" type="textarea" :rows="2" placeholder="璇疯緭鍏ュ唴瀹�"></el-input>
+            </el-form-item>
+            <el-form-item label="涓嶇鍚堢殑渚濇嵁鍙婃潯娆惧彿">
+                <el-input v-model="form.nonConformityClause" type="textarea" :rows="2" placeholder="璇疯緭鍏ュ唴瀹�"></el-input>
+            </el-form-item>
+        </el-card>
+        <el-form-item label-width="0">
+            <div style=" display: flex; width: 100%; justify-content: space-between; margin-top: 15px;">
+                <div>
+                    鎿嶄綔浜猴細{{ currentResponsible }}
+                </div>
+                <div v-if="step == 0 || step == 1">
+                    <el-button v-if="step == 1" :disabled="false" @click="cancel">椹冲洖</el-button>
+                    <el-button :disabled="false" @click="save">淇濆瓨</el-button>
+                    <el-button type="primary" @click="onSubmit"
+                        :disabled="(supervisedPersonId != null && userId != supervisedPersonId) ||
+                            ((departId == 18 && ![12, 10, 16].includes(userId)) || (departId == 19 && ![35, 41, 16].includes(userId)))">鎻愪氦</el-button>
+                </div>
+            </div>
+        </el-form-item>
+    </el-form>
+</template>
+<script>
+import { mapGetters } from "vuex";
+export default {
+    props: {
+        departId: {
+            type: Number,
+            default: () => {
+                return null;
+            }
+        },
+        isPermission: {
+            type: Boolean,
+            default: false,
+        },
+        supervisedPersonId: {
+            type: Number,
+            default: null
+        },
+        currentResponsible: {
+            type: String,
+            default: ''
+        },
+        disabled: {
+            type: Boolean,
+            default: false
+        },
+        userList: {
+            type: Array,
+            default: () => {
+                return []
+            }
+        },
+        step: {
+            type: Number,
+            default: 0
+        },
+        condiForm: {
+            type: Object,
+            default: () => {
+                return {}
+            }
+        }
+    },
+    computed: {
+        form: {
+            get() {
+                return this.condiForm
+            },
+            set(val) {
+                this.$emit('update:condiForm', val)
+            }
+        },
+        ...mapGetters(["userId"]),
+    },
+    data() {
+        return {
+            checkbox: [
+                {
+                    label: '绠$悊璇勫',
+                    value: 0
+                }, {
+                    label: '鍐呴儴瀹℃牳',
+                    value: 1
+                }, {
+                    label: '妫�娴嬭繃绋嬫帶鍒�',
+                    value: 2
+                }, {
+                    label: '鍐呴儴璐ㄩ噺鎺у埗',
+                    value: 3
+                }, {
+                    label: '鍐呴儴鐩戠潱',
+                    value: 4
+                }, {
+                    label: '澶栭儴璇勫/妫�鏌�',
+                    value: 5
+                }, {
+                    label: '椤惧鎶曡瘔/鎰忚鍙嶉',
+                    value: 6
+                }, {
+                    label: '鍏朵粬',
+                    value: 7
+                }
+            ],
+        }
+    },
+    created() {
+    },
+    methods: {
+        onSubmit() {
+            this.$emit('nextStep', 'submit')
+        },
+        save() {
+            this.$emit('nextStep', 'save')
+        },
+        cancel() {
+            this.$emit('cancel', 'cancel')
+        }
+    }
+}
+</script>
\ No newline at end of file
diff --git a/src/views/CNAS/personnel/personnelInfo/Department/components/Records/control/Step/Inform.vue b/src/views/CNAS/personnel/personnelInfo/Department/components/Records/control/Step/Inform.vue
new file mode 100644
index 0000000..45b5a65
--- /dev/null
+++ b/src/views/CNAS/personnel/personnelInfo/Department/components/Records/control/Step/Inform.vue
@@ -0,0 +1,103 @@
+<template>
+    <el-form :model="form" label-width="160px" style="position: relative" :disabled="disabled" size="small">
+        <el-card :body-style="{ height: '350px', overflow: 'auto' }">
+            <el-form-item label="閫氱煡瀹㈡埛">
+                <el-radio-group v-model="form.whetherInformCustomer">
+                    <el-radio :label="1">鏄�</el-radio>
+                    <el-radio :label="2">鍚�</el-radio>
+                </el-radio-group>
+            </el-form-item>
+            <el-form-item label="鎭㈠宸ヤ綔">
+                <el-radio-group v-model="form.whetherResumeWork">
+                    <el-radio :label="1">鏄�</el-radio>
+                    <el-radio :label="2">鍚�</el-radio>
+                </el-radio-group>
+            </el-form-item>
+            <el-form-item label="璐ㄩ噺璐熻矗浜�">
+                <el-select v-model="form.qualitySupervisorId" placeholder="璇烽�夋嫨">
+                    <el-option v-for="(item, index) in userList" :key="index" :label="item.name"
+                        :value="item.id"></el-option>
+                </el-select>
+            </el-form-item>
+        </el-card>
+        <el-form-item label-width="0">
+            <div style=" display: flex; width: 100%; justify-content: space-between; margin-top: 15px;">
+                <div>
+                    鎿嶄綔浜猴細{{ currentResponsible }}
+                </div>
+                <div v-if="step == 4">
+                    <el-button @click="cancel">椹冲洖</el-button>
+                    <el-button type="primary" @click="onSubmit"
+                        :disabled="(departId == 18 && ![12, 10, 16].includes(userId)) || (departId == 19 && ![35, 41, 16].includes(userId))">鎻愪氦</el-button>
+                </div>
+            </div>
+        </el-form-item>
+    </el-form>
+</template>
+<script>
+import { mapGetters } from "vuex";
+export default {
+    props: {
+        departId: {
+            type: Number,
+            default: () => {
+                return null;
+            }
+        },
+        isPermission: {
+            type: Boolean,
+            default: false,
+        },
+        currentResponsible: {
+            type: String,
+            default: ''
+        },
+        disabled: {
+            type: Boolean,
+            default: false
+        },
+        userList: {
+            type: Array,
+            default: []
+        },
+        step: {
+            type: Number,
+            default: 0
+        },
+        inform: {
+            type: Object,
+            default: () => {
+                return {}
+            }
+        }
+    },
+    computed: {
+        form: {
+            get() {
+                return this.inform
+            },
+            set(val) {
+                this.$emit('update:inform', val)
+            }
+        },
+        ...mapGetters(["userId"]),
+    },
+    data() {
+        return {
+        }
+    },
+    created() {
+    },
+    methods: {
+        onSubmit() {
+            this.$emit('nextStep', 'submit')
+        },
+        save() {
+            this.$emit('nextStep', 'save')
+        },
+        cancel() {
+            this.$emit('cancel', 'cancel')
+        }
+    }
+}
+</script>
\ No newline at end of file
diff --git a/src/views/CNAS/personnel/personnelInfo/Department/components/Records/control/Step/MeasureForm.vue b/src/views/CNAS/personnel/personnelInfo/Department/components/Records/control/Step/MeasureForm.vue
new file mode 100644
index 0000000..61d72b5
--- /dev/null
+++ b/src/views/CNAS/personnel/personnelInfo/Department/components/Records/control/Step/MeasureForm.vue
@@ -0,0 +1,110 @@
+<template>
+    <el-form :model="form" label-width="200px" style="position: relative;" :disabled="disabled" size="small">
+        <el-card :body-style="{ height: '350px', overflow: 'auto' }">
+            <el-form-item label="璐d换閮ㄩ棬">
+                <el-select v-model="form.responsibleDepartmentId" placeholder="璇烽�夋嫨" @change="filterUserList">
+                    <el-option label="閫氫俊浜у搧瀹為獙瀹�" :value="18"></el-option>
+                    <el-option label="鐢靛姏浜у搧瀹為獙瀹�" :value="19"></el-option>
+                </el-select>
+            </el-form-item>
+            <el-form-item label="璐d换浜�">
+                <el-select v-model="form.responsibleDepartmentPersonId" placeholder="璇烽�夋嫨">
+                    <el-option v-for="(item, index) in userListTwo" :key="index" :label="item.name"
+                        :value="item.id"></el-option>
+                </el-select>
+            </el-form-item>
+            <el-form-item label="娑堥櫎涓嶇鍚堝伐浣滄墍閲囧彇鐨勬帾鏂�">
+                <el-input v-model="form.treatmentMeasures" type="textarea" :rows="2" placeholder="璇疯緭鍏ュ唴瀹�"></el-input>
+            </el-form-item>
+        </el-card>
+        <el-form-item v-if="step == 2" label-width="0px" :disabled="disabled">
+            <div style=" display: flex; width: 100%; justify-content: space-between; margin-top: 15px;">
+                <div>
+                    鎿嶄綔浜猴細{{ currentResponsible }}
+                </div>
+                <div>
+                    <el-button @click="cancel">椹冲洖</el-button>
+                    <el-button type="primary" @click="onSubmit"
+                        :disabled="(departId == 18 && ![12, 10, 16].includes(userId)) || (departId == 19 && ![35, 41, 16].includes(userId))">鎻愪氦</el-button>
+                </div>
+            </div>
+        </el-form-item>
+    </el-form>
+</template>
+<script>
+import { mapGetters } from "vuex";
+export default {
+    props: {
+        departId: {
+            type: Number,
+            default: () => {
+                return null;
+            }
+        },
+        isPermission: {
+            type: Boolean,
+            default: false,
+        },
+        currentResponsible: {
+            type: String,
+            default: ''
+        },
+        disabled: {
+            type: Boolean,
+            default: false
+        },
+        userList: {
+            type: Array,
+            default: []
+        },
+        step: {
+            type: Number,
+            default: 0
+        },
+        handleForm: {
+            type: Object,
+            default: () => {
+                return {}
+            }
+        }
+    },
+    computed: {
+        form: {
+            get() {
+                return this.handleForm
+            },
+            set(val) {
+                this.$emit('update:handleForm', val)
+            }
+        },
+        ...mapGetters(["userId"]),
+    },
+    data() {
+        return {
+            userListTwo: []
+        }
+    },
+    mounted() {
+        this.userListTwo = JSON.parse(JSON.stringify(this.userList))
+    },
+    created() {
+    },
+    methods: {
+        filterUserList() {
+            this.userListTwo = this.userList.filter(item => item.departLimsId.includes(this.form.responsibleDepartmentId))
+            if (!this.userListTwo.some(item => item.id == this.form.responsibleDepartmentPersonId)) {
+                this.form.responsibleDepartmentPersonId = null
+            }
+        },
+        onSubmit() {
+            this.$emit('nextStep', 'submit')
+        },
+        save() {
+            this.$emit('nextStep', 'save')
+        },
+        cancel() {
+            this.$emit('cancel', 'cancel')
+        }
+    }
+}
+</script>
\ No newline at end of file
diff --git a/src/views/CNAS/personnel/personnelInfo/Department/components/Records/control/Step/RectifyForm.vue b/src/views/CNAS/personnel/personnelInfo/Department/components/Records/control/Step/RectifyForm.vue
new file mode 100644
index 0000000..5ac10eb
--- /dev/null
+++ b/src/views/CNAS/personnel/personnelInfo/Department/components/Records/control/Step/RectifyForm.vue
@@ -0,0 +1,101 @@
+<template>
+    <el-form :model="form" label-width="160px" style="position: relative" :disabled="disabled" size="small">
+        <el-card :body-style="{ height: '350px', overflow: 'auto' }">
+            <el-form-item label="鏄惁闇�瑕侀噰鍙栫籂姝f帾鏂�">
+                <el-radio-group v-model="form.correctiveMeasure">
+                    <el-radio :label="1">鏄�</el-radio>
+                    <el-radio :label="2">鍚�</el-radio>
+                </el-radio-group>
+            </el-form-item>
+            <el-form-item label="绾犳鎺柦澶勭悊鍗曡窡韪�">
+                <el-radio-group v-model="form.correctiveMeasureFollowTracks">
+                    <el-radio :label="1">鏄�</el-radio>
+                    <el-radio :label="2">鍚�</el-radio>
+                </el-radio-group>
+            </el-form-item>
+            <el-form-item label="鎶�鏈礋璐d汉">
+                <el-select v-model="form.correctiveMeasurePersonId" placeholder="璇烽�夋嫨">
+                    <el-option v-for="(item, index) in userList" :key="index" :label="item.name"
+                        :value="item.id"></el-option>
+                </el-select>
+            </el-form-item>
+        </el-card>
+        <el-form-item label-width="0">
+            <div style=" display: flex; width: 100%; justify-content: space-between; margin-top: 15px;">
+                <div>
+                    鎿嶄綔浜猴細{{ currentResponsible }}
+                </div>
+                <div v-if="step == 3">
+                    <el-button @click="cancel">椹冲洖</el-button>
+                    <el-button type="primary" @click="onSubmit"
+                        :disabled="(departId == 18 && ![12, 10, 16].includes(userId)) || (departId == 19 && ![35, 41, 16].includes(userId))">鎻愪氦</el-button>
+                </div>
+            </div>
+        </el-form-item>
+    </el-form>
+</template>
+<script>
+import { mapGetters } from "vuex";
+export default {
+    props: {
+        departId: {
+            type: Number,
+            default: () => {
+                return null;
+            }
+        },
+        isPermission: {
+            type: Boolean,
+            default: false,
+        },
+        currentResponsible: {
+            type: String,
+            default: ''
+        },
+        disabled: {
+            type: Boolean,
+            default: false
+        },
+        userList: {
+            type: Array,
+            default: []
+        },
+        step: {
+            type: Number,
+            default: 0
+        },
+        rectifyForm: {
+            type: Object,
+            default: () => {
+                return {}
+            }
+        }
+    },
+    computed: {
+        form: {
+            get() {
+                return this.rectifyForm
+            },
+            set(val) {
+                this.$emit('update:rectifyForm', val)
+            }
+        },
+        ...mapGetters(["userId"]),
+    },
+    data() {
+        return {
+        }
+    },
+    methods: {
+        onSubmit() {
+            this.$emit('nextStep', 'submit')
+        },
+        save() {
+            this.$emit('nextStep', 'save')
+        },
+        cancel() {
+            this.$emit('cancel', 'cancel')
+        }
+    }
+}
+</script>
\ No newline at end of file
diff --git a/src/views/CNAS/personnel/personnelInfo/Department/components/Records/control/index.vue b/src/views/CNAS/personnel/personnelInfo/Department/components/Records/control/index.vue
new file mode 100644
index 0000000..325cf70
--- /dev/null
+++ b/src/views/CNAS/personnel/personnelInfo/Department/components/Records/control/index.vue
@@ -0,0 +1,312 @@
+<template>
+    <div>
+        <el-dialog :visible.sync="dialogVisible" title="涓嶇鍚堝伐浣滄帶鍒跺崟">
+            <el-steps :active="active" :align-center="true" finish-status="success">
+                <el-step v-for="(item, index) in stepList" :key="index" :title="item.label" style="cursor: pointer;"
+                    @click.native="setStep(item.value)"></el-step>
+            </el-steps>
+            <el-divider></el-divider>
+            <ConditionForm v-if="pageStatus == 0" :departId="departId" :isPermission="isPermission"
+                :supervisedPersonId="mainForm.condiForm.supervisedPersonId" :condiForm.sync="mainForm.condiForm"
+                :currentResponsible="currentResponsible" :disabled="active != 0" :step="active" :userList="userList"
+                @nextStep="submit"></ConditionForm>
+            <ConditionForm v-if="pageStatus == 1" :departId="departId" :isPermission="isPermission"
+                :supervisedPersonId="mainForm.condiForm.supervisedPersonId" :condiForm.sync="mainForm.condiForm"
+                :currentResponsible="currentResponsible" :disabled="true" :step="active" :userList="userList"
+                @cancel="cancel" @nextStep="submit"></ConditionForm>
+            <MeasureForm v-if="pageStatus == 2" :departId="departId" :isPermission="isPermission"
+                :currentResponsible="currentResponsible" :disabled="active != 2" :handleForm.sync="mainForm.handleForm"
+                :step="active" :userList="userList" @cancel="cancel" @nextStep="submit"></MeasureForm>
+            <RectifyForm v-if="pageStatus == 3" :departId="departId" :isPermission="isPermission"
+                :currentResponsible="currentResponsible" :disabled="active != 3"
+                :rectifyForm.sync="mainForm.rectifyForm" :step="active" :userList="userList" @cancel="cancel"
+                @nextStep="submit"></RectifyForm>
+            <Inform v-if="pageStatus == 4" :departId="departId" :isPermission="isPermission" :disabled="active != 4"
+                :inform.sync="mainForm.inform" :step="active" :userList="userList" @cancel="cancel" @nextStep="submit">
+            </Inform>
+            <el-result v-if="pageStatus == 5" icon="success" subTitle="澶勭悊瀹屾垚" title="瀹℃牳瀹屾垚">
+            </el-result>
+        </el-dialog>
+    </div>
+</template>
+<script>
+import ConditionForm from './Step/ConditionForm.vue'
+import MeasureForm from './Step/MeasureForm.vue'
+import RectifyForm from './Step/RectifyForm.vue'
+import Inform from './Step/Inform.vue'
+import {
+    selectUserList,
+    personSupervisionControlSheetPage,
+    addOrUpdatePersonSupervisionControl
+} from '@/api/cnas/personnel/personnelInfo.js'
+export default {
+    props: {
+        departId: {
+            type: Number,
+            default: () => {
+                return null;
+            }
+        },
+    },
+    components: {
+        ConditionForm, MeasureForm, RectifyForm, Inform
+    },
+    data() {
+        return {
+            isPermission: true,
+            supervisedPersonId: null,
+            active: 0,
+            pageStatus: 0,
+            dialogVisible: false,
+            currentResponsible: undefined,
+            stepList: [{
+                label: '宸ヤ綔鎯呭喌',
+                value: 0
+            }, {
+                label: '琚洃鐫d汉纭',
+                value: 1
+            }, {
+                label: '澶勭悊鎺柦',
+                value: 2
+            }, {
+                label: '绾犳鎺柦',
+                value: 3
+            }, {
+                label: '閫氱煡瀹㈡埛',
+                value: 4
+            }
+            ],
+            supervisionRecordId: undefined,
+            controlId: undefined,
+            mainForm: {
+                condiForm: {
+                    departmentHeadId: undefined,
+                    supervisedPersonId: undefined,
+                    discoveryApproach: [],
+                    notConformDetails: undefined,
+                    nonConformityClause: undefined,
+                    departLimsId: undefined
+                },
+                handleForm: {
+                    responsibleDepartmentPersonId: undefined,
+                    treatmentMeasures: undefined,
+                    departLimsId: undefined
+                },
+                rectifyForm: {
+                    correctiveMeasure: undefined,
+                    correctiveMeasureFollowTracks: undefined,
+                    correctiveMeasurePersonId: undefined,
+                    departLimsId: undefined
+                },
+                inform: {
+                    whetherInformCustomer: undefined,
+                    whetherResumeWork: undefined,
+                    qualitySupervisorId: undefined,
+                    departLimsId: undefined
+                }
+            },
+            userList: [],
+            controlType: undefined
+        }
+    },
+    mounted() {
+        this.isPermission = isPermission("isSubmit")
+        console.log('鏉冮檺', this.isPermission);
+    },
+    methods: {
+        /**
+         * @desc 鍒濆鍖栬〃鍗�
+         */
+        initForm() {
+            this.mainForm.condiForm.departmentHeadId = undefined
+            this.mainForm.condiForm.supervisedPersonId = undefined
+            this.mainForm.condiForm.discoveryApproach = []
+            this.mainForm.condiForm.notConformDetails = undefined
+            this.mainForm.condiForm.nonConformityClause = undefined
+            this.mainForm.condiForm.departLimsId = undefined
+            this.mainForm.handleForm.responsibleDepartmentPersonId = undefined
+            this.mainForm.handleForm.treatmentMeasures = undefined
+            this.mainForm.handleForm.departLimsId = undefined
+            this.mainForm.rectifyForm.correctiveMeasure = undefined
+            this.mainForm.rectifyForm.correctiveMeasureFollowTracks = undefined
+            this.mainForm.rectifyForm.correctiveMeasurePersonId = undefined
+            this.mainForm.rectifyForm.departLimsId = undefined
+            this.mainForm.inform.whetherInformCustomer = undefined
+            this.mainForm.inform.whetherResumeWork = undefined
+            this.mainForm.inform.qualitySupervisorId = undefined
+            this.mainForm.inform.departLimsId = undefined
+        },
+        /**
+         * @desc 鎵撳紑妯℃�佹
+         * @param {鐩戠潱璁板綍id} id
+         */
+        openDialog(id) {
+            this.dialogVisible = true
+            this.getUserList()
+            this.getControlData(id)
+        },
+        /**
+         * @desc 鑾峰彇鐢ㄦ埛淇℃伅
+         */
+        async getUserList() {
+            const { code, data } = await selectUserList()
+            if (code == 200) {
+                this.userList = data
+            }
+        },
+        /**
+         * @desc 鏌ヨ鐩戠潱璁板綍鎺у埗鍗�
+         * @param {鐩戠潱璁板綍id} id
+         */
+        async getControlData(id) {
+            const { code, data } = await personSupervisionControlSheetPage({ id })
+            if (code == 202) {
+                this.controlType = '鏂板'
+                this.supervisionRecordId = id
+                this.active = 0
+                this.pageStatus = 0
+                this.controlId = undefined
+                this.initForm()
+            }
+            if (code == 200) {
+                this.currentResponsible = data.currentResponsible
+                this.controlType = '缂栬緫'
+                this.controlId = data.id
+                this.active = Number(data.currentState)
+                this.pageStatus = Number(data.currentState === 4 ? 0 : data.currentState)
+                // 绗�1銆�2姝ユ暟鎹�
+                this.mainForm.condiForm.departmentHeadId = data.departmentHeadId
+                this.mainForm.condiForm.supervisedPersonId = data.supervisedPersonId
+                this.mainForm.condiForm.notConformDetails = data.notConformDetails
+                this.mainForm.condiForm.nonConformityClause = data.nonConformityClause
+                this.mainForm.condiForm.departLimsId = data.departLimsId
+                // 绗�3姝ユ暟鎹�
+                this.mainForm.handleForm.responsibleDepartmentPersonId = data.responsibleDepartmentPersonId
+                this.mainForm.handleForm.treatmentMeasures = data.treatmentMeasures
+                this.mainForm.handleForm.departLimsId = data.departLimsId
+                // 绗�4姝ユ暟鎹�
+                this.mainForm.rectifyForm.correctiveMeasure = data.correctiveMeasure
+                this.mainForm.rectifyForm.correctiveMeasureFollowTracks = data.correctiveMeasureFollowTracks
+                this.mainForm.rectifyForm.correctiveMeasurePersonId = data.correctiveMeasurePersonId
+                this.mainForm.rectifyForm.departLimsId = data.departLimsId
+                // 绗�5姝ユ暟鎹�
+                this.mainForm.inform.whetherInformCustomer = data.whetherInformCustomer
+                this.mainForm.inform.whetherResumeWork = data.whetherResumeWork
+                this.mainForm.inform.qualitySupervisorId = data.qualitySupervisorId
+                this.mainForm.inform.departLimsId = data.departLimsId
+                this.supervisionRecordId = data.supervisionRecordId
+
+
+                this.supervisedPersonId = data.supervisedPersonId
+            }
+        },
+        submit(type) {
+            let currentState = undefined
+            if (type == 'submit') {
+                currentState = this.active + 1
+            } else if (type == 'save') {
+                currentState = undefined
+            }
+            if (this.active == 0) {
+                let { discoveryApproach, ...condiFormRest } = this.mainForm.condiForm
+                let approcahStr = discoveryApproach.join(',')
+                this.submitForm({
+                    id: this.controlId,
+                    supervisionRecordId: this.supervisionRecordId,
+                    discoveryApproach: approcahStr,
+                    currentState: currentState,
+                    discovererDate: this.$moment().format('YYYY-MM-DD HH:mm:ss'),
+                    ...condiFormRest
+                })
+            }
+            if (this.active == 1) {
+                let { discoveryApproach, ...condiFormRest } = this.mainForm.condiForm
+                let approcahStr = discoveryApproach.join(',')
+                this.submitForm({
+                    id: this.controlId,
+                    supervisionRecordId: this.supervisionRecordId,
+                    discoveryApproach: approcahStr,
+                    currentState: currentState,
+                    supervisedPersonDate: this.$moment().format('YYYY-MM-DD'),
+                    ...condiFormRest
+                })
+            }
+            if (this.active == 2) {
+                let { handleForm } = this.mainForm
+                this.submitForm({
+                    id: this.controlId,
+                    supervisionRecordId: this.supervisionRecordId,
+                    currentState: currentState,
+                    responsibleDepartmentDate: this.$moment().format('YYYY-MM-DD HH:mm:ss'),
+                    ...handleForm
+                })
+            }
+            if (this.active == 3) {
+                let { rectifyForm } = this.mainForm
+                this.submitForm({
+                    id: this.controlId,
+                    supervisionRecordId: this.supervisionRecordId,
+                    currentState: currentState,
+                    correctiveMeasureDate: this.$moment().format('YYYY-MM-DD HH:mm:ss'),
+                    ...rectifyForm
+                })
+            }
+            if (this.active == 4) {
+                let { inform } = this.mainForm
+                this.submitForm({
+                    id: this.controlId,
+                    supervisionRecordId: this.supervisionRecordId,
+                    currentState: currentState,
+                    qualitySupervisorDate: this.$moment().format('YYYY-MM-DD HH:mm:ss'),
+                    ...inform
+                })
+            }
+        },
+        /**
+         * @desc 鎻愪氦琛ㄥ崟
+         */
+        async submitForm(form) {
+            let user = JSON.parse(localStorage.getItem('user'));
+            form.responsibleDepartmentId = Number(form.responsibleDepartmentId)
+            const { code } = await addOrUpdatePersonSupervisionControl({
+                currentResponsible: user.name,
+                ...form
+            })
+            if (this.controlType == '鏂板') {
+                if (code == 200) {
+                    this.$message.success('鎻愪氦鎴愬姛')
+                }
+            } else if (this.controlType == '缂栬緫') {
+                if (code == 200) {
+                    this.$message.success('鎻愪氦鎴愬姛')
+                }
+            }
+            this.$emit('getTableData')
+            this.dialogVisible = false
+        },
+        /**
+         * @desc 椹冲洖
+         */
+        cancel() {
+            let currentState = this.active - 1
+            this.submitForm({
+                id: this.controlId,
+                supervisionRecordId: this.supervisionRecordId,
+                currentState: currentState,
+            })
+        },
+        setStep(e) {
+            this.pageStatus = e
+        }
+    }
+}
+</script>
+<style scoped>
+.dialog-footer {
+    width: 100%;
+}
+
+>>>.el-dialog__footer {
+    padding-right: 20px;
+}
+</style>
diff --git a/src/views/CNAS/personnel/personnelInfo/Department/components/Records/dispose/Step/Fact.vue b/src/views/CNAS/personnel/personnelInfo/Department/components/Records/dispose/Step/Fact.vue
new file mode 100644
index 0000000..75c287c
--- /dev/null
+++ b/src/views/CNAS/personnel/personnelInfo/Department/components/Records/dispose/Step/Fact.vue
@@ -0,0 +1,108 @@
+<template>
+    <el-form :model="form" :disabled="disabled" label-width="140px" size="small" style="position: relative">
+        <el-card :body-style="{ height: '350px', overflow: 'auto' }">
+            <el-form-item label="鎻愬嚭閮ㄩ棬">
+                <!-- <el-select
+                    v-model="form.proposingDepartment" 
+                    placeholder="璇烽�夋嫨"
+                    style="width: 100%"
+                >
+                    <el-option label="閫氫俊浜у搧瀹為獙瀹�" :value="18"></el-option>
+                    <el-option label="鐢靛姏浜у搧瀹為獙瀹�" :value="19"></el-option>
+                </el-select> -->
+                <el-input :disabled="true" v-model="form.proposingDepartment"></el-input>
+            </el-form-item>
+
+            <el-form-item label="浜哄憳閫夋嫨">
+                <el-select v-model="form.proposingDepartmentPersonId" placeholder="璇烽�夋嫨" style="width: 100%">
+                    <el-option v-for="(item, index) in userList" :key="index" :label="item.name"
+                        :value="item.id"></el-option>
+                </el-select>
+            </el-form-item>
+
+            <el-form-item label="涓嶅悎鏍兼垨鍋忕鎻忚堪">
+                <el-input type="textarea" v-model="form.descriptionNonconformity" :rows="2" placeholder="璇疯緭鍏ュ唴瀹�">
+                </el-input>
+            </el-form-item>
+        </el-card>
+        <el-form-item label-width="0">
+            <div style="display: flex; width: 100%; justify-content: space-between; margin-top: 15px;">
+                <div>
+                    鎿嶄綔浜猴細{{ currentResponsible }}
+                </div>
+                <div v-if="step == 0">
+                    <el-button :disabled="false" @click="cancel">椹冲洖</el-button>
+                    <el-button @click="save">淇濆瓨</el-button>
+                    <el-button type="primary" @click="submit"
+                        :disabled="(departId == 18 && ![12, 10, 16].includes(userId)) || (departId == 19 && ![35, 41, 16].includes(userId))">鎻愪氦</el-button>
+                </div>
+            </div>
+        </el-form-item>
+    </el-form>
+</template>
+<script>
+import { mapGetters } from "vuex";
+export default {
+    props: {
+        departId: {
+            type: Number,
+            default: () => {
+                return null;
+            }
+        },
+        isPermission: {
+            type: Boolean,
+            default: false,
+        },
+        currentResponsible: {
+            type: String,
+            default: ''
+        },
+        factForm: {
+            type: Object,
+            default: () => {
+                return {}
+            }
+        },
+        userList: {
+            type: Array,
+            default: []
+        },
+        step: {
+            type: Number,
+            default: 0
+        },
+        disabled: {
+            type: Boolean,
+            default: false
+        }
+    },
+    computed: {
+        form: {
+            get() {
+                this.$set(this.factForm, 'proposingDepartment', '鐩戠潱鍛�')
+                return this.factForm
+            },
+            set(val) {
+                this.$emit('update:factForm', val)
+            }
+        },
+        ...mapGetters(["userId"]),
+    },
+    data() {
+        return {
+        }
+    },
+    methods: {
+        submit() {
+            this.$emit('nextStep', 'submit')
+        },
+        save() {
+            this.$emit('nextStep', 'save')
+        },
+        cancel() {
+            this.$emit('cancel', 'cancel')
+        }
+    }
+}
+</script>
\ No newline at end of file
diff --git a/src/views/CNAS/personnel/personnelInfo/Department/components/Records/dispose/Step/Measure.vue b/src/views/CNAS/personnel/personnelInfo/Department/components/Records/dispose/Step/Measure.vue
new file mode 100644
index 0000000..bd8be58
--- /dev/null
+++ b/src/views/CNAS/personnel/personnelInfo/Department/components/Records/dispose/Step/Measure.vue
@@ -0,0 +1,121 @@
+<template>
+    <el-form :model="form" :disabled="disabled" label-width="130px" size="small" style="position: relative">
+        <el-card :body-style="{ height: '350px', overflow: 'auto' }">
+            <el-form-item label="璐d换閮ㄩ棬">
+                <!-- <el-select v-model="form.correctiveActionId" placeholder="璇烽�夋嫨">
+                    <el-option
+                        v-for="(item, index) in userList"
+                        :key="index"
+                        :label="item.name"
+                        :value="item.id"
+                    ></el-option>
+                </el-select> -->
+                <el-select @change="filterUserList" v-model="form.causeAnalysisId" placeholder="璇烽�夋嫨"
+                    style="width: 100%">
+                    <el-option label="閫氫俊浜у搧瀹為獙瀹�" :value="18"></el-option>
+                    <el-option label="鐢靛姏浜у搧瀹為獙瀹�" :value="19"></el-option>
+                </el-select>
+            </el-form-item>
+            <el-form-item label="璐d换浜�">
+                <el-select v-model="form.correctiveActionId" placeholder="璇烽�夋嫨">
+                    <el-option v-for="(item, index) in userListTwo" :key="index" :label="item.name"
+                        :value="item.id"></el-option>
+                </el-select>
+            </el-form-item>
+            <el-form-item label="绾犳鎺柦">
+                <el-input type="textarea" v-model="form.correctiveMeasure" :rows="2" placeholder="璇疯緭鍏ュ唴瀹�">
+                </el-input>
+            </el-form-item>
+            <el-form-item label="鎻愬嚭瑕佹眰閮ㄩ棬纭">
+                <el-input type="textarea" v-model="form.requestDepartmentConfirmation" :rows="2" placeholder="璇疯緭鍏ュ唴瀹�">
+                </el-input>
+            </el-form-item>
+        </el-card>
+        <el-form-item label-width="0">
+            <div style="display: flex; width: 100%; justify-content: space-between; margin-top: 15px;">
+                <div>
+                    鎿嶄綔浜猴細{{ currentResponsible }}
+                </div>
+                <div v-if="step == 2">
+                    <el-button :disabled="false" @click="cancel">椹冲洖</el-button>
+                    <el-button type="primary" @click="submit"
+                        :disabled="(departId == 18 && ![12, 10, 16].includes(userId)) || (departId == 19 && ![35, 41, 16].includes(userId))">鎻愪氦</el-button>
+                </div>
+            </div>
+        </el-form-item>
+    </el-form>
+</template>
+<script>
+import { mapGetters } from "vuex";
+export default {
+    props: {
+        departId: {
+            type: Number,
+            default: () => {
+                return null;
+            }
+        },
+        isPermission: {
+            type: Boolean,
+            default: false,
+        },
+        currentResponsible: {
+            type: String,
+            default: ''
+        },
+        measureForm: {
+            type: Object,
+            default: {}
+        },
+        userList: {
+            type: Array,
+            default: []
+        },
+        step: {
+            type: Number,
+            default: 0
+        },
+        disabled: {
+            type: Boolean,
+            default: false
+        }
+    },
+    computed: {
+        form: {
+            get() {
+                return this.measureForm
+            },
+            set(val) {
+                this.$emit('update:measureForm', val)
+            }
+        },
+        ...mapGetters(["userId"]),
+    },
+    data() {
+        return {
+            userListTwo: []
+        }
+    },
+    mounted() {
+        this.userListTwo = JSON.parse(JSON.stringify(this.userList))
+        console.log('this.userListTwo', this.userListTwo);
+    },
+    methods: {
+        filterUserList() {
+            this.userListTwo = this.userList.filter(item => item.departLimsId.includes(this.form.causeAnalysisId))
+            if (!this.userListTwo.some(item => item.id == this.form.correctiveActionId)) {
+                this.form.correctiveActionId = null
+            }
+        },
+        submit() {
+            this.$emit('nextStep', 'submit')
+        },
+        save() {
+            this.$emit('nextStep', 'save')
+        },
+        cancel() {
+            this.$emit('cancel', 'cancel')
+        }
+    }
+}
+</script>
\ No newline at end of file
diff --git a/src/views/CNAS/personnel/personnelInfo/Department/components/Records/dispose/Step/Reason.vue b/src/views/CNAS/personnel/personnelInfo/Department/components/Records/dispose/Step/Reason.vue
new file mode 100644
index 0000000..6f0cb59
--- /dev/null
+++ b/src/views/CNAS/personnel/personnelInfo/Department/components/Records/dispose/Step/Reason.vue
@@ -0,0 +1,122 @@
+<template>
+    <el-form :model="form" :disabled="disabled" label-width="140px" size="small" style="position: relative;">
+        <el-card :body-style="{ height: '350px', overflow: 'auto' }">
+            <el-form-item label="璐d换閮ㄩ棬">
+                <!-- <el-select
+                    v-model="form.causeAnalysisPersonId"
+                    placeholder="璇烽�夋嫨"
+                    style="width: 100%"
+                >
+                    <el-option
+                        v-for="(item, index) in userList"
+                        :key="index"
+                        :label="item.name"
+                        :value="item.id"
+                    ></el-option>
+                </el-select> -->
+                <el-select @change="filterUserList" v-model="form.causeAnalysisId" placeholder="璇烽�夋嫨"
+                    style="width: 100%">
+                    <el-option label="閫氫俊浜у搧瀹為獙瀹�" :value="18"></el-option>
+                    <el-option label="鐢靛姏浜у搧瀹為獙瀹�" :value="19"></el-option>
+                </el-select>
+            </el-form-item>
+
+            <el-form-item label="浜哄憳閫夋嫨">
+                <el-select v-model="form.causeAnalysisPersonId" placeholder="璇烽�夋嫨" style="width: 100%">
+                    <el-option v-for="(item, index) in userListTwo" :key="index" :label="item.name"
+                        :value="item.id"></el-option>
+                </el-select>
+            </el-form-item>
+
+            <el-form-item label="鍘熷洜鍒嗘瀽">
+                <el-input type="textarea" v-model="form.causeAnalysis" :rows="2" placeholder="璇疯緭鍏ュ唴瀹�">
+                </el-input>
+            </el-form-item>
+        </el-card>
+        <el-form-item label-width="0">
+            <div style="display: flex; width: 100%; justify-content: space-between; margin-top: 15px;">
+                <div>
+                    <span>鎿嶄綔浜猴細{{ currentResponsible }}</span>
+                </div>
+                <div v-if="step == 1">
+                    <el-button :disabled="false" @click="cancel">椹冲洖</el-button>
+                    <el-button type="primary" @click="submit"
+                        :disabled="(departId == 18 && ![12, 10, 16].includes(userId)) || (departId == 19 && ![35, 41, 16].includes(userId))">鎻愪氦</el-button>
+                </div>
+            </div>
+        </el-form-item>
+    </el-form>
+</template>
+<script>
+import { mapGetters } from "vuex";
+export default {
+    props: {
+        departId: {
+            type: Number,
+            default: () => {
+                return null;
+            }
+        },
+        isPermission: {
+            type: Boolean,
+            default: false,
+        },
+        currentResponsible: {
+            type: String,
+            default: ''
+        },
+        userList: {
+            type: Array,
+            default: []
+        },
+        reasonForm: {
+            type: Object,
+            default: {}
+        },
+        step: {
+            type: Number,
+            default: 0
+        },
+        disabled: {
+            type: Boolean,
+            default: false
+        }
+    },
+    computed: {
+        form: {
+            get() {
+                return this.reasonForm
+            },
+            set(val) {
+                this.$emit('update:reasonForm', val)
+            }
+        },
+        ...mapGetters(["userId"]),
+    },
+    data() {
+        return {
+            userListTwo: []
+        }
+    },
+    mounted() {
+        this.userListTwo = JSON.parse(JSON.stringify(this.userList))
+    },
+    methods: {
+        filterUserList() {
+            this.userListTwo = this.userList.filter(item => item.departLimsId.includes(this.form.causeAnalysisId))
+            if (!this.userListTwo.some(item => item.id == this.form.causeAnalysisPersonId)) {
+                this.form.causeAnalysisPersonId = null
+            }
+        },
+        submit() {
+            this.$emit('nextStep', 'submit')
+        },
+        save() {
+            this.$emit('nextStep', 'save')
+        },
+        cancel() {
+            this.$emit('cancel', 'cancel')
+        }
+    }
+}
+</script>
\ No newline at end of file
diff --git a/src/views/CNAS/personnel/personnelInfo/Department/components/Records/dispose/Step/Result.vue b/src/views/CNAS/personnel/personnelInfo/Department/components/Records/dispose/Step/Result.vue
new file mode 100644
index 0000000..3f47dd2
--- /dev/null
+++ b/src/views/CNAS/personnel/personnelInfo/Department/components/Records/dispose/Step/Result.vue
@@ -0,0 +1,111 @@
+<template>
+    <el-form :model="form" :disabled="disabled" label-width="130px" size="small" style="position: relative">
+        <el-card :body-style="{ height: '350px', overflow: 'auto' }">
+            <el-form-item label="楠岃瘉閮ㄩ棬">
+                <!-- <el-select
+                v-model="form.verificationDepartmentPersonId" 
+                placeholder="璇烽�夋嫨"
+                style="width: 100%"
+            >
+                <el-option
+                    v-for="(item, index) in userList"
+                    :key="index"
+                    :label="item.name"
+                    :value="item.id"
+                ></el-option>
+            </el-select> -->
+                <el-input :disabled="true" v-model="form.verificationDepartment"></el-input>
+            </el-form-item>
+
+            <el-form-item label="浜哄憳閫夋嫨">
+                <el-select v-model="form.verificationDepartmentPersonId" placeholder="璇烽�夋嫨" style="width: 100%">
+                    <el-option v-for="(item, index) in userList" :key="index" :label="item.name"
+                        :value="item.id"></el-option>
+                </el-select>
+            </el-form-item>
+
+            <el-form-item label="瀹炴柦楠岃瘉缁撴灉">
+                <el-input type="textarea" v-model="form.implementationVerificationResults" :rows="2"
+                    placeholder="璇疯緭鍏ュ唴瀹�">
+                </el-input>
+            </el-form-item>
+        </el-card>
+        <el-form-item label-width="0">
+            <div style="display: flex; width: 100%; justify-content: space-between; margin-top: 15px;">
+                <div>
+                    鎿嶄綔浜猴細{{ currentResponsible }}
+                </div>
+                <div v-if="step == 3">
+                    <el-button :disabled="false" @click="cancel">椹冲洖</el-button>
+                    <el-button type="primary" @click="submit"
+                        :disabled="(departId == 18 && ![12, 10, 16].includes(userId)) || (departId == 19 && ![35, 41, 16].includes(userId))">鎻愪氦</el-button>
+                </div>
+            </div>
+        </el-form-item>
+    </el-form>
+</template>
+<script>
+import { mapGetters } from "vuex";
+export default {
+    props: {
+        departId: {
+            type: Number,
+            default: () => {
+                return null;
+            }
+        },
+        isPermission: {
+            type: Boolean,
+            default: false,
+        },
+        currentResponsible: {
+            type: String,
+            default: ''
+        },
+        resultForm: {
+            type: Object,
+            default: {}
+        },
+        step: {
+            type: Number,
+            default: 0
+        },
+        disabled: {
+            type: Boolean,
+            default: false
+        },
+        userList: {
+            type: Array,
+            default: []
+        },
+    },
+    computed: {
+        form: {
+            get() {
+                this.$set(this.resultForm, 'verificationDepartment', '璐ㄩ噺璐熻矗浜�')
+                return this.resultForm
+            },
+            set(val) {
+                this.$emit('update:resultForm', val)
+            }
+        },
+        ...mapGetters(["userId"]),
+    },
+    data() {
+        return {
+        }
+    },
+    methods: {
+        submit() {
+            this.$emit('nextStep', 'submit')
+        },
+        save() {
+            this.$emit('nextStep', 'save')
+        },
+        cancel() {
+            this.$emit('cancel', 'cancel')
+        }
+    }
+}
+</script>
+<style scoped></style>
\ No newline at end of file
diff --git a/src/views/CNAS/personnel/personnelInfo/Department/components/Records/dispose/index.vue b/src/views/CNAS/personnel/personnelInfo/Department/components/Records/dispose/index.vue
new file mode 100644
index 0000000..7dad14c
--- /dev/null
+++ b/src/views/CNAS/personnel/personnelInfo/Department/components/Records/dispose/index.vue
@@ -0,0 +1,239 @@
+<template>
+    <div>
+        <el-dialog title="绾犻敊澶勭悊鍗�" :visible.sync="dialogVisible">
+            <el-steps :active="active" finish-status="success" :align-center="true">
+                <el-step style="cursor: pointer;" v-for="(item, index) in stepList" :key="index" :title="item.label"
+                    @click.native="setStep(item.value)"></el-step>
+            </el-steps>
+            <el-divider></el-divider>
+            <Fact v-if="pageStatus == 0" :departId="departId" :isPermission="isPermission"
+                :factForm.sync="mainForm.factForm" :userList="userList" :currentResponsible="currentResponsible"
+                :disabled="active != 0" :step="active" @nextStep="submit" @cancel="cancel"></Fact>
+            <Reason v-if="pageStatus == 1" :isPermission="isPermission" :departId="departId"
+                :reasonForm.sync="mainForm.reasonForm" :userList="userList" :currentResponsible="currentResponsible"
+                :disabled="active != 1" :step="active" @nextStep="submit" @cancel="cancel"></Reason>
+            <Measure v-if="pageStatus == 2" :departId="departId" :isPermission="isPermission"
+                :measureForm.sync="mainForm.measureForm" :userList="userList" :currentResponsible="currentResponsible"
+                :disabled="active != 2" :step="active" @nextStep="submit" @cancel="cancel"></Measure>
+            <Result v-if="pageStatus == 3" :departId="departId" :isPermission="isPermission"
+                :resultForm.sync="mainForm.resultForm" :userList="userList" :currentResponsible="currentResponsible"
+                :disabled="active != 3" :step="active" @nextStep="submit" @cancel="cancel"></Result>
+            <!-- <div slot="footer" class="dialog-footer">
+                <el-button v-if="active == 4" type="primary" @click="submit(5)">瀹屾垚</el-button>
+            </div> -->
+        </el-dialog>
+    </div>
+</template>
+<script>
+import Fact from './Step/Fact.vue'
+import Reason from './Step/Reason.vue'
+import Measure from './Step/Measure.vue'
+import Result from './Step/Result.vue'
+import { dateFormat } from '@/utils/date.js'
+import {
+    selectUserList,
+    personSupervisionProcessingPage,
+    addOrUpdatePersonnelServiceProcessing
+} from '@/api/cnas/personnel/personnelInfo.js'
+export default {
+    props: {
+        departId: {
+            type: Number,
+            default: () => {
+                return null;
+            }
+        },
+    },
+    components: {
+        Fact, Reason, Measure, Result
+    },
+    data() {
+        return {
+            isPermission: true,
+            active: 0,
+            pageStatus: 0,
+            dialogVisible: false,
+            currentResponsible: undefined,
+            stepList: [
+                {
+                    label: '闂鎻忚堪',
+                    value: 0
+                }, {
+                    label: '鍘熷洜鍒嗘瀽',
+                    value: 1
+                }, {
+                    label: '绾犳鎺柦',
+                    value: 2
+                }, {
+                    label: '楠岃瘉缁撴灉',
+                    value: 3
+                }
+            ],
+            supervisionRecordId: undefined,
+            processId: undefined,
+            mainForm: {
+                factForm: {
+                    proposingDepartmentPersonId: undefined,
+                    descriptionNonconformity: undefined
+                },
+                reasonForm: {
+                    causeAnalysisPersonId: undefined,
+                    causeAnalysis: undefined
+                },
+                measureForm: {
+                    correctiveActionId: undefined,
+                    correctiveMeasure: undefined,
+                    requestDepartmentConfirmation: undefined
+                },
+                resultForm: {
+                    verificationDepartmentPersonId: undefined,
+                    implementationVerificationResults: undefined
+                }
+            },
+            userList: [],
+        }
+    },
+    mounted() {
+        this.isPermission = isPermission("isSubmit")
+        console.log('鏉冮檺', this.isPermission);
+    },
+    methods: {
+        openDialog(id) {
+            this.dialogVisible = true
+            this.getUserList()
+            this.getProcessData(id)
+        },
+        /**
+         * @desc 鑾峰彇鐢ㄦ埛淇℃伅
+         */
+        async getUserList() {
+            const { code, data } = await selectUserList()
+            if (code == 200) {
+                this.userList = data
+            }
+        },
+        /**
+         * @desc 鏌ヨ鐩戠潱璁板綍澶勭悊鍗�
+         * @param {鐩戠潱璁板綍id} id
+         */
+        async getProcessData(id) {
+            const { code, data } = await personSupervisionProcessingPage({ id })
+            if (code == 202) {
+                this.controlType = '鏂板'
+                this.supervisionRecordId = id
+                this.active = 0
+                this.pageStatus = 0
+                this.processId = undefined
+            }
+            if (code == 200) {
+                this.currentResponsible = data.currentResponsible
+                this.controlType = '缂栬緫'
+                this.supervisionRecordId = id
+                this.processId = data.processingId
+                this.active = Number(data.currentState)
+                this.pageStatus = Number(data.currentState === 2 ? 0 : data.currentState)
+                // 绗�1姝ユ暟鎹�
+                this.mainForm.factForm.proposingDepartmentPersonId = data.proposingDepartmentPersonId
+                this.mainForm.factForm.descriptionNonconformity = data.descriptionNonconformity
+                // 绗�2姝ユ暟鎹�
+                this.mainForm.reasonForm.causeAnalysisPersonId = data.causeAnalysisPersonId
+                this.mainForm.reasonForm.causeAnalysis = data.causeAnalysis
+                // 绗�3姝ユ暟鎹�
+                this.mainForm.measureForm.correctiveActionId = data.correctiveActionId
+                this.mainForm.measureForm.correctiveMeasure = data.correctiveMeasure
+                this.mainForm.measureForm.requestDepartmentConfirmation = data.requestDepartmentConfirmation
+                // 绗�4姝ユ暟鎹�
+                this.mainForm.resultForm.verificationDepartmentPersonId = data.verificationDepartmentPersonId
+                this.mainForm.resultForm.implementationVerificationResults = data.implementationVerificationResults
+            }
+        },
+        closeDialog() {
+            this.dialogVisible = false
+        },
+        submit(type) {
+            let currentState = undefined
+            if (type == 'submit') {
+                currentState = this.active + 1
+            } else if (type == 'save') {
+                currentState = undefined
+            }
+            if (this.active == 0) {
+                // 绗�1姝�
+                console.log('绗�1姝�', this.active, currentState)
+                let { factForm } = this.mainForm
+                this.submitForm({
+                    proposingDepartmentDate: dateFormat(new Date(), 'YYYY-MM-DD HH:mm:ss'),
+                    currentState: currentState,
+                    ...factForm
+                })
+            } else if (this.active == 1) {
+                // 绗�2姝�
+                console.log('绗�2姝�', this.active, currentState)
+                let { reasonForm } = this.mainForm
+                this.submitForm({
+                    causeAnalysisDate: dateFormat(new Date(), 'YYYY-MM-DD HH:mm:ss'),
+                    currentState: currentState,
+                    ...reasonForm
+                })
+            } else if (this.active == 2) {
+                // 绗�3姝�
+                console.log('绗�3姝�', this.active, currentState)
+                let { measureForm } = this.mainForm
+                let { requestDepartmentConfirmation, ...measureFormRest } = measureForm
+                this.submitForm({
+                    correctiveActionDate: dateFormat(new Date(), 'YYYY-MM-DD HH:mm:ss'),
+                    currentState: currentState,
+                    requestDepartmentConfirmation: requestDepartmentConfirmation ? 1 : 2,
+                    ...measureFormRest
+                })
+            } else if (this.active == 3) {
+                // 绗�4姝�
+                console.log('绗�4姝�', this.active, currentState)
+                let { resultForm } = this.mainForm
+                this.submitForm({
+                    verificationDepartmentDate: dateFormat(new Date(), 'YYYY-MM-DD HH:mm:ss'),
+                    currentState: currentState,
+                    ...resultForm
+                })
+            }
+        },
+        /**
+         * @desc 鎻愪氦琛ㄥ崟
+         */
+        async submitForm(form) {
+            console.log('鎻愪氦琛ㄥ崟', form)
+            const { code } = await addOrUpdatePersonnelServiceProcessing({
+                processingId: this.processId,
+                supervisionRecordId: this.supervisionRecordId,
+                ...form
+            })
+            if (this.controlType == '鏂板') {
+                if (code == 200) {
+                    this.$message.success('鎻愪氦鎴愬姛')
+                }
+            } else if (this.controlType == '缂栬緫') {
+                if (code == 200) {
+                    this.$message.success('鎻愪氦鎴愬姛')
+                }
+            }
+            this.$emit('getTableData')
+            this.dialogVisible = false
+        },
+        /**
+         * @desc 椹冲洖
+         */
+        cancel() {
+            let currentState = this.active - 1
+            this.submitForm({
+                id: this.processId,
+                supervisionRecordId: this.supervisionRecordId,
+                currentState: currentState,
+            })
+        },
+        setStep(e) {
+            console.log(e)
+            this.pageStatus = e
+        }
+    }
+}
+</script>
diff --git a/src/views/CNAS/personnel/personnelInfo/Department/components/Records/index.vue b/src/views/CNAS/personnel/personnelInfo/Department/components/Records/index.vue
new file mode 100644
index 0000000..413d1a2
--- /dev/null
+++ b/src/views/CNAS/personnel/personnelInfo/Department/components/Records/index.vue
@@ -0,0 +1,406 @@
+<template>
+    <div class="flex_column">
+        <div>
+            <TableCard :showTitle="false">
+                <template v-slot:form>
+                    <div class="items_center">
+                        <!-- <span>鍏抽敭瀛�</span>
+                        <el-input size="small" class="search" v-model="superviseForm.searchVal" placeholder="璇疯緭鍏�"></el-input>
+                        <el-button type="primary" size="small">鏌ヨ</el-button> -->
+                        <el-button v-if="multipleSelection.length > 0" slot="reference" size="small" type="danger"
+                            @click="delRecords">鍒犻櫎</el-button>
+                    </div>
+                    <div>
+                        <el-button size="small" type="primary" @click="addRecord"
+                            v-show="departId && departId != 1">鏂板</el-button>
+                    </div>
+                </template>
+                <template v-slot:table>
+                    <limsTable :column="superviseColumnData" :handleSelectionChange="handleSelectionChange"
+                        :height="'calc(100vh - 19em)'" :isSelection="true" :table-data="superviseTableData"
+                        :table-loading="superviseLoading" rowKey="id" style="margin-top: 18px; padding: 0 15px;"
+                        :page="page" @pagination="pagination">
+                        <div slot="action" slot-scope="scope">
+                            <el-button type="text" @click="openDownloadDia(scope.row)">
+                                <span>瀵煎嚭</span>
+                            </el-button>
+                            <el-button type="text" @click="openRecord(scope.row)">
+                                <span>鐩戠潱璁板綍</span>
+                            </el-button>
+                            <el-button type="text" @click="openControl(scope.row.id)"
+                                :disabled="scope.row.evaluationSupervisionSituation != '涓嶇鍚�'">
+                                <span :style="renderBtn(scope.row.currentStateControl)">鎺у埗鍗�</span>
+                            </el-button>
+                            <el-button type="text" @click="openDispose(scope.row.id)"
+                                :disabled="scope.row.correctiveMeasure != '1'">
+                                <span :style="renderBtn(scope.row.currentStateProcessing)">澶勭悊鍗�</span>
+                            </el-button>
+                        </div>
+                    </limsTable>
+                </template>
+            </TableCard>
+        </div>
+        <RecordAdd ref="recordModal" @submit="getTableData" :departId="departId"></RecordAdd>
+        <ControlModal ref="controlModal" @getTableData="getTableData" :departId="departId"></ControlModal>
+        <DisposeModal ref="disposeModal" @getTableData='getTableData' :departId="departId"></DisposeModal>
+        <el-dialog :visible.sync="downloadDialog" title="瀵煎嚭" width="600px">
+            <span>
+                <el-button :disabled="!download.currentStateControl" plain type="primary"
+                    @click="controlDown">鎺у埗鍗曞鍑�</el-button>
+                <el-button :disabled="!download.currentStateProcessing" plain type="primary"
+                    @click="processingDown">澶勭悊鍗曞鍑�</el-button>
+                <el-button plain type="primary" @click="supervisoryDown">鐩戠潱璁板綍瀵煎嚭</el-button>
+            </span>
+            <span slot="footer" class="dialog-footer">
+                <el-button @click="downloadDialog = false">鍙� 娑�</el-button>
+            </span>
+        </el-dialog>
+    </div>
+</template>
+<script>
+import TableCard from '@/components/TableCard/index.vue';
+import RecordAdd from "./Add.vue"
+import limsTable from "@/components/Table/lims-table.vue";
+import ControlModal from "./control/index.vue"
+import DisposeModal from "./dispose/index.vue"
+import {
+    personSupervisionRecordPage,
+    deletePersonSupervisionRecord,
+    exportSupervisionControlSheet,
+    exportSupervisionProcessingSheet,
+    exportPersonSupervisionRecord
+} from '@/api/cnas/personnel/personnelInfo.js'
+export default {
+    props: {
+        isDepartment: {
+            type: Boolean,
+            default: false
+        },
+        departId: {
+            type: Number,
+            default: () => {
+                return null;
+            }
+        },
+    },
+    components: {
+        TableCard,
+        RecordAdd,
+        limsTable,
+        ControlModal,
+        DisposeModal
+    },
+    data() {
+        return {
+            loading: false,
+            page: {
+                current: 1,
+                pageSize: 20,
+                total: 0
+            },
+            // 鐩戠潱璁板綍
+            superviseForm: {
+                searchVal: undefined
+            },
+            superviseColumnData: [
+                // {
+                //     label: 'id',
+                //     prop: 'id'
+                // }, 
+                {
+                    label: '妫�娴嬩汉鍛�',
+                    prop: 'testerName',
+                    width: 120
+                }, {
+                    label: '鐩戠潱浜哄憳',
+                    prop: 'supervisorName',
+                    width: 120
+                }, {
+                    label: '妫�楠岄」鐩�',
+                    prop: 'testItem',
+                    width: 120
+                }, {
+                    label: '鏍峰搧缂栧彿',
+                    prop: 'sampleNumber',
+                    width: 120
+                }, {
+                    label: '妫�楠屾棩鏈�',
+                    prop: 'detectionDate',
+                    width: 160
+                }, {
+                    label: '鎺у埗鍗曠姸鎬�',
+                    prop: 'currentStateControl',
+                    formatData: (item) => {
+                        let result = undefined
+                        switch (item) {
+                            case '0':
+                                result = '宸ヤ綔鎯呭喌'
+                                break;
+                            case '1':
+                                result = '琚洃鐫d汉纭'
+                                break;
+                            case '2':
+                                result = '澶勭悊鎺柦'
+                                break;
+                            case '3':
+                                result = '绾犳鎺柦'
+                                break;
+                            case '4':
+                                result = '閫氱煡瀹㈡埛'
+                                break;
+                        }
+                        return result
+                    },
+                    width: 140,
+                }, {
+                    label: '娴佺▼鍗曠姸鎬�',
+                    prop: 'currentStateProcessing',
+                    formatData: (item) => {
+                        let result = undefined
+                        switch (item) {
+                            case '0':
+                                result = '闂鎻忚堪'
+                                break;
+                            case '1':
+                                result = '鍘熷洜鍒嗘瀽'
+                                break;
+                            case '2':
+                                result = '绾犳鎺柦'
+                                break;
+                            case '3':
+                                result = '楠岃瘉缁撴灉'
+                                break;
+                        }
+                        return result
+                    },
+                    width: 140,
+                }, {
+                    label: '浜哄憳',
+                    prop: 'personnel',
+                    width: 150
+                }, {
+                    label: '璁惧浠櫒',
+                    prop: 'instrumentEquipment',
+                    width: 140
+                }, {
+                    label: '宸ヤ綔鐜',
+                    prop: 'workingEnvironment',
+                    width: 140
+                }, {
+                    label: '鏍峰搧閲囬泦',
+                    prop: 'sampleCollection',
+                    width: 140
+                }, {
+                    label: '鏍峰搧鐨勫噯澶�',
+                    prop: 'samplePreparation',
+                    width: 140
+                }, {
+                    label: '妫�楠屾柟娉�',
+                    prop: 'testMethod',
+                    width: 120
+                }, {
+                    label: '妫�娴嬭褰�',
+                    prop: 'testingRecords',
+                    width: 120
+                }, {
+                    label: '妫�楠屾姤鍛�',
+                    prop: 'testReport',
+                    width: 120
+                }, {
+                    label: '鐩戠潱鎯呭喌璇勪环',
+                    prop: 'evaluationSupervisionSituation',
+                    width: 140
+                }, {
+                    label: '涓嶇鍚堝鐞嗘剰瑙�',
+                    prop: 'doNotMeetTheHandlingOpinions',
+                    width: 140
+                }, {
+                    fixed: 'right',
+                    dataType: "slot",
+                    width: 280,
+                    label: '鎿嶄綔',
+                    slot: 'action',
+                }
+            ],
+            superviseTableData: [],
+            superviseLoading: false,
+            multipleSelection: [],
+            downloadDialog: false,
+            download: {
+                currentStateControl: '',
+                currentStateProcessing: '',
+            },
+            downloadId: '',
+        }
+    },
+    mounted() {
+        this.getTableData()
+    },
+    methods: {
+        /**
+         * @desc 鑾峰彇鏍戠殑浜哄憳id
+         */
+        getDepart() {
+            this.getTableData()
+        },
+        pagination({ page, limit }) {
+            this.page.current = page;
+            this.page.pageSize = limit;
+            this.getTableData();
+        },
+        // 鑾峰彇鐩戠潱璁板綍
+        async getTableData() {
+            this.loading = true
+            const { code, data } = await personSupervisionRecordPage({
+                departLimsId: this.isDepartment ? this.departId : null,
+                userId: this.isDepartment ? null : this.departId,
+                current: this.page.current,
+                size: this.page.pageSize
+            })
+            if (code == 200) {
+                this.superviseTableData = data.records
+                this.page.total = data.total
+            }
+            this.loading = false
+        },
+        // 鏂板鐩戠潱璁板綍
+        addRecord(row, type = false) {
+            this.$refs.recordModal.openDialog({ departId: this.departId, ...row }, type)
+        },
+        openRecord(row) {
+            this.$refs.recordModal.openDialog(row, true)
+        },
+        // 鎵撳紑瀵煎嚭寮规
+        openDownloadDia(row) {
+            this.downloadDialog = true
+            this.download = row
+            console.log('this.download', this.download.currentStateProcessing, this.download.currentStateControl);
+            this.downloadId = row.id
+        },
+        // 鎺у埗鍗曞鍑�
+        controlDown() {
+            exportSupervisionControlSheet({ supervisionRecordId: this.downloadId }).then(res => {
+                this.outLoading = false
+                const blob = new Blob([res], { type: 'application/msword' });
+                this.$download.saveAs(blob, '鎺у埗鍗曞鍑�' + '.docx')
+            })
+        },
+        // 澶勭悊鍗曞鍑�
+        processingDown() {
+            exportSupervisionProcessingSheet({ supervisionRecordId: this.downloadId }).then(res => {
+                this.outLoading = false
+                const blob = new Blob([res], { type: 'application/msword' });
+                this.$download.saveAs(blob, '澶勭悊鍗曞鍑�' + '.docx')
+            })
+        },
+        // 鐩戠潱璁板綍瀵煎嚭
+        supervisoryDown() {
+            exportPersonSupervisionRecord({ id: this.downloadId }).then(res => {
+                this.outLoading = false
+                const blob = new Blob([res], { type: 'application/msword' });
+                this.$download.saveAs(blob, '鐩戠潱璁板綍瀵煎嚭' + '.docx')
+            })
+        },
+        // 鏄剧ず鎺у埗鍗�
+        openControl(id) {
+            this.$refs.controlModal.openDialog(id)
+        },
+        // 鏄剧ず澶勭悊鍗�
+        openDispose(id) {
+            this.$refs.disposeModal.openDialog(id)
+        },
+        // 琛ㄦ牸澶氶�夋縺娲诲悗鍋氫粈涔�
+        handleSelectionChange(val) {
+            this.multipleSelection = val
+        },
+        /**
+         * @desc 鎵归噺鍒犻櫎鐩戠潱璁板綍
+         */
+        delRecords() {
+            this.$confirm(
+                '姝ゆ搷浣滃皢鍒犻櫎閫変腑鏁版嵁, 鏄惁缁х画?',
+                '鎻愮ず',
+                {
+                    confirmButtonText: '纭畾',
+                    cancelButtonText: '鍙栨秷',
+                    type: 'warning'
+                })
+                .then(() => {
+                    console.log(this.multipleSelection)
+                    let ids = this.multipleSelection.map((item) => item.id)
+                    const code = this.delTableData(ids)
+                    this.$message({
+                        type: code == 200 ? 'success' : 'error',
+                        message: code == 200 ? '鍒犻櫎鎴愬姛锛�' : '鍒犻櫎澶辫触锛�'
+                    });
+                    this.getTableData()
+                })
+        },
+        // 鍒犻櫎api
+        async delTableData(ids) {
+            const { code } = await this.$axios({
+                method: 'delete',
+                url: deletePersonSupervisionRecord,
+                data: ids
+            })
+            return code
+        },
+        // 琛岃儗鏅壊
+        renderBtn(currentState) {
+            let status = Number(currentState)
+            let res = {}
+            switch (status) {
+                case 0:
+                    break;
+                case 1:
+                    res = { color: '#337ecc' }
+                    break;
+                case 2:
+                    res = { color: '#409EFF' }
+                    break;
+                case 3:
+                    res = { color: '#79bbff' }
+                    break;
+                case 4:
+                    res = { color: '#a0cfff' }
+                    break;
+            }
+            return res;
+        }
+    },
+    watch: {
+        // 鐩戝惉鐐瑰嚮el-tree鐨勬暟鎹紝杩涜鏁版嵁鍒锋柊
+        departId: {
+            handler(newId, oldId) {
+                if (this.isDepartment) {
+                    this.getTableData();
+                } else {
+                    this.getTableData()
+                }
+            }
+        }
+    }
+}
+</script>
+<style scoped>
+.flex_column {
+    display: flex;
+    flex-direction: column;
+    justify-content: space-between;
+}
+
+
+.items_center {
+    display: flex;
+    align-items: center;
+}
+
+.date_box {
+    margin: 0 5px;
+}
+
+.search {
+    width: 150px;
+    padding: 0 16px;
+}
+</style>
diff --git a/src/views/CNAS/personnel/personnelInfo/Department/components/Records/supervise/ApproveForm.vue b/src/views/CNAS/personnel/personnelInfo/Department/components/Records/supervise/ApproveForm.vue
new file mode 100644
index 0000000..6563eb8
--- /dev/null
+++ b/src/views/CNAS/personnel/personnelInfo/Department/components/Records/supervise/ApproveForm.vue
@@ -0,0 +1,84 @@
+<template>
+    <el-form
+        :model="form"
+        label-width="100px"
+        :disabled="disabled"
+        size="small"
+    >
+        <el-form-item label="鎶�鏈礋璐d汉">
+            <el-select 
+                v-model="form.technicalDirector" 
+                placeholder="璇烽�夋嫨" 
+                style="width: 100%"
+            >
+                <el-option
+                    v-for="(item, index) in userList"
+                    :key="index"
+                    :label="item.name"
+                    :value="item.id"
+                ></el-option>
+            </el-select>
+        </el-form-item>
+        <!-- <el-form-item label="瀹℃壒">
+            <el-input 
+                type="textarea"
+                :rows="2" 
+                placeholder="璇疯緭鍏�"
+            ></el-input>
+        </el-form-item> -->
+        <el-form-item v-if="!disabled" style="text-align: right;">
+            <el-button size="small" type="danger" @click="close">椹冲洖</el-button>
+            <el-button size="small" type="primary" @click="submit">鎻愪氦</el-button>
+        </el-form-item>
+    </el-form>
+</template>
+<script>
+export default {
+    props: {
+        userList: {
+            type: Array,
+            default: () => {
+                return []
+            }
+        },
+        approveForm: {
+            type: Object,
+            default: {}
+        },
+        isEdit: {
+            type: Boolean,
+            default: false
+        },
+        disabled: {
+            type: Boolean,
+            default: false
+        }
+    },
+    computed: {
+        form: {
+            get() {
+                return this.approveForm
+            },
+            set(val) {
+                this.$emit('approveForm', val)
+            }
+        }
+    },
+    data() {
+        return {
+          
+        }
+    },
+    methods: {
+        submit() {
+            this.$emit('submit', 2)
+        },
+        /**
+         * @desc 椹冲洖
+         */
+        close() {
+            this.$emit('close', 2)
+        }
+    }
+}
+</script>
\ No newline at end of file
diff --git a/src/views/CNAS/personnel/personnelInfo/Department/components/Records/supervise/SuperviseForm.vue b/src/views/CNAS/personnel/personnelInfo/Department/components/Records/supervise/SuperviseForm.vue
new file mode 100644
index 0000000..92280f6
--- /dev/null
+++ b/src/views/CNAS/personnel/personnelInfo/Department/components/Records/supervise/SuperviseForm.vue
@@ -0,0 +1,201 @@
+<template>
+     <el-form
+        :model="ruleForm"
+        :disabled="disabled"
+        label-width="100px"
+        size="small"
+    >
+        <el-row>
+            <el-col :span="12">
+                <el-form-item label="妫�娴嬩汉鍛�">
+                    <el-select v-model="ruleForm.testerId" placeholder="璇烽�夋嫨" style="width: 100%">
+                        <el-option
+                            v-for="(item, index) in userList"
+                            :key="index"
+                            :label="item.name"
+                            :value="item.id"
+                        ></el-option>
+                    </el-select>
+                </el-form-item>
+            </el-col>
+            <el-col :span="12">
+                <el-form-item label="鐩戠潱鍛�">
+                    <el-select v-model="ruleForm.supervisorId" placeholder="璇烽�夋嫨" style="width: 100%">
+                        <el-option
+                            v-for="(item, index) in userList"
+                            :key="index"
+                            :label="item.name"
+                            :value="item.id"
+                        ></el-option>
+                    </el-select>
+                </el-form-item>
+            </el-col>
+        </el-row>
+        <el-row>
+            <el-col :span="12">
+                <el-form-item label="妫�娴嬮」鐩�">
+                    <el-input v-model="ruleForm.testItem" placeholder="璇疯緭鍏�"></el-input>
+                </el-form-item>
+            </el-col>
+            <el-col :span="12">
+                <el-form-item label="鏍峰搧缂栧彿">
+                    <el-input v-model="ruleForm.sampleNumber" placeholder="璇疯緭鍏�"></el-input>
+                </el-form-item>
+            </el-col>
+        </el-row>
+        <el-row>
+            <el-col :span="12">
+                <el-form-item label="妫�娴嬫棩鏈�">
+                    <el-date-picker
+                        v-model="ruleForm.detectionDate"
+                        value-format="yyyy-MM-dd"
+                        type="date"
+                        placeholder="閫夋嫨鏃ユ湡"
+                        style="width: 100%;"
+                    >
+                    </el-date-picker>
+                </el-form-item>
+            </el-col>
+            <el-col :span="12">
+                <el-form-item label="浜哄憳">
+                    <!-- <el-select 
+                        v-model="ruleForm.personnel" 
+                        placeholder="璇烽�夋嫨" 
+                        style="width: 100%"
+                        multiple
+                    >
+                        <el-option
+                            v-for="(item, index) in userList"
+                            :key="index"
+                            :label="item.name"
+                            :value="item.id"
+                        ></el-option>
+                    </el-select> -->
+                    <el-input v-model="ruleForm.personnel" type="textarea" :rows="2" style="width: 100%" placeholder="璇疯緭鍏�"></el-input>
+                </el-form-item>
+            </el-col>
+        </el-row>
+        <el-row>
+            <el-col :span="12">
+                <el-form-item label="浠櫒璁惧">
+                    <el-input v-model="ruleForm.instrumentEquipment" placeholder="璇疯緭鍏�"></el-input>
+                </el-form-item>
+            </el-col>
+            <el-col :span="12">
+                <el-form-item label="宸ヤ綔鐜">
+                    <el-input v-model="ruleForm.workingEnvironment" placeholder="璇疯緭鍏�"></el-input>
+                </el-form-item>
+            </el-col>
+        </el-row>
+        <el-row>
+            <el-col :span="12">
+                <el-form-item label="鏍峰搧閲囬泦">
+                    <el-input v-model="ruleForm.sampleCollection" placeholder="璇疯緭鍏�"></el-input>
+                </el-form-item>
+            </el-col>
+            <el-col :span="12">
+                <el-form-item label="鏍峰搧鐨勫噯澶�">
+                    <el-input v-model="ruleForm.samplePreparation" placeholder="璇疯緭鍏�"></el-input>
+                </el-form-item>
+            </el-col>
+        </el-row>
+        <el-row>
+            <el-col :span="12">
+                <el-form-item label="妫�娴嬫柟娉�">
+                    <el-input v-model="ruleForm.testMethod" placeholder="璇疯緭鍏�"></el-input>
+                </el-form-item>
+            </el-col>
+            <el-col :span="12">
+                <el-form-item label="妫�娴嬭褰�">
+                    <el-input v-model="ruleForm.testingRecords" placeholder="璇疯緭鍏�"></el-input>
+                </el-form-item>
+            </el-col>
+        </el-row>
+        <el-row>
+            <el-col :span="12">
+                <el-form-item label="妫�娴嬫姤鍛�">
+                    <el-input v-model="ruleForm.testReport" placeholder="璇疯緭鍏�"></el-input>
+                </el-form-item>
+            </el-col>
+            <el-col :span="12">
+                <el-form-item label="鐩戠潱鎯呭喌璇勪环">
+                    <el-select v-model="ruleForm.evaluationSupervisionSituation" placeholder="璇烽�夋嫨" style="width: 100%;">
+                        <el-option label="绗﹀悎" value="绗﹀悎"></el-option>
+                        <el-option label="涓嶇鍚�" value="涓嶇鍚�"></el-option>
+                    </el-select>
+
+                </el-form-item>
+            </el-col>
+        </el-row>
+        <el-row>
+            <el-col :span="12">
+                <el-form-item label="澶勭悊鎰忚">
+                    <el-input v-model="ruleForm.doNotMeetTheHandlingOpinions" placeholder="璇疯緭鍏�"></el-input>
+                </el-form-item>
+            </el-col>
+        </el-row>
+        <el-row>
+            <el-col v-show="isEdit && !disabled" :span="24">
+                <el-form-item style="text-align: right;">
+                    <el-button size="small" @click="close">鍙栨秷</el-button>
+                    <el-button size="small" type="primary" @click="approve">瀹℃壒</el-button>
+                </el-form-item>
+            </el-col>
+            <el-col v-show="!isEdit" :span="24">
+                <el-form-item style="text-align: right;">
+                    <el-button size="small" type="primary" @click="addData">鎻愪氦</el-button>
+                </el-form-item>
+            </el-col>
+        </el-row>
+    </el-form>
+</template>
+<script>
+
+export default {
+    props: {
+        isEdit: {
+            type: Boolean,
+            default: false
+        },
+        userList: {
+            type: Array,
+            default: () => {
+                return []
+            }
+        },
+        superviseForm: {
+            type: Object,
+            default: {}
+        },
+        disabled: {
+            type: Boolean,
+            default: false
+        }
+    },
+    computed: {
+        ruleForm: {
+            get() {
+                return this.superviseForm
+            },
+            set(val) {
+                this.$emit('superviseForm', val)
+            }
+        }
+    },
+    data() {
+        return {
+        }
+    },
+    methods: {
+        close() {
+            this.$emit('close')
+        },
+        approve() {
+            this.$emit('submit', 1)
+        },
+        addData() {
+            this.$emit('addData', 1)
+        }
+    }
+}
+</script>
\ No newline at end of file
diff --git a/src/views/CNAS/personnel/personnelInfo/Department/components/TrainingRecord/index.vue b/src/views/CNAS/personnel/personnelInfo/Department/components/TrainingRecord/index.vue
new file mode 100644
index 0000000..4f228e4
--- /dev/null
+++ b/src/views/CNAS/personnel/personnelInfo/Department/components/TrainingRecord/index.vue
@@ -0,0 +1,285 @@
+<!-- 鍩硅璁板綍 -->
+<template>
+  <div>
+    <div class="flex_table">
+      <div v-if="isDepartment" style="width: 50%">
+        <TableCard :showTitle="false">
+          <template v-slot:form>
+            <div class="items_center">
+              <span>濮撳悕</span>
+              <el-input v-model="trainingPagination.userName" class="search" clearable placeholder="璇疯緭鍏�"
+                size="small"></el-input>
+              <el-button size="small" type="primary" @click="getPersonnelTraining(departId)">鏌ヨ</el-button>
+            </div>
+            <div>
+              <!--              <el-button :loading="outLoading" size="small" type="primary" @click="exportExcel">瀵煎嚭</el-button>-->
+            </div>
+          </template>
+          <template v-slot:table>
+            <limsTable :column="trainingColumn" :currentChange="currentChange" :height="'calc(100vh - 18em)'"
+              :highlightCurrentRow="true" :table-data="trainingTableData" :table-loading="trainingLoading"
+              style="padding: 0 15px;" :page="trainingPagination" @pagination="trainingPaginationMethod">
+            </limsTable>
+          </template>
+        </TableCard>
+      </div>
+      <div :style="`width: ${isDepartment ? '50%' : '100%'};`">
+        <TableCard :showTitle="false">
+          <template v-slot:form>
+            <div class="items_center">
+              <span>骞翠唤</span>
+              <el-date-picker v-model="searchForm.trainingDate" clearable format="yyyy" placeholder="閫夋嫨骞�" size="small"
+                style="margin: 0 10px" type="year" value-format="yyyy">
+              </el-date-picker>
+              <el-button size="small" type="primary"
+                @click="queryPersonnelDetailsPage(currentChangeRow.userId)">鏌ヨ</el-button>
+              <el-button size="small" type="primary" @click="openDownloadDia(currentChangeRow)">瀵煎嚭</el-button>
+            </div>
+          </template>
+          <template v-slot:table>
+            <limsTable :column="trainingPersonColumn" :height="'calc(100vh - 18em)'"
+              :table-data="trainingPersonTableData" :table-loading="trainingPersonLoading" style="padding: 0 15px;"
+              :page="trainingPersonPagination" @pagination="trainingPersonPaginationMethod">
+            </limsTable>
+          </template>
+        </TableCard>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import limsTable from "@/components/Table/lims-table.vue";
+import TableCard from "@/components/TableCard/index.vue";
+import {
+  exportTrainingRecord,
+  trainingSelectTrainingRecord,
+  queryPersonnelDetails,
+} from '@/api/cnas/personnel/personnelInfo.js'
+export default {
+  components: { TableCard, limsTable },
+  props: {
+    departId: {
+      type: Number,
+      default: () => {
+        return null;
+      }
+    },
+    isDepartment: {
+      type: Boolean,
+      default: false
+    }
+  },
+  data() {
+    return {
+      outLoading: false,
+      trainingForm: {},
+      trainingColumn: [
+        {
+          label: '鍛樺伐缂栧彿',
+          prop: 'account',
+          width: '100'
+        }, {
+          label: '濮撳悕',
+          prop: 'name'
+        }, {
+          label: '鎵�鍦ㄩ儴闂�',
+          prop: 'departLimsName',
+          width: '150'
+        }, {
+          label: '鑱岀О',
+          prop: 'professionalTitle'
+        }, {
+          label: '鏈�楂樺鍘�',
+          prop: 'officialAcademicRedentials',
+          width: '100'
+        }, {
+          label: '鍏ュ崟浣嶆椂闂�',
+          prop: 'unitTime',
+          width: '150'
+        },
+        // {
+        //   fixed: 'right',
+        //   dataType: 'action',
+        //   width: 80,
+        //   label: '鎿嶄綔',
+        //   operation: [
+        //     {
+        //       name: '瀵煎嚭',
+        //       type: 'text',
+        //       clickFun: (row) => {
+        //         this.openDownloadDia(row)
+        //       }
+        //     }
+        //   ]
+        // }
+      ],
+      trainingTableData: [],
+      trainingLoading: false,
+      trainingPagination: {
+        size: 20,
+        total: 0,
+        current: 1,
+        userName: null
+      },
+      searchForm: {
+        trainingDate: ''
+      },
+      trainingPersonColumn: [
+        {
+          label: '鍩硅鏃ユ湡',
+          prop: 'trainingDate'
+        }, {
+          label: '鍩硅鍐呭',
+          prop: 'trainingContent'
+        }, {
+          label: '鍩硅璇炬椂',
+          prop: 'educationBackground'
+        }, {
+          label: '璇炬椂',
+          prop: 'classHour'
+        }, {
+          label: '鍩硅缁撴灉',
+          prop: 'examinationResults',
+        }, {
+          label: '澶囨敞',
+          prop: 'remarks'
+        }
+      ],
+      trainingPersonTableData: [],
+      trainingPersonLoading: false,
+      trainingPersonPagination: {
+        size: 20,
+        current: 1,
+        total: 0
+      },
+      currentChangeRow: '',
+    };
+  },
+  mounted() {
+    this.getPersonnelTraining(this.departId);
+  },
+  methods: {
+    // exportExcel() {
+    //   this.outLoading = true;
+    //   const name = this.isDepartment ? 'departmentId' : 'userId';
+    //   this.$axios.get(this.$api.personnel.personTrackRecordExport + `&${name}=` + this.departId, { responseType: 'blob' }).then(res => {
+    //     this.outLoading = false;
+    //     this.$message.success('瀵煎嚭鎴愬姛');
+    //     const blob = new Blob([res], { type: 'application/octet-stream' });
+    //     const url = URL.createObjectURL(blob);
+    //     const link = document.createElement('a');
+    //     link.href = url;
+    //     link.download = '鍩硅璁板綍.xlsx';
+    //     link.click();
+    //   }).catch(err => {
+    //     this.outLoading = false;
+    //   })
+    // },
+    // 鏌ヨ
+    refreshTable() {
+      this.getPersonnelTraining(this.departId);
+    },
+    // 鍩硅璁板綍瀵煎嚭
+    openDownloadDia(row) {
+      let date = this.searchForm.trainingDate
+      if (!date) {
+        date = this.$moment().format('YYYY')
+      }
+      console.log('date----', date);
+      exportTrainingRecord({
+        userId: row.userId,
+        trainingDate: date
+      }).then(res => {
+        this.outLoading = false
+        const blob = new Blob([res], { type: 'application/msword' });
+        this.$download.saveAs(blob, '鍩硅璁板綍瀵煎嚭' + '.docx')
+      })
+    },
+    // 鑾峰彇瀹為獙瀹�-鍩硅璁″垝鍒楄〃淇℃伅
+    getPersonnelTraining(departId) {
+      // const name = this.isDepartment ? 'departmentId' : 'userId';
+      trainingSelectTrainingRecord({
+        departmentId: departId,
+        ...this.trainingPagination
+      }).then(res => {
+        this.trainingTableData = res.data.records;
+        this.trainingPagination.total = res.data.total;
+        if (this.trainingTableData.length > 0) {
+          this.currentChange(this.trainingTableData[0]);
+        }
+      });
+    },
+    // 鑾峰彇涓汉-鍩硅璁″垝鍒楄〃淇℃伅
+    currentChange(row) {
+      this.currentChangeRow = row
+      if (row === null) {
+        row = this.trainingTableData[0]
+      }
+      this.queryPersonnelDetailsPage(row.userId)
+    },
+    queryPersonnelDetailsPage(userId) {
+      if (this.searchForm.trainingDate === null) {
+        this.searchForm.trainingDate = ''
+      }
+      queryPersonnelDetails({
+        userId,
+        ...this.trainingPersonPagination
+      }).then(res => {
+        this.trainingPersonTableData = res.data.records;
+        this.trainingPersonPagination.total = res.data.total;
+      });
+    },
+    // 鍒嗛〉
+    trainingPaginationMethod({ page, limit }) {
+      this.trainingPagination.current = page;
+      this.trainingPagination.size = limit;
+      this.getPersonnelTraining(this.departId);
+    },
+    // 鍒嗛〉
+    trainingPersonPaginationMethod({ page, limit }) {
+      this.trainingPersonPagination.current = page;
+      this.trainingPersonPagination.size = limit;
+      this.queryPersonnelDetailsPage(this.currentChangeRow.userId);
+    },
+  },
+  watch: {
+    departId: {
+      handler(newId, oldId) {
+        if (this.isDepartment) {
+          this.getPersonnelTraining(newId);
+        } else {
+          this.queryPersonnelDetailsPage(newId)
+        }
+      }
+    }
+  }
+};
+</script>
+<style scoped>
+>>>.el-form-item {
+  margin-bottom: 13px;
+}
+
+.flex_table {
+  display: flex;
+  flex-direction: row;
+  justify-content: space-between;
+}
+
+.pagination {
+  display: flex;
+  justify-content: space-between;
+  margin-top: 10px;
+}
+
+.items_center {
+  display: flex;
+  align-items: center;
+}
+
+.search {
+  width: 150px;
+  padding: 0 6px;
+}
+</style>
diff --git a/src/views/CNAS/personnel/personnelInfo/Department/components/rewardPunishmentRecord/index.vue b/src/views/CNAS/personnel/personnelInfo/Department/components/rewardPunishmentRecord/index.vue
new file mode 100644
index 0000000..a9e1122
--- /dev/null
+++ b/src/views/CNAS/personnel/personnelInfo/Department/components/rewardPunishmentRecord/index.vue
@@ -0,0 +1,316 @@
+<!-- 濂栨儵璁板綍 -->
+<template>
+  <div>
+    <div style="text-align: left; margin-bottom: 15px;">
+      <label>濮撳悕</label>
+      <el-input v-model="search.userName" clearable placeholder="璇疯緭鍏ュ叧閿瓧" size="small" style="width: 20vh;"></el-input>
+      <label style="margin-left: 1em">濂栨儵鏃ユ湡</label>
+      <el-date-picker v-model="search.searchTimeList" :picker-options="pickerOptions" align="right" clearable
+        end-placeholder="缁撴潫鏃ユ湡" format="yyyy-MM-dd" range-separator="鑷�" size="small" start-placeholder="寮�濮嬫棩鏈�"
+        style="width: 20%" type="daterange" unlink-panels value-format="yyyy-MM-dd 00:00:00">
+      </el-date-picker>
+      <el-button size="small" type="primary" @click="getPersonnelTraining(departId)">鏌ヨ</el-button>
+      <div style="float: right;">
+        <el-button :loading="outLoading" size="small" type="primary" @click="handleDown">瀵煎嚭</el-button>
+        <el-button size="small" type="primary" @click="dialogVisible = true">鏂板</el-button>
+      </div>
+    </div>
+    <div class="table">
+      <el-table :data="tableData" height="70vh" style="width: 100%">
+        <el-table-column label="搴忓彿" type="index" width="120">
+          <template v-slot="scope">
+            <span>{{ (search.current - 1) * search.size + scope.$index + 1 }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column label="鍛樺伐缂栧彿" min-width="180" prop="account">
+        </el-table-column>
+        <el-table-column label="濮撳悕" min-width="180" prop="userName">
+        </el-table-column>
+        <el-table-column label="濂栨儵绾у埆" min-width="180" prop="rewardPunishLevel">
+        </el-table-column>
+        <el-table-column label="濂栨儵鏃堕棿" min-width="180" prop="rewardPunishTime">
+        </el-table-column>
+        <el-table-column label="濂栨儵鍚嶇О" min-width="180" prop="rewardPunishName">
+        </el-table-column>
+        <el-table-column label="濂栨儵鍏蜂綋鍐呭" min-width="120" prop="rewardPunishContent">
+        </el-table-column>
+        <el-table-column label="濂栨儵鍗曚綅" min-width="180" prop="rewardPunishWorkUnit">
+        </el-table-column>
+        <el-table-column label="鍒涘缓浜�" min-width="180" prop="createUserName">
+        </el-table-column>
+        <el-table-column fixed="right" label="鎿嶄綔" width="100">
+          <template v-slot="scope">
+            <el-button size="small" type="text" @click="editForm(scope.row)">缂栬緫</el-button>
+            <el-button size="small" type="text" @click="deleteRow(scope.row)">鍒犻櫎</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+      <el-pagination :current-page="1" :page-size="search.size" :page-sizes="[10, 20, 30, 50, 100]"
+        :total="search.total" layout="->,total, sizes, prev, pager, next, jumper" @size-change="handleSizeChange"
+        @current-change="handleCurrentChange">
+      </el-pagination>
+    </div>
+    <el-dialog :visible.sync="dialogVisible" title="鎻愮ず" width="50%" @open="getUserList">
+      <div style="height: 40vh">
+        <el-form ref="form" :model="form" :rules="rules" label-width="120px">
+          <el-col :span="12">
+            <el-form-item label="鍛樺伐缂栧彿">
+              <el-input v-model="form.account" disabled size="small"></el-input>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="鍛樺伐濮撳悕" prop="userName">
+              <el-select v-model="form.userName" placeholder="璇烽�夋嫨" size="small" style="width: 100%" value-key="id"
+                @change="selectUserChange">
+                <el-option v-for="item in responsibleOptions" :key="item.id" :label="item.name" :value="item">
+                </el-option>
+              </el-select>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="濂栨儵绾у埆" prop="rewardPunishLevel">
+              <el-input v-model="form.rewardPunishLevel" size="small"></el-input>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="濂栨儵鍚嶇О" prop="rewardPunishName">
+              <el-input v-model="form.rewardPunishName" size="small"></el-input>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="濂栨儵鏃堕棿" prop="rewardPunishTime">
+              <el-date-picker v-model="form.rewardPunishTime" format="yyyy-MM-dd HH:mm:ss" placeholder="閫夋嫨鏃ユ湡"
+                size="small" style="width: 100%" type="datetime" value-format="yyyy-MM-dd HH:mm:ss">
+              </el-date-picker>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="濂栨儵鍗曚綅" prop="rewardPunishWorkUnit">
+              <el-input v-model="form.rewardPunishWorkUnit" size="small"></el-input>
+            </el-form-item>
+          </el-col>
+          <el-col :span="24">
+            <el-form-item label="濂栨儵鍐呭">
+              <el-input v-model="form.rewardPunishContent" :rows="2" size="small" type="textarea"></el-input>
+            </el-form-item>
+          </el-col>
+        </el-form>
+      </div>
+      <span slot="footer" class="dialog-footer">
+        <el-button @click="dialogVisible = false">鍙� 娑�</el-button>
+        <el-button type="primary" @click="saveOrUpdate">纭� 瀹�</el-button>
+      </span>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import {
+  deleteRewardPunishment,
+  addOrUpdateRewardPunishment,
+  rewardPunishmentPage
+} from '@/api/cnas/personnel/personnelInfo.js'
+export default {
+  props: {
+    departId: {
+      type: Number,
+      default: () => {
+        return null;
+      }
+    },
+    isDepartment: {
+      type: Boolean,
+      default: false
+    }
+  },
+  data() {
+    return {
+      tableData: [],
+      search: {
+        size: 20,
+        current: 1,
+        total: 0,
+        userName: '',
+        searchTimeList: []
+      },
+      form: {},
+      dialogVisible: false,
+      outLoading: false,
+      pickerOptions: {
+        shortcuts: [{
+          text: '鏈�杩戜竴鍛�',
+          onClick(picker) {
+            const end = new Date();
+            const start = new Date();
+            start.setTime(start.getTime() - 3600 * 1000 * 24 * 7);
+            picker.$emit('pick', [start, end]);
+          }
+        }, {
+          text: '鏈�杩戜竴涓湀',
+          onClick(picker) {
+            const end = new Date();
+            const start = new Date();
+            start.setTime(start.getTime() - 3600 * 1000 * 24 * 30);
+            picker.$emit('pick', [start, end]);
+          }
+        }, {
+          text: '鏈�杩戜笁涓湀',
+          onClick(picker) {
+            const end = new Date();
+            const start = new Date();
+            start.setTime(start.getTime() - 3600 * 1000 * 24 * 90);
+            picker.$emit('pick', [start, end]);
+          }
+        }]
+      },
+      rules: {
+        userName: [{
+          required: true, message: '璇烽�夋嫨鍛樺伐濮撳悕', trigger: 'change'
+        }],
+        rewardPunishLevel: [{
+          required: true, message: '璇疯緭鍏ュ鎯╃骇鍒�', trigger: 'blur'
+        }],
+        rewardPunishName: [{
+          required: true, message: '璇疯緭鍏ュ鎯╁悕绉�', trigger: 'blur'
+        }],
+        rewardPunishTime: [{
+          required: true, message: '璇疯緭鍏ュ鎯╂椂闂�', trigger: 'blur'
+        }],
+        rewardPunishWorkUnit: [{
+          required: true, message: '璇疯緭鍏ュ鎯╁崟浣�', trigger: 'blur'
+        }]
+      },
+      responsibleOptions: []
+    };
+  },
+  mounted() {
+    this.getPersonnelTraining(this.departId);
+  },
+  methods: {
+    handleSizeChange(val) {
+      this.search.size = val
+      this.getPersonnelTraining(this.departId);
+    },
+    handleCurrentChange(val) {
+      this.search.current = val
+      this.getPersonnelTraining(this.departId);
+    },
+    async getPersonnelTraining() {
+      const { code, data } = await rewardPunishmentPage({
+        userId: this.isDepartment ? '' : this.departId,
+        departmentId: this.isDepartment ? this.departId : '',
+        current: this.search.curent,
+        size: this.search.size,
+        userName: this.search.userName,
+        startTime: this.search.searchTimeList && this.search.searchTimeList[0],
+        endTime: this.search.searchTimeList && this.search.searchTimeList[1],
+      })
+      if (code == 200) {
+        this.tableData = data.records
+        this.search.total = data.total
+      }
+    },
+    handleDown() {
+      this.outLoading = true
+      this.$axios.post(this.$api.deviceCheck.rewardPunishmentExport, {
+        userId: this.isDepartment ? '' : this.departId,
+        departmentId: this.isDepartment ? this.departId : '',
+        userName: this.search.userName,
+        startTime: this.search.searchTimeList && this.search.searchTimeList[0],
+        endTime: this.search.searchTimeList && this.search.searchTimeList[1]
+      }, { responseType: 'blob' }).then(res => {
+        this.outLoading = false
+        const blob = new Blob([res], {
+          type: 'application/force-download'
+        })
+        //灏咮lob 瀵硅薄杞崲鎴愬瓧绗︿覆
+        let reader = new FileReader();
+        reader.readAsText(blob, 'utf-8');
+        reader.onload = () => {
+          try {
+            let result = JSON.parse(reader.result);
+            if (result.message) {
+              this.$message.error(result.message);
+            } else {
+              // 鍒涘缓涓�涓秴閾炬帴锛屽皢鏂囦欢娴佽祴杩涘幓锛岀劧鍚庡疄鐜拌繖涓秴閾炬帴鐨勫崟鍑讳簨浠�
+              const elink = document.createElement('a')
+              elink.download = decodeURI('濂栨儵璁板綍' + '.xlsx')
+              elink.style.display = 'none'
+              elink.href = URL.createObjectURL(blob)
+              document.body.appendChild(elink)
+              elink.click();
+              URL.revokeObjectURL(elink.href) // 閲婃斁URL 瀵硅薄
+              document.body.removeChild(elink)
+              this.$message.success('瀵煎嚭鎴愬姛')
+            }
+          } catch (err) {
+            console.log(err);
+            // 鍒涘缓涓�涓秴閾炬帴锛屽皢鏂囦欢娴佽祴杩涘幓锛岀劧鍚庡疄鐜拌繖涓秴閾炬帴鐨勫崟鍑讳簨浠�
+            const elink = document.createElement('a')
+            elink.download = decodeURI('濂栨儵璁板綍' + '.xlsx')
+            elink.style.display = 'none'
+            elink.href = URL.createObjectURL(blob)
+            document.body.appendChild(elink)
+            elink.click();
+            URL.revokeObjectURL(elink.href) // 閲婃斁URL 瀵硅薄
+            document.body.removeChild(elink)
+            this.$message.success('瀵煎嚭鎴愬姛')
+          }
+        }
+      })
+    },
+    // 鑾峰彇璐熻矗浜轰俊鎭帴鍙�
+    getUserList() {
+      this.$axios.get(this.$api.deviceScope.selectUserList).then(res => {
+        if (res.code == 200) {
+          this.responsibleOptions = res.data
+        }
+      })
+    },
+    selectUserChange(val) {
+      this.form.userName = val.name
+      this.form.account = val.account
+      this.form.userId = val.id
+    },
+    editForm(row) {
+      this.dialogVisible = true
+      this.form = { ...row };
+    },
+    saveOrUpdate() {
+      this.$refs.form.validate(async (valid) => {
+        if (valid) {
+          this.dialogVisible = false
+          const { code, data } = await addOrUpdateRewardPunishment(this.form)
+          if (code == 200) {
+            this.$message.success("鎿嶄綔鎴愬姛锛�")
+            this.getPersonnelTraining(this.departId);
+          }
+        }
+      })
+    },
+    async deleteRow(row) {
+      const { code, data } = await deleteRewardPunishment({
+        id: row.id
+      })
+      if (code == 200) {
+        this.$message.success("鎿嶄綔鎴愬姛锛�")
+        this.getPersonnelTraining(this.departId);
+      }
+    }
+  },
+  watch: {
+    // 鐩戝惉鐐瑰嚮el-tree鐨勬暟鎹紝杩涜鏁版嵁鍒锋柊
+    departId: {
+      handler(newId, oldId) {
+        this.getPersonnelTraining(newId);
+      }
+    },
+    dialogVisible(newVal) {
+      if (newVal === false) {
+        this.form = {}
+        this.$refs['form'].clearValidate()
+      }
+    }
+  }
+};
+</script>
diff --git a/src/views/CNAS/personnel/personnelInfo/Department/components/trackRecord/index.vue b/src/views/CNAS/personnel/personnelInfo/Department/components/trackRecord/index.vue
new file mode 100644
index 0000000..7efd792
--- /dev/null
+++ b/src/views/CNAS/personnel/personnelInfo/Department/components/trackRecord/index.vue
@@ -0,0 +1,298 @@
+<!-- 宸ヤ綔灞ュ巻 -->
+<template>
+  <div>
+    <div style="text-align: right; margin-bottom: 15px;">
+      <el-button v-if="clickNodeVal.userId" size="small" type="primary" @click="dialogVisible = true">娣诲姞宸ヤ綔灞ュ巻</el-button>
+      <el-button :loading="outLoading" size="small" type="primary" @click="exportExcel">瀵煎嚭excel</el-button>
+    </div>
+    <div class="table">
+      <el-table :data="tableData" height="70vh" style="width: 100%">
+        <el-table-column label="搴忓彿" type="index" width="120">
+          <template v-slot="scope">
+            <span>{{ (search.current - 1) * search.size + scope.$index + 1 }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column label="璧峰鏃ユ湡" min-width="180" prop="startTime">
+        </el-table-column>
+        <el-table-column label="缁撴潫鏃ユ湡" min-width="180" prop="endTime">
+        </el-table-column>
+        <el-table-column label="宸ヤ綔鍗曚綅" min-width="120" prop="placeWork">
+        </el-table-column>
+        <el-table-column label="宸ヤ綔閮ㄩ棬" min-width="120" prop="department">
+        </el-table-column>
+        <el-table-column label="鑱屽姟" min-width="120" prop="post">
+        </el-table-column>
+        <el-table-column label="澶囨敞" min-width="180" prop="remarks">
+        </el-table-column>
+        <el-table-column label="鍒涘缓浜�" min-width="180" prop="createUser">
+        </el-table-column>
+        <el-table-column label="鍒涘缓鏃堕棿" min-width="180" prop="createTime">
+        </el-table-column>
+        <el-table-column fixed="right" label="鎿嶄綔" width="150">
+          <template v-slot="scope">
+            <el-button size="small" type="text" @click="downloadFile(scope.row.fileName)">瀵煎嚭</el-button>
+            <el-button size="small" type="text" @click="checkFun(scope.row)">鏌ョ湅</el-button>
+            <el-button size="small" style="color: red;" type="text" @click="deleteFun(scope.row.id)">鍒犻櫎</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+      <el-pagination :current-page="1" :page-size="search.size" :page-sizes="[10, 20, 30, 50, 100]"
+        :total="search.total" layout="->,total, sizes, prev, pager, next, jumper" @size-change="handleSizeChange"
+        @current-change="handleCurrentChange">
+      </el-pagination>
+    </div>
+    <el-dialog :visible.sync="dialogVisible" title="鎻愮ず" width="45%">
+      <div style="height: 30vh;">
+        <el-form ref="ruleForm" :model="ruleForm" :rules="rules" class="demo-ruleForm" label-width="100px">
+          <el-row>
+            <el-col :span="12">
+              <el-form-item label="璧峰鏃ユ湡" prop="startTime">
+                <el-date-picker v-model="ruleForm.startTime" format="yyyy-MM-dd" placeholder="閫夋嫨鏃ユ湡" required
+                  size="small" style="width: 99%;" type="date" value-format="yyyy-MM-dd HH:mm:ss">
+                </el-date-picker>
+              </el-form-item>
+            </el-col>
+            <el-col :span="12">
+              <el-form-item label="缁撴潫鏃ユ湡">
+                <el-date-picker v-model="ruleForm.endTime" format="yyyy-MM-dd" placeholder="閫夋嫨鏃ユ湡" size="small"
+                  style="width: 99%;" type="date" value-format="yyyy-MM-dd HH:mm:ss">
+                </el-date-picker>
+              </el-form-item>
+            </el-col>
+          </el-row>
+          <el-row>
+            <el-col :span="12">
+              <el-form-item label="宸ヤ綔鍗曚綅" prop="placeWork">
+                <el-input v-model="ruleForm.placeWork" clearable required size="small"></el-input>
+              </el-form-item>
+            </el-col>
+            <el-col :span="12">
+              <el-form-item label="宸ヤ綔閮ㄩ棬" prop="department">
+                <el-input v-model="ruleForm.department" clearable required size="small"></el-input>
+              </el-form-item>
+            </el-col>
+          </el-row>
+          <el-row>
+            <el-col :span="12">
+              <el-form-item label="鏈�楂樿亴鍔�" prop="post">
+                <el-input v-model="ruleForm.post" clearable required size="small"></el-input>
+              </el-form-item>
+            </el-col>
+            <el-col :span="12">
+              <el-form-item label="闄勪欢璧勬枡">
+                <el-row>
+                  <el-col :span="17"><el-input v-model="ruleForm.fileName" disabled size="small"></el-input></el-col>
+                  <el-col :span="7">
+                    <el-upload ref="upload" :action="action" :on-change="handleChangePic" :on-success="onSuccess"
+                      :show-file-list="false" style="float: left; margin: 0 20px;" :headers="uploadHeader">
+                      <el-button slot="trigger" class="uploadFile" size="mini" type="primary">娴忚</el-button>
+                    </el-upload>
+                  </el-col>
+                </el-row>
+              </el-form-item>
+            </el-col>
+          </el-row>
+          <el-row>
+            <el-col :span="24">
+              <el-form-item label="澶囨敞">
+                <el-input v-model="ruleForm.remarks" clearable size="small"></el-input>
+              </el-form-item>
+            </el-col>
+          </el-row>
+        </el-form>
+      </div>
+      <span slot="footer" class="dialog-footer">
+        <el-button @click="dialogVisible = false">鍙� 娑�</el-button>
+        <el-button type="primary" @click="saveOrUpdate">{{ isUpdate ? '鏇� 鏂�' : '淇� 瀛�' }}</el-button>
+      </span>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import {
+  personTrackRecordExport,
+  personTrackRecordUpdate,
+  personTrackRecordSave,
+  personTrackRecordDelete,
+  personTrackRecordSelect,
+} from '@/api/cnas/personnel/personnelInfo.js'
+export default {
+  props: {
+    clickNodeVal: {
+      type: Object,
+      default: () => {
+        return {};
+      }
+    }
+  },
+  data() {
+    return {
+      tableData: [],
+      search: {
+        size: 20,
+        current: 1,
+        total: 0
+      },
+      dialogVisible: false,
+      ruleForm: {
+        fileName: '',
+        sysFileName: ''
+      },
+      rules: {
+        startTime: [
+          { required: true, message: '璇疯緭鍏ヨ捣濮嬫棩鏈�', trigger: 'blur' },
+          { required: true, message: '璇疯緭鍏ヨ捣濮嬫棩鏈�', trigger: 'change' }
+        ],
+        placeWork: [
+          { required: true, message: '璇疯緭鍏ュ伐浣滃崟浣�', trigger: 'blur' }
+        ],
+        department: [
+          { required: true, message: '璇疯緭鍏ュ伐浣滈儴闂�', trigger: 'blur' }
+        ],
+        post: [
+          { required: true, message: '璇疯緭鍏ユ渶楂樿亴鍔�', trigger: 'blur' }
+        ]
+      },
+      isUpdate: false,
+      outLoading: false
+    };
+  },
+  created() {
+    this.init();
+  },
+  computed: {
+    action() {
+      return this.javaApi + '/personBasicInfo/saveCNASFile'
+    }
+  },
+  methods: {
+    downloadFile(fileName) {
+      this.$download.saveAs(fileName, fileName)
+    },
+    handleChangePic(file, fileList) {
+      if (fileList.length > 1) {
+        fileList.splice(0, 1);
+      }
+    },
+    onSuccess(response, file, fileList) {
+      if (response.code === 200) {
+        this.$set(this.ruleForm, 'fileName', response.data)
+      } else {
+        this.$message.warning(response.message)
+      }
+    },
+    exportExcel() {
+      this.outLoading = true
+      let userId = this.clickNodeVal.userId ? this.clickNodeVal.userId : null
+      let departmentId = this.clickNodeVal.id ? this.clickNodeVal.id : null
+      personTrackRecordExport({
+        userId,
+        departmentId
+      }).then(res => {
+        this.outLoading = false
+        const blob = new Blob([res], { type: 'application/octet-stream' });
+        this.$download.saveAs(blob, '宸ヤ綔灞ュ巻.xlsx')
+      })
+    },
+    saveOrUpdate() {
+      this.$refs['ruleForm'].validate((valid) => {
+        if (valid) {
+          if (this.isUpdate) {
+            personTrackRecordUpdate(this.ruleForm).then(res => {
+              if (res.code = 200) {
+                this.dialogVisible = false
+                this.$message.success('鏇存柊鎴愬姛锛�')
+                this.init()
+              }
+            })
+          } else {
+            this.ruleForm.userId = this.clickNodeVal.userId
+            personTrackRecordSave(this.ruleForm).then(res => {
+              if (res.code = 200) {
+                this.dialogVisible = false
+                this.$message.success('鏂板鎴愬姛锛�')
+                this.init()
+              }
+            })
+          }
+        } else {
+          return false;
+        }
+      });
+    },
+    deleteFun(id) {
+      this.$confirm('姝ゆ搷浣滃皢姘镐箙鍒犻櫎璇ユ暟鎹�, 鏄惁缁х画?', '鎻愮ず', {
+        confirmButtonText: '纭畾',
+        cancelButtonText: '鍙栨秷',
+        type: 'warning'
+      }).then(() => {
+        personTrackRecordDelete({ id }).then(res => {
+          this.$message.success('鍒犻櫎鎴愬姛锛�')
+          this.init()
+        })
+      }).catch(() => {
+        this.$message({
+          type: 'info',
+          message: '宸插彇娑堝垹闄�'
+        });
+      });
+    },
+    handleSizeChange(val) {
+      this.search.size = val
+      this.init()
+    },
+    handleCurrentChange(val) {
+      this.search.current = val
+      this.init()
+    },
+    // 鍒濆鍖栬皟鐢�
+    init() {
+      if (this.clickNodeVal.userId) {
+        this.getPersonnelTraining(this.clickNodeVal.userId ? this.clickNodeVal.userId : null, null);
+      } else {
+        this.getPersonnelTraining(null, this.clickNodeVal.id ? this.clickNodeVal.id : null);
+      }
+    },
+    getPersonnelTraining(userId, departmentId) {
+      personTrackRecordSelect({
+        userId,
+        departmentId,
+        ...this.search
+      }).then(res => {
+        this.tableData = res.data.records
+        this.search.total = res.data.total
+      })
+    },
+    checkFun(row) {
+      this.ruleForm = { ...row }
+      this.dialogVisible = true
+      this.isUpdate = true
+    }
+  },
+  watch: {
+    // 鐩戝惉鐐瑰嚮el-tree鐨勬暟鎹紝杩涜鏁版嵁鍒锋柊
+    clickNodeVal(newVal) {
+      if (newVal.userId) {
+        // 鐢ㄦ埛id
+        this.getPersonnelTraining(newVal.userId, null);
+      } else {
+        // 閮ㄩ棬id
+        this.getPersonnelTraining(null, newVal.id);
+      }
+    },
+    dialogVisible(newVal) {
+      if (!newVal) {
+        this.isUpdate = false
+        this.$refs.ruleForm.resetFields();
+        this.ruleForm = {}
+      }
+    }
+  }
+};
+</script>
+<style scoped>
+>>>.el-form-item {
+  margin-bottom: 13px;
+}
+</style>
diff --git a/src/views/CNAS/personnel/personnelInfo/Department/index.vue b/src/views/CNAS/personnel/personnelInfo/Department/index.vue
new file mode 100644
index 0000000..b902c86
--- /dev/null
+++ b/src/views/CNAS/personnel/personnelInfo/Department/index.vue
@@ -0,0 +1,156 @@
+<template>
+  <el-tabs v-model="activeName" :lazy="true" type="border-card">
+    <el-tab-pane label="浜哄憳鍩烘湰淇℃伅" name="浜哄憳鍩烘湰淇℃伅">
+      <PersonnelList v-if="activeName === '浜哄憳鍩烘湰淇℃伅' && isShowAll" ref="personnelList"
+        :currentCompaniesList="currentCompaniesList" :departId="departId" @refreshTree="refreshTree"
+        @updatePerson="updatePerson"></PersonnelList>
+      <personnelInformation v-if="activeName === '浜哄憳鍩烘湰淇℃伅' && !isShowAll" :clickNodeVal="clickNodeVal">
+      </personnelInformation>
+    </el-tab-pane>
+    <el-tab-pane label="鍩硅璁″垝" name="鍩硅璁″垝">
+      <PersonnelTraining v-if="activeName === '鍩硅璁″垝'" ref="personnelTraining" :flag="flag" :departId="departId"
+        :isDepartment="isDepartment"></PersonnelTraining>
+    </el-tab-pane>
+    <el-tab-pane label="鐩戠潱璁″垝" name="鐩戠潱璁″垝">
+      <Plan v-if="activeName === '鐩戠潱璁″垝'" :departId="departId"></Plan>
+    </el-tab-pane>
+    <el-tab-pane label="宀椾綅鑱岃矗" name="宀椾綅鑱岃矗">
+      <job-responsibilities v-if="activeName === '宀椾綅鑱岃矗'" ref="jobResponsibilities" :departId="departId"
+        :isDepartment="isDepartment"></job-responsibilities>
+    </el-tab-pane>
+    <el-tab-pane label="宸ヤ綔灞ュ巻" name="宸ヤ綔灞ュ巻">
+      <trackRecord v-if="activeName === '宸ヤ綔灞ュ巻'" :clickNodeVal="clickNodeVal"></trackRecord>
+    </el-tab-pane>
+    <el-tab-pane label="濂栨儵璁板綍" name="濂栨儵璁板綍">
+      <rewardPunishmentRecord v-if="activeName === '濂栨儵璁板綍'" :departId="departId" :isDepartment="isDepartment">
+      </rewardPunishmentRecord>
+    </el-tab-pane>
+    <el-tab-pane label="鍩硅璁板綍" name="鍩硅璁板綍">
+      <training-record v-if="activeName === '鍩硅璁板綍'" ref="trainingRecord" :departId="departId"
+        :isDepartment="isDepartment"></training-record>
+    </el-tab-pane>
+    <el-tab-pane label="鐩戠潱璁板綍" name="鐩戠潱璁板綍">
+      <Records v-if="activeName === '鐩戠潱璁板綍'" ref="recordsRef" :departId="departId" :isDepartment="isDepartment">
+      </Records>
+    </el-tab-pane>
+    <el-tab-pane label="浠昏亴鎺堟潈璁板綍" name="浠昏亴鎺堟潈璁板綍">
+      <Mandate v-if="activeName === '浠昏亴鎺堟潈璁板綍'" ref="manDateRef" :departId="departId" :isDepartment="isDepartment">
+      </Mandate>
+    </el-tab-pane>
+    <el-tab-pane label="浜哄憳鑳藉姏" name="浜哄憳鑳藉姏">
+      <personnel-capacity v-if="activeName === '浜哄憳鑳藉姏'" ref="personnelCapacity" :departId="departId"
+        :isDepartment="isDepartment"></personnel-capacity>
+    </el-tab-pane>
+    <el-tab-pane label="娌熼�氳褰�" name="娌熼�氳褰�">
+      <Communicate v-if="activeName === '娌熼�氳褰�'" ref="communicateRef" :departId="departId" :isDepartment="isDepartment">
+      </Communicate>
+    </el-tab-pane>
+  </el-tabs>
+</template>
+<script>
+import Plan from './components/Plan/index.vue';
+import Records from './components/Records/index.vue';
+import Communicate from './components/Communicate/index.vue';
+import Mandate from './components/Mandate/index.vue';
+import PersonnelList from './components/PersonnelList/index.vue';
+import PersonnelTraining from './components/PersonnelTraining/index.vue';
+import JobResponsibilities from './components/JobResponsibilities/index.vue';
+import TrainingRecord from './components/TrainingRecord/index.vue';
+import PersonnelCapacity from './components/PersonnelCapacity/index.vue';
+import trackRecord from "./components/trackRecord/index.vue";
+import rewardPunishmentRecord from "./components/rewardPunishmentRecord/index.vue";
+import PersonnelInformation from "./components/PersonnelInformation/index.vue";
+
+export default {
+  props: {
+    clickNodeVal: {
+      type: Object,
+      default: () => {
+        return {};
+      }
+    },
+    departId: {
+      type: Number,
+      default: 0
+    },
+    isDepartment: {
+      type: Boolean,
+      default: false
+    },
+    isShowAll: {
+      type: Boolean,
+      default: false
+    },
+    currentCompaniesList: {
+      type: Array,
+      default: []
+    }
+  },
+  components: {
+    PersonnelInformation,
+    rewardPunishmentRecord,
+    trackRecord,
+    PersonnelCapacity,
+    TrainingRecord,
+    JobResponsibilities,
+    PersonnelTraining,
+    PersonnelList,
+    Plan,
+    Records,
+    Communicate,
+    Mandate
+  },
+  watch: {
+    departId: {
+      handler(newId, oldId) {
+        if (newId) {
+          switch (this.activeName) {
+            case '娌熼�氳褰�':
+              this.$refs.communicateRef.getDepart(newId);
+              break;
+            case '浠昏亴鎺堟潈璁板綍':
+              this.$refs.manDateRef.getDepart(newId);
+              break;
+            default:
+              break;
+          }
+        }
+      }
+    }
+  },
+  data() {
+    return {
+      flag: true,
+      activeName: '浜哄憳鍩烘湰淇℃伅',
+    }
+  },
+  created() {
+    // this.flag =  isPermission('personTrainingSelect')
+    // console.log('this.flag',this.flag);
+  },
+  methods: {
+    updatePerson(row) {
+      this.$parent.updatePerson(row);
+    },
+    refreshTree() {
+      this.$parent.refreshTree();
+    },
+  }
+};
+</script>
+<style scoped>
+.box {
+  height: calc(100vh - 11em);
+}
+
+.el-tabs>>>.el-tabs--border-card {
+  box-shadow: unset;
+  border: unset;
+}
+
+.flex_column {
+  display: flex;
+  flex-direction: column;
+  justify-content: space-between;
+}
+</style>
diff --git a/src/views/CNAS/personnel/personnelInfo/index.vue b/src/views/CNAS/personnel/personnelInfo/index.vue
new file mode 100644
index 0000000..a01831f
--- /dev/null
+++ b/src/views/CNAS/personnel/personnelInfo/index.vue
@@ -0,0 +1,297 @@
+<template>
+  <div class="main">
+
+    <div class="main_left">
+      <el-row>
+        <el-col :span="20">
+          <el-input v-model="search" class="div_left_input" clearable placeholder="杈撳叆鍏抽敭瀛楄繘琛屾悳绱�" size="small"
+            suffix-icon="el-icon-search" @blur="searchFilter" @clear="searchFilter"
+            @keyup.enter.native="searchFilter"></el-input>
+        </el-col>
+        <el-col :span="4" style="text-align: center;line-height: 30px; margin-top: 14px">
+          <el-button circle icon="el-icon-plus" size="mini" type="primary" @click="handleAdd"></el-button>
+        </el-col>
+      </el-row>
+      <el-tree ref="tree" :data="list" :default-expanded-keys="[1]" :expand-on-click-node="false"
+        :filter-node-method="filterNode" :props="{ children: 'children', label: 'name' }" highlight-current
+        node-key="id" style="height:calc(100% - 80px);overflow-y: scroll;scrollbar-width: none;"
+        @node-click="handleNodeClick">
+        <div slot-scope="{ node, data }" class="custom-tree-node">
+          <el-row style="width: 100%;">
+            <el-col :span="22" style="text-align: left;">
+              <span><i
+                  :class="`node_i ${data.children != undefined && data.children.length > 0 ? 'el-icon-folder-opened' : 'el-icon-tickets'}`"></i>
+                {{ data.name }}</span>
+            </el-col>
+            <el-col v-if="node.level > 1 && data.id !== null" :span="2" style="text-align: right;">
+              <el-button size="mini" type="text" @click.stop="remove(node, data)">
+                <i class="el-icon-delete"></i>
+              </el-button>
+            </el-col>
+          </el-row>
+        </div>
+      </el-tree>
+    </div>
+    <div style="width: 10px;"></div>
+    <div class="main_right">
+      <!-- 閮ㄩ棬 -->
+      <Department ref="departRef" :clickNodeVal="clickNodeVal" :currentCompaniesList="currentCompaniesList"
+        :departId="departId" :isDepartment="isDepartment" :isShowAll="isShowAll" />
+    </div>
+    <el-dialog :visible.sync="addDia" title="鏋舵瀯鏂板" width="400px">
+      <div class="body">
+        <el-row style="line-height: 50px;">
+          <el-col :span="6" style="text-align: right;">
+            <span class="required-span">* </span>鏋舵瀯鍚嶇О锛�
+          </el-col>
+          <el-col :offset="1" :span="16">
+            <el-input v-model="addOb.name" clearable placeholder="璇疯緭鍏ユ灦鏋勫悕绉�" size="small"
+              @keyup.enter.native="addStandardTree"></el-input>
+          </el-col>
+        </el-row>
+      </div>
+      <span slot="footer" class="dialog-footer">
+        <el-button @click="addDia = false">鍙� 娑�</el-button>
+        <el-button type="primary" @click="addStandardTree">纭� 瀹�</el-button>
+      </span>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import Department from './Department/index.vue';
+import {
+  delDepartmentLims,
+  addDepartmentLims,
+  selectCNSAPersonTree,
+} from '@/api/cnas/personnel/personnelInfo.js'
+
+export default {
+  components: {
+    Department
+  },
+  data() {
+    return {
+      isShowAll: true, //  鏄惁灞曠ず鏍囩鏍�
+      departId: 0,
+      list: [],
+      addDia: false,
+      addOb: {
+        name: '',
+        fatherId: ''
+      },
+      search: '',
+      clickNodeVal: {},
+      addUserForm: {
+        name: ''
+      },
+      currentCompaniesList: [],
+      entity: {
+        name: '',
+        departLimsId: '',
+        orderBy: {
+          field: 'id',
+          order: 'asc'
+        }
+      },
+      overallRecord: '浜哄憳鍒楄〃',
+      isDepartment: false,
+    };
+  },
+  mounted() {
+    this.geList();
+  },
+  methods: {
+    remove(node, data) {
+      this.$confirm("鏄惁鍒犻櫎璇ュ眰绾�", "鎻愮ず", {
+        type: "error"
+      }).then(() => {
+        this.treeLoad = true
+        delDepartmentLims({
+          id: data.id
+        }).then(res => {
+          if (res.code == 201) return
+          this.$message.success('宸插垹闄�')
+          this.geList();
+        })
+      }).catch(e => { })
+    },
+    addStandardTree() {
+      if (this.addOb.name == null || this.addOb.factory == '') {
+        this.$message.error('鏋勬灦鍚嶇О鏄繀濉」')
+        return
+      }
+      addDepartmentLims(this.addOb).then(res => {
+        if (res.code === 201) {
+          return
+        }
+        this.$message.success('娣诲姞鎴愬姛')
+        this.addDia = false
+        this.geList();
+        this.addOb.name = ''
+        this.addOb.fatherId = ''
+      })
+    },
+    handleAdd() {
+      if (this.addOb.fatherId) {
+        this.addDia = true;
+      } else {
+        this.$message.error('璇烽�夋嫨涓�涓灦鏋勫眰绾�')
+      }
+    },
+    // 浜哄憳鍒楄〃缂栬緫
+    updatePerson(row) {
+      const node = this.findNodeById(this.list, row.name);
+      if (node) {
+        this.handleNodeClick(node);
+      } else {
+        this.$message.warning('鏈壘鍒拌浜哄憳');
+      }
+    },
+    // 鏂板缓浜哄憳鍚庡埛鏂版爲
+    refreshTree() {
+      this.geList()
+    },
+    findNodeById(treeData, name) {
+      for (let i = 0; i < treeData.length; i++) {
+        if (treeData[i].name === name) {
+          return treeData[i]; // 鎵惧埌鑺傜偣锛岃繑鍥炶鑺傜偣
+        }
+        if (treeData[i].children && treeData[i].children.length > 0) {
+          const foundNode = this.findNodeById(treeData[i].children, name);
+          if (foundNode) {
+            return foundNode; // 鍦ㄥ瓙鑺傜偣涓壘鍒帮紝杩斿洖璇ヨ妭鐐�
+          }
+        }
+      }
+      return null; // 娌℃湁鎵惧埌鑺傜偣锛岃繑鍥瀗ull
+    },
+    searchFilter() {
+      this.$refs.tree.filter(this.search);
+    },
+    // 鑾峰彇鏍�
+    geList() {
+      selectCNSAPersonTree().then(res => {
+        this.list = res.data;
+        if (this.list.length > 0) {
+          this.isDepartment = true;
+          this.departId = this.list[0].id
+        }
+      });
+    },
+    filterNode(value, data) {
+      if (!value) return true;
+      return data.name.indexOf(value) !== -1;
+    },
+    handleNodeClick(val, node, el) {
+      //鏍戠殑鍊�
+      this.clickNodeVal = val;
+      // 瀛樺偍鐖剁骇鑺傜偣绾ф暟
+      if (node) {
+        this.getNodeParent(node);
+        this.clickNodeVal.level = node.level;
+        this.clickNodeVal.parent = node.parent.data;
+      }
+      this.entity.departLimsId = val.id;
+      this.addOb.fatherId = val.id;
+      // 鏄惁鏄剧ず璁惧璇︽儏
+      this.isShowAll = val.id !== null;
+      if (val.id) {	// 濡傛灉鏄疄楠屽
+        this.departId = val.id;
+        this.isDepartment = true;
+      }
+      if (val.userId) { // 鏄汉鍛�
+        this.departId = val.userId;
+        this.isDepartment = false
+      }
+    },
+    getNodeParent(val) {
+      if (val.parent != null) {
+        this.currentCompaniesList[val.level - 1] = val.data.id;
+        this.selectTree += ' - ' + val.label;
+        this.getNodeParent(val.parent);
+      }
+    }
+  }
+};
+</script>
+
+<style scoped>
+.custom-tree-node {
+  width: 80%;
+  line-height: 32px;
+}
+
+.custom-tree-node .el-icon-delete {
+  color: #3A7BFA;
+  opacity: 0;
+  font-size: 15px;
+}
+
+.custom-tree-node:hover .el-icon-delete {
+  opacity: 1;
+}
+
+.node_i {
+  color: orange;
+  font-size: 18px;
+}
+
+.main {
+  display: flex;
+  padding: 15px 0;
+}
+
+.main_left {
+  background: #ffffff;
+  text-align: center;
+  height: calc(100vh - 6.5em);
+  width: 240px;
+  border-radius: 15px;
+}
+
+.main_right {
+  width: calc(100% - 240px);
+  border-radius: 15px;
+}
+
+.div_left_input {
+  margin: 15px 0;
+  width: 90%;
+}
+
+>>>.el-tabs--border-card>.el-tabs__header .el-tabs__item {
+  border: 0 none;
+}
+
+>>>.el-tabs--border-card>.el-tabs__header .el-tabs__item.is-active {
+  color: black;
+}
+
+>>>.el-tabs--border-card>.el-tabs__header {
+  border-bottom: none;
+}
+
+.search {
+  background-color: #fff;
+  height: 100%;
+  display: flex;
+  justify-content: end;
+}
+
+.search_thing {
+  width: 350px;
+  display: flex;
+  align-items: center;
+}
+
+.search_label {
+  width: 110px;
+  font-size: 14px;
+  text-align: right;
+}
+
+.search_input {
+  width: calc(100% - 110px);
+}
+</style>
diff --git a/src/views/CNAS/systemManagement/measuresDealRisks/components/hazardIdentificationRiskAssessment.vue b/src/views/CNAS/systemManagement/measuresDealRisks/components/hazardIdentificationRiskAssessment.vue
index cdc0c7a..abab933 100644
--- a/src/views/CNAS/systemManagement/measuresDealRisks/components/hazardIdentificationRiskAssessment.vue
+++ b/src/views/CNAS/systemManagement/measuresDealRisks/components/hazardIdentificationRiskAssessment.vue
@@ -124,7 +124,6 @@
 </template>
 
 <script>
-import { getToken } from "@/utils/auth";
 import {
   getPageResults,
   dangerousRiskApproval,
diff --git a/src/views/structural/capabilityAndLaboratory/capability/index.vue b/src/views/structural/capabilityAndLaboratory/capability/index.vue
index 47973df..f130807 100644
--- a/src/views/structural/capabilityAndLaboratory/capability/index.vue
+++ b/src/views/structural/capabilityAndLaboratory/capability/index.vue
@@ -10,7 +10,7 @@
         </el-col>
         <el-col :span="12" style="text-align: right;">
           <el-upload v-if="radio === 0" ref='upload1' style="display: inline;margin-right: 8px" :action="uploadAction1"
-            :before-upload="beforeUpload1" :headers="token" :on-error="onError1" :on-success="handleSuccessUp1"
+            :before-upload="beforeUpload1" :headers="uploadHeader" :on-error="onError1" :on-success="handleSuccessUp1"
             :show-file-list="false" accept='.doc,.docx,.xls,.xlsx'>
             <el-button size="small" type="primary">瀵煎叆</el-button>
           </el-upload>
@@ -81,9 +81,9 @@
     </el-dialog>
     <el-dialog :visible.sync="uploadDia" title="鏁版嵁瀵煎叆" width="500px">
       <div style="margin: 0 auto;">
-        <el-upload ref="upload" :action="uploadAction" :auto-upload="false" :file-list="fileList" :headers="token"
-          :limit="1" :on-change="beforeUpload" :on-error="onError" :on-success="onSuccess" accept=".xlsx" drag
-          name="file">
+        <el-upload ref="upload" :action="uploadAction" :auto-upload="false" :file-list="fileList"
+          :headers="uploadHeader" :limit="1" :on-change="beforeUpload" :on-error="onError" :on-success="onSuccess"
+          accept=".xlsx" drag name="file">
           <i class="el-icon-upload"></i>
           <div class="el-upload__text">灏嗘枃浠舵嫋鍒版澶勶紝鎴�<em>鐐瑰嚮涓婁紶</em></div>
         </el-upload>
diff --git a/src/views/structural/capabilityAndLaboratory/laboratory/index.vue b/src/views/structural/capabilityAndLaboratory/laboratory/index.vue
index da211f7..aebb5e9 100644
--- a/src/views/structural/capabilityAndLaboratory/laboratory/index.vue
+++ b/src/views/structural/capabilityAndLaboratory/laboratory/index.vue
@@ -120,14 +120,14 @@
         </el-form-item>
         <el-form-item label="璧勮川鍥剧墖">
           <el-upload ref="upload" :action="uploadAction" :on-success="(m) => handleSuccessUpImg(m, 'imageUrl')"
-            accept="image/jpg,image/jpeg,image/png" :multiple="false" :limit="1" :headers="headers"
+            accept="image/jpg,image/jpeg,image/png" :multiple="false" :limit="1" :headers="uploadHeader"
             :on-change="beforeUpload" :on-error="onError">
             <el-button slot="trigger" size="small" type="primary">閫夊彇鍥剧墖</el-button>
           </el-upload>
         </el-form-item>
         <el-form-item label="璧勮川闄勪欢">
           <el-upload ref="upload1" :action="uploadAction" :on-success="(m) => handleSuccessUpImg(m, 'fileUrl')"
-            accept="image/jpg,image/jpeg,image/png,application/pdf,.doc,.docx" :headers="headers" :multiple="false"
+            accept="image/jpg,image/jpeg,image/png,application/pdf,.doc,.docx" :headers="uploadHeader" :multiple="false"
             :limit="1" :on-change="beforeUpload1" :on-error="onError1">
             <el-button slot="trigger" size="small" type="primary">閫夊彇鏂囦欢</el-button>
           </el-upload>

--
Gitblit v1.9.3