已添加61个文件
已修改12个文件
17205 ■■■■■ 文件已修改
package.json 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/cnas/systemManagement/correctiveAction.js 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/cnas/systemManagement/customerSatisfaction.js 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/cnas/systemManagement/documentControl.js 276 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/cnas/systemManagement/documentRecords.js 364 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/cnas/systemManagement/internalAuditManagement.js 386 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/cnas/systemManagement/managementReview.js 159 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/cnas/systemManagement/measuresDealRisks.js 112 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/standard/model.js 21 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/system/user.js 169 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/stamps/主任.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/stamps/储能.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/stamps/射频.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/stamps/技术负责人.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/stamps/电力.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/stamps/综合室.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/stamps/装备.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/stamps/质量负责人.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/stamps/通信.png 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Preview/filePreview.vue 230 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Table/lims-table.vue 485 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/UpPdfStamp/index.vue 165 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main.js 133 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/plugins/download.js 131 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/store/getters.js 38 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/store/modules/user.js 146 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/downHtmlToPDF.js 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/index.js 301 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/request.js 250 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/CNAS/systemManagement/correctiveAction/components/ViewTestRecord.vue 169 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/CNAS/systemManagement/correctiveAction/components/correctiveInfo.vue 258 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/CNAS/systemManagement/correctiveAction/index.vue 202 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/CNAS/systemManagement/customerManagement/base.vue 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/CNAS/systemManagement/customerManagement/components/formDialog.vue 256 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/CNAS/systemManagement/customerManagement/customerSatisfaction.vue 402 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/CNAS/systemManagement/documentControl/components/ControlledFileApplication.vue 578 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/CNAS/systemManagement/documentControl/components/DistributionCollectionRecord.vue 596 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/CNAS/systemManagement/documentControl/components/FileChangeRequest.vue 703 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/CNAS/systemManagement/documentControl/components/FileList.vue 438 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/CNAS/systemManagement/documentControl/components/FileObsoletionRequest.vue 492 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/CNAS/systemManagement/documentControl/index.vue 67 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/CNAS/systemManagement/documentRecords/approvalRecord.vue 513 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/CNAS/systemManagement/documentRecords/cancellationRecord.vue 478 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/CNAS/systemManagement/documentRecords/distributionCollectionRecord.vue 522 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/CNAS/systemManagement/documentRecords/outDocumenRecordt.vue 540 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/CNAS/systemManagement/documentRecords/regularReviewsRecord.vue 743 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/CNAS/systemManagement/documentRecords/revisionRecord.vue 867 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/CNAS/systemManagement/internalAuditManagement/components/ViewTestRecord.vue 176 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/CNAS/systemManagement/internalAuditManagement/components/auditInspection.vue 253 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/CNAS/systemManagement/internalAuditManagement/components/auditInspectionDia.vue 231 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/CNAS/systemManagement/internalAuditManagement/components/auditMeetingSign.vue 201 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/CNAS/systemManagement/internalAuditManagement/components/auditMeetingSignDia.vue 183 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/CNAS/systemManagement/internalAuditManagement/components/auditReport.vue 311 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/CNAS/systemManagement/internalAuditManagement/components/auditReportDia.vue 333 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/CNAS/systemManagement/internalAuditManagement/components/correctiveAction.vue 181 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/CNAS/systemManagement/internalAuditManagement/components/correctiveActionDIa.vue 409 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/CNAS/systemManagement/internalAuditManagement/components/implementPlanDia.vue 307 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/CNAS/systemManagement/internalAuditManagement/components/implementationPlan.vue 291 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/CNAS/systemManagement/internalAuditManagement/components/yearPlan.vue 313 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/CNAS/systemManagement/internalAuditManagement/components/yearPlanDia.vue 342 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/CNAS/systemManagement/internalAuditManagement/index.vue 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/CNAS/systemManagement/managementReview/components/managementFormDIa.vue 246 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/CNAS/systemManagement/managementReview/components/managementReviewPlan.vue 306 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/CNAS/systemManagement/managementReview/components/meetingRecords.vue 196 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/CNAS/systemManagement/managementReview/components/meetingRecordsDia.vue 158 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/CNAS/systemManagement/managementReview/components/reviewReport.vue 266 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/CNAS/systemManagement/managementReview/components/reviewReportDia.vue 259 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/CNAS/systemManagement/managementReview/index.vue 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/CNAS/systemManagement/measuresDealRisks/components/hazardIdentificationRiskAssessment.vue 331 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/CNAS/systemManagement/measuresDealRisks/components/listRiskAnalysisControlPlans.vue 298 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/CNAS/systemManagement/measuresDealRisks/index.vue 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/standard/model/index.vue 120 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
vue.config.js 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
package.json
@@ -37,6 +37,9 @@
  },
  "dependencies": {
    "@riophae/vue-treeselect": "0.4.0",
    "@vue-office/docx": "^1.6.3",
    "@vue-office/excel": "^1.7.14",
    "@vue/composition-api": "^1.7.2",
    "axios": "0.28.1",
    "clipboard": "2.0.8",
    "core-js": "3.37.1",
@@ -45,10 +48,13 @@
    "file-saver": "2.0.5",
    "fuse.js": "6.4.3",
    "highlight.js": "9.18.5",
    "html2canvas": "^1.4.1",
    "js-beautify": "1.13.0",
    "js-cookie": "3.0.1",
    "jsencrypt": "3.0.0-rc.1",
    "jspdf": "^3.0.0",
    "mammoth": "^1.9.0",
    "moment": "^2.30.1",
    "nprogress": "0.2.0",
    "print-js": "^1.6.0",
    "quill": "2.0.2",
@@ -58,10 +64,12 @@
    "vue": "2.6.12",
    "vue-count-to": "1.0.13",
    "vue-cropper": "0.5.5",
    "vue-demi": "^0.14.10",
    "vue-meta": "2.4.0",
    "vue-router": "3.4.9",
    "vuedraggable": "2.24.3",
    "vuex": "3.6.0"
    "vuex": "3.6.0",
    "worker-loader": "^3.0.8"
  },
  "devDependencies": {
    "@vue/cli-plugin-babel": "4.4.6",
src/api/cnas/systemManagement/correctiveAction.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,59 @@
// çº æ­£æŽªæ–½ç›¸å…³æŽ¥å£
import request from "@/utils/request";
//查询监督纠正措施列表
export function pageSuperviseDetailCorrect(query) {
  return request({
    url: "/qualitySupervise/pageSuperviseDetailCorrect",
    method: "get",
    params: query,
  });
}
//导出监督纠正措施
export function exportSuperviseDetaillCorrect(query) {
  return request({
    url: "/qualitySupervise/exportSuperviseDetaillCorrect",
    method: "get",
    headers: {
      responseType: "blob",
    },
    params: query,
  });
}
//查询监督纠正措施附件
export function getSuperviseDetailCorrectFileList(query) {
  return request({
    url: "/qualitySupervise/getSuperviseDetailCorrectFileList",
    method: "get",
    params: query,
  });
}
//删除监督纠正措施附件
export function delSuperviseDetailCorrectFile(query) {
  return request({
    url: "/qualitySupervise/delSuperviseDetailCorrectFile",
    method: "delete",
    params: query,
  });
}
//查询监督纠正处理
export function getSuperviseDetailCorrect(query) {
  return request({
    url: "/qualitySupervise/getSuperviseDetailCorrect",
    method: "get",
    params: query,
  });
}
//查询今年人员培训信息
export function getThisYearTrainingDetailed(query) {
  return request({
    url: "/personTraining/getThisYearTrainingDetailed",
    method: "get",
    params: query,
  });
}
src/api/cnas/systemManagement/customerSatisfaction.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,56 @@
// å®¢æˆ·æ»¡æ„åº¦ç›¸å…³æŽ¥å£
import request from "@/utils/request";
//客户满意度调查列表
export function pageClientSatisfaction(query) {
  return request({
    url: "/clientSatisfaction/pageClientSatisfaction",
    method: "get",
    params: query,
  });
}
//查询客户分析附件
export function pageAnalyseFile(query) {
  return request({
    url: "/clientSatisfaction/pageAnalyseFile",
    method: "get",
    params: query,
  });
}
//删除新增客户满意度调查
export function delClientSatisfaction(query) {
  return request({
    url: "/clientSatisfaction/delClientSatisfaction",
    method: "delete",
    params: query,
  });
}
//删除客户分析附件
export function delAnalyseFile(query) {
  return request({
    url: "/clientSatisfaction/delAnalyseFile",
    method: "delete",
    params: query,
  });
}
// æ–°å¢žå®¢æˆ·æ»¡æ„åº¦è°ƒæŸ¥
export function addClientSatisfaction(data) {
  return request({
    url: "/clientSatisfaction/addClientSatisfaction",
    method: "post",
    data: data,
  });
}
// ä¿®æ”¹æ–°å¢žå®¢æˆ·æ»¡æ„åº¦è°ƒæŸ¥
export function updateClientSatisfaction(data) {
  return request({
    url: "/clientSatisfaction/updateClientSatisfaction",
    method: "post",
    data: data,
  });
}
src/api/cnas/systemManagement/documentControl.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,276 @@
// ä½“系文件控制相关接口
import request from "@/utils/request";
// æ–‡ä»¶æ¸…单-附件上传
export function uploadFileManageDocumentList(data) {
  return request({
    url: "/manageDocumentList/uploadFileManageDocumentList",
    method: "post",
    headers: { "Content-Type": "application/x-www-form-urlencoded" },
    data: data,
  });
}
//文件清单-列表
export function pageManageDocumentList(query) {
  return request({
    url: "/manageDocumentList/pageManageDocumentList",
    method: "get",
    params: query,
  });
}
//文件清单-删除
export function delManageDocumentList(query) {
  return request({
    url: "/manageDocumentList/delManageDocumentList",
    method: "delete",
    params: query,
  });
}
// æ–‡ä»¶æ¸…单-编辑
export function doManageDocumentList(data) {
  return request({
    url: "/manageDocumentList/doManageDocumentList",
    method: "post",
    data: data,
  });
}
// æ–‡ä»¶å—控-新增
export function addManageDocumentControlled(data) {
  return request({
    url: "/manageDocumentControlled/addManageDocumentControlled",
    method: "post",
    headers: { "Content-Type": "application/x-www-form-urlencoded" },
    data: data,
  });
}
// æ–‡ä»¶å—控-修改
export function doManageDocumentControlled(data) {
  return request({
    url: "/manageDocumentControlled/doManageDocumentControlled",
    method: "post",
    headers: { "Content-Type": "application/x-www-form-urlencoded" },
    data: data,
  });
}
//文件受控-获取pdf文件流
export function checkManageDocumentControlledPdf(query) {
  return request({
    url: "/manageDocumentControlled/checkManageDocumentControlledPdf",
    method: "get",
    responseType: "blob",
    params: query,
  });
}
// æ–‡ä»¶å—控-审核
export function checkManageDocumentControlled(data) {
  return request({
    url: "/manageDocumentControlled/checkManageDocumentControlled",
    method: "post",
    headers: { "Content-Type": "application/x-www-form-urlencoded" },
    data: data,
  });
}
//文件受控-删除
export function delManageDocumentControlled(query) {
  return request({
    url: "/manageDocumentControlled/delManageDocumentControlled",
    method: "delete",
    params: query,
  });
}
//文件受控-列表
export function pageManageDocumentControlled(query) {
  return request({
    url: "/manageDocumentControlled/pageManageDocumentControlled",
    method: "get",
    params: query,
  });
}
//文件作废-列表
export function pageManageDocumentCancel(query) {
  return request({
    url: "/manageDocumentCancel/pageManageDocumentCancel",
    method: "get",
    params: query,
  });
}
// æ–‡ä»¶å‘放回收-导出
export function exportManageDocumentIssueRecycle(query) {
  return request({
    url: "/manageDocumentIssueRecycle/exportManageDocumentIssueRecycle",
    method: "get",
    responseType: "blob",
    params: query,
  });
}
// æ–‡ä»¶å‘放回收-新增
export function addManageDocumentIssueRecycle(data) {
  return request({
    url: "/manageDocumentIssueRecycle/addManageDocumentIssueRecycle",
    method: "post",
    headers: { "Content-Type": "application/x-www-form-urlencoded" },
    data: data,
  });
}
// æ–‡ä»¶å‘放回收-编辑
export function doManageDocumentIssueRecycle(data) {
  return request({
    url: "/manageDocumentIssueRecycle/doManageDocumentIssueRecycle",
    method: "post",
    data: data,
  });
}
// æ–‡ä»¶å‘放回收-审核
export function checkManageDocumentIssueRecycle(data) {
  return request({
    url: "/manageDocumentIssueRecycle/checkManageDocumentIssueRecycle",
    method: "post",
    data: data,
  });
}
// æ–‡ä»¶å‘放回收-列表
export function pageManageDocumentIssueRecycle(query) {
  return request({
    url: "/manageDocumentIssueRecycle/pageManageDocumentIssueRecycle",
    method: "get",
    params: query,
  });
}
//文件发放回收-列表
export function delManageDocumentIssueRecycle(query) {
  return request({
    url: "/manageDocumentIssueRecycle/delManageDocumentIssueRecycle",
    method: "delete",
    params: query,
  });
}
// æ–‡ä»¶å˜æ›´-导出
export function exportManageDocumentAlter(query) {
  return request({
    url: "/manageDocumentAlter/exportManageDocumentAlter",
    method: "get",
    responseType: "blob",
    params: query,
  });
}
// æ–‡ä»¶å˜æ›´-新增
export function addManageDocumentAlter(data) {
  return request({
    url: "/manageDocumentAlter/addManageDocumentAlter",
    method: "post",
    headers: { "Content-Type": "application/x-www-form-urlencoded" },
    data: data,
  });
}
// æ–‡ä»¶å˜æ›´-编辑
export function doManageDocumentAlter(data) {
  return request({
    url: "/manageDocumentAlter/doManageDocumentAlter",
    method: "post",
    headers: { "Content-Type": "application/x-www-form-urlencoded" },
    data: data,
  });
}
// æ–‡ä»¶å˜æ›´-转换流
export function checkManageDocumentAlterPdf(query) {
  return request({
    url: "/manageDocumentAlter/checkManageDocumentAlterPdf",
    method: "get",
    responseType: "blob",
    params: query,
  });
}
// æ–‡ä»¶å˜æ›´-审核
export function checkManageDocumentAlter(data) {
  return request({
    url: "/manageDocumentAlter/checkManageDocumentAlter",
    method: "post",
    headers: { "Content-Type": "application/x-www-form-urlencoded" },
    data: data,
  });
}
//文件变更-删除
export function delManageDocumentAlter(query) {
  return request({
    url: "/manageDocumentAlter/delManageDocumentAlter",
    method: "delete",
    params: query,
  });
}
// æ–‡ä»¶å˜æ›´-列表
export function pageManageDocumentAlter(query) {
  return request({
    url: "/manageDocumentAlter/pageManageDocumentAlter",
    method: "get",
    params: query,
  });
}
// æ–‡ä»¶ä½œåºŸ-新增
export function addManageDocumentCancel(data) {
  return request({
    url: "/manageDocumentCancel/addManageDocumentCancel",
    method: "post",
    data: data,
  });
}
// æ–‡ä»¶ä½œåºŸ-编辑
export function doManageDocumentCancel(data) {
  return request({
    url: "/manageDocumentCancel/doManageDocumentCancel",
    method: "post",
    data: data,
  });
}
// æ–‡ä»¶ä½œåºŸ-审核
export function checkManageDocumentCancel(data) {
  return request({
    url: "/manageDocumentCancel/checkManageDocumentCancel",
    method: "post",
    data: data,
  });
}
//文件作废-导出
export function exportManageDocumentCancel(query) {
  return request({
    url: "/manageDocumentCancel/exportManageDocumentCancel",
    method: "get",
    responseType: "blob",
    params: query,
  });
}
//文件作废-删除
export function delManageDocumentCancel(query) {
  return request({
    url: "/manageDocumentCancel/delManageDocumentCancel",
    method: "delete",
    params: query,
  });
}
src/api/cnas/systemManagement/documentRecords.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,364 @@
// ä½“系文件记录相关接口
import request from "@/utils/request";
// æ–‡ä»¶å®¡æ‰¹è®°å½•-新增
export function addManageRecordCheck(data) {
  return request({
    url: "/manageRecordCheck/addManageRecordCheck",
    method: "post",
    data: data,
  });
}
// æ–‡ä»¶å®¡æ‰¹è®°å½•-修改
export function doManageRecordCheck(data) {
  return request({
    url: "/manageRecordCheck/doManageRecordCheck",
    method: "post",
    data: data,
  });
}
//文件审批记录-导出
export function exportOutManageRecordCheck(query) {
  return request({
    url: "/manageRecordCheck/exportOutManageRecordCheck",
    method: "get",
    params: query,
  });
}
// æ–‡ä»¶å®¡æ‰¹è®°å½•-审核
export function checkManageRecordCheck(data) {
  return request({
    url: "/manageRecordCheck/checkManageRecordCheck",
    method: "post",
    data: data,
  });
}
// æ–‡ä»¶å®¡æ‰¹è®°å½•-批准
export function ratifyManageRecordCheck(data) {
  return request({
    url: "/manageRecordCheck/ratifyManageRecordCheck",
    method: "post",
    data: data,
  });
}
//文件审批记录-删除
export function delManageRecordCheck(query) {
  return request({
    url: "/manageRecordCheck/delManageRecordCheck",
    method: "delete",
    params: query,
  });
}
//文件审批记录-列表
export function pageManageRecordCheck(query) {
  return request({
    url: "/manageRecordCheck/pageManageRecordCheck",
    method: "get",
    params: query,
  });
}
// å¤–来文件确认记录-新增
export function addManageRecordVerify(data) {
  return request({
    url: "/manageRecordVerify/addManageRecordVerify",
    method: "post",
    data: data,
  });
}
//外来文件确认记录-填写--列表
export function pageManageRecordVerify(query) {
  return request({
    url: "/manageRecordVerify/pageManageRecordVerify",
    method: "get",
    params: query,
  });
}
// å¤–来文件确认记录-历史--提交
export function submitManageRecordTotal(data) {
  return request({
    url: "/manageRecordTotal/submitManageRecordTotal",
    method: "post",
    data: data,
  });
}
// å¤–来文件确认记录-历史--审核
export function ratifyManageRecordTotal(data) {
  return request({
    url: "/manageRecordTotal/ratifyManageRecordTotal",
    method: "post",
    data: data,
  });
}
//外来文件确认记录-填写--删除
export function delManageRecordVerify(query) {
  return request({
    url: "/manageRecordVerify/delManageRecordVerify",
    method: "delete",
    params: query,
  });
}
//外来文件确认记录-历史--列表
export function pageManageRecordTotal(query) {
  return request({
    url: "/manageRecordTotal/pageManageRecordTotal",
    method: "get",
    params: query,
  });
}
// å¤–来文件确认记录-填写--修改
export function doManageRecordVerify(data) {
  return request({
    url: "/manageRecordVerify/doManageRecordVerify",
    method: "post",
    data: data,
  });
}
//文件发放回收记录-导出
export function exportOutManageRecordIssueRecycle(query) {
  return request({
    url: "/manageRecordIssueRecycle/exportOutManageRecordIssueRecycle",
    method: "get",
    params: query,
  });
}
// æ–‡ä»¶å‘放回收记录-新增
export function addManageRecordIssueRecycle(data) {
  return request({
    url: "/manageRecordIssueRecycle/addManageRecordIssueRecycle",
    method: "post",
    data: data,
  });
}
// æ–‡ä»¶å‘放回收记录-编辑
export function doManageRecordIssueRecycle(data) {
  return request({
    url: "/manageRecordIssueRecycle/doManageRecordIssueRecycle",
    method: "post",
    data: data,
  });
}
//查询CNAS人员侧边栏
export function selectCNSAPersonTree(query) {
  return request({
    url: "/personBasicInfo/selectCNSAPersonTree",
    method: "get",
    params: query,
  });
}
//文件发放回收记录-列表
export function pageManageRecordIssueRecycle(query) {
  return request({
    url: "/manageRecordIssueRecycle/pageManageRecordIssueRecycle",
    method: "get",
    params: query,
  });
}
//文件发放回收记录-删除
export function delManageRecordIssueRecycle(query) {
  return request({
    url: "/manageRecordIssueRecycle/delManageRecordIssueRecycle",
    method: "delete",
    params: query,
  });
}
//文件修订-导出列表
export function exportOutManageRecordAudit(query) {
  return request({
    url: "/manageRecordAudit/exportOutManageRecordAudit",
    method: "get",
    params: query,
  });
}
// æ–‡ä»¶ä¿®è®¢-新增
export function addManageRecordAudit(data) {
  return request({
    url: "/manageRecordAudit/addManageRecordAudit",
    method: "post",
    headers: { "Content-Type": "application/x-www-form-urlencoded" },
    data: data,
  });
}
// æ–‡ä»¶ä¿®è®¢-编辑
export function doManageRecordAudit(data) {
  return request({
    url: "/manageRecordAudit/doManageRecordAudit",
    method: "post",
    headers: { "Content-Type": "application/x-www-form-urlencoded" },
    data: data,
  });
}
// æ–‡ä»¶ä¿®è®¢-批准
export function ratifyManageRecordAudit(data) {
  return request({
    url: "/manageRecordAudit/ratifyManageRecordAudit",
    method: "post",
    data: data,
  });
}
//文件修订-列表
export function pageManageRecordAudit(query) {
  return request({
    url: "/manageRecordAudit/pageManageRecordAudit",
    method: "get",
    params: query,
  });
}
//文件修订-删除
export function delManageRecordAudit(query) {
  return request({
    url: "/manageRecordAudit/delManageRecordAudit",
    method: "delete",
    params: query,
  });
}
//文件定期审查记录-导出
export function exportOutManageRecordIntervals(query) {
  return request({
    url: "/manageRecordIntervals/exportOutManageRecordIntervals",
    method: "get",
    params: query,
  });
}
// æ–‡ä»¶å®šæœŸå®¡æŸ¥è®°å½•-新增
export function addManageRecordIntervals(data) {
  return request({
    url: "/manageRecordIntervals/addManageRecordIntervals",
    method: "post",
    data: data,
  });
}
// æ–‡ä»¶å®šæœŸå®¡æŸ¥è®°å½•-编辑
export function doManageRecordIntervals(data) {
  return request({
    url: "/manageRecordIntervals/doManageRecordIntervals",
    method: "post",
    data: data,
  });
}
// æ–‡ä»¶å®šæœŸå®¡æŸ¥è®°å½•-历史记录-批准
export function ratifyManageRecordIntervalsTotal(data) {
  return request({
    url: "/manageRecordIntervalsTotal/ratifyManageRecordIntervalsTotal",
    method: "post",
    data: data,
  });
}
// æ–‡ä»¶å®šæœŸå®¡æŸ¥è®°å½•-历史记录-提交
export function submitManageRecordIntervalsTotal(data) {
  return request({
    url: "/manageRecordIntervalsTotal/submitManageRecordIntervalsTotal",
    method: "post",
    data: data,
  });
}
//文件定期审查记录-列表
export function pageManageRecordIntervals(query) {
  return request({
    url: "/manageRecordIntervals/pageManageRecordIntervals",
    method: "get",
    params: query,
  });
}
//文件定期审查记录-历史记录-列表
export function pageManageRecordIntervalsTotal(query) {
  return request({
    url: "/manageRecordIntervalsTotal/pageManageRecordIntervalsTotal",
    method: "get",
    params: query,
  });
}
//文件定期审查记录-删除
export function delManageRecordIntervals(query) {
  return request({
    url: "/manageRecordIntervals/delManageRecordIntervals",
    method: "delete",
    params: query,
  });
}
//文件作废记录-导出
export function exportOutManageRecordCancel(query) {
  return request({
    url: "/manageRecordCancel/exportOutManageRecordCancel",
    method: "get",
    params: query,
  });
}
// æ–‡ä»¶ä½œåºŸè®°å½•-新增
export function addManageRecordCancel(data) {
  return request({
    url: "/manageRecordCancel/addManageRecordCancel",
    method: "post",
    data: data,
  });
}
// æ–‡ä»¶ä½œåºŸè®°å½•-编辑
export function doManageRecordCancel(data) {
  return request({
    url: "/manageRecordCancel/doManageRecordCancel",
    method: "post",
    data: data,
  });
}
// æ–‡ä»¶ä½œåºŸè®°å½•-批准
export function ratifyManageRecordCancel(data) {
  return request({
    url: "/manageRecordCancel/ratifyManageRecordCancel",
    method: "post",
    data: data,
  });
}
//文件作废记录-删除
export function delManageRecordCancel(query) {
  return request({
    url: "/manageRecordCancel/delManageRecordCancel",
    method: "delete",
    params: query,
  });
}
//文件作废记录-列表
export function pageManageRecordCancel(query) {
  return request({
    url: "/manageRecordCancel/pageManageRecordCancel",
    method: "get",
    params: query,
  });
}
src/api/cnas/systemManagement/internalAuditManagement.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,386 @@
// å†…审管理相关接口
import request from "@/utils/request";
//年度计划-分页
export function pageInternalPlan(query) {
  return request({
    url: "/internalPlan/pageInternalPlan",
    method: "get",
    params: query,
  });
}
//年度计划-删除
export function delInternalPlan(query) {
  return request({
    url: "/internalPlan/delInternalPlan",
    method: "delete",
    params: query,
  });
}
//年度计划-导出
export function exportInternalPlan(query) {
  return request({
    url: "/internalPlan/exportInternalPlan",
    method: "get",
    responseType: "blob",
    params: query,
  });
}
//年度计划详情
export function getInternalPlanOne(query) {
  return request({
    url: "/internalPlan/getInternalPlanOne",
    method: "get",
    params: query,
  });
}
// å¹´åº¦è®¡åˆ’-新增
export function addInternalPlan(data) {
  return request({
    url: "/internalPlan/addInternalPlan",
    method: "post",
    data: data,
  });
}
// å¹´åº¦è®¡åˆ’-修改
export function updateInternalPlan(data) {
  return request({
    url: "/internalPlan/updateInternalPlan",
    method: "post",
    data: data,
  });
}
// å¹´åº¦è®¡åˆ’-审核
export function examineInternalPlan(data) {
  return request({
    url: "/internalPlan/examineInternalPlan",
    method: "post",
    data: data,
  });
}
// å¹´åº¦è®¡åˆ’-批准
export function ratifyInternalPlan(data) {
  return request({
    url: "/internalPlan/ratifyInternalPlan",
    method: "post",
    data: data,
  });
}
//内审实施计划分页查询
export function pageInternalImplement(query) {
  return request({
    url: "/internalImplement/pageInternalImplement",
    method: "get",
    params: query,
  });
}
//内审实施计划删除
export function delInternalImplement(query) {
  return request({
    url: "/internalImplement/delInternalImplement",
    method: "delete",
    params: query,
  });
}
//导出内审实施计划
export function exportInternalImplement(query) {
  return request({
    url: "/internalImplement/exportInternalImplement",
    method: "get",
    responseType: "blob",
    params: query,
  });
}
//内审实施计划详情
export function getInternalImplementOne(query) {
  return request({
    url: "/internalImplement/getInternalImplementOne",
    method: "get",
    params: query,
  });
}
// å†…审实施计划新增
export function addInternalImplement(data) {
  return request({
    url: "/internalImplement/addInternalImplement",
    method: "post",
    data: data,
  });
}
// å†…审实施计划修改
export function updateInternalImplement(data) {
  return request({
    url: "/internalImplement/updateInternalImplement",
    method: "post",
    data: data,
  });
}
// å†…审实施计划修改
export function ratifyInternalImplement(data) {
  return request({
    url: "/internalImplement/ratifyInternalImplement",
    method: "post",
    data: data,
  });
}
//会议签到查询
export function pageInternalMeeting(query) {
  return request({
    url: "/internalMeeting/pageInternalMeeting",
    method: "get",
    params: query,
  });
}
// ä¼šè®®ç­¾åˆ°åˆ é™¤
export function delInternalMeeting(query) {
  return request({
    url: "/internalMeeting/delInternalMeeting",
    method: "delete",
    params: query,
  });
}
//导出内审会议
export function exportInternalMeeting(query) {
  return request({
    url: "/internalMeeting/exportInternalMeeting",
    method: "get",
    responseType: "blob",
    params: query,
  });
}
//会议签到查询详情
export function getInternalMeetingOne(query) {
  return request({
    url: "/internalMeeting/getInternalMeetingOne",
    method: "get",
    params: query,
  });
}
// æ–°å¢žä¼šè®®ç­¾åˆ°
export function addInternalMeeting(data) {
  return request({
    url: "/internalMeeting/addInternalMeeting",
    method: "post",
    data: data,
  });
}
// ä¼šè®®ç­¾åˆ°ä¿®æ”¹
export function updateInternalMeeting(data) {
  return request({
    url: "/internalMeeting/updateInternalMeeting",
    method: "post",
    data: data,
  });
}
//内审检查分页查询
export function pageInternalCheck(query) {
  return request({
    url: "/internalCheck/pageInternalCheck",
    method: "get",
    params: query,
  });
}
//内审检查删除
export function delInternalCheck(query) {
  return request({
    url: "/internalCheck/delInternalCheck",
    method: "delete",
    params: query,
  });
}
//导出内审检查
export function exportInternalCheck(query) {
  return request({
    url: "/internalCheck/exportInternalCheck",
    method: "get",
    responseType: "blob",
    params: query,
  });
}
//内审检查详情
export function getInternalCheckOne(query) {
  return request({
    url: "/internalCheck/getInternalCheckOne",
    method: "get",
    params: query,
  });
}
// å†…审检查新增
export function addInternalCheck(data) {
  return request({
    url: "/internalCheck/addInternalCheck",
    method: "post",
    data: data,
  });
}
// å†…审检查修改
export function updateInternalCheck(data) {
  return request({
    url: "/internalCheck/updateInternalCheck",
    method: "post",
    data: data,
  });
}
// å†…审检查批准
export function ratifyInternalCheck(data) {
  return request({
    url: "/internalCheck/ratifyInternalCheck",
    method: "post",
    data: data,
  });
}
//查询内审管理纠正措施列表
export function pageInternalCorrect(query) {
  return request({
    url: "/internalCorrect/pageInternalCorrect",
    method: "get",
    params: query,
  });
}
//导出内审管理纠正措施附件
export function exportInternalCorrect(query) {
  return request({
    url: "/internalCorrect/exportInternalCorrect",
    method: "get",
    responseType: "blob",
    params: query,
  });
}
//查询内审管理纠正处理详情
export function getInternalCorrect(query) {
  return request({
    url: "/internalCorrect/getInternalCorrect",
    method: "get",
    params: query,
  });
}
// æäº¤å†…审管理纠正措施列表
export function addInternalCorrect(data) {
  return request({
    url: "/internalCorrect/addInternalCorrect",
    method: "post",
    data: data,
  });
}
//内审报告删除
export function delInternalReport(query) {
  return request({
    url: "/internalReport/delInternalReport",
    method: "delete",
    params: query,
  });
}
//内审报告分页查询
export function pageInternalReport(query) {
  return request({
    url: "/internalReport/pageInternalReport",
    method: "get",
    params: query,
  });
}
//导出内审报告
export function exportInternalReport(query) {
  return request({
    url: "/internalReport/exportInternalReport",
    method: "get",
    responseType: "blob",
    params: query,
  });
}
//内审报告详情
export function getInternalReportOne(query) {
  return request({
    url: "/internalReport/getInternalReportOne",
    method: "get",
    params: query,
  });
}
// å†…审报告新增
export function addInternalReport(data) {
  return request({
    url: "/internalReport/addInternalReport",
    method: "post",
    data: data,
  });
}
// å†…审报告修改
export function updateInternalReport(data) {
  return request({
    url: "/internalReport/updateInternalReport",
    method: "post",
    data: data,
  });
}
// å†…审报告审核
export function examineInternalReport(data) {
  return request({
    url: "/internalReport/examineInternalReport",
    method: "post",
    data: data,
  });
}
// å†…审报告负责人填写
export function qualityInternalReport(data) {
  return request({
    url: "/internalReport/qualityInternalReport",
    method: "post",
    data: data,
  });
}
//查询内审管理纠正措施附件
export function getInternalCorrectFileList(query) {
  return request({
    url: "/internalCorrect/getInternalCorrectFileList",
    method: "get",
    params: query,
  });
}
//删除内审管理纠正措施附件
export function delInternalCorrectFile(query) {
  return request({
    url: "/internalCorrect/delInternalCorrectFile",
    method: "delete",
    params: query,
  });
}
src/api/cnas/systemManagement/managementReview.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,159 @@
// ç®¡ç†è¯„审相关接口
import request from "@/utils/request";
// ç®¡ç†è®¡åˆ’-上传附件
export function addReviewProgramFile(data) {
  return request({
    url: "/manageReviewProgramFile/addReviewProgramFile",
    method: "post",
    headers: { "Content-Type": "application/x-www-form-urlencoded" },
    data: data,
  });
}
//管理计划-附件列表
export function selectReviewProgramFile(query) {
  return request({
    url: "/manageReviewProgramFile/selectReviewProgramFile",
    method: "get",
    params: query,
  });
}
//管理计划-查询管理评审计划
export function getPageReviewProgram(query) {
  return request({
    url: "/manageReviewProgram/getPageReviewProgram",
    method: "get",
    params: query,
  });
}
//管理计划-删除管理评审计划
export function deleteReviewProgram(query) {
  return request({
    url: "/manageReviewProgram/deleteReviewProgram",
    method: "delete",
    params: query,
  });
}
//管理计划
export function exportReviewProgram(query) {
  return request({
    url: "/manageReviewProgram/exportReviewProgram",
    method: "get",
    responseType: "blob",
    params: query,
  });
}
// ç®¡ç†è®¡åˆ’-编辑管理评审计划
export function modifyReviewProgram(data) {
  return request({
    url: "/manageReviewProgram/modifyReviewProgram",
    method: "post",
    data: data,
  });
}
//会议记录-查询管理评审会议记录
export function getPageMeeting(query) {
  return request({
    url: "/manageMeeting/getPageMeeting",
    method: "get",
    params: query,
  });
}
//会议记录-删除管理评审会议记录
export function deleteMeeting(query) {
  return request({
    url: "/manageMeeting/deleteMeeting",
    method: "delete",
    params: query,
  });
}
//会议记录-下载管理评审会议记录
export function exportMeeting(query) {
  return request({
    url: "/manageMeeting/exportMeeting",
    method: "get",
    responseType: "blob",
    params: query,
  });
}
// ç®¡ç†è®¡åˆ’-新增管理评审会议记录
export function addMeeting(data) {
  return request({
    url: "/manageMeeting/addMeeting",
    method: "post",
    data: data,
  });
}
// ç®¡ç†è®¡åˆ’-修改管理评审会议记录
export function modifyMeeting(data) {
  return request({
    url: "/manageMeeting/modifyMeeting",
    method: "post",
    data: data,
  });
}
//评审会议报告-查询管理评审会议报告
export function getPageReviewReport(query) {
  return request({
    url: "/manageReviewReport/getPageReviewReport",
    method: "get",
    params: query,
  });
}
//评审会议报告-删除管理评审会议报告
export function deleteReviewReport(query) {
  return request({
    url: "/manageReviewReport/deleteReviewReport",
    method: "delete",
    params: query,
  });
}
//评审会议报告-下载
export function exportReviewReport(query) {
  return request({
    url: "/manageReviewReport/exportReviewReport",
    method: "get",
    responseType: "blob",
    params: query,
  });
}
// è¯„审会议报告-编辑管理评审会议报告
export function modifyReviewReport(data) {
  return request({
    url: "/manageReviewReport/modifyReviewReport",
    method: "post",
    data: data,
  });
}
// è¯„审会议报告-新增管理评审会议报告
export function addReviewReport(data) {
  return request({
    url: "/manageReviewReport/addReviewReport",
    method: "post",
    data: data,
  });
}
// è¯„审会议报告-新增管理评审计划
export function addReviewProgram(data) {
  return request({
    url: "/manageReviewProgram/addReviewProgram",
    method: "post",
    data: data,
  });
}
src/api/cnas/systemManagement/measuresDealRisks.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,112 @@
// åº”对风险的措施相关接口
import request from "@/utils/request";
//危险因素辨识与风险评价结果一览 åˆ†é¡µ
export function getPageResults(query) {
  return request({
    url: "/manageRiskAssessmentResults/getPageResults",
    method: "get",
    params: query,
  });
}
// å±é™©å› ç´ è¾¨è¯†ä¸Žé£Žé™©è¯„价结果一览 å®¡æ‰¹
export function dangerousRiskApproval(data) {
  return request({
    url: "/manageRiskAssessmentResults/dangerousRiskApproval",
    method: "post",
    data: data,
  });
}
// å±é™©å› ç´ è¾¨è¯†ä¸Žé£Žé™©è¯„价结果一览 æ‰¹å‡†
export function hazardIdentificationAndRiskApproval(data) {
  return request({
    url: "/manageRiskAssessmentResults/hazardIdentificationAndRiskApproval",
    method: "post",
    data: data,
  });
}
//危险因素辨识与风险评价结果一览 åˆ é™¤
export function removeRiskFactors(query) {
  return request({
    url: "/manageRiskAssessmentResults/removeRiskFactors",
    method: "delete",
    params: query,
  });
}
// å±é™©å› ç´ è¾¨è¯†ä¸Žé£Žé™©è¯„价结果一览 æ–°å¢ž
export function addNewRiskFactors(data) {
  return request({
    url: "/manageRiskAssessmentResults/addNewRiskFactors",
    method: "post",
    data: data,
  });
}
//危险因素辨识与风险评价结果一览 å¯¼å‡º
export function exportHazardFactorIdentification(query) {
  return request({
    url: "/manageRiskAssessmentResults/exportHazardFactorIdentification",
    method: "get",
    responseType: "blob",
    params: query,
  });
}
//重大风险因素分析及控制计划清单 åˆ†é¡µ
export function getPageList(query) {
  return request({
    url: "/manageControlPlanList/getPageList",
    method: "get",
    params: query,
  });
}
// é‡å¤§é£Žé™©å› ç´ åˆ†æžåŠæŽ§åˆ¶è®¡åˆ’清单 å®¡æ ¸
export function riskAnalysisApprovalOfControlPlanChecklist(data) {
  return request({
    url: "/manageControlPlanList/riskAnalysisApprovalOfControlPlanChecklist",
    method: "post",
    data: data,
  });
}
// é‡å¤§é£Žé™©å› ç´ åˆ†æžåŠæŽ§åˆ¶è®¡åˆ’清单 æ‰¹å‡†
export function approvalOfControlPlanChecklist(data) {
  return request({
    url: "/manageControlPlanList/approvalOfControlPlanChecklist",
    method: "post",
    data: data,
  });
}
//重大风险因素分析及控制计划清单 åˆ é™¤
export function deleteSignificantRiskFactorAnalysis(query) {
  return request({
    url: "/manageControlPlanList/deleteSignificantRiskFactorAnalysis",
    method: "delete",
    params: query,
  });
}
// é‡å¤§é£Žé™©å› ç´ åˆ†æžåŠæŽ§åˆ¶è®¡åˆ’清单 æ–°å¢ž
export function analysisOfMajorRiskFactorsAdded(data) {
  return request({
    url: "/manageControlPlanList/analysisOfMajorRiskFactorsAdded",
    method: "post",
    data: data,
  });
}
//重大风险因素分析及控制计划清单 å¯¼å‡º
export function exportSignificantRiskFactors(query) {
  return request({
    url: "/manageControlPlanList/exportSignificantRiskFactors",
    method: "get",
    responseType: "blob",
    params: query,
  });
}
src/api/standard/model.js
@@ -1,20 +1,11 @@
import request from "@/utils/request";
// æŸ¥è¯¢å®¢æˆ·åˆ—表
export function selectStandardTemplatePageList(data) {
export function selectStandardTemplatePageList(query) {
  return request({
    url: "/StandardTemplate/selectStandardTemplatePageList",
    method: "post",
    data: data,
  });
}
// æ¨¡ç‰ˆå¤åˆ¶
export function copyStandardTemplate(data) {
  return request({
    url: "/StandardTemplate/copyStandardTemplate",
    method: "post",
    data: data,
    method: "get",
    params: query,
  });
}
@@ -37,11 +28,11 @@
}
// åˆ é™¤æ£€éªŒæ¨¡æ¿
export function delStandardTemplate(data) {
export function delStandardTemplate(query) {
  return request({
    url: "/StandardTemplate/delStandardTemplate",
    method: "post",
    data: data,
    method: "delete",
    params: query,
  });
}
src/api/system/user.js
@@ -1,182 +1,191 @@
import request from '@/utils/request'
import request from "@/utils/request";
import { parseStrEmpty } from "@/utils/ruoyi";
// æŸ¥è¯¢ç”¨æˆ·åˆ—表
export function listUser(query) {
  return request({
    url: '/system/user/list',
    method: 'get',
    params: query
  })
    url: "/system/user/list",
    method: "get",
    params: query,
  });
}
// æŸ¥è¯¢ç”¨æˆ·è¯¦ç»†
export function getUser(userId) {
  return request({
    url: '/system/user/' + parseStrEmpty(userId),
    method: 'get'
  })
    url: "/system/user/" + parseStrEmpty(userId),
    method: "get",
  });
}
// æ–°å¢žç”¨æˆ·
export function addUser(data) {
  return request({
    url: '/system/user',
    method: 'post',
    data: data
  })
    url: "/system/user",
    method: "post",
    data: data,
  });
}
// ä¿®æ”¹ç”¨æˆ·
export function updateUser(data) {
  return request({
    url: '/system/user',
    method: 'put',
    data: data
  })
    url: "/system/user",
    method: "put",
    data: data,
  });
}
// åˆ é™¤ç”¨æˆ·
export function delUser(userId) {
  return request({
    url: '/system/user/' + userId,
    method: 'delete'
  })
    url: "/system/user/" + userId,
    method: "delete",
  });
}
// ç”¨æˆ·å¯†ç é‡ç½®
export function resetUserPwd(userId, password) {
  const data = {
    userId,
    password
  }
    password,
  };
  return request({
    url: '/system/user/resetPwd',
    method: 'put',
    data: data
  })
    url: "/system/user/resetPwd",
    method: "put",
    data: data,
  });
}
// ç”¨æˆ·çŠ¶æ€ä¿®æ”¹
export function changeUserStatus(userId, status) {
  const data = {
    userId,
    status
  }
    status,
  };
  return request({
    url: '/system/user/changeStatus',
    method: 'put',
    data: data
  })
    url: "/system/user/changeStatus",
    method: "put",
    data: data,
  });
}
// æŸ¥è¯¢ç”¨æˆ·ä¸ªäººä¿¡æ¯
export function getUserProfile() {
  return request({
    url: '/system/user/profile',
    method: 'get'
  })
    url: "/system/user/profile",
    method: "get",
  });
}
// ä¿®æ”¹ç”¨æˆ·ä¸ªäººä¿¡æ¯
export function updateUserProfile(data) {
  return request({
    url: '/system/user/profile',
    method: 'put',
    data: data
  })
    url: "/system/user/profile",
    method: "put",
    data: data,
  });
}
// ç”¨æˆ·å¯†ç é‡ç½®
export function updateUserPwd(oldPassword, newPassword) {
  const data = {
    oldPassword,
    newPassword
  }
    newPassword,
  };
  return request({
    url: '/system/user/profile/updatePwd',
    method: 'put',
    data: data
  })
    url: "/system/user/profile/updatePwd",
    method: "put",
    data: data,
  });
}
// ç”¨æˆ·å¤´åƒä¸Šä¼ 
export function uploadAvatar(data) {
  return request({
    url: '/system/user/profile/avatar',
    method: 'post',
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
    data: data
  })
    url: "/system/user/profile/avatar",
    method: "post",
    headers: { "Content-Type": "application/x-www-form-urlencoded" },
    data: data,
  });
}
// æŸ¥è¯¢æŽˆæƒè§’色
export function getAuthRole(userId) {
  return request({
    url: '/system/user/authRole/' + userId,
    method: 'get'
  })
    url: "/system/user/authRole/" + userId,
    method: "get",
  });
}
// ä¿å­˜æŽˆæƒè§’色
export function updateAuthRole(data) {
  return request({
    url: '/system/user/authRole',
    method: 'put',
    params: data
  })
    url: "/system/user/authRole",
    method: "put",
    params: data,
  });
}
// æŸ¥è¯¢éƒ¨é—¨ä¸‹æ‹‰æ ‘结构
export function deptTreeSelect() {
  return request({
    url: '/system/user/deptTree',
    method: 'get'
  })
    url: "/system/user/deptTree",
    method: "get",
  });
}
// èŽ·å–äººäº‹ç³»ç»Ÿç»„ç»‡
export function selectCompaniesList() {
  return request({
    url: '/companies/selectCompaniesList',
    method: 'get'
  })
    url: "/companies/selectCompaniesList",
    method: "get",
  });
}
// èŽ·å–äººäº‹ç³»ç»Ÿç»„ç»‡ä¸‹çš„äººå‘˜
export function selectSimpleList(data) {
  return request({
    url: '/companies/selectSimpleList',
    method: 'post',
    params: data
  })
    url: "/companies/selectSimpleList",
    method: "post",
    params: data,
  });
}
// èŽ·å–äººäº‹ç³»ç»Ÿç»„ç»‡ä¸‹çš„äººå‘˜
export function addPersonUser(data) {
  return request({
    url: '/companies/addPersonUser',
    method: 'post',
    params: data
  })
    url: "/companies/addPersonUser",
    method: "post",
    params: data,
  });
}
// èŽ·å–è§’è‰²
export function selectRoleList() {
  return request({
    url: '/role/selectRoleList',
    method: 'get',
  })
    url: "/role/selectRoleList",
    method: "get",
  });
}
// èŽ·å–å•ä½
export function selectCustomEnum() {
  return request({
    url: '/user/selectCustomEnum',
    method: 'get',
  })
    url: "/user/selectCustomEnum",
    method: "get",
  });
}
// æäº¤æ·»åŠ æž¶æž„ä¿¡æ¯
export function addDepartment(params) {
  return request({
    url: '/department/addDepartment',
    method: 'post',
    params: params
  })
    url: "/department/addDepartment",
    method: "post",
    params: params,
  });
}
// èŽ·å–ç”¨æˆ·åˆ—è¡¨
export function selectUserCondition(query) {
  return request({
    url: "/system/newUser/selectUserCondition",
    method: "get",
    params: query,
  });
}
src/assets/stamps/Ö÷ÈÎ.png
src/assets/stamps/´¢ÄÜ.png
src/assets/stamps/É䯵.png
src/assets/stamps/¼¼Êõ¸ºÔðÈË.png
src/assets/stamps/µçÁ¦.png
src/assets/stamps/×ÛºÏÊÒ.png
src/assets/stamps/×°±¸.png
src/assets/stamps/ÖÊÁ¿¸ºÔðÈË.png
src/assets/stamps/ͨÐÅ.png
src/components/Preview/filePreview.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,230 @@
<template>
  <div>
    <div v-if="isImage">
      <img :src="imgUrl" alt="Image Preview" />
    </div>
    <div v-if="isPdf">
      <object :data="fileUrl" type="application/pdf" width="100%" height="750px">
        <p>您的浏览器不支持 PDF é¢„览。<a :href="fileUrl" style="color: #3a7bfa;" target="_blank">下载 PDF æ–‡ä»¶</a></p>
      </object>
    </div>
    <div v-if="isDoc">
      <p v-if="!isDocShow">文档无法直接预览,请下载查看。</p>
      <a :href="fileUrl" v-if="!isDocShow" target="_blank">下载文件</a>
      <vue-office-docx v-else :src="fileUrl" style="height: 100vh;" @rendered="renderedHandler" @error="errorHandler" />
    </div>
    <div v-if="isXls">
      <p v-if="!isDocShow">文档无法直接预览,请下载查看。</p>
      <a :href="fileUrl" v-if="!isDocShow" target="_blank">下载文件</a>
      <vue-office-excel v-else :src="fileUrl" :options="options" style="height: 100vh;" @rendered="renderedHandler"
        @error="errorHandler" />
    </div>
    <div v-if="isZipOrRar">
      <p>压缩文件无法直接预览,请下载查看。</p>
      <a :href="fileUrl" target="_blank">下载文件</a>
    </div>
    <div v-if="isCsv">
      <p v-if="csvList.length == 0">CSV æ–‡ä»¶æ— æ³•直接预览,请下载查看。</p>
      <a :href="fileUrl" v-if="csvList.length == 0" target="_blank">下载文件</a>
      <el-tabs type="border-card" v-if="csvList.length > 0" tab-position="bottom">
        <el-tab-pane :label="item.sheetName" v-for="(item, index) in csvList" :key="index">
          <el-table :data="item.tableData" height="75vh">
            <el-table-column :label="m.label" :prop="m.prop" v-for="(m, i) in item.column" :key="i" min-width="120px"
              show-overflow-tooltip>
              <template slot-scope="scope" slot="header">
                <div>
                  <el-tooltip :content="m.label" placement="top">
                    <div class="oneLine">
                      <span>{{ m.label }}</span>
                    </div>
                  </el-tooltip>
                </div>
              </template>
            </el-table-column>
          </el-table>
        </el-tab-pane>
      </el-tabs>
    </div>
    <div v-if="!isSupported">
      <p>不支持的文件格式</p>
    </div>
  </div>
</template>
<script>
import VueOfficeDocx from '@vue-office/docx'
//引入相关样式
import '@vue-office/docx/lib/index.css'
import VueOfficeExcel from '@vue-office/excel'
//引入相关样式
import '@vue-office/excel/lib/index.css'
export default {
  components: {
    VueOfficeDocx,
    VueOfficeExcel,
  },
  props: {
    fileUrl: {
      type: String,
      required: true
    },
    currentFile: {
      type: Object,
      required: true
    },
  },
  data() {
    return {
      isDocShow: true,
      options: {
        xls: false,       //预览xlsx文件设为false;预览xls文件设为true
        minColLength: 0,  // excel最少渲染多少列,如果想实现xlsx文件内容有几列,就渲染几列,可以将此值设置为0.
        minRowLength: 0,  // excel最少渲染多少行,如果想实现根据xlsx实际函数渲染,可以将此值设置为0.
        widthOffset: 10,  //如果渲染出来的结果感觉单元格宽度不够,可以在默认渲染的列表宽度上再加 Npx宽
        heightOffset: 10, //在默认渲染的列表高度上再加 Npx高
        beforeTransformData: (workbookData) => { return workbookData }, //底层通过exceljs获取excel文件内容,通过该钩子函数,可以对获取的excel文件内容进行修改,比如某个单元格的数据显示不正确,可以在此自行修改每个单元格的value值。
        transformData: (workbookData) => { return workbookData }, //将获取到的excel数据进行处理之后且渲染到页面之前,可通过transformData对即将渲染的数据及样式进行修改,此时每个单元格的text值就是即将渲染到页面上的内容
      },
      csvList: [],//csv文件数据
      imgUrl: ''
    }
  },
  computed: {
    isImage() {
      let state = /\.(jpg|jpeg|png|gif)$/i.test(this.fileUrl)
      this.imgUrl = this.fileUrl
      if (state) {
        this.imgUrl = this.fileUrl.replaceAll('word', 'img')
      }
      console.log(11111, this.imgUrl)
      return state;
    },
    isPdf() {
      return /\.pdf$/i.test(this.fileUrl);
    },
    isDoc() {
      return /\.(doc|docx)$/i.test(this.fileUrl);
    },
    isXls() {
      let state = /\.(xls|xlsx)$/i.test(this.fileUrl)
      if (state) {
        if (/\.(xlsx)$/i.test(this.fileUrl)) {
          this.options.xls = false
        } else {
          this.options.xls = true
        }
      }
      return state;
    },
    isZipOrRar() {
      return /\.(zip|rar)$/i.test(this.fileUrl);
    },
    isCsv() {
      let state = /\.csv$/i.test(this.fileUrl)
      if (state) {
        this.loadCSVData();
        // this.main()
      }
      return state;
    },
    isSupported() {
      return this.isImage || this.isPdf || this.isDoc || this.isZipOrRar || this.isCsv || this.isXls;
    }
  },
  methods: {
    renderedHandler() {
      console.log("渲染完成")
      this.isDocShow = true
      this.resetStyle()
    },
    errorHandler() {
      console.log("渲染失败")
      this.isDocShow = false
    },
    async loadCSVData() {
      this.$axios.post(this.$api.insOrderPlan.preview, {
        id: this.currentFile.id,
      }).then(res => {
        let arr = res.data
        arr = arr.map(m => {
          let obj = {
            sheetName: m.sheetName,
            tableData: [],
            column: []
          }
          obj.tableData = this.formatCSVToTable(m.content.replaceAll('null', ' '))
          // .replaceAll('MIN','=MIN').replaceAll('MAX','=MAX').replaceAll('AVERAGE','=AVERAGE')
          for (let item in obj.tableData[0]) {
            obj.column.push({
              label: item,
              prop: item,
            })
          }
          return obj
        })
        this.csvList = arr
      }).catch(err => {
        console.log(err)
      })
    },
    formatCSVToTable(str) {
      const result = [];
      const jsonObj = str.split("\n");
      let arrHeader = [];
      for (const i in jsonObj) {
        if (typeof jsonObj[i] === 'string' && jsonObj[i].length > 0) {
          const row = `${jsonObj[i]}`;
          if (row.trim().length > 0) {
            const kv = jsonObj[i].split(',');
            if (i == 0) {
              // èŽ·å–column表头
              arrHeader = kv;
            } else {
              const obj = {};
              for (let index = 0; index < arrHeader.length; index++) {
                // ç»„装表格数据
                const name = String(arrHeader[index]);
                if (!arrHeader[index]) continue
                if (!obj[name]) {
                  try {
                    if (kv[index]) {
                      obj[name] = String(kv[index]);
                    } else {
                      obj[name] = '';
                    }
                  } catch (err) {
                    obj[name] = '';
                  }
                }
              }
              result.push(obj);
            }
          }
        }
      }
      return result
    },
    resetStyle() {
      const elements = document.querySelectorAll('[style*="pt"]');
      for (const element of elements) {
        const style = element.getAttribute('style');
        if (!!style) {
          element.setAttribute('style', style.replace(/pt/g, 'px'));
        }
      }
    },
  }
}
</script>
<style scoped>
img {
  max-width: 100%;
}
.oneLine {
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}
</style>
src/components/Table/lims-table.vue
@@ -1,183 +1,117 @@
<template>
  <div>
    <!-- è¡¨æ ¼ -->
    <el-table
      ref="multipleTable"
      v-loading="tableLoading"
      :border="border"
      :data="tableData"
      :header-cell-style="{ background: '#f8f8f9', color: '#515a6e' }"
      :height="height"
      :highlight-current-row="highlightCurrentRow"
      :row-class-name="rowClassName"
      :row-style="rowStyle"
      :row-key="rowKey"
      stripe
      style="width: 100%"
      tooltip-effect="dark"
      @row-click="rowClick"
      @current-change="currentChange"
      @selection-change="handleSelectionChange"
    >
      <template v-if="isSelection">
        <el-table-column type="selection" width="55" />
      </template>
      <template>
        <el-table-column align="center" label="序号" type="index" width="60" />
      </template>
    <el-table ref="multipleTable" v-loading="tableLoading" :border="border" :data="tableData"
      :header-cell-style="{ background: '#f8f8f9', color: '#515a6e' }" :height="height"
      :highlight-current-row="highlightCurrentRow" :row-class-name="rowClassName" :row-style="rowStyle"
      :row-key="rowKey" :span-method="spanMethod" stripe style="width: 100%" tooltip-effect="dark" @row-click="rowClick"
      @current-change="currentChange" @selection-change="handleSelectionChange" class="lims-table">
      <el-table-column align="center" type="selection" width="55" v-if="isSelection" />
      <el-table-column align="center" label="序号" type="index" width="60" :index="indexMethod" />
      <template v-for="(item, index) in column">
        <el-table-column
          :column-key="item.columnKey"
          :filter-method="item.filterHandler"
          :filter-multiple="item.filterMultiple"
          :filtered-value="item.filteredValue"
          :filters="item.filters"
          :fixed="item.fixed"
          :label="item.label"
          :min-width="item.minWidth"
          :prop="item.prop"
          :show-overflow-tooltip="item.showOverflowTooltip"
          :sortable="item.sortable ? true : false"
          :type="item.type"
          :width="item.width"
          align="center"
        >
          <!-- <div class="123" v-if="item.type == ''"> -->
          <template
            v-if="item.hasOwnProperty('colunmTemplate')"
            :slot="item.colunmTemplate"
            slot-scope="scope"
          >
            <slot
              v-if="item.theadSlot"
              :index="index"
              :name="item.theadSlot"
              :row="scope.row"
            />
          </template>
      <el-table-column v-for="(item, index) in column" :key="index" :column-key="item.columnKey"
        :filter-method="item.filterHandler" :filter-multiple="item.filterMultiple" :filtered-value="item.filteredValue"
        :filters="item.filters" :fixed="item.fixed" :label="item.label" :min-width="item.minWidth" :prop="item.prop"
        :show-overflow-tooltip="item.dataType === 'action' || item.dataType === 'slot' ? false : true"
        :sortable="item.sortable ? true : false" :type="item.type"
        :width="item.dataType === 'action' ? getWidth(item.operation) : item.width" align="center">
        <!-- <div class="123" v-if="item.type == ''"> -->
        <template v-if="item.hasOwnProperty('colunmTemplate')" :slot="item.colunmTemplate" slot-scope="scope">
          <slot v-if="item.theadSlot" :index="index" :name="item.theadSlot" :row="scope.row" />
        </template>
          <template slot-scope="scope">
            <!-- æ’æ§½ -->
            <div v-if="item.dataType == 'slot'">
              <slot
                v-if="item.slot"
                :index="scope.$index"
                :name="item.slot"
                :row="scope.row"
              />
            </div>
            <!-- è¿›åº¦æ¡ -->
            <div v-else-if="item.dataType == 'progress'">
              <el-progress :percentage="Number(scope.row[item.prop])" />
            </div>
        <template slot-scope="scope">
          <!-- æ’æ§½ -->
          <div v-if="item.dataType == 'slot'">
            <slot v-if="item.slot" :index="scope.$index" :name="item.slot" :row="scope.row" />
          </div>
          <!-- è¿›åº¦æ¡ -->
          <div v-else-if="item.dataType == 'progress'">
            <el-progress :percentage="Number(scope.row[item.prop])" />
          </div>
          <!-- å›¾ç‰‡ -->
          <div v-else-if="item.dataType == 'image'">
            <img :src="javaApi + '/img/' + scope.row[item.prop]" alt=""
              style="width: 40px; height: 40px; margin-top: 10px" />
          </div>
            <!-- tag -->
            <div v-else-if="item.dataType == 'tag'">
              <el-tag
                v-if="
                  typeof dataTypeFn(scope.row[item.prop], item.formatData) ==
                  'string'
                "
                :title="scope.row[item.prop] | formatters(item.formatData)"
                :type="formatType(scope.row[item.prop], item.formatType)"
                >{{
                  scope.row[item.prop] | formatters(item.formatData)
                }}</el-tag
              >
              <el-tag
                v-for="(tag, index) in dataTypeFn(
                  scope.row[item.prop],
                  item.formatData
                )"
                v-else-if="
                  typeof dataTypeFn(scope.row[item.prop], item.formatData) ==
                  'object'
                "
                :key="index"
                :title="scope.row[item.prop] | formatters(item.formatData)"
                :type="formatType(tag, item.formatType)"
                >{{
                  item.tagGroup
          <!-- tag -->
          <div v-else-if="item.dataType == 'tag'">
            <el-tag v-if="
              typeof dataTypeFn(scope.row[item.prop], item.formatData) ==
              'string'
            " :title="scope.row[item.prop] | formatters(item.formatData)"
              :type="formatType(scope.row[item.prop], item.formatType)">{{ scope.row[item.prop] |
                formatters(item.formatData) }}</el-tag>
            <el-tag v-for="(tag, index) in dataTypeFn(
              scope.row[item.prop],
              item.formatData
            )" v-else-if="
              typeof dataTypeFn(scope.row[item.prop], item.formatData) ==
              'object'
            " :key="index" :title="scope.row[item.prop] | formatters(item.formatData)"
              :type="formatType(tag, item.formatType)">{{
                item.tagGroup
                  ? tag[item.tagGroup.label]
                    ? tag[item.tagGroup.label]
                      ? tag[item.tagGroup.label]
                      : tag
                    : tag
                }}</el-tag
              >
              <el-tag
                v-else
                :title="scope.row[item.prop] | formatters(item.formatData)"
                :type="formatType(scope.row[item.prop], item.formatType)"
                >{{
                  scope.row[item.prop] | formatters(item.formatData)
                }}</el-tag
              >
            </div>
                  : tag
              }}</el-tag>
            <el-tag v-else :title="scope.row[item.prop] | formatters(item.formatData)"
              :type="formatType(scope.row[item.prop], item.formatType)">{{ scope.row[item.prop] |
                formatters(item.formatData) }}</el-tag>
          </div>
            <!-- æŒ‰é’® -->
            <div v-else-if="item.dataType == 'action'">
              <template v-for="(o, key) in item.operation">
                <el-button
                  v-if="o.type != 'upload'"
                  v-show="o.showHide ? o.showHide(scope.row) : true"
                  :disabled="o.disabled ? o.disabled(scope.row) : false"
                  :icon="o.icon | iconFn(scope.row)"
                  :plain="o.plain"
                  :size="o.size"
                  :style="{ color: o.color }"
                  :type="o.type | typeFn(scope.row)"
                  @click="o.clickFun(scope.row)"
                >
                  {{ o.name }}
                </el-button>
                <el-upload
                  action="#"
                  :on-change="
                    (file, fileList) => o.clickFun(scope.row, file, fileList)
                  "
                  :multiple="o.multiple ? o.multiple : false"
                  :limit="o.limit ? o.limit : 1"
                  :disabled="o.disabled ? o.disabled(scope.row) : false"
                  :accept="
                    o.accept
                      ? o.accept
                      : '.jpg,.jpeg,.png,.gif,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.pdf,.zip,.rar'
                  "
                  v-if="o.type == 'upload'"
                  style="display: inline-block; width: 50px"
                  v-show="o.showHide ? o.showHide(scope.row) : true"
                  :auto-upload="false"
                  :on-exceed="onExceed"
                  :show-file-list="false"
                >
                  <el-button
                    :size="o.size ? o.size : 'small'"
                    type="text"
                    :disabled="o.disabled ? o.disabled(scope.row) : false"
                    >{{ o.name }}</el-button
                  >
                </el-upload>
              </template>
            </div>
            <!-- é»˜è®¤çº¯å±•示数据 -->
            <div v-else>
              <span v-if="!item.formatData">{{ scope.row[item.prop] }}</span>
              <span v-else>{{
                scope.row[item.prop] | formatters(item.formatData)
              }}</span>
            </div>
          </template>
        </el-table-column>
      </template>
          <!-- æŒ‰é’® -->
          <div v-else-if="item.dataType == 'action'">
            <template v-for="(o, key) in item.operation">
              <el-button v-show="o.type != 'upload'" size="mini" v-if="o.showHide ? o.showHide(scope.row) : true"
                :disabled="o.disabled ? o.disabled(scope.row) : false" :icon="iconFn(o)" :plain="o.plain"
                :style="{ color: o.name === '删除' ? '#f56c6c' : o.color }" :type="o.type | typeFn(scope.row)"
                @click="o.clickFun(scope.row)" :key="key">
                {{ o.name }}
              </el-button>
              <el-upload :action="javaApi + o.url + '?id=' + (o.uploadIdFun ? o.uploadIdFun(scope.row) : scope.row.id)"
                size="mini" ref="upload" :multiple="o.multiple ? o.multiple : false" :limit="1"
                :disabled="o.disabled ? o.disabled(scope.row) : false" :accept="o.accept
                  ? o.accept
                  : '.jpg,.jpeg,.png,.gif,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.pdf,.zip,.rar'
                  " v-if="o.type == 'upload' && o.url" style="display: inline-block; width: 50px"
                v-show="o.showHide ? o.showHide(scope.row) : true" :headers="uploadHeader" :on-error="onError"
                :on-exceed="onExceed" :on-success="handleSuccessUp" :show-file-list="false" :key="key">
                <el-button :size="o.size ? o.size : 'small'" type="text"
                  :disabled="o.disabled ? o.disabled(scope.row) : false">{{ o.name }}</el-button>
              </el-upload>
              <el-upload action="#" :on-change="(file, fileList) => o.clickFun(scope.row, file, fileList)
                " :multiple="o.multiple ? o.multiple : false" :limit="o.limit ? o.limit : 1"
                :disabled="o.disabled ? o.disabled(scope.row) : false" :accept="o.accept
                  ? o.accept
                  : '.jpg,.jpeg,.png,.gif,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.pdf,.zip,.rar'
                  " v-if="o.type == 'upload' && !o.url" style="display: inline-block; width: 50px"
                v-show="o.showHide ? o.showHide(scope.row) : true" :auto-upload="false" :on-exceed="onExceed"
                :show-file-list="false" :key="key">
                <el-button :size="o.size ? o.size : 'small'" type="text"
                  :disabled="o.disabled ? o.disabled(scope.row) : false">{{ o.name }}</el-button>
              </el-upload>
            </template>
          </div>
          <!-- å¯ç‚¹å‡»çš„æ–‡å­— -->
          <div v-else-if="item.dataType == 'link'" class="cell link" style="width: 100%"
            @click="goLink(scope.row, item.linkMethod)">
            <span v-if="!item.formatData">{{ scope.row[item.prop] }}</span>
          </div>
          <!-- é»˜è®¤çº¯å±•示数据 -->
          <div v-else class="cell" style="width: 100%">
            <span v-if="!item.formatData">{{ scope.row[item.prop] }}</span>
            <span v-else>{{
              scope.row[item.prop] | formatters(item.formatData)
            }}</span>
          </div>
        </template>
      </el-table-column>
    </el-table>
    <pagination
      v-show="page.total > 0"
      :total="page.total"
      :page.sync="page.current"
      :limit.sync="page.size"
      @pagination="pagination"
    />
    <pagination v-show="page.total > 0" :total="page.total" :layout="page.layout" :page.sync="page.current"
      :limit.sync="page.size" @pagination="pagination" />
  </div>
</template>
@@ -234,11 +168,6 @@
export default {
  name: "ZTTable",
  filters: {
    iconFn(val, row) {
      if (typeof val === "function") {
        return val(row);
      } else return val;
    },
    typeFn(val, row) {
      // console.log(val, row, '11111111');
      if (typeof val === "function") {
@@ -272,24 +201,24 @@
    handleSelectionChange: {
      type: Function,
      default: () => {
        return () => {};
        return () => { };
      },
    },
    rowClick: {
      type: Function,
      default: () => {
        return () => {};
        return () => { };
      },
    },
    currentChange: {
      type: Function,
      default: () => {
        return () => {};
        return () => { };
      },
    },
    border: {
      type: Boolean,
      default: false,
      default: true,
    },
    highlightCurrentRow: {
      type: Boolean,
@@ -309,11 +238,11 @@
    },
    rowClassName: {
      type: Function,
      default: () => {},
      default: () => { },
    },
    rowStyle: {
      type: Object || Function,
      default: () => {},
      default: () => { },
    },
    tableData: {
      type: Array,
@@ -332,12 +261,45 @@
          total: 0,
          current: 0,
          size: 10,
          layout: "total, sizes, prev, pager, next, jumper",
        };
      },
    },
  },
  data() {
    return {
      spanList: [],
    };
  },
  mounted() {
    this.calculateSpanInfo();
  },
  methods: {
    getWidth(row) {
      let count = 0;
      row.forEach((a) => {
        if (a.showHide !== undefined && a.showHide()) {
          count += a.name.length;
        } else if (!a.showHide) {
          count += a.name.length;
        }
      });
      return count * 15 + 70 + "px";
    },
    iconFn(row) {
      if (row.name === "编辑" || row.name === "修改") {
        return "el-icon-edit";
      } else if (row.name === "删除") {
        return "el-icon-delete";
      } else if (row.name === "查看") {
        return "el-icon-view";
      } else {
        return row.icon;
      }
      // if (typeof (val) === 'function') {
      //   return val(row);
      // } else return val;
    },
    formatType(val, format) {
      if (typeof format === "function") {
        return format(val);
@@ -351,18 +313,171 @@
    setCurrent(row) {
      this.$refs.multipleTable.setCurrentRow();
    },
    handleSuccessUp(response, label) {
      if (typeof label === "string") {
        if (response.code == 200) {
          this.upData[label] = response.data.url;
        }
      } else {
        if (response.code == 200) {
          this.$message.success("上传成功");
        }
      }
    },
    onError(err, file, fileList) {
      this.$message.error("上传失败");
      this.$refs.upload.clearFiles();
      this.uploading = false;
    },
    onExceed() {
      this.$message.warning("超出文件个数");
    },
    pagination(page, limit) {
      this.$emit("pagination", { pageNum: page, pageSize: limit });
    pagination({ page, limit }) {
      this.$emit("pagination", { page: page, limit: limit });
    },
    indexMethod(index) {
      // return index * 2;
      return (this.page.current - 1) * this.page.size + index + 1;
    },
    // ç‚¹å‡»å•元格link事件
    goLink(row, linkMethod) {
      if (!linkMethod) {
        return this.$message.warning("请配置lingk事件");
      }
      this.$parent[linkMethod](row);
    },
    // åˆå¹¶å•元格
    calculateSpanInfo() {
      // åˆå§‹åŒ–每列的合并信息
      this.spanList = [];
      this.column.forEach((m, i) => {
        if (m.mergeCol) {
          this.spanList.push({
            arr: [],
            position: 0,
            name: m.prop,
            index: i + 1,
          });
        }
      });
      this.spanList.forEach((item, i) => {
        this.rowspan(
          this.spanList[i].arr,
          this.spanList[i].position,
          item.name
        );
      });
    },
    rowspan(spanArr, position, spanName) {
      this.tableData.forEach((item, index) => {
        if (index === 0) {
          spanArr.push(1);
          position = 0;
        } else {
          if (
            this.tableData[index][spanName] ===
            this.tableData[index - 1][spanName]
          ) {
            spanArr[position] += 1;
            spanArr.push(0);
          } else {
            spanArr.push(1);
            position = index;
          }
        }
      });
    },
    // åˆå¹¶å•元格
    spanMethod({ row, column, rowIndex, columnIndex }) {
      // ä¸€èˆ¬çš„合并行
      if (this.column.find((m) => m.mergeCol)) {
        let i = null;
        let obj = this.spanList.find((item, index) => {
          i = index;
          return item.index == columnIndex;
        });
        if (obj) {
          const _row = this.spanList[i].arr[rowIndex];
          const _col = _row > 0 ? 1 : 0;
          return {
            rowspan: _row,
            colspan: _col,
          };
        }
      }
      // // ç‰¹æ®Šçš„合并行
      // if (
      //   this.data.spanConfig != undefined &&
      //   this.data.spanConfig.special &&
      //   this.data.spanConfig.special.main &&
      //   this.data.spanConfig.special.rows &&
      //   this.data.spanConfig.special.rows.length > 0
      // ) {
      //   let i = null;
      //   let obj = this.data.spanConfig.special.rows.find((item, index) => {
      //     i = index;
      //     return item.index == columnIndex;
      //   });
      //   if (obj) {
      //     const _row = this.specialSpanList[i].arr[rowIndex];
      //     const _col = _row > 0 ? 1 : 0;
      //     return {
      //       rowspan: _row,
      //       colspan: _col,
      //     };
      //   }
      // }
    },
  },
};
</script>
<style scoped>
.el-table >>> .el-table__empty-text {
.el-table>>>.el-table__empty-text {
  text-align: center;
}
>>>.cell {
  padding: 0 !important;
}
.cell {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  padding-right: 4px !important;
  padding-left: 10px !important;
}
.link {
  color: rgb(64, 158, 255);
  cursor: pointer;
}
>>>.el-table__body-wrapper::-webkit-scrollbar {
  height: 14px;
  /* è®¾ç½®æ»šåŠ¨æ¡å®½åº¦ */
}
</style>
<style>
.lims-table .highlight-warning-row-border td:first-child {
  border-left: 4px solid #ffcd29;
}
.lims-table .highlight-warning-row-border td:last-child {
  border-right: 4px solid #ffcd29;
}
/* .lims-table .highlight-danger-row-border td {
        border-top: 2px solid red;
        border-bottom: 2px solid red;
    } */
.lims-table .highlight-danger-row-border td:first-child {
  border-left: 4px solid #f56c6c;
}
.lims-table .highlight-danger-row-border td:last-child {
  border-right: 4px solid #f56c6c;
}
</style>
src/components/UpPdfStamp/index.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,165 @@
<template>
  <div class="up-pdf-stamp">
    <div class="work" style="display: flex;justify-content: space-between;align-items: center;margin-bottom: 10px;"
      v-if="isUpFile">
      <input type="file" @change="handleFileUpload" accept="application/pdf" ref="fileInput" />
    </div>
    <p style="color: red;font-size: 12px;margin: 16px 0;" v-if="canvasNumPages > 0">提示:在文件范围内,单击鼠标盖章,双击鼠标已盖好章处可删除当前章</p>
    <canvas ref="pdfCanvas" @click="e => handleCanvasClick(e, index)" style="border: 1px solid #000;"
      @dblclick="e => removeStamp(e, index)" v-for="(item, index) in canvasNumPages" :key="index"></canvas>
  </div>
</template>
<script>
import jsPDF from "jspdf";
import file from '@/utils/file.js'
export default {
  props: ['isUpFile'],
  data() {
    return {
      pdfDoc: null, // å­˜å‚¨ä¸Šä¼ çš„ PDF æ•°æ®
      stamps: [], // è®°å½•盖章的位置
      contextList: [],//canvas列表
      canvasNumPages: 0,// å­˜å‚¨ PDF æ€»é¡µæ•°
      stampWidth: 120, // ç›–章宽度
      stampHeight: 80, // ç›–章高度
      stampsName: '',
      stampsList: ['主任', '质量负责人', '技术负责人', '综合室', '通信', '电力', '装备', '储能', '射频'],
      fileName: '文件名'
    };
  },
  methods: {
    handleFileUpload(event) {
      const file = event.target.files[0];
      if (file.size > 20 * 1024 * 1024) {
        this.$refs.fileInput.value = ""; // æ¸…空文件输入框内容
        return this.$message.error('文件大小不能超过20M')
      }
      this.lookFile(file)
    },
    lookFile(file, currentStamp) {
      this.fileName = file.name
      if (currentStamp) {
        this.stampsName = currentStamp
      } else {
        const index = this.stampsList.indexOf(m => file.name.includes(m))
        if (index > -1) {
          this.stampsName = this.stampsList[index]
        } else {
          this.stampsName = '综合室'
        }
      }
      if (file && file.type === 'application/pdf') {
        const reader = new FileReader();
        reader.onload = (e) => {
          const typedArray = new Uint8Array(e.target.result);
          this.loadPDF(typedArray);
        };
        reader.readAsArrayBuffer(file);
      } else {
        this.$message.error('请选择 PDF æ–‡ä»¶');
      }
    },
    loadPDF(typedArray) {
      pdfjsLib.getDocument(typedArray).promise.then(pdfDoc_ => {
        this.pdfDoc = pdfDoc_;
        this.canvasNumPages = this.pdfDoc._pdfInfo.numPages
        this.stamps = []
        this.contextList = []
        for (let i = 1; i <= this.canvasNumPages; i++) {
          this.$nextTick(() => {
            this.renderPage(i); // æ¸²æŸ“页面
          });
          this.stamps.push([])
        }
      });
    },
    // æ¸²æŸ“指定页面
    renderPage(pageNum) {
      this.pdfDoc.getPage(pageNum).then(page => {
        const canvas = this.$refs.pdfCanvas[pageNum - 1];
        this.contextList.push(canvas.getContext("2d"))
        const viewport = page.getViewport({ scale: 1.5 });
        canvas.width = viewport.width;
        canvas.height = viewport.height;
        page.render({
          canvasContext: this.contextList[pageNum - 1],
          viewport: viewport
        }).promise.then(() => {
          this.stamps[pageNum - 1].forEach(m => {
            this.drawStamps(m.x, m.y, pageNum - 1)
          })
        });
      });
    },
    // å•击--添加章
    handleCanvasClick(event, i) {
      const x = event.offsetX;
      const y = event.offsetY;
      const index = this.stamps[i].findIndex(stamp => {
        let x0 = x - stamp.x;
        let y0 = y - stamp.y;
        return x0 > 0 && x0 < this.stampWidth && y0 > 0 && y0 < this.stampHeight;
      });
      if (index > -1) return;
      this.drawStamps(x, y, i)
      this.stamps[i].push({ x, y });
    },
    // åŒå‡»--删除盖章
    removeStamp(event, i) {
      const x = event.offsetX;
      const y = event.offsetY;
      // æŸ¥æ‰¾è¢«åŒå‡»çš„ç›–ç« 
      const index = this.stamps[i].findIndex(stamp => {
        let x0 = x - stamp.x;
        let y0 = y - stamp.y;
        return x0 > 0 && x0 < this.stampWidth && y0 > 0 && y0 < this.stampHeight;
      });
      if (index === -1) return;
      this.stamps[i].splice(index, 1); // åˆ é™¤æŒ‡å®šçš„ç›–ç« 
      this.contextList[i].clearRect(0, 0, this.contextList[i].width, this.contextList[i].height);
      this.renderPage(i + 1)
    },
    // æ¸²æŸ“ç« 
    drawStamps(x, y, index) {
      var img = new Image();
      console.log(this.stampsName)
      // è®¾ç½®å›¾ç‰‡æº
      img.src = require("@/assets/stamps/" + this.stampsName + ".png"); // æ›¿æ¢ä¸ºä½ çš„图片链接
      let that = this
      img.onload = function () {
        // å›¾ç‰‡åŠ è½½å®ŒæˆåŽï¼Œå°†å›¾ç‰‡ç»˜åˆ¶åˆ°canvas上
        that.contextList[index].drawImage(img, x, y, that.stampWidth, that.stampHeight);
      };
    },
    // ç”Ÿæˆ PDF çš„函数
    async generatePDF() {
      if (this.contextList.length === 0) {
        this.$message({ message: '请先上传PDF文件', type: 'error' });
        this.$emit('uploadPDFErr')
        return false
      }
      const pdf = new jsPDF("p", "mm", "a4");
      for (let i = 0; i < this.contextList.length; i++) {
        const imgData = this.$refs.pdfCanvas[i].toDataURL('image/jpeg', 0.7);
        const pdfWidth = pdf.internal.pageSize.getWidth();
        const pdfHeight = (this.$refs.pdfCanvas[i].height * pdfWidth) / this.$refs.pdfCanvas[i].width;
        pdf.addImage(imgData, "JPEG", 0, 0, pdfWidth, pdfHeight); // å°†å›¾ç‰‡æ·»åŠ åˆ° PDF
        if (i !== this.contextList.length - 1) {
          pdf.addPage(); // æ·»åŠ æ–°çš„ä¸€é¡µ
        }
      }
      // å°† PDF æ–‡ä»¶ä¿å­˜æˆ–上传
      const pdfOutput = pdf.output('blob'); // èŽ·å– PDF æ–‡ä»¶çš„ Blob å¯¹è±¡
      // ä¸Šä¼ åˆ°åŽç«¯
      return this.$emit('uploadPDF', pdfOutput, this.fileName)
    },
  }
}
</script>
<style scoped></style>
src/main.js
@@ -1,70 +1,101 @@
import Vue from 'vue'
import Vue from "vue";
import Cookies from 'js-cookie'
import Cookies from "js-cookie";
import Element from 'element-ui'
import './assets/styles/element-variables.scss'
import Element from "element-ui";
import "./assets/styles/element-variables.scss";
import '@/assets/styles/index.scss' // global css
import '@/assets/styles/ruoyi.scss' // ruoyi css
import App from './App'
import store from './store'
import router from './router'
import directive from './directive' // directive
import plugins from './plugins' // plugins
import { download } from '@/utils/request'
import "@/assets/styles/index.scss"; // global css
import "@/assets/styles/ruoyi.scss"; // ruoyi css
import App from "./App";
import store from "./store";
import router from "./router";
import directive from "./directive"; // directive
import plugins from "./plugins"; // plugins
import { download } from "@/utils/request";
import './assets/icons' // icon
import './permission' // permission control
import "./assets/icons"; // icon
import "./permission"; // permission control
import { getDicts } from "@/api/system/dict/data";
import { getConfigKey } from "@/api/system/config";
import { parseTime, resetForm, addDateRange, selectDictLabel, selectDictLabels, handleTree } from "@/utils/ruoyi";
import {
  parseTime,
  resetForm,
  addDateRange,
  selectDictLabel,
  selectDictLabels,
  handleTree,
} from "@/utils/ruoyi";
import { dictToValue } from "@/utils/index";
// åˆ†é¡µç»„ä»¶
import Pagination from "@/components/Pagination";
// è‡ªå®šä¹‰è¡¨æ ¼å·¥å…·ç»„ä»¶
import RightToolbar from "@/components/RightToolbar"
import RightToolbar from "@/components/RightToolbar";
// å¯Œæ–‡æœ¬ç»„ä»¶
import Editor from "@/components/Editor"
import Editor from "@/components/Editor";
// æ–‡ä»¶ä¸Šä¼ ç»„ä»¶
import FileUpload from "@/components/FileUpload"
import FileUpload from "@/components/FileUpload";
// å›¾ç‰‡ä¸Šä¼ ç»„ä»¶
import ImageUpload from "@/components/ImageUpload"
import ImageUpload from "@/components/ImageUpload";
// å›¾ç‰‡é¢„览组件
import ImagePreview from "@/components/ImagePreview"
import ImagePreview from "@/components/ImagePreview";
// å­—典标签组件
import DictTag from '@/components/DictTag'
import DictTag from "@/components/DictTag";
// å¤´éƒ¨æ ‡ç­¾ç»„ä»¶
import VueMeta from 'vue-meta'
import VueMeta from "vue-meta";
// å­—典数据组件
import DictData from '@/components/DictData'
import DictData from "@/components/DictData";
import { checkPermi } from "@/utils/permission"; // æƒé™åˆ¤æ–­å‡½æ•°
import { getToken } from "@/utils/auth";
// æ—¶é—´è½¬æ¢
import Moment from "moment";
// å…¨å±€æ–¹æ³•挂载
Vue.prototype.getDicts = getDicts
Vue.prototype.getConfigKey = getConfigKey
Vue.prototype.parseTime = parseTime
Vue.prototype.resetForm = resetForm
Vue.prototype.addDateRange = addDateRange
Vue.prototype.selectDictLabel = selectDictLabel
Vue.prototype.selectDictLabels = selectDictLabels
Vue.prototype.download = download
Vue.prototype.handleTree = handleTree
Vue.prototype.getDicts = getDicts;
Vue.prototype.getConfigKey = getConfigKey;
Vue.prototype.parseTime = parseTime;
Vue.prototype.resetForm = resetForm;
Vue.prototype.addDateRange = addDateRange;
Vue.prototype.selectDictLabel = selectDictLabel;
Vue.prototype.selectDictLabels = selectDictLabels;
Vue.prototype.download = download;
Vue.prototype.handleTree = handleTree;
Vue.prototype.dictToValue = dictToValue;
Vue.prototype.HaveJson = (val) => {
  return JSON.parse(JSON.stringify(val))
}
  return JSON.parse(JSON.stringify(val));
};
Vue.prototype.javaApi = process.env.VUE_APP_BASE_API
  ? process.env.VUE_APP_BASE_API
  : "http://192.168.0.104:8002";
Vue.prototype.checkPermi = checkPermi;
Vue.prototype.uploadHeader = {
  Authorization: "Bearer " + getToken(),
};
// è§£å†³el-radio-group单选框自身的bug
Vue.directive("removeAriaHidden", {
  bind(el, binding) {
    let ariaEls = el.querySelectorAll(".el-radio__original");
    ariaEls.forEach((item) => {
      item.removeAttribute("aria-hidden");
    });
  },
});
Vue.use(Moment);
Vue.prototype.$moment = Moment;
// å…¨å±€ç»„件挂载
Vue.component('DictTag', DictTag)
Vue.component('Pagination', Pagination)
Vue.component('RightToolbar', RightToolbar)
Vue.component('Editor', Editor)
Vue.component('FileUpload', FileUpload)
Vue.component('ImageUpload', ImageUpload)
Vue.component('ImagePreview', ImagePreview)
Vue.component("DictTag", DictTag);
Vue.component("Pagination", Pagination);
Vue.component("RightToolbar", RightToolbar);
Vue.component("Editor", Editor);
Vue.component("FileUpload", FileUpload);
Vue.component("ImageUpload", ImageUpload);
Vue.component("ImagePreview", ImagePreview);
Vue.use(directive)
Vue.use(plugins)
Vue.use(VueMeta)
DictData.install()
Vue.use(directive);
Vue.use(plugins);
Vue.use(VueMeta);
DictData.install();
/**
 * If you don't want to use mock-server
@@ -76,14 +107,14 @@
 */
Vue.use(Element, {
  size: Cookies.get('size') || 'medium' // set element-ui default size
})
  size: Cookies.get("size") || "medium", // set element-ui default size
});
Vue.config.productionTip = false
Vue.config.productionTip = false;
new Vue({
  el: '#app',
  el: "#app",
  router,
  store,
  render: h => h(App)
})
  render: (h) => h(App),
});
src/plugins/download.js
@@ -1,79 +1,126 @@
import axios from 'axios'
import {Loading, Message} from 'element-ui'
import { saveAs } from 'file-saver'
import { getToken } from '@/utils/auth'
import errorCode from '@/utils/errorCode'
import axios from "axios";
import { Loading, Message } from "element-ui";
import { saveAs } from "file-saver";
import { getToken } from "@/utils/auth";
import errorCode from "@/utils/errorCode";
import { blobValidate } from "@/utils/ruoyi";
const baseURL = process.env.VUE_APP_BASE_API
const baseURL = process.env.VUE_APP_BASE_API;
let downloadLoadingInstance;
export default {
  name(name, isDelete = true) {
    var url = baseURL + "/common/download?fileName=" + encodeURIComponent(name) + "&delete=" + isDelete
    var url =
      baseURL +
      "/common/download?fileName=" +
      encodeURIComponent(name) +
      "&delete=" +
      isDelete;
    axios({
      method: 'get',
      method: "get",
      url: url,
      responseType: 'blob',
      headers: { 'Authorization': 'Bearer ' + getToken() }
      responseType: "blob",
      headers: { Authorization: "Bearer " + getToken() },
    }).then((res) => {
      const isBlob = blobValidate(res.data);
      if (isBlob) {
        const blob = new Blob([res.data])
        this.saveAs(blob, decodeURIComponent(res.headers['download-filename']))
        const blob = new Blob([res.data]);
        this.saveAs(blob, decodeURIComponent(res.headers["download-filename"]));
      } else {
        this.printErrMsg(res.data);
      }
    })
    });
  },
  resource(resource) {
    var url = baseURL + "/common/download/resource?resource=" + encodeURIComponent(resource);
    var url =
      baseURL +
      "/common/download/resource?resource=" +
      encodeURIComponent(resource);
    axios({
      method: 'get',
      method: "get",
      url: url,
      responseType: 'blob',
      headers: { 'Authorization': 'Bearer ' + getToken() }
      responseType: "blob",
      headers: { Authorization: "Bearer " + getToken() },
    }).then((res) => {
      const isBlob = blobValidate(res.data);
      if (isBlob) {
        const blob = new Blob([res.data])
        this.saveAs(blob, decodeURIComponent(res.headers['download-filename']))
        const blob = new Blob([res.data]);
        this.saveAs(blob, decodeURIComponent(res.headers["download-filename"]));
      } else {
        this.printErrMsg(res.data);
      }
    })
    });
  },
  zip(url, name) {
    var url = baseURL + url
    downloadLoadingInstance = Loading.service({ text: "正在下载数据,请稍候", spinner: "el-icon-loading", background: "rgba(0, 0, 0, 0.7)", })
    var url = baseURL + url;
    downloadLoadingInstance = Loading.service({
      text: "正在下载数据,请稍候",
      spinner: "el-icon-loading",
      background: "rgba(0, 0, 0, 0.7)",
    });
    axios({
      method: 'get',
      method: "get",
      url: url,
      responseType: 'blob',
      headers: { 'Authorization': 'Bearer ' + getToken() }
    }).then((res) => {
      const isBlob = blobValidate(res.data);
      if (isBlob) {
        const blob = new Blob([res.data], { type: 'application/zip' })
        this.saveAs(blob, name)
      } else {
        this.printErrMsg(res.data);
      }
      downloadLoadingInstance.close();
    }).catch((r) => {
      console.error(r)
      Message.error('下载文件出现错误,请联系管理员!')
      downloadLoadingInstance.close();
      responseType: "blob",
      headers: { Authorization: "Bearer " + getToken() },
    })
      .then((res) => {
        const isBlob = blobValidate(res.data);
        if (isBlob) {
          const blob = new Blob([res.data], { type: "application/zip" });
          this.saveAs(blob, name);
        } else {
          this.printErrMsg(res.data);
        }
        downloadLoadingInstance.close();
      })
      .catch((r) => {
        console.error(r);
        Message.error("下载文件出现错误,请联系管理员!");
        downloadLoadingInstance.close();
      });
  },
  saveAs(text, name, opts) {
    saveAs(text, name, opts);
    if (typeof text === "string") {
      // è·¯å¾„下载
      saveAs(text, name, opts);
      Message.success("数据导出成功");
    } else {
      // æµä¸‹è½½
      blobToText(text)
        .then((result) => {
          Message.error(result.msg);
        })
        .catch(() => {
          saveAs(text, name, opts);
          Message.success("数据导出成功");
        });
    }
  },
  async printErrMsg(data) {
    const resText = await data.text();
    const rspObj = JSON.parse(resText);
    const errMsg = errorCode[rspObj.code] || rspObj.msg || errorCode['default']
    const errMsg = errorCode[rspObj.code] || rspObj.msg || errorCode["default"];
    Message.error(errMsg);
  }
}
  },
};
// å°†blob转成文本
function blobToText(blob) {
  return new Promise((resolve, reject) => {
    const fileReader = new FileReader();
    fileReader.readAsText(blob);
    fileReader.onload = function () {
      try {
        const result = JSON.parse(this.result);
        if (result && result["code"] !== 200) {
          resolve(result);
        } else {
          reject();
        }
      } catch (e) {
        reject();
      }
    };
  });
}
src/store/getters.js
@@ -1,19 +1,21 @@
const getters = {
  sidebar: state => state.app.sidebar,
  size: state => state.app.size,
  device: state => state.app.device,
  dict: state => state.dict.dict,
  visitedViews: state => state.tagsView.visitedViews,
  cachedViews: state => state.tagsView.cachedViews,
  token: state => state.user.token,
  avatar: state => state.user.avatar,
  name: state => state.user.name,
  introduction: state => state.user.introduction,
  roles: state => state.user.roles,
  permissions: state => state.user.permissions,
  permission_routes: state => state.permission.routes,
  topbarRouters:state => state.permission.topbarRouters,
  defaultRoutes:state => state.permission.defaultRoutes,
  sidebarRouters:state => state.permission.sidebarRouters,
}
export default getters
  sidebar: (state) => state.app.sidebar,
  size: (state) => state.app.size,
  device: (state) => state.app.device,
  dict: (state) => state.dict.dict,
  visitedViews: (state) => state.tagsView.visitedViews,
  cachedViews: (state) => state.tagsView.cachedViews,
  token: (state) => state.user.token,
  avatar: (state) => state.user.avatar,
  name: (state) => state.user.name,
  nickName: (state) => state.user.nickName,
  userId: (state) => state.user.id,
  introduction: (state) => state.user.introduction,
  roles: (state) => state.user.roles,
  permissions: (state) => state.user.permissions,
  permission_routes: (state) => state.permission.routes,
  topbarRouters: (state) => state.permission.topbarRouters,
  defaultRoutes: (state) => state.permission.defaultRoutes,
  sidebarRouters: (state) => state.permission.sidebarRouters,
};
export default getters;
src/store/modules/user.js
@@ -1,106 +1,120 @@
import { login, logout, getInfo } from '@/api/login'
import { getToken, setToken, removeToken } from '@/utils/auth'
import { isHttp, isEmpty } from "@/utils/validate"
import defAva from '@/assets/images/profile.jpg'
import { login, logout, getInfo } from "@/api/login";
import { getToken, setToken, removeToken } from "@/utils/auth";
import { isHttp, isEmpty } from "@/utils/validate";
import defAva from "@/assets/images/profile.jpg";
const user = {
  state: {
    token: getToken(),
    id: '',
    name: '',
    avatar: '',
    id: "",
    name: "",
    avatar: "",
    nickName: "",
    roles: [],
    permissions: []
    permissions: [],
  },
  mutations: {
    SET_TOKEN: (state, token) => {
      state.token = token
      state.token = token;
    },
    SET_ID: (state, id) => {
      state.id = id
      state.id = id;
    },
    SET_NAME: (state, name) => {
      state.name = name
      state.name = name;
    },
    SET_AVATAR: (state, avatar) => {
      state.avatar = avatar
      state.avatar = avatar;
    },
    SET_NICKNAME: (state, nickName) => {
      state.nickName = nickName;
    },
    SET_ROLES: (state, roles) => {
      state.roles = roles
      state.roles = roles;
    },
    SET_PERMISSIONS: (state, permissions) => {
      state.permissions = permissions
    }
      state.permissions = permissions;
    },
  },
  actions: {
    // ç™»å½•
    Login({ commit }, userInfo) {
      const username = userInfo.username.trim()
      const password = userInfo.password
      const code = userInfo.code
      const uuid = userInfo.uuid
      const username = userInfo.username.trim();
      const password = userInfo.password;
      const code = userInfo.code;
      const uuid = userInfo.uuid;
      return new Promise((resolve, reject) => {
        login(username, password, code, uuid).then(res => {
          setToken(res.token)
          commit('SET_TOKEN', res.token)
          resolve()
        }).catch(error => {
          reject(error)
        })
      })
        login(username, password, code, uuid)
          .then((res) => {
            setToken(res.token);
            commit("SET_TOKEN", res.token);
            resolve();
          })
          .catch((error) => {
            reject(error);
          });
      });
    },
    // èŽ·å–ç”¨æˆ·ä¿¡æ¯
    GetInfo({ commit, state }) {
      return new Promise((resolve, reject) => {
        getInfo().then(res => {
          const user = res.user
          let avatar = user.avatar || ""
          if (!isHttp(avatar)) {
            avatar = (isEmpty(avatar)) ? defAva : process.env.VUE_APP_BASE_API + avatar
          }
          if (res.roles && res.roles.length > 0) { // éªŒè¯è¿”回的roles是否是一个非空数组
            commit('SET_ROLES', res.roles)
            commit('SET_PERMISSIONS', res.permissions)
          } else {
            commit('SET_ROLES', ['ROLE_DEFAULT'])
          }
          commit('SET_ID', user.userId)
          commit('SET_NAME', user.userName)
          commit('SET_AVATAR', avatar)
          resolve(res)
        }).catch(error => {
          reject(error)
        })
      })
        getInfo()
          .then((res) => {
            const user = res.user;
            let avatar = user.avatar || "";
            if (!isHttp(avatar)) {
              avatar = isEmpty(avatar)
                ? defAva
                : process.env.VUE_APP_BASE_API + avatar;
            }
            if (res.roles && res.roles.length > 0) {
              // éªŒè¯è¿”回的roles是否是一个非空数组
              commit("SET_ROLES", res.roles);
              commit("SET_PERMISSIONS", res.permissions);
            } else {
              commit("SET_ROLES", ["ROLE_DEFAULT"]);
            }
            commit("SET_ID", user.userId);
            commit("SET_NAME", user.userName);
            commit("SET_AVATAR", avatar);
            commit("SET_NICKNAME", user.nickName);
            resolve(res);
          })
          .catch((error) => {
            reject(error);
          });
      });
    },
    // é€€å‡ºç³»ç»Ÿ
    LogOut({ commit, state }) {
      return new Promise((resolve, reject) => {
        logout(state.token).then(() => {
          commit('SET_TOKEN', '')
          commit('SET_ROLES', [])
          commit('SET_PERMISSIONS', [])
          removeToken()
          resolve()
        }).catch(error => {
          reject(error)
        })
      })
        logout(state.token)
          .then(() => {
            commit("SET_TOKEN", "");
            commit("SET_ROLES", []);
            commit("SET_PERMISSIONS", []);
            removeToken();
            resolve();
          })
          .catch((error) => {
            reject(error);
          });
      });
    },
    // å‰ç«¯ ç™»å‡º
    FedLogOut({ commit }) {
      return new Promise(resolve => {
        commit('SET_TOKEN', '')
        removeToken()
        resolve()
      })
    }
  }
}
      return new Promise((resolve) => {
        commit("SET_TOKEN", "");
        removeToken();
        resolve();
      });
    },
  },
};
export default user
export default user;
src/utils/downHtmlToPDF.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,22 @@
import html2canvas from "html2canvas";
import jsPDF from "jspdf";
export async function exportHtmlToPDF(element, name = "exported") {
  try {
    // å°† HTML å…ƒç´ è½¬æ¢ä¸º canvas
    console.log("正在将 HTML è½¬æ¢ä¸º canvas...", element);
    const canvas = await html2canvas(element, { useCORS: true });
    const imgData = canvas.toDataURL("image/png");
    // åˆ›å»º PDF
    const pdf = new jsPDF("p", "mm", "a4");
    const pdfWidth = pdf.internal.pageSize.getWidth();
    const pdfHeight = (canvas.height * pdfWidth) / canvas.width;
    pdf.addImage(imgData, "PNG", 10, 10, pdfWidth - 20, pdfHeight - 20);
    pdf.save(name + ".pdf");
    console.log("PDF å¯¼å‡ºæˆåŠŸï¼");
  } catch (error) {
    console.error("导出 PDF å¤±è´¥ï¼š", error);
  }
}
src/utils/index.js
@@ -1,18 +1,25 @@
import { parseTime } from './ruoyi'
import { parseTime } from "./ruoyi";
/**
 * è¡¨æ ¼æ—¶é—´æ ¼å¼åŒ–
 */
export function formatDate(cellValue) {
  if (cellValue == null || cellValue == "") return "";
  var date = new Date(cellValue)
  var year = date.getFullYear()
  var month = date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1
  var day = date.getDate() < 10 ? '0' + date.getDate() : date.getDate()
  var hours = date.getHours() < 10 ? '0' + date.getHours() : date.getHours()
  var minutes = date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes()
  var seconds = date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds()
  return year + '-' + month + '-' + day + ' ' + hours + ':' + minutes + ':' + seconds
  var date = new Date(cellValue);
  var year = date.getFullYear();
  var month =
    date.getMonth() + 1 < 10
      ? "0" + (date.getMonth() + 1)
      : date.getMonth() + 1;
  var day = date.getDate() < 10 ? "0" + date.getDate() : date.getDate();
  var hours = date.getHours() < 10 ? "0" + date.getHours() : date.getHours();
  var minutes =
    date.getMinutes() < 10 ? "0" + date.getMinutes() : date.getMinutes();
  var seconds =
    date.getSeconds() < 10 ? "0" + date.getSeconds() : date.getSeconds();
  return (
    year + "-" + month + "-" + day + " " + hours + ":" + minutes + ":" + seconds
  );
}
/**
@@ -21,40 +28,40 @@
 * @returns {string}
 */
export function formatTime(time, option) {
  if (('' + time).length === 10) {
    time = parseInt(time) * 1000
  if (("" + time).length === 10) {
    time = parseInt(time) * 1000;
  } else {
    time = +time
    time = +time;
  }
  const d = new Date(time)
  const now = Date.now()
  const d = new Date(time);
  const now = Date.now();
  const diff = (now - d) / 1000
  const diff = (now - d) / 1000;
  if (diff < 30) {
    return '刚刚'
    return "刚刚";
  } else if (diff < 3600) {
    // less 1 hour
    return Math.ceil(diff / 60) + '分钟前'
    return Math.ceil(diff / 60) + "分钟前";
  } else if (diff < 3600 * 24) {
    return Math.ceil(diff / 3600) + '小时前'
    return Math.ceil(diff / 3600) + "小时前";
  } else if (diff < 3600 * 24 * 2) {
    return '1天前'
    return "1天前";
  }
  if (option) {
    return parseTime(time, option)
    return parseTime(time, option);
  } else {
    return (
      d.getMonth() +
      1 +
      '月' +
      "月" +
      d.getDate() +
      '日' +
      "日" +
      d.getHours() +
      '时' +
      "时" +
      d.getMinutes() +
      '分'
    )
      "分"
    );
  }
}
@@ -63,18 +70,18 @@
 * @returns {Object}
 */
export function getQueryObject(url) {
  url = url == null ? window.location.href : url
  const search = url.substring(url.lastIndexOf('?') + 1)
  const obj = {}
  const reg = /([^?&=]+)=([^?&=]*)/g
  url = url == null ? window.location.href : url;
  const search = url.substring(url.lastIndexOf("?") + 1);
  const obj = {};
  const reg = /([^?&=]+)=([^?&=]*)/g;
  search.replace(reg, (rs, $1, $2) => {
    const name = decodeURIComponent($1)
    let val = decodeURIComponent($2)
    val = String(val)
    obj[name] = val
    return rs
  })
  return obj
    const name = decodeURIComponent($1);
    let val = decodeURIComponent($2);
    val = String(val);
    obj[name] = val;
    return rs;
  });
  return obj;
}
/**
@@ -83,14 +90,14 @@
 */
export function byteLength(str) {
  // returns the byte length of an utf8 string
  let s = str.length
  let s = str.length;
  for (var i = str.length - 1; i >= 0; i--) {
    const code = str.charCodeAt(i)
    if (code > 0x7f && code <= 0x7ff) s++
    else if (code > 0x7ff && code <= 0xffff) s += 2
    if (code >= 0xDC00 && code <= 0xDFFF) i--
    const code = str.charCodeAt(i);
    if (code > 0x7f && code <= 0x7ff) s++;
    else if (code > 0x7ff && code <= 0xffff) s += 2;
    if (code >= 0xdc00 && code <= 0xdfff) i--;
  }
  return s
  return s;
}
/**
@@ -98,13 +105,13 @@
 * @returns {Array}
 */
export function cleanArray(actual) {
  const newArray = []
  const newArray = [];
  for (let i = 0; i < actual.length; i++) {
    if (actual[i]) {
      newArray.push(actual[i])
      newArray.push(actual[i]);
    }
  }
  return newArray
  return newArray;
}
/**
@@ -112,13 +119,13 @@
 * @returns {Array}
 */
export function param(json) {
  if (!json) return ''
  if (!json) return "";
  return cleanArray(
    Object.keys(json).map(key => {
      if (json[key] === undefined) return ''
      return encodeURIComponent(key) + '=' + encodeURIComponent(json[key])
    Object.keys(json).map((key) => {
      if (json[key] === undefined) return "";
      return encodeURIComponent(key) + "=" + encodeURIComponent(json[key]);
    })
  ).join('&')
  ).join("&");
}
/**
@@ -126,21 +133,21 @@
 * @returns {Object}
 */
export function param2Obj(url) {
  const search = decodeURIComponent(url.split('?')[1]).replace(/\+/g, ' ')
  const search = decodeURIComponent(url.split("?")[1]).replace(/\+/g, " ");
  if (!search) {
    return {}
    return {};
  }
  const obj = {}
  const searchArr = search.split('&')
  searchArr.forEach(v => {
    const index = v.indexOf('=')
  const obj = {};
  const searchArr = search.split("&");
  searchArr.forEach((v) => {
    const index = v.indexOf("=");
    if (index !== -1) {
      const name = v.substring(0, index)
      const val = v.substring(index + 1, v.length)
      obj[name] = val
      const name = v.substring(0, index);
      const val = v.substring(index + 1, v.length);
      obj[name] = val;
    }
  })
  return obj
  });
  return obj;
}
/**
@@ -148,9 +155,9 @@
 * @returns {string}
 */
export function html2Text(val) {
  const div = document.createElement('div')
  div.innerHTML = val
  return div.textContent || div.innerText
  const div = document.createElement("div");
  div.innerHTML = val;
  return div.textContent || div.innerText;
}
/**
@@ -160,21 +167,21 @@
 * @returns {Object}
 */
export function objectMerge(target, source) {
  if (typeof target !== 'object') {
    target = {}
  if (typeof target !== "object") {
    target = {};
  }
  if (Array.isArray(source)) {
    return source.slice()
    return source.slice();
  }
  Object.keys(source).forEach(property => {
    const sourceProperty = source[property]
    if (typeof sourceProperty === 'object') {
      target[property] = objectMerge(target[property], sourceProperty)
  Object.keys(source).forEach((property) => {
    const sourceProperty = source[property];
    if (typeof sourceProperty === "object") {
      target[property] = objectMerge(target[property], sourceProperty);
    } else {
      target[property] = sourceProperty
      target[property] = sourceProperty;
    }
  })
  return target
  });
  return target;
}
/**
@@ -183,18 +190,18 @@
 */
export function toggleClass(element, className) {
  if (!element || !className) {
    return
    return;
  }
  let classString = element.className
  const nameIndex = classString.indexOf(className)
  let classString = element.className;
  const nameIndex = classString.indexOf(className);
  if (nameIndex === -1) {
    classString += '' + className
    classString += "" + className;
  } else {
    classString =
      classString.substr(0, nameIndex) +
      classString.substr(nameIndex + className.length)
      classString.substr(nameIndex + className.length);
  }
  element.className = classString
  element.className = classString;
}
/**
@@ -202,10 +209,10 @@
 * @returns {Date}
 */
export function getTime(type) {
  if (type === 'start') {
    return new Date().getTime() - 3600 * 1000 * 24 * 90
  if (type === "start") {
    return new Date().getTime() - 3600 * 1000 * 24 * 90;
  } else {
    return new Date(new Date().toDateString())
    return new Date(new Date().toDateString());
  }
}
@@ -216,38 +223,38 @@
 * @return {*}
 */
export function debounce(func, wait, immediate) {
  let timeout, args, context, timestamp, result
  let timeout, args, context, timestamp, result;
  const later = function() {
  const later = function () {
    // æ®ä¸Šä¸€æ¬¡è§¦å‘æ—¶é—´é—´éš”
    const last = +new Date() - timestamp
    const last = +new Date() - timestamp;
    // ä¸Šæ¬¡è¢«åŒ…装函数被调用时间间隔 last å°äºŽè®¾å®šæ—¶é—´é—´éš” wait
    if (last < wait && last > 0) {
      timeout = setTimeout(later, wait - last)
      timeout = setTimeout(later, wait - last);
    } else {
      timeout = null
      timeout = null;
      // å¦‚果设定为immediate===true,因为开始边界已经调用过了此处无需调用
      if (!immediate) {
        result = func.apply(context, args)
        if (!timeout) context = args = null
        result = func.apply(context, args);
        if (!timeout) context = args = null;
      }
    }
  }
  };
  return function(...args) {
    context = this
    timestamp = +new Date()
    const callNow = immediate && !timeout
  return function (...args) {
    context = this;
    timestamp = +new Date();
    const callNow = immediate && !timeout;
    // å¦‚果延时不存在,重新设定延时
    if (!timeout) timeout = setTimeout(later, wait)
    if (!timeout) timeout = setTimeout(later, wait);
    if (callNow) {
      result = func.apply(context, args)
      context = args = null
      result = func.apply(context, args);
      context = args = null;
    }
    return result
  }
    return result;
  };
}
/**
@@ -258,18 +265,18 @@
 * @returns {Object}
 */
export function deepClone(source) {
  if (!source && typeof source !== 'object') {
    throw new Error('error arguments', 'deepClone')
  if (!source && typeof source !== "object") {
    throw new Error("error arguments", "deepClone");
  }
  const targetObj = source.constructor === Array ? [] : {}
  Object.keys(source).forEach(keys => {
    if (source[keys] && typeof source[keys] === 'object') {
      targetObj[keys] = deepClone(source[keys])
  const targetObj = source.constructor === Array ? [] : {};
  Object.keys(source).forEach((keys) => {
    if (source[keys] && typeof source[keys] === "object") {
      targetObj[keys] = deepClone(source[keys]);
    } else {
      targetObj[keys] = source[keys]
      targetObj[keys] = source[keys];
    }
  })
  return targetObj
  });
  return targetObj;
}
/**
@@ -277,16 +284,16 @@
 * @returns {Array}
 */
export function uniqueArr(arr) {
  return Array.from(new Set(arr))
  return Array.from(new Set(arr));
}
/**
 * @returns {string}
 */
export function createUniqueString() {
  const timestamp = +new Date() + ''
  const randomNum = parseInt((1 + Math.random()) * 65536) + ''
  return (+(randomNum + timestamp)).toString(32)
  const timestamp = +new Date() + "";
  const randomNum = parseInt((1 + Math.random()) * 65536) + "";
  return (+(randomNum + timestamp)).toString(32);
}
/**
@@ -296,7 +303,7 @@
 * @returns {boolean}
 */
export function hasClass(ele, cls) {
  return !!ele.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)'))
  return !!ele.className.match(new RegExp("(\\s|^)" + cls + "(\\s|$)"));
}
/**
@@ -305,7 +312,7 @@
 * @param {string} cls
 */
export function addClass(ele, cls) {
  if (!hasClass(ele, cls)) ele.className += ' ' + cls
  if (!hasClass(ele, cls)) ele.className += " " + cls;
}
/**
@@ -315,76 +322,84 @@
 */
export function removeClass(ele, cls) {
  if (hasClass(ele, cls)) {
    const reg = new RegExp('(\\s|^)' + cls + '(\\s|$)')
    ele.className = ele.className.replace(reg, ' ')
    const reg = new RegExp("(\\s|^)" + cls + "(\\s|$)");
    ele.className = ele.className.replace(reg, " ");
  }
}
export function makeMap(str, expectsLowerCase) {
  const map = Object.create(null)
  const list = str.split(',')
  const map = Object.create(null);
  const list = str.split(",");
  for (let i = 0; i < list.length; i++) {
    map[list[i]] = true
    map[list[i]] = true;
  }
  return expectsLowerCase
    ? val => map[val.toLowerCase()]
    : val => map[val]
  return expectsLowerCase ? (val) => map[val.toLowerCase()] : (val) => map[val];
}
export const exportDefault = 'export default '
export const exportDefault = "export default ";
export const beautifierConf = {
  html: {
    indent_size: '2',
    indent_char: ' ',
    max_preserve_newlines: '-1',
    indent_size: "2",
    indent_char: " ",
    max_preserve_newlines: "-1",
    preserve_newlines: false,
    keep_array_indentation: false,
    break_chained_methods: false,
    indent_scripts: 'separate',
    brace_style: 'end-expand',
    indent_scripts: "separate",
    brace_style: "end-expand",
    space_before_conditional: true,
    unescape_strings: false,
    jslint_happy: false,
    end_with_newline: true,
    wrap_line_length: '110',
    wrap_line_length: "110",
    indent_inner_html: true,
    comma_first: false,
    e4x: true,
    indent_empty_lines: true
    indent_empty_lines: true,
  },
  js: {
    indent_size: '2',
    indent_char: ' ',
    max_preserve_newlines: '-1',
    indent_size: "2",
    indent_char: " ",
    max_preserve_newlines: "-1",
    preserve_newlines: false,
    keep_array_indentation: false,
    break_chained_methods: false,
    indent_scripts: 'normal',
    brace_style: 'end-expand',
    indent_scripts: "normal",
    brace_style: "end-expand",
    space_before_conditional: true,
    unescape_strings: false,
    jslint_happy: true,
    end_with_newline: true,
    wrap_line_length: '110',
    wrap_line_length: "110",
    indent_inner_html: true,
    comma_first: false,
    e4x: true,
    indent_empty_lines: true
  }
}
    indent_empty_lines: true,
  },
};
// é¦–字母大小
export function titleCase(str) {
  return str.replace(/( |^)[a-z]/g, L => L.toUpperCase())
  return str.replace(/( |^)[a-z]/g, (L) => L.toUpperCase());
}
// ä¸‹åˆ’转驼峰
export function camelCase(str) {
  return str.replace(/_[a-z]/g, str1 => str1.substr(-1).toUpperCase())
  return str.replace(/_[a-z]/g, (str1) => str1.substr(-1).toUpperCase());
}
export function isNumberStr(str) {
  return /^[+-]?(0|([1-9]\d*))(\.\d+)?$/g.test(str)
  return /^[+-]?(0|([1-9]\d*))(\.\d+)?$/g.test(str);
}
// ä¿®æ­£å­—典结构
export function dictToValue(arr) {
  return arr.map((m) => {
    return {
      value: m.dictValue,
      label: m.dictLabel,
      type: m.listClass,
    };
  });
}
src/utils/request.js
@@ -1,114 +1,148 @@
import axios from 'axios'
import { Notification, MessageBox, Message, Loading } from 'element-ui'
import store from '@/store'
import { getToken } from '@/utils/auth'
import errorCode from '@/utils/errorCode'
import axios from "axios";
import { Notification, MessageBox, Message, Loading } from "element-ui";
import store from "@/store";
import { getToken } from "@/utils/auth";
import errorCode from "@/utils/errorCode";
import { tansParams, blobValidate } from "@/utils/ruoyi";
import cache from '@/plugins/cache'
import { saveAs } from 'file-saver'
import cache from "@/plugins/cache";
import { saveAs } from "file-saver";
let downloadLoadingInstance;
// æ˜¯å¦æ˜¾ç¤ºé‡æ–°ç™»å½•
export let isRelogin = { show: false };
axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8'
axios.defaults.headers["Content-Type"] = "application/json;charset=utf-8";
// åˆ›å»ºaxios实例
const service = axios.create({
  // axios中请求配置有baseURL选项,表示请求URL公共部分
  baseURL: process.env.VUE_APP_BASE_API,
  // è¶…æ—¶
  timeout: 10000
})
  timeout: 10000 * 60,
});
// request拦截器
service.interceptors.request.use(config => {
  // æ˜¯å¦éœ€è¦è®¾ç½® token
  const isToken = (config.headers || {}).isToken === false
  // æ˜¯å¦éœ€è¦é˜²æ­¢æ•°æ®é‡å¤æäº¤
  const isRepeatSubmit = (config.headers || {}).repeatSubmit === false
  if (getToken() && !isToken) {
    config.headers['Authorization'] = 'Bearer ' + getToken() // è®©æ¯ä¸ªè¯·æ±‚携带自定义token è¯·æ ¹æ®å®žé™…情况自行修改
  }
  // get请求映射params参数
  if (config.method === 'get' && config.params) {
    let url = config.url + '?' + tansParams(config.params);
    url = url.slice(0, -1);
    config.params = {};
    config.url = url;
  }
  if (!isRepeatSubmit && (config.method === 'post' || config.method === 'put')) {
    const requestObj = {
      url: config.url,
      data: typeof config.data === 'object' ? JSON.stringify(config.data) : config.data,
      time: new Date().getTime()
service.interceptors.request.use(
  (config) => {
    // æ˜¯å¦éœ€è¦è®¾ç½® token
    const isToken = (config.headers || {}).isToken === false;
    // æ˜¯å¦éœ€è¦é˜²æ­¢æ•°æ®é‡å¤æäº¤
    const isRepeatSubmit = (config.headers || {}).repeatSubmit === false;
    if (getToken() && !isToken) {
      config.headers["Authorization"] = "Bearer " + getToken(); // è®©æ¯ä¸ªè¯·æ±‚携带自定义token è¯·æ ¹æ®å®žé™…情况自行修改
    }
    const requestSize = Object.keys(JSON.stringify(requestObj)).length; // è¯·æ±‚数据大小
    const limitSize = 5 * 1024 * 1024; // é™åˆ¶å­˜æ”¾æ•°æ®5M
    if (requestSize >= limitSize) {
      console.warn(`[${config.url}]: ` + '请求数据大小超出允许的5M限制,无法进行防重复提交验证。')
      return config;
    // get请求映射params参数
    if (config.method === "get" && config.params) {
      let url = config.url + "?" + tansParams(config.params);
      url = url.slice(0, -1);
      config.params = {};
      config.url = url;
    }
    const sessionObj = cache.session.getJSON('sessionObj')
    if (sessionObj === undefined || sessionObj === null || sessionObj === '') {
      cache.session.setJSON('sessionObj', requestObj)
    } else {
      const s_url = sessionObj.url;                  // è¯·æ±‚地址
      const s_data = sessionObj.data;                // è¯·æ±‚数据
      const s_time = sessionObj.time;                // è¯·æ±‚æ—¶é—´
      const interval = 1000;                         // é—´é𔿗¶é—´(ms),小于此时间视为重复提交
      if (s_data === requestObj.data && requestObj.time - s_time < interval && s_url === requestObj.url) {
        const message = '数据正在处理,请勿重复提交';
        console.warn(`[${s_url}]: ` + message)
        return Promise.reject(new Error(message))
    if (
      !isRepeatSubmit &&
      (config.method === "post" || config.method === "put")
    ) {
      const requestObj = {
        url: config.url,
        data:
          typeof config.data === "object"
            ? JSON.stringify(config.data)
            : config.data,
        time: new Date().getTime(),
      };
      const requestSize = Object.keys(JSON.stringify(requestObj)).length; // è¯·æ±‚数据大小
      const limitSize = 5 * 1024 * 1024; // é™åˆ¶å­˜æ”¾æ•°æ®5M
      if (requestSize >= limitSize) {
        console.warn(
          `[${config.url}]: ` +
            "请求数据大小超出允许的5M限制,无法进行防重复提交验证。"
        );
        return config;
      }
      const sessionObj = cache.session.getJSON("sessionObj");
      if (
        sessionObj === undefined ||
        sessionObj === null ||
        sessionObj === ""
      ) {
        cache.session.setJSON("sessionObj", requestObj);
      } else {
        cache.session.setJSON('sessionObj', requestObj)
        const s_url = sessionObj.url; // è¯·æ±‚地址
        const s_data = sessionObj.data; // è¯·æ±‚数据
        const s_time = sessionObj.time; // è¯·æ±‚æ—¶é—´
        const interval = 1000; // é—´é𔿗¶é—´(ms),小于此时间视为重复提交
        if (
          s_data === requestObj.data &&
          requestObj.time - s_time < interval &&
          s_url === requestObj.url
        ) {
          const message = "数据正在处理,请勿重复提交";
          console.warn(`[${s_url}]: ` + message);
          return Promise.reject(new Error(message));
        } else {
          cache.session.setJSON("sessionObj", requestObj);
        }
      }
    }
    return config;
  },
  (error) => {
    console.log(error);
    Promise.reject(error);
  }
  return config
}, error => {
    console.log(error)
    Promise.reject(error)
})
);
// å“åº”拦截器
service.interceptors.response.use(res => {
service.interceptors.response.use(
  (res) => {
    // æœªè®¾ç½®çŠ¶æ€ç åˆ™é»˜è®¤æˆåŠŸçŠ¶æ€
    const code = res.data.code || 200;
    // èŽ·å–é”™è¯¯ä¿¡æ¯
    const msg = errorCode[code] || res.data.msg || errorCode['default']
    const msg = errorCode[code] || res.data.msg || errorCode["default"];
    // äºŒè¿›åˆ¶æ•°æ®åˆ™ç›´æŽ¥è¿”回
    if (res.request.responseType ===  'blob' || res.request.responseType ===  'arraybuffer') {
      return res.data
    if (
      res.request.responseType === "blob" ||
      res.request.responseType === "arraybuffer"
    ) {
      return res.data;
    }
    if (code === 401) {
      if (!isRelogin.show) {
        isRelogin.show = true;
        MessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', { confirmButtonText: '重新登录', cancelButtonText: '取消', type: 'warning' }).then(() => {
          isRelogin.show = false;
          store.dispatch('LogOut').then(() => {
            location.href = '/index';
        MessageBox.confirm(
          "登录状态已过期,您可以继续留在该页面,或者重新登录",
          "系统提示",
          {
            confirmButtonText: "重新登录",
            cancelButtonText: "取消",
            type: "warning",
          }
        )
          .then(() => {
            isRelogin.show = false;
            store.dispatch("LogOut").then(() => {
              location.href = "/index";
            });
          })
      }).catch(() => {
        isRelogin.show = false;
      });
    }
      return Promise.reject('无效的会话,或者会话已过期,请重新登录。')
          .catch(() => {
            isRelogin.show = false;
          });
      }
      return Promise.reject("无效的会话,或者会话已过期,请重新登录。");
    } else if (code === 500) {
      Message({ message: msg, type: 'error' })
      return Promise.reject(new Error(msg))
      Message({ message: msg, type: "error" });
      return Promise.reject(new Error(msg));
    } else if (code === 601) {
      Message({ message: msg, type: 'warning' })
      return Promise.reject('error')
      Message({ message: msg, type: "warning" });
      return Promise.reject("error");
    } else if (code !== 200) {
      Notification.error({ title: msg })
      return Promise.reject('error')
      Notification.error({ title: msg });
      return Promise.reject("error");
    } else {
      return res.data
      return res.data;
    }
  },
  error => {
    console.log('err' + error)
  (error) => {
    console.log("err" + error);
    let { message } = error;
    if (message == "Network Error") {
      message = "后端接口连接异常";
@@ -117,36 +151,48 @@
    } else if (message.includes("Request failed with status code")) {
      message = "系统接口" + message.substr(message.length - 3) + "异常";
    }
    Message({ message: message, type: 'error', duration: 5 * 1000 })
    return Promise.reject(error)
    Message({ message: message, type: "error", duration: 5 * 1000 });
    return Promise.reject(error);
  }
)
);
// é€šç”¨ä¸‹è½½æ–¹æ³•
export function download(url, params, filename, config) {
  downloadLoadingInstance = Loading.service({ text: "正在下载数据,请稍候", spinner: "el-icon-loading", background: "rgba(0, 0, 0, 0.7)", })
  return service.post(url, params, {
    transformRequest: [(params) => { return tansParams(params) }],
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
    responseType: 'blob',
    ...config
  }).then(async (data) => {
    const isBlob = blobValidate(data);
    if (isBlob) {
      const blob = new Blob([data])
      saveAs(blob, filename)
    } else {
      const resText = await data.text();
      const rspObj = JSON.parse(resText);
      const errMsg = errorCode[rspObj.code] || rspObj.msg || errorCode['default']
      Message.error(errMsg);
    }
    downloadLoadingInstance.close();
  }).catch((r) => {
    console.error(r)
    Message.error('下载文件出现错误,请联系管理员!')
    downloadLoadingInstance.close();
  })
  downloadLoadingInstance = Loading.service({
    text: "正在下载数据,请稍候",
    spinner: "el-icon-loading",
    background: "rgba(0, 0, 0, 0.7)",
  });
  return service
    .post(url, params, {
      transformRequest: [
        (params) => {
          return tansParams(params);
        },
      ],
      headers: { "Content-Type": "application/x-www-form-urlencoded" },
      responseType: "blob",
      ...config,
    })
    .then(async (data) => {
      const isBlob = blobValidate(data);
      if (isBlob) {
        const blob = new Blob([data]);
        saveAs(blob, filename);
      } else {
        const resText = await data.text();
        const rspObj = JSON.parse(resText);
        const errMsg =
          errorCode[rspObj.code] || rspObj.msg || errorCode["default"];
        Message.error(errMsg);
      }
      downloadLoadingInstance.close();
    })
    .catch((r) => {
      console.error(r);
      Message.error("下载文件出现错误,请联系管理员!");
      downloadLoadingInstance.close();
    });
}
export default service
export default service;
src/views/CNAS/systemManagement/correctiveAction/components/ViewTestRecord.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,169 @@
<template>
  <div>
    <el-dialog :visible.sync="filesDialogVisible" title="附件" width="80%" @closed="closeFilesLook">
      <div style="display: flex;justify-content: space-between;">
        <el-upload ref='upload' :action="fileAction" :auto-upload="true" :before-upload="fileBeforeUpload"
          :data="{ superviseDetailsCorrectId: info.superviseDetailsCorrectId }" :headers="uploadHeader"
          :on-error="onError" :on-success="handleSuccessUp" :show-file-list="false"
          accept='.jpg,.jpeg,.png,.gif,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.pdf,.zip,.rar' style="width: 80px !important;">
          <el-button size="small" style="height: 38px" type="primary">附件上传</el-button>
        </el-upload>
      </div>
      <div>
        <limsTable ref="yearTable" :column="columnData" :height="'calc(100vh - 30em)'" :highlightCurrentRow="true"
          :table-data="tableData" :table-loading="tableLoading" style="margin-top: 0.5em;">
        </limsTable>
      </div>
    </el-dialog>
    <el-dialog :visible.sync="lookDialogVisible" fullscreen title="查看附件" top="5vh" width="800px">
      <filePreview v-if="lookDialogVisible" :currentFile="{}" :fileUrl="javaApi + '/word/' + currentInfo.fileUrl"
        style="height: 90vh;overflow-y: auto;" />
    </el-dialog>
  </div>
</template>
<script>
import limsTable from "@/components/Table/lims-table.vue";
import filePreview from '@/components/Preview/filePreview.vue'
import {
  getSuperviseDetailCorrectFileList,
  delSuperviseDetailCorrectFile,
} from '@/api/cnas/systemManagement/correctiveAction.js'
export default {
  name: 'ViewTestRecord',
  // import å¼•入的组件需要注入到对象中才能使用
  components: { filePreview, limsTable },
  data() {
    // è¿™é‡Œå­˜æ”¾æ•°æ®
    return {
      filesDialogVisible: false,
      tableLoading: false,
      filesLookInfo: {},
      columnData: [
        {
          label: '文件名称',
          prop: 'fileName',
          minWidth: '150px'
        },
        {
          dataType: 'action',
          minWidth: '100',
          label: '操作',
          fixed: 'right',
          operation: [
            {
              name: '预览',
              type: 'text',
              clickFun: (row) => {
                this.handleLook(row)
              }
            },
            {
              name: '下载',
              type: 'text',
              clickFun: (row) => {
                this.upload(row)
              }
            },
            {
              name: '删除',
              type: 'text',
              color: '#f56c6c',
              clickFun: (row) => {
                this.delete(row)
              }
            }
          ]
        }
      ],
      tableData: [],
      info: {},
      currentInfo: {},
      lookDialogVisible: false,
    };
  },
  // æ–¹æ³•集合
  methods: {
    openDia(row) {
      this.filesDialogVisible = true
      this.info = row
      this.searchTableList()
    },
    // æŸ¥è¯¢é™„件列表
    searchTableList() {
      this.tableLoading = true
      getSuperviseDetailCorrectFileList({ superviseDetailsCorrectId: this.info.superviseDetailsCorrectId }).then(res => {
        this.tableLoading = false
        if (res.code === 201) return
        this.tableData = res.data
      }).catch(err => {
        this.tableLoading = false
        console.log('err---', err);
      })
    },
    closeFilesLook() {
      this.filesDialogVisible = false
    },
    // æŸ¥çœ‹æ–‡ä»¶
    handleLook(row) {
      this.currentInfo = row
      this.lookDialogVisible = true
    },
    // ä¸‹è½½
    upload(row) {
      let url = '';
      if (row.type == 1) {
        url = this.javaApi + '/img/' + row.fileUrl
        this.$download.saveAs(url, row.fileName);
      } else {
        url = this.javaApi + '/word/' + row.fileUrl
        this.$download.saveAs(url, row.fileName);
      }
    },
    // åˆ é™¤
    delete(row) {
      this.tableLoading = true
      delSuperviseDetailCorrectFile({ superviseDetailsCorrectFileId: row.superviseDetailsCorrectFileId }).then(res => {
        this.tableLoading = false
        if (res.code === 201) return
        this.$message.success('删除成功')
        this.searchTableList()
      }).catch(err => {
        this.tableLoading = false
        console.log('err---', err);
      })
    },
    // ä¸Šä¼ éªŒè¯
    fileBeforeUpload(file) {
      let flag = true
      if (file.size > 1024 * 1024 * 10) {
        this.$message.error('上传文件不超过10M');
        this.$refs.upload.clearFiles()
        flag = false
      }
      if (!flag) {
        return Promise.reject(flag); //正确的终止
      }
    },
    onError(err, file, fileList, type) {
      this.$message.error('上传失败')
      this.$refs.upload.clearFiles()
    },
    handleSuccessUp(response,) {
      this.upLoading = false;
      if (response.code == 200) {
        this.$message.success('上传成功');
        this.searchTableList()
      }
    },
  },
  computed: {
    fileAction() {
      return this.javaApi + '/qualitySupervise/uploadSuperviseDetailCorrectFile'
    }
  },
};
</script>
<style scoped></style>
src/views/CNAS/systemManagement/correctiveAction/components/correctiveInfo.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,258 @@
<template>
  <div>
    <el-dialog :close-on-click-modal="false" :close-on-press-escape="false" :visible.sync="formDia" title="纠正措施处理单"
      width="60%" @close="closeProcessingDia">
      <div style="height: 660px; overflow-y: auto">
        <table border="1" cellspacing="10" class="tables">
          <tr>
            <td class="td-title">
              <p>培训计划:</p>
            </td>
            <td class="td-info" colspan="3">
              <el-select v-model="form.personTrainingDetailedId" clearable filterable style="width: 100%" disabled
                placeholder="请选择" size="small">
                <el-option v-for="item in yearTrainingDetailed" :key="item.id" :label="item.trainingObjectives"
                  :value="item.id">
                </el-option>
              </el-select>
            </td>
          </tr>
          <tr>
            <td class="td-title">
              <p>不合格或偏离事实的描述:</p>
            </td>
            <td class="td-info" colspan="3">
              <span class="td-info1"> {{ form.raiseResult }}</span>
            </td>
          </tr>
          <tr>
            <td class="td-title">
              <p>提出人:</p>
            </td>
            <td class="td-info">
              {{ form.raiseUserName }}
            </td>
            <td class="td-title">
              <p>提出部门:</p>
            </td>
            <td class="td-info">
              {{ form.raiseDepartment }}
            </td>
          </tr>
          <tr>
            <td class="td-title">
              <p>日期:</p>
            </td>
            <td class="td-info" colspan="3">
              {{ form.raiseTime }}
            </td>
          </tr>
          <tr>
            <td class="td-title">
              <p>原因分析:</p>
            </td>
            <td class="td-info" colspan="3">
              <span class="td-info1"> {{ form.causeResult }}</span>
            </td>
          </tr>
          <tr>
            <td class="td-title">
              <p>原因分析人:</p>
            </td>
            <td class="td-info">
              {{ form.causeUserName }}
            </td>
            <td class="td-title">
              <p>责任部门:</p>
            </td>
            <td class="td-info">
              {{ form.causeDepartment }}
            </td>
          </tr>
          <tr>
            <td class="td-title">
              <p>原因分析日期:</p>
            </td>
            <td class="td-info" colspan="3">
              {{ form.causeTime }}
            </td>
          </tr>
          <tr>
            <td class="td-title">
              <p>纠正措施:</p>
            </td>
            <td class="td-info" colspan="3">
              <span class="td-info1"> {{ form.correctResult }}</span>
            </td>
          </tr>
          <tr>
            <td class="td-title">
              <p>提出要求部门确认:</p>
            </td>
            <td class="td-info" colspan="3">
              <span class="td-info1"> {{ form.raiseDepartmentAffirm }}</span>
            </td>
          </tr>
          <tr>
            <td class="td-title">
              <p>纠正人:</p>
            </td>
            <td class="td-info">
              {{ form.correctUserName }}
            </td>
            <td class="td-title">
              <p>责任部门:</p>
            </td>
            <td class="td-info">
              {{ form.correctDepartment }}
            </td>
          </tr>
          <tr>
            <td class="td-title">
              <p>纠正日期:</p>
            </td>
            <td class="td-info" colspan="3">
              {{ form.correctTime }}
            </td>
          </tr>
          <tr>
            <td class="td-title">
              <p>实施验证结果:</p>
            </td>
            <td class="td-info" colspan="3">
              <span class="td-info1"> {{ form.validationResult }}</span>
            </td>
          </tr>
          <tr>
            <td class="td-title">
              <p>验证人:</p>
            </td>
            <td class="td-info">
              {{ form.validationUserName }}
            </td>
            <td class="td-title">
              <p>责任部门:</p>
            </td>
            <td class="td-info">
              {{ form.validationDepartment }}
            </td>
          </tr>
          <tr>
            <td class="td-title">
              <p>验证日期:</p>
            </td>
            <td class="td-info" colspan="3">
              {{ form.validationTime }}
            </td>
          </tr>
        </table>
      </div>
    </el-dialog>
  </div>
</template>
<script>
import {
  getSuperviseDetailCorrect,
  getThisYearTrainingDetailed,
} from '@/api/cnas/systemManagement/correctiveAction.js'
export default {
  name: 'correctiveInfo',
  // import å¼•入的组件需要注入到对象中才能使用
  components: {},
  data() {
    // è¿™é‡Œå­˜æ”¾æ•°æ®
    return {
      formDia: false,
      yearTrainingDetailed: [],
      form: {
        superviseDetailsId: '',
        raiseResult: '',
        vdeRaiseResult: '',
        causeUserId: '',
        raiseUserName: '',
        raiseDepartment: '',
        raiseTime: '',
        causeResult: '',
        causeUserName: '',
        causeDepartment: '',
        causeTime: '',
        correctUserId: '',
        correctResult: '',
        raiseDepartmentAffirm: '',
        correctUserName: '',
        correctDepartment: '',
        correctTime: '',
        validationUserId: '',
        validationResult: '',
        validationUserName: '',
        validationDepartment: '',
        validationTime: '',
      },
    };
  },
  // æ–¹æ³•集合
  methods: {
    openDia(row) {
      this.formDia = true
      this.searchInfo(row)
      this.form.superviseDetailsId = row.superviseDetailsId
      this.getYearTrainingDetailed() // èŽ·å–åŸ¹è®­è®¡åˆ’
    },
    // æŸ¥è¯¢ç›‘控计划详情实施信息
    searchInfo(row) {
      this.form.qualityMonitorDetailsId = row.qualityMonitorDetailsId
      getSuperviseDetailCorrect({ superviseDetailsId: row.superviseDetailsId }).then(res => {
        if (res.code === 201) return
        this.form = res.data
      }).catch(err => {
        console.log('err---', err);
      })
    },
    getYearTrainingDetailed() {
      getThisYearTrainingDetailed().then(res => {
        this.yearTrainingDetailed = res.data
      })
    },
    // å…³é—­å¼¹æ¡†
    closeProcessingDia() {
      this.formDia = false
    },
  }
};
</script>
<style scoped>
>>>.el-dialog {
  margin: 5vh auto 50px !important;
}
.tables {
  table-layout: fixed;
  width: 100%;
  margin-top: 10px;
}
.td-title {
  height: 40px;
  width: 170px;
  text-align: center;
  font-size: 14px;
  word-wrap: break-word;
  white-space: normal;
  padding: 6px;
}
.td-info {
  padding: 6px;
}
.td-info1 {
  display: inline-block;
  width: 100%;
  text-align: left;
  font-size: 14px;
  word-wrap: break-word;
  white-space: normal;
}
</style>
src/views/CNAS/systemManagement/correctiveAction/index.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,202 @@
<template>
  <div>
    <div class="search-background">
      <span class="search-group">
        <span style="width: 150px">不合格描述:</span>
        <el-input v-model="searchForm.raiseResult" clearable size="small"></el-input>
      </span>
      <span class="search-group">
        <el-button size="small" @click="resetSearchForm">重 ç½®</el-button>
        <el-button size="small" type="primary" @click="searchList">查 è¯¢</el-button>
      </span>
    </div>
    <div class="table">
      <div>
        <TableCard :showForm="false" :showTitle="false">
          <template v-slot:table>
            <limsTable :column="tableColumn" :height="'calc(100vh - 17em)'" :table-data="tableData"
              :table-loading="tableLoading" style="padding: 0 15px;margin-bottom: 16px" @pagination="pagination"
              :page="page">
            </limsTable>
          </template>
        </TableCard>
      </div>
    </div>
    <corrective-info v-if="correctiveInfo" ref="correctiveInfo"></corrective-info>
    <ViewTestRecord v-if="viewTestRecordDialog" ref="viewTestRecordDialog"></ViewTestRecord>
  </div>
</template>
<script>
import TableCard from '@/components/TableCard/index.vue';
import limsTable from "@/components/Table/lims-table.vue";
import CorrectiveInfo from './components/correctiveInfo.vue';
// import QualityInfo from '../do/a7-nonconforming-item/qualityInfo.vue';
import ViewTestRecord from './components/ViewTestRecord.vue';
import {
  pageSuperviseDetailCorrect,
  exportSuperviseDetaillCorrect,
} from '@/api/cnas/systemManagement/correctiveAction.js'
export default {
  name: 'a8-corrective-action',
  // import å¼•入的组件需要注入到对象中才能使用
  components: {
    // QualityInfo,
    CorrectiveInfo,
    limsTable,
    TableCard,
    ViewTestRecord
  },
  data() {
    // è¿™é‡Œå­˜æ”¾æ•°æ®
    return {
      searchForm: {
        raiseResult: '',
      },
      tableColumn: [
        {
          label: '不合格或偏离事实的描述',
          prop: 'raiseResult',
          minWidth: '100'
        },
        {
          label: '原因分析',
          prop: 'causeResult',
          minWidth: '100'
        },
        {
          label: '纠正措施',
          prop: 'correctResult',
          minWidth: '100'
        },
        {
          label: '实施验证结果',
          prop: 'validationResult',
          minWidth: '100'
        },
        {
          dataType: 'action',
          minWidth: '60',
          label: '操作',
          operation: [
            {
              name: '查看',
              type: 'text',
              clickFun: (row) => {
                this.viewInfo(row);
              },
            },
            {
              name: '导出',
              type: 'text',
              clickFun: (row) => {
                this.handleDown(row)
              }
            },
            {
              name: '查看附件',
              type: 'text',
              clickFun: (row) => {
                this.viewFiles(row);
              },
            },
          ]
        }
      ],
      tableData: [],
      tableLoading: false,
      page: {
        size: 20,
        current: 1,
        total: 0,
      },
      correctiveInfo: false,
      viewTestRecordDialog: false,
    };
  },
  mounted() {
    this.searchList()
  },
  // æ–¹æ³•集合
  methods: {
    // æŸ¥è¯¢åˆ—表
    searchList() {
      const entity = {
        raiseResult: this.searchForm.raiseResult,
      }
      const page = this.page
      this.tableLoading = true
      pageSuperviseDetailCorrect({ ...entity, ...page }).then(res => {
        this.tableLoading = false
        if (res.code === 201) return
        this.tableData = res.data.records
        this.page.total = res.data.total
      }).catch(err => {
        console.log('err---', err);
        this.tableLoading = false
      })
    },
    // å¯¼å‡º
    handleDown(row) {
      exportSuperviseDetaillCorrect({ superviseDetailsCorrectId: row.superviseDetailsCorrectId }).then(res => {
        this.outLoading = false
        const blob = new Blob([res], { type: 'application/msword' });
        this.$download.saveAs(blob, '监督纠正措施' + '.docx');
      })
    },
    // é‡ç½®æŸ¥è¯¢æ¡ä»¶
    resetSearchForm() {
      this.searchForm.raiseResult = '';
      this.searchList()
    },
    // æŸ¥çœ‹è¯¦æƒ…
    viewInfo(row) {
      this.correctiveInfo = true
      this.$nextTick(() => {
        this.$refs.correctiveInfo.openDia(row)
      })
    },
    // æŸ¥çœ‹é™„ä»¶
    viewFiles(row) {
      this.viewTestRecordDialog = true
      this.$nextTick(() => {
        this.$refs.viewTestRecordDialog.openDia(row)
      })
    },
    pagination({ page, limit }) {
      this.page.current = page;
      this.page.size = limit;
      this.searchList();
    },
  }
};
</script>
<style scoped>
.view-title {
  display: flex;
  justify-content: space-between;
  align-items: center;
  height: 60px;
  padding-left: 20px;
}
.search-background {
  width: 100%;
  height: 80px;
  line-height: 80px;
  background-color: #ffffff;
  display: flex;
}
.search-group {
  display: flex;
  align-items: center;
  margin: 0 20px;
}
.table {
  background-color: #ffffff;
}
</style>
src/views/CNAS/systemManagement/customerManagement/base.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,11 @@
<template>
  <div>客户基本信息管理</div>
</template>
<script>
export default {
}
</script>
<style></style>
src/views/CNAS/systemManagement/customerManagement/components/formDialog.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,256 @@
<template>
  <div>
    <el-dialog :close-on-click-modal="false" :close-on-press-escape="false" :visible.sync="formDia" title="客户满意度调查表"
      width="70%" @close="closeFormDia">
      <table border="1" cellspacing="10" class="tables">
        <tr>
          <td class="td-title">
            <p>单位名称:</p>
          </td>
          <td class="td-info" colspan="2">
            <el-input v-model="form.unitName" placeholder="请输入内容" size="small">
            </el-input>
          </td>
          <td class="td-title">
            <p>日期:</p>
          </td>
          <td class="td-info" colspan="2">
            <el-date-picker v-model="form.fillDate" format="yyyy-MM-dd" placeholder="选择日期" size="small" type="date"
              value-format="yyyy-MM-dd">
            </el-date-picker>
          </td>
        </tr>
        <tr>
          <td class="td-title">
            <p>姓名:</p>
          </td>
          <td class="td-info">
            <el-input v-model="form.userName" placeholder="请输入内容" size="small">
            </el-input>
          </td>
          <td class="td-title">
            <p>部门:</p>
          </td>
          <td class="td-info">
            <el-input v-model="form.department" placeholder="请输入内容" size="small">
            </el-input>
          </td>
          <td class="td-title">
            <p>联系电话:</p>
          </td>
          <td class="td-info">
            <el-input v-model="form.contactNumber" placeholder="请输入内容" size="small">
            </el-input>
          </td>
        </tr>
        <tr>
          <td class="td-title">
            <p>服务态度:</p>
          </td>
          <td class="td-info" colspan="2">
            <el-radio-group v-model="form.serviceAttitude" v-removeAriaHidden>
              <el-radio :label="0">满意</el-radio>
              <el-radio :label="1">一般</el-radio>
              <el-radio :label="2">不满意</el-radio>
            </el-radio-group>
          </td>
          <td class="td-title">
            <p>建议:</p>
          </td>
          <td class="td-info" colspan="2">
            <el-input v-model="form.serviceAttitudeSuggestion" placeholder="请输入内容" size="small">
            </el-input>
          </td>
        </tr>
        <tr>
          <td class="td-title">
            <p>技术能力:</p>
          </td>
          <td class="td-info" colspan="2">
            <el-radio-group v-model="form.technicalCompetence" v-removeAriaHidden>
              <el-radio :label="0">满意</el-radio>
              <el-radio :label="1">一般</el-radio>
              <el-radio :label="2">不满意</el-radio>
            </el-radio-group>
          </td>
          <td class="td-title">
            <p>建议:</p>
          </td>
          <td class="td-info" colspan="2">
            <el-input v-model="form.technicalCompetenceSuggestion" placeholder="请输入内容" size="small">
            </el-input>
          </td>
        </tr>
        <tr>
          <td class="td-title">
            <p>检测工作:</p>
          </td>
          <td class="td-info" colspan="2">
            <el-radio-group v-model="form.inspectionWork" v-removeAriaHidden>
              <el-radio :label="0">满意</el-radio>
              <el-radio :label="1">一般</el-radio>
              <el-radio :label="2">不满意</el-radio>
            </el-radio-group>
          </td>
          <td class="td-title">
            <p>建议:</p>
          </td>
          <td class="td-info" colspan="2">
            <el-input v-model="form.inspectionWorkSuggestion" placeholder="请输入内容" size="small">
            </el-input>
          </td>
        </tr>
        <tr>
          <td class="td-title">
            <p>收费合理性:</p>
          </td>
          <td class="td-info" colspan="2">
            <el-radio-group v-model="form.reasonableFees" v-removeAriaHidden>
              <el-radio :label="0">满意</el-radio>
              <el-radio :label="1">一般</el-radio>
              <el-radio :label="2">不满意</el-radio>
            </el-radio-group>
          </td>
          <td class="td-title">
            <p>建议:</p>
          </td>
          <td class="td-info" colspan="2">
            <el-input v-model="form.reasonableFeesSuggestion" placeholder="请输入内容" size="small">
            </el-input>
          </td>
        </tr>
        <tr>
          <td class="td-title">
            <p>您对我们的希望:</p>
          </td>
          <td class="td-info" colspan="5">
            <el-input v-model="form.remark" :rows="4" placeholder="请输入内容" size="small" type="textarea">
            </el-input>
          </td>
        </tr>
      </table>
      <span slot="footer" class="dialog-footer">
        <el-button @click="closeFormDia">取 æ¶ˆ</el-button>
        <el-button :loading="editLoad" type="primary" @click="handleEdit">提 äº¤</el-button>
      </span>
    </el-dialog>
  </div>
</template>
<script>
import {
  addClientSatisfaction,
  updateClientSatisfaction
} from '@/api/cnas/systemManagement/customerSatisfaction.js'
export default {
  name: 'formDialog',
  // import å¼•入的组件需要注入到对象中才能使用
  components: {},
  data() {
    // è¿™é‡Œå­˜æ”¾æ•°æ®
    return {
      formDia: false,
      form: {
        unitName: '',
        fillDate: '',
        userName: '',
        department: '',
        contactNumber: '',
        serviceAttitude: '',
        technicalCompetence: '',
        technicalCompetenceSuggestion: '',
        inspectionWork: '',
        inspectionWorkSuggestion: '',
        reasonableFees: '',
        reasonableFeesSuggestion: '',
        remark: '',
        clientSatisfactionId: '',
      },
      operationType: '',
      editLoad: false,
    };
  },
  // æ–¹æ³•集合
  methods: {
    openDia(type, row) {
      this.formDia = true;
      this.operationType = type
      if (this.operationType === 'edit') {
        this.form = { ...row }
      }
    },
    handleEdit() {
      if (!this.form.unitName) {
        this.$message.warning('请填写单位名称')
        return
      }
      if (!this.form.department) {
        this.$message.warning('请填写部门')
        return
      }
      this.editLoad = true
      if (this.operationType === 'add') {
        addClientSatisfaction(this.form).then(res => {
          this.editLoad = false
          if (res.code === 201) return
          this.$message.success('提交成功')
          this.closeFormDia()
        }).catch(err => {
          console.log('err---', err);
          this.editLoad = false
        })
      } else {
        updateClientSatisfaction(this.form).then(res => {
          this.editLoad = false
          if (res.code === 201) return
          this.$message.success('提交成功')
          this.closeFormDia()
        }).catch(err => {
          console.log('err---', err);
          this.editLoad = false
        })
      }
    },
    closeFormDia() {
      this.formDia = false;
      this.$emit('closeFormDia')
    },
  }
};
</script>
<style scoped>
>>>.el-dialog {
  margin: 10vh auto 50px !important;
}
.tables {
  table-layout: fixed;
  width: 100%;
  margin-top: 10px;
}
.td-title {
  height: 40px;
  width: 170px;
  text-align: center;
  font-size: 14px;
  word-wrap: break-word;
  white-space: normal;
  padding: 6px;
}
.td-info {
  padding: 6px;
}
.td-info1 {
  display: inline-block;
  width: 100%;
  text-align: left;
  font-size: 14px;
  word-wrap: break-word;
  white-space: normal;
}
</style>
src/views/CNAS/systemManagement/customerManagement/customerSatisfaction.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,402 @@
<template>
  <div>
    <div>
      <div class="search-background">
        <span v-if="tabIndex === '0'" class="search-group">
          <span style="width: 150px">单位名称:</span>
          <el-input v-model="searchForm.unitName" clearable size="small"></el-input>
        </span>
        <span v-if="tabIndex === '1'" class="search-group">
          <span style="width: 150px">文件名称:</span>
          <el-input v-model="searchForm1.fileName" clearable size="small"></el-input>
        </span>
        <span class="search-group">
          <el-button size="small" @click="resetSearchForm">重 ç½®</el-button>
          <el-button size="small" type="primary" @click="searchList">查 è¯¢</el-button>
        </span>
        <div class="btn">
          <el-button v-if="tabIndex === '0'" size="small" type="primary" @click="openFormDia('add')">新 å¢ž</el-button>
          <el-upload v-if="tabIndex === '1'" ref='upload' :action="action" :before-upload="beforeUpload"
            :headers="uploadHeader" :on-error="onError" :on-success="handleSuccessUp" :show-file-list="false"
            accept='.jpg,.jpeg,.png,.gif,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.pdf,.zip,.rar'>
            <el-button :loading="upLoading" size="small" type="primary">导入</el-button>
          </el-upload>
        </div>
      </div>
      <div class="table">
        <div class="table-tab">
          <el-radio-group v-model="tabIndex" @change="searchList" size="small">
            <el-radio-button label="0">客户满意度</el-radio-button>
            <el-radio-button label="1">综合分析</el-radio-button>
          </el-radio-group>
        </div>
        <div v-if="tabIndex === '0'">
          <TableCard :showForm="false" :showTitle="false">
            <template v-slot:table>
              <limsTable :column="tableColumn" :height="'calc(100vh - 22em)'" :table-data="tableData"
                :table-loading="tableLoading" style="padding: 0 15px;margin-bottom: 16px" @pagination="pagination"
                :page="page">
              </limsTable>
            </template>
          </TableCard>
        </div>
        <div v-if="tabIndex === '1'">
          <TableCard :showForm="false" :showTitle="false">
            <template v-slot:table>
              <limsTable :column="tableColumn1" :height="'calc(100vh - 22em)'" :table-data="tableData1"
                :table-loading="tableLoading1" style="padding: 0 15px;margin-bottom: 16px" @pagination="pagination0">
              </limsTable>
            </template>
          </TableCard>
        </div>
      </div>
    </div>
    <el-dialog :visible.sync="lookDialogVisible" fullscreen title="查看附件" top="5vh" width="800px">
      <filePreview v-if="lookDialogVisible" :currentFile="{}" :fileUrl="javaApi + '/word/' + currentInfo.fileUrl"
        style="height: 90vh;overflow-y: auto;" />
    </el-dialog>
    <FormDialog v-if="formDialog" ref="formDialog" @closeFormDia="closeFormDia"></FormDialog>
  </div>
</template>
<script>
import TableCard from '@/components/TableCard/index.vue';
import limsTable from "@/components/Table/lims-table.vue";
import FormDialog from './components/formDialog.vue';
import filePreview from '@/components/Preview/filePreview.vue'
import {
  pageClientSatisfaction,
  pageAnalyseFile,
  delClientSatisfaction,
  delAnalyseFile,
} from '@/api/cnas/systemManagement/customerSatisfaction.js'
export default {
  name: 'a8-customer-satisfaction',
  // import å¼•入的组件需要注入到对象中才能使用
  components: { filePreview, FormDialog, limsTable, TableCard },
  data() {
    // è¿™é‡Œå­˜æ”¾æ•°æ®
    return {
      searchForm: {
        unitName: '',
      },
      searchForm1: {
        fileName: '',
      },
      tabIndex: '0',
      tableColumn: [
        {
          label: '单位名称',
          prop: 'unitName',
          minWidth: '100'
        },
        {
          label: '日期',
          prop: 'fillDate',
          minWidth: '100'
        },
        {
          label: '姓名',
          prop: 'userName',
          minWidth: '100'
        },
        {
          label: '部门',
          prop: 'department',
          minWidth: '100'
        },
        {
          label: '联系电话',
          prop: 'contactNumber',
          minWidth: '100'
        },
        {
          label: '创建日期',
          prop: 'createTime',
          minWidth: '100',
        },
        {
          dataType: 'action',
          minWidth: '80',
          label: '操作',
          operation: [
            {
              name: '编辑',
              type: 'text',
              clickFun: (row) => {
                this.openFormDia('edit', row);
              },
            },
            {
              name: '删除',
              type: 'text',
              color: '#f56c6c',
              clickFun: (row) => {
                this.delPlan(row)
              }
            }
          ]
        }
      ],
      tableData: [],
      tableLoading: false,
      page: {
        size: 20,
        current: 1,
        total: 0,
      },
      tableColumn1: [
        {
          label: '附件名称',
          prop: 'fileName',
          minWidth: '100'
        },
        {
          label: '创建人',
          prop: 'userName',
          minWidth: '100'
        },
        {
          label: '创建时间',
          prop: 'createTime',
          minWidth: '100'
        },
        {
          dataType: 'action',
          minWidth: '50',
          label: '操作',
          operation: [
            {
              name: '预览',
              type: 'text',
              clickFun: (row) => {
                this.handleLook(row)
              }
            },
            {
              name: '下载',
              type: 'text',
              clickFun: (row) => {
                this.upload(row);
              },
            },
            {
              name: '删除',
              type: 'text',
              color: '#f56c6c',
              clickFun: (row) => {
                this.delFile(row)
              }
            }
          ]
        }
      ],
      tableData1: [],
      tableLoading1: false,
      page1: {
        size: 20,
        current: 1,
        total: 0,
      },
      formDialog: false,
      upLoading: false,
      currentInfo: {},
      lookDialogVisible: false,
    };
  },
  mounted() {
    this.searchList()
  },
  // æ–¹æ³•集合
  methods: {
    // æŸ¥è¯¢åˆ—表
    searchList() {
      const entity = this.tabIndex === '0' ? this.searchForm : this.searchForm1
      const page = this.tabIndex === '0' ? this.page : this.page1
      if (this.tabIndex === '0') {
        this.tableLoading = true
        pageClientSatisfaction({ ...entity, ...page }).then(res => {
          this.tableLoading = false
          if (res.code === 201) return
          this.tableData = res.data.records
          this.page.total = res.data.total
        }).catch(err => {
          console.log('err---', err);
          this.tableLoading = false
        })
      } else {
        this.tableLoading1 = true
        pageAnalyseFile({ ...entity, ...page }).then(res => {
          this.tableLoading1 = false
          if (res.code === 201) return
          this.tableData1 = res.data.records
          this.page1.total = res.data.total
        }).catch(err => {
          console.log('err---', err);
          this.tableLoading1 = false
        })
      }
    },
    openFormDia(type, row) {
      this.formDialog = true
      this.$nextTick(() => {
        this.$refs.formDialog.openDia(type, row);
      })
    },
    closeFormDia() {
      this.formDialog = false
      this.searchList()
    },
    // é‡ç½®æŸ¥è¯¢æ¡ä»¶
    resetSearchForm() {
      this.searchForm.unitName = '';
      this.searchForm1.fileName = '';
      this.searchList()
    },
    // å¯¼å…¥æµç¨‹
    beforeUpload(file) {
      if (file.size > 1024 * 1024 * 10) {
        this.$message.error('上传文件不超过10M');
        this.$refs.upload.clearFiles()
        return false;
      } else {
        this.upLoading = true;
        return true;
      }
    },
    onError(err, file, fileList) {
      this.$message.error('上传失败')
      this.$refs.upload.clearFiles()
    },
    handleSuccessUp(response) {
      this.upLoading = false;
      if (response.code == 200) {
        this.$message.success('上传成功');
        this.searchList()
      }
    },
    // åˆ é™¤å®¢æˆ·æ»¡æ„åº¦
    delPlan(row) {
      this.$confirm('此操作将永久删除该数据, æ˜¯å¦ç»§ç»­?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        this.tableLoading = true
        delClientSatisfaction({ clientSatisfactionId: row.clientSatisfactionId }).then(res => {
          this.tableLoading = false
          if (res.code === 201) return
          this.$message.success('删除成功')
          this.searchList()
        }).catch(err => {
          this.tableLoading = false
          console.log('err---', err);
        })
      }).catch(() => {
        this.$message({
          type: 'info',
          message: '已取消删除'
        });
      });
    },
    // æŸ¥çœ‹æ–‡ä»¶
    handleLook(row) {
      this.currentInfo = row
      this.lookDialogVisible = true
    },
    // ä¸‹è½½å®¢æˆ·ç¦å»º
    upload(row) {
      let url = '';
      if (row.type == 1) {
        url = this.javaApi + '/img/' + row.fileUrl
        this.$download.saveAs(url, row.fileName);
      } else {
        url = this.javaApi + '/word/' + row.fileUrl
        this.$download.saveAs(url, row.fileName);
      }
    },
    // åˆ é™¤å®¢æˆ·åˆ†æžé™„ä»¶
    delFile(row) {
      this.$confirm('此操作将永久删除该数据, æ˜¯å¦ç»§ç»­?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        this.tableLoading = true
        delAnalyseFile({ analyseFileId: row.analyseFileId }).then(res => {
          this.tableLoading = false
          if (res.code === 201) return
          this.$message.success('删除成功')
          this.searchList()
        }).catch(err => {
          this.tableLoading = false
          console.log('err---', err);
        })
      }).catch(() => {
        this.$message({
          type: 'info',
          message: '已取消删除'
        });
      });
    },
    // åˆ†é¡µ
    pagination({ page, limit }) {
      this.page.current = page;
      this.page.size = limit;
      this.searchList();
    },
    // åˆ†é¡µ
    pagination0({ page, limit }) {
      this.page.current = page;
      this.page.size = limit;
      this.searchList();
    },
  },
  // ç”¨äºŽä¸Šä¼ æ–‡ä»¶çš„信息
  computed: {
    action() {
      return this.javaApi + '/clientSatisfaction/uploadAnalyseFile'
    }
  },
};
</script>
<style scoped>
.view-title {
  display: flex;
  justify-content: space-between;
  align-items: center;
  height: 60px;
  padding-left: 20px;
}
.search-background {
  width: 100%;
  height: 80px;
  line-height: 80px;
  background-color: #ffffff;
  display: flex;
  position: relative;
}
.search-group {
  display: flex;
  align-items: center;
  margin: 0 20px;
}
.table {
  background-color: #ffffff;
}
.table-tab {
  margin: 0 20px 20px 20px;
}
.btn {
  position: absolute;
  top: 16px;
  right: 20px;
}
</style>
src/views/CNAS/systemManagement/documentControl/components/ControlledFileApplication.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,578 @@
<template>
  <!-- æ–‡ä»¶å—控申请 -->
  <div class="controlled-file-application" style="height: 100%;">
    <div class="search">
      <div class="search_thing">
        <div class="search_label">申请文件编号:</div>
        <div class="search_input"><el-input size="small" placeholder="请输入" clearable v-model="queryParams.documentCode"
            @keyup.enter.native="refreshTable()"></el-input></div>
      </div>
      <!-- <div class="search_thing">
        <div class="search_label">申请人:</div>
        <div class="search_input"><el-input size="small" placeholder="请输入" clearable
            v-model="queryParams.createUserName" @keyup.enter.native="refreshTable()"></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="refreshTable()">查 è¯¢</el-button>
      </div>
      <div class="btns" style="padding-left: 30px;">
        <el-button size="small" type="primary"
          @click="addDialogVisible = true, addInfo = {}, file = null">文件受控申请</el-button>
      </div>
    </div>
    <div class="table">
      <lims-table :tableData="tableData" :column="column" :page="page" :tableLoading="tableLoading"
        :height="'calc(100vh - 290px)'" @pagination="pagination"></lims-table>
    </div>
    <el-dialog title="文件受控申请" :visible.sync="addDialogVisible" width="800px" top="10vh">
      <el-row>
        <el-col :span="12" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label"><span style="color:red;margin-right: 4px;">*</span>申请编号:</div>
            <div class="search_input"><el-input size="small" placeholder="请输入" clearable
                v-model="addInfo.documentCode"></el-input></div>
          </div>
        </el-col>
        <el-col :span="12" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">责任人:</div>
            <div class="search_input">
              <el-select v-model="addInfo.dutyUser" size="small" style="width: 100%;" filterable>
                <el-option v-for="item in personList" :key="item.value" :label="item.label" :value="item.value">
                </el-option>
              </el-select>
            </div>
          </div>
        </el-col>
        <el-col :span="12" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">文件类别:</div>
            <div class="search_input">
              <el-select v-model="addInfo.type" size="small" style="width: 100%;">
                <el-option v-for="item in fileType" :key="item.value" :label="item.label" :value="item.value">
                </el-option>
              </el-select>
            </div>
          </div>
        </el-col>
        <el-col :span="12" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">文件名称:</div>
            <div class="search_input"><el-input size="small" placeholder="请输入" clearable
                v-model="addInfo.name"></el-input></div>
          </div>
        </el-col>
        <el-col :span="12" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">文件版本:</div>
            <div class="search_input"><el-input size="small" placeholder="请输入" clearable
                v-model="addInfo.version"></el-input></div>
          </div>
        </el-col>
        <el-col :span="12" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">上传附件:</div>
            <div class="search_input"><el-upload style="margin: 8px 0 0px 50px;" action="#" :auto-upload="false"
                :multiple="false" accept='.pdf' :on-change="handleChangeUpload" v-if="addDialogVisible">
                <el-button size="small" type="primary">上传附件</el-button>
              </el-upload></div>
          </div>
        </el-col>
        <el-col :span="12" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">作者:</div>
            <div class="search_input">
              <!-- <el-input size="small" placeholder="请输入" clearable v-model="addInfo.writer"></el-input> -->
              <el-select v-model="addInfo.writer" size="small" style="width: 100%;" filterable>
                <el-option v-for="item in personList" :key="item.value" :label="item.label" :value="item.label">
                </el-option>
              </el-select>
            </div>
          </div>
        </el-col>
        <el-col :span="12" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">提交日期:</div>
            <div class="search_input">
              <el-date-picker v-model="addInfo.submitDate" type="date" size="small" placeholder="选择日期"
                format="yyyy-MM-dd" value-format="yyyy-MM-dd" style="width: 100%;">
              </el-date-picker>
            </div>
          </div>
        </el-col>
        <el-col :span="12" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">说明:</div>
            <div class="search_input"><el-input size="small" placeholder="请输入" clearable v-model="addInfo.instructions"
                type="textarea" :rows="2"></el-input></div>
          </div>
        </el-col>
      </el-row>
      <span slot="footer" class="dialog-footer">
        <el-button @click="addDialogVisible = false">取 æ¶ˆ</el-button>
        <el-button type="primary" @click="handleAdd" :loading="addLoading">ç¡® å®š</el-button>
      </span>
    </el-dialog>
    <el-dialog title="查看附件" :visible.sync="lookDialogVisible" width="800px" top="5vh" fullscreen>
      <filePreview v-if="lookDialogVisible" :fileUrl="javaApi + '/word/' + currentInfo.url" :currentFile="{}"
        style="height: 90vh;overflow-y: auto;" />
    </el-dialog>
    <el-dialog title="审核" :visible.sync="checkDialogVisible" width="1000px" top="5vh">
      <UpPdfStamp ref="UpPdfStamp" v-if="checkDialogVisible" @uploadPDF="uploadPDF" :isUpFile="false"></UpPdfStamp>
      <span slot="footer" class="dialog-footer">
        <el-button @click="handleCheckSub('不通过')" :loading="noCheckLoading">不通过</el-button>
        <el-button type="primary" @click="handleCheckSub('通过')" :loading="checkLoading">通 è¿‡</el-button>
      </span>
    </el-dialog>
    <el-dialog title="选择受控章" :visible.sync="checkStampDialogVisible" width="600px" top="5vh">
      <div class="stamp-list">
        <img :src="require('@/assets/stamps/' + item + '.png')" alt="" v-for="(item, index) in stampsList" :key="index"
          style="width: 120px;height: 80px;margin: 6px;" class="stamp" :class="{ active: currentStamp == item }"
          @click="currentStamp = item">
      </div>
      <span slot="footer" class="dialog-footer">
        <el-button @click="checkStampDialogVisible = false">取 æ¶ˆ</el-button>
        <el-button type="primary" @click="handleCheck0(currentInfo)">ç¡® å®š</el-button>
      </span>
    </el-dialog>
  </div>
</template>
<script>
import UpPdfStamp from '@/components/UpPdfStamp/index.vue'
import filePreview from '@/components/Preview/filePreview.vue'
import limsTable from "@/components/Table/lims-table.vue";
import {
  selectUserCondition,
} from "@/api/system/user.js";
import {
  addManageDocumentControlled,
  doManageDocumentControlled,
  checkManageDocumentControlledPdf,
  delManageDocumentControlled,
  pageManageDocumentControlled,
  checkManageDocumentControlled,
} from '@/api/cnas/systemManagement/documentControl.js'
import { mapGetters } from "vuex";
export default {
  components: {
    filePreview,
    UpPdfStamp,
    limsTable
  },
  computed: {
    ...mapGetters(["nickName"]),
  },
  data() {
    return {
      upLoading: false,
      addPower: false,
      addDialogVisible: false,
      addLoading: false,
      lookDialogVisible: false,
      checkDialogVisible: false,
      checkStampDialogVisible: false,
      addInfo: {},
      personList: [],
      fileType: [],
      file: null,
      currentInfo: {},
      checkLoading: false,
      noCheckLoading: false,
      type: '',
      stampsList: ['主任', '质量负责人', '技术负责人', '综合室', '通信', '电力', '装备', '储能', '射频'],
      currentStamp: '主任',
      queryParams: {},
      tableData: [],
      column: [
        { label: "申请文件编号", prop: "documentCode" },
        {
          label: "文件类别", prop: "type", width: "120px", dataType: "tag",
          formatData: (params) => {
            return this.fileType.find((m) => m.value == params).label;
          },
          formatType: (params) => {
            return this.fileType.find((m) => m.value == params).type;
          },
        },
        {
          label: "申请人",
          prop: "createUserName",
        },
        { label: "申请时间", prop: "createTime" },
        { label: "说明", prop: "instructions" },
        { label: "提交日期", prop: "submitDate" },
        { label: "责任人", prop: "dutyUserName" },
        {
          label: "申请状态", prop: "state", dataType: "tag",
          formatData: (params) => {
            return params;
          },
          formatType: (params) => {
            if (params == '通过') {
              return 'success'
            } else {
              return 'danger'
            }
          },
        },
        {
          dataType: "action",
          fixed: "right",
          label: "操作",
          operation: [
            {
              name: "编辑",
              type: "text",
              clickFun: (row) => {
                this.handleUpdate(row);
              },
              disabled: (row) => {
                return row.state == '通过'
              }
            },
            {
              name: "审核",
              type: "text",
              clickFun: (row) => {
                this.handleCheck(row);
              },
              disabled: (row) => {
                return !row.dutyUserName.includes(this.nickName) || row.state == '通过'
              }
            },
            {
              name: "查看附件",
              type: "text",
              clickFun: (row) => {
                this.handleLook(row);
              },
            },
            {
              name: "下载",
              type: "text",
              clickFun: (row) => {
                this.handleDown(row);
              },
            },
            {
              name: "删除",
              type: "text",
              clickFun: (row) => {
                this.handleDelete(row);
              },
              disabled: (row, index) => {
                return row.state == '通过'
              }
            },
          ],
        },
      ],
      page: {
        total: 0,
        size: 10,
        current: 0,
      },
      tableLoading: false,
    }
  },
  mounted() {
    this.getList()
    this.getAuthorizedPerson()
    this.selectEnumByCategory()
  },
  methods: {
    getList() {
      this.tableLoading = true;
      let param = { ...this.queryParams, ...this.page };
      delete param.total;
      pageManageDocumentControlled({ ...param })
        .then((res) => {
          this.tableLoading = false;
          if (res.code === 200) {
            this.tableData = res.data.records;
            this.page.total = res.data.total;
          }
        })
        .catch((err) => {
          this.tableLoading = false;
        });
    },
    pagination({ page, limit }) {
      this.page.current = page;
      this.page.size = limit;
      this.getList();
    },
    refreshTable() {
      this.page.current = 1;
      this.getList();
    },
    refresh() {
      this.queryParams = {};
      this.page.current = 1;
      this.getList();
    },
    getPower() {
      let power = JSON.parse(sessionStorage.getItem('power'))
      let up = false
      let del = false
      let add = false
      // let check = false
      for (var i = 0; i < power.length; i++) {
        if (power[i].menuMethod == 'addManageDocumentControlled') {
          up = true
        }
        if (power[i].menuMethod == 'addManageDocumentControlled') {
          add = true
        }
        if (power[i].menuMethod == 'delManageDocumentControlled') {
          del = true
        }
        // if (power[i].menuMethod == 'checkManageDocumentControlled') {
        //   check = true
        // }
      }
      // if (!check) {
      //   this.componentData.do.splice(2, 1)
      // }
      if (!del) {
        this.componentData.do.splice(1, 1)
      }
      if (!up) {
        this.componentData.do.splice(0, 1)
      }
      this.addPower = add
    },
    getAuthorizedPerson() {
      selectUserCondition().then(res => {
        let data = []
        res.data.forEach(a => {
          data.push({
            label: a.name,
            value: a.id
          })
        })
        this.personList = data
      })
    },
    selectEnumByCategory() {
      // æ–‡ä»¶ç±»åˆ«
      this.getDicts("document_type").then((response) => {
        this.fileType = this.dictToValue(response.data);
      });
    },
    // æäº¤
    handleAdd() {
      if (!this.addInfo.documentCode) return this.$message({ type: 'error', message: "请输入编号" })
      if (!this.addInfo.id) {
        // æ–°å¢ž
        let fd = new FormData();
        //文件信息中raw才是真的文件
        if (this.file) {
          fd.append("file", this.file.raw);
        }
        for (let m in this.addInfo) {
          fd.append(m, this.addInfo[m])
        }
        this.addLoading = true
        addManageDocumentControlled(fd).then(res => {
          this.addLoading = false
          if (res.code == 200) {
            this.$message({
              type: 'success',
              message: '添加成功'
            })
            this.refreshTable()
            this.addDialogVisible = false
          } else {
            this.$message({
              type: 'error',
              message: '添加失败'
            })
          }
        })
      } else {
        // ä¿®æ”¹
        let { id, documentCode, dutyUser, type, name, version, writer, submitDate, instructions } = this.addInfo
        let fd = new FormData();
        //文件信息中raw才是真的文件
        if (this.file) {
          fd.append("file", this.file.raw);
        }
        fd.append("id", id);
        fd.append("documentCode", documentCode);
        fd.append("dutyUser", dutyUser);
        fd.append("type", type);
        fd.append("name", name);
        fd.append("version", version);
        fd.append("writer", writer);
        fd.append("submitDate", submitDate);
        fd.append("instructions", instructions);
        this.addLoading = true
        doManageDocumentControlled(fd).then(res => {
          this.addLoading = false
          if (res.code == 200) {
            this.refreshTable()
            this.addDialogVisible = false
          } else {
            this.$message({
              type: 'error',
              message: '添加失败'
            })
          }
        })
      }
    },
    handleChangeUpload(file, fileLists) {
      this.file = file
      this.$set(this.addInfo, 'name', file.name)
    },
    // ç¼–辑
    handleUpdate(row) {
      this.title = '文件变更申请'
      this.addInfo = this.HaveJson(row)
      this.addDialogVisible = true
    },
    // æŸ¥çœ‹é™„ä»¶
    handleLook(row) {
      this.currentInfo = row
      this.lookDialogVisible = true
    },
    // å®¡æ ¸
    handleCheck(row) {
      this.title = '审核'
      this.currentInfo = row
      if (!row.url) return this.$message.warning('文件未上传')
      this.checkStampDialogVisible = true
    },
    handleCheck0(row) {
      this.checkStampDialogVisible = false
      this.checkDialogVisible = true
      checkManageDocumentControlledPdf({ id: row.id }).then(res => {
        const blob = new Blob([res]);
        const file = new File([blob], row.name, { type: 'application/pdf' })
        this.$refs.UpPdfStamp.lookFile(file, this.currentStamp)
      }).catch(err => {
        console.log(err)
      })
    },
    handleDown(row) {
      if (!row.url) return this.$message.warning('文件未上传')
      let url = this.javaApi + '/word/' + row.url
      this.$download.saveAs(url, row.url);
    },
    async uploadPDF(pdfBlob) {
      const formData = new FormData();
      formData.append('file', pdfBlob, this.fileName + '.pdf'); // æ–‡ä»¶å­—段
      formData.append('id', this.currentInfo.id); // æ–‡ä»¶åå­—段
      formData.append('state', this.type); // æ–‡ä»¶åå­—段
      formData.append('writer', this.currentInfo.writer); // æ–‡ä»¶åå­—段
      try {
        let res = await checkManageDocumentControlled(formData)
        this.checkLoading = false
        this.noCheckLoading = false
        if (res.code == 200) {
          this.$message({ message: '操作成功', type: 'success' });
          this.checkDialogVisible = false;
          this.refreshTable()
          return true
        } else {
          this.$message({ message: '操作失败', type: 'error' });
          return false
        }
      } catch (e) {
        this.checkLoading = false
        this.noCheckLoading = false
      }
    },
    handleCheckSub(type) {
      this.type = type
      if (type == '通过') {
        this.checkLoading = true
      } else {
        this.noCheckLoading = true
      }
      this.addLoading = true
      this.$refs['UpPdfStamp'].generatePDF()
    },
    handleDelete(row) {
      this.$confirm("是否删除该条数据?", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      })
        .then(() => {
          delManageDocumentControlled({ id: row.id }).then((res) => {
            if (res.code == 201) return;
            this.$message.success("删除成功");
            this.refresh();
          });
        })
        .catch(() => { });
    },
  }
}
</script>
<style scoped>
.title {
  height: 60px;
  line-height: 60px;
}
.search {
  background-color: #fff;
  height: 40px;
  display: flex;
  align-items: center;
  position: relative;
}
.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 {
  background-color: #fff;
  height: calc(100% - 60px - 80px);
  padding: 20px;
}
.btns {
  position: absolute;
  right: 20px;
  top: 5px;
}
.stamp {
  cursor: pointer;
  border: #fff 1px solid;
}
.stamp:hover {
  border: #3A7BFA 1px solid;
  box-shadow: inset 0px 0px 15px #3A7BFA;
}
.stamp.active {
  border: #3A7BFA 1px solid;
  box-shadow: inset 0px 0px 15px #3A7BFA;
}
</style>
src/views/CNAS/systemManagement/documentControl/components/DistributionCollectionRecord.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,596 @@
<template>
  <!-- å‘放回收记录 -->
  <div class="distribution-collection-record" style="height: 100%;">
    <div class="search">
      <div class="search_thing">
        <div class="search_label">文件编号:</div>
        <div class="search_input"><el-input v-model="queryParams.documentCode" clearable placeholder="请输入" size="small"
            @keyup.enter.native="refreshTable()"></el-input></div>
      </div>
      <div class="search_thing">
        <div class="search_label">文件名称:</div>
        <div class="search_input"><el-input v-model="queryParams.name" clearable placeholder="请输入" size="small"
            @keyup.enter.native="refreshTable()"></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="refreshTable()">查 è¯¢</el-button>
      </div>
      <div class="btns" style="padding-left: 30px;">
        <el-button v-if="addPower" size="small" type="primary"
          @click="addDialogVisible = true, addInfo = {}, radio = '发放'">添加发放记录</el-button>
        <el-button v-if="outPower" :loading="outLoading" size="small" type="primary" @click="handleOut">导出</el-button>
      </div>
    </div>
    <div class="table">
      <lims-table :tableData="tableData" :column="column" :page="page" :tableLoading="tableLoading"
        :height="'calc(100vh - 290px)'" @pagination="pagination"></lims-table>
    </div>
    <el-dialog :title="'添加' + radio + '记录'" :visible.sync="addDialogVisible" top="10vh" width="800px">
      <el-row v-if="addDialogVisible">
        <el-col :span="12" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label"><span style="color:red;margin-right: 4px;">*</span>申请编号:</div>
            <div class="search_input">
              <el-select v-model="addInfo.documentCode" :disabled="radio == '回收'" allow-create clearable filterable
                size="small" style="width: 100%;" @change="changeFileList">
                <el-option v-for="item in fileList" :key="item.documentCode" :label="item.documentCode"
                  :value="item.documentCode">
                </el-option>
              </el-select>
            </div>
          </div>
        </el-col>
        <el-col v-if="radio == '发放'" :span="12" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label"><span style="color:red;margin-right: 4px;">*</span>发放人:</div>
            <div class="search_input">
              <el-select v-model="addInfo.issueUser" filterable size="small" style="width: 100%;">
                <el-option v-for="item in personList" :key="item.value" :label="item.label" :value="item.value">
                </el-option>
              </el-select>
            </div>
          </div>
        </el-col>
        <el-col v-else :span="12" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label"><span style="color:red;margin-right: 4px;">*</span>回收人:</div>
            <div class="search_input">
              <el-select v-model="addInfo.recycleUser" filterable size="small" style="width: 100%;">
                <el-option v-for="item in personList" :key="item.value" :label="item.label" :value="item.value">
                </el-option>
              </el-select>
            </div>
          </div>
        </el-col>
        <el-col :span="12" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label"><span style="color:red;margin-right: 4px;">*</span>审批人:</div>
            <div class="search_input">
              <el-select v-model="addInfo.receiveUser" :disabled="radio != '发放'" filterable size="small"
                style="width: 100%;">
                <el-option v-for="item in personList" :key="item.value" :label="item.label" :value="item.value">
                </el-option>
              </el-select>
            </div>
          </div>
        </el-col>
        <el-col :span="12" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">文件名称:</div>
            <div class="search_input"><el-input v-model="addInfo.name" :disabled="radio == '回收'" clearable
                placeholder="请输入" size="small"></el-input></div>
          </div>
        </el-col>
        <el-col :span="12" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">文件版本:</div>
            <div class="search_input"><el-input v-model="addInfo.version" :disabled="radio == '回收'" clearable
                placeholder="请输入" size="small"></el-input></div>
          </div>
        </el-col>
        <el-col :span="12" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">文件状态:</div>
            <div class="search_input">
              <el-select v-model="addInfo.state" :disabled="radio == '回收'" size="small" style="width: 100%;">
                <el-option v-for="(item, index) in fileState" :key="index" :label="item.label"
                  :value="item.value"></el-option>
              </el-select>
            </div>
          </div>
        </el-col>
        <el-col v-if="radio == '发放'" :span="12" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">发放编号:</div>
            <div class="search_input"><el-input v-model="addInfo.issueCode" clearable placeholder="请输入"
                size="small"></el-input></div>
          </div>
        </el-col>
        <el-col v-else :span="12" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">回收编号:</div>
            <div class="search_input"><el-input v-model="addInfo.recycleCode" clearable placeholder="请输入"
                size="small"></el-input></div>
          </div>
        </el-col>
        <el-col v-if="radio == '发放'" :span="12" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">发放时间:</div>
            <div class="search_input">
              <el-date-picker v-model="addInfo.issueDate" format="yyyy-MM-dd" placeholder="选择日期" size="small"
                style="width: 100%;" type="date" value-format="yyyy-MM-dd">
              </el-date-picker>
            </div>
          </div>
        </el-col>
        <el-col v-else :span="12" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">回收时间:</div>
            <div class="search_input">
              <el-date-picker v-model="addInfo.recycleDate" format="yyyy-MM-dd" placeholder="选择日期" size="small"
                style="width: 100%;" type="date" value-format="yyyy-MM-dd">
              </el-date-picker>
            </div>
          </div>
        </el-col>
        <el-col v-if="radio == '发放'" :span="12" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">发放说明:</div>
            <div class="search_input"><el-input v-model="addInfo.issueNote" :rows="2" clearable placeholder="请输入"
                size="small" type="textarea"></el-input></div>
          </div>
        </el-col>
        <el-col v-else :span="12" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">回收说明:</div>
            <div class="search_input"><el-input v-model="addInfo.recycleNote" :rows="2" clearable placeholder="请输入"
                size="small" type="textarea"></el-input></div>
          </div>
        </el-col>
        <el-col v-if="radio == '发放'" :span="12" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">上传附件:</div>
            <div class="search_input"><el-upload :auto-upload="false" :multiple="false" :on-change="handleChangeUpload"
                accept='.pdf,.doc,.docx,.xls,.xlsx' action="#" style="margin: 8px 0 0px 50px;">
                <el-button size="small" type="primary">上传附件</el-button>
              </el-upload></div>
          </div>
        </el-col>
      </el-row>
      <span slot="footer" class="dialog-footer">
        <el-button @click="addDialogVisible = false">取 æ¶ˆ</el-button>
        <el-button :loading="addLoading" type="primary" @click="handleAdd">ç¡® å®š</el-button>
      </span>
    </el-dialog>
    <el-dialog :visible.sync="lookDialogVisible" fullscreen title="查看附件" top="5vh" width="800px">
      <filePreview v-if="lookDialogVisible" :currentFile="{}" :fileUrl="javaApi + '/word/' + currentInfo.url"
        style="height: 90vh;overflow-y: auto;" />
    </el-dialog>
  </div>
</template>
<script>
import limsTable from "@/components/Table/lims-table.vue";
import filePreview from '@/components/Preview/filePreview.vue'
import {
  selectUserCondition,
} from "@/api/system/user.js";
import {
  pageManageDocumentList,
  pageManageDocumentCancel,
  exportManageDocumentIssueRecycle,
  addManageDocumentIssueRecycle,
  doManageDocumentIssueRecycle,
  checkManageDocumentIssueRecycle,
  pageManageDocumentIssueRecycle,
  delManageDocumentIssueRecycle,
} from '@/api/cnas/systemManagement/documentControl.js'
import { mapGetters } from "vuex";
export default {
  components: {
    filePreview,
    limsTable
  },
  computed: {
    ...mapGetters(["userId"]),
  },
  data() {
    return {
      ddPower: false,
      outPower: true,
      addInfo: {},
      addPower: true,
      addLoading: false,
      addDialogVisible: false,
      outLoading: false,
      personList: [],
      fileList: [],
      fileList0: [],
      radio: '发放',
      fileState: [],
      file: null,
      currentInfo: {},
      lookDialogVisible: false,
      queryParams: {},
      tableData: [],
      column: [
        { label: "文件编号", prop: "documentCode" },
        { label: "文件名称", prop: "name" },
        {
          label: "文件版本",
          prop: "version",
        },
        { label: "文件状态", prop: "documentState" },
        { label: "发放编号", prop: "issueCode" },
        { label: "发放人", prop: "issueUserName" },
        { label: "发放日期", prop: "issueDate" },
        { label: "回收人", prop: "recycleUserName" },
        { label: "回收日期", prop: "recycleDate" },
        {
          dataType: "action",
          fixed: "right",
          label: "操作",
          operation: [
            {
              name: "回收记录",
              type: "text",
              clickFun: (row) => {
                this.handleUpdate(row);
              }
            },
            {
              name: "删除",
              type: "text",
              clickFun: (row) => {
                this.handleDelete(row);
              },
              disabFun: (row, index) => {
                return row.documentState == '通过'
              }
            },
            {
              name: "查看附件",
              type: "text",
              clickFun: (row) => {
                this.handleLook(row);
              },
              disabFun: (row, index) => {
                return !row.url
              }
            },
            {
              name: "审核",
              type: "text",
              clickFun: (row) => {
                this.handleCheck(row);
              },
              disabFun: (row, index) => {
                return row.receiveUser != this.userId || row.documentState == '通过'
              }
            },
          ],
        },
      ],
      page: {
        total: 0,
        size: 10,
        current: 0,
      },
      tableLoading: false,
    }
  },
  mounted() {
    this.getList()
    this.getAuthorizedPerson()
    this.getFileList()
    this.getFileList0()
    this.selectEnumByCategory()
  },
  methods: {
    getPower() {
      let power = JSON.parse(sessionStorage.getItem('power'))
      let out = false
      let del = false
      let add = false
      // let check = false
      for (var i = 0; i < power.length; i++) {
        if (power[i].menuMethod == 'exportManageDocumentIssueRecycle') {
          out = true
        }
        if (power[i].menuMethod == 'addManageDocumentIssueRecycle') {
          add = true
        }
        if (power[i].menuMethod == 'delManageDocumentIssueRecycle') {
          del = true
        }
        // if (power[i].menuMethod == 'checkManageDocumentControlled') {
        //   check = true
        // }
      }
      // if (!check) {
      //   this.componentData.do.splice(2, 1)
      // }
      if (!del) {
        this.componentData.do.splice(1, 1)
      }
      if (!add) {
        this.componentData.do.splice(0, 1)
      }
      this.addPower = add
      this.outPower = out
    },
    getList() {
      this.tableLoading = true;
      let param = { ...this.queryParams, ...this.page };
      delete param.total;
      pageManageDocumentIssueRecycle({ ...param })
        .then((res) => {
          this.tableLoading = false;
          if (res.code === 200) {
            this.tableData = res.data.records;
            this.page.total = res.data.total;
          }
        })
        .catch((err) => {
          this.tableLoading = false;
        });
    },
    pagination({ page, limit }) {
      this.page.current = page;
      this.page.size = limit;
      this.getList();
    },
    refresh() {
      this.queryParams = {};
      this.page.current = 1;
      this.getList();
    },
    refreshTable() {
      this.page.current = 1;
      this.getList();
    },
    selectEnumByCategory() {
      // æ–‡ä»¶çŠ¶æ€
      this.getDicts("document_state").then((response) => {
        this.fileState = this.dictToValue(response.data);
      });
    },
    // èŽ·å–äººå‘˜åˆ—è¡¨
    getAuthorizedPerson() {
      selectUserCondition().then(res => {
        let data = []
        res.data.forEach(a => {
          data.push({
            label: a.name,
            value: a.id
          })
        })
        this.personList = data
      })
    },
    // èŽ·å–æ–‡ä»¶åˆ—è¡¨--文件清单
    getFileList() {
      pageManageDocumentList({
        current: -1,
        size: -1
      }).then(res => {
        this.fileList = res.data.records
      }).catch(err => { })
    },
    // èŽ·å–æ–‡ä»¶åˆ—è¡¨--作废文件
    getFileList0() {
      pageManageDocumentCancel({
        current: -1,
        size: -1
      }).then(res => {
        this.fileList0 = res.data.records
      }).catch(err => { })
    },
    // å¯¼å‡º
    handleOut() {
      this.outLoading = true
      // queryParams
      exportManageDocumentIssueRecycle(this.queryParams).then(res => {
        this.outLoading = false
        const blob = new Blob([res], { type: 'application/octet-stream' });
        this.$download.saveAs(blob, '发放回收记录.xlsx');
      })
    },
    changeFileList(e) {
      if (e) {
        let obj = this.fileList.find(a => a.documentCode == e)
        if (obj) {
          this.addInfo.name = obj.name
          this.addInfo.version = obj.version
          this.addInfo.state = obj.state
        }
      }
    },
    // æäº¤
    handleAdd() {
      if (!this.addInfo.documentCode) {
        this.$message.error('请选择文件')
        return
      }
      if (!this.addInfo.receiveUser) {
        this.$message.error('请选择审批人')
        return
      }
      if (this.radio == '发放') {
        if (!this.addInfo.issueUser) {
          this.$message.error('请选择发放人')
          return
        }
      } else {
        if (!this.addInfo.recycleUser) {
          this.$message.error('请选择回收人')
          return
        }
      }
      this.addLoading = true;
      if (!this.addInfo.id) {
        // æ–°å¢žå‘放记录
        let fd = new FormData();
        //文件信息中raw才是真的文件
        if (this.file) {
          fd.append("file", this.file.raw);
        }
        for (let key in this.addInfo) {
          fd.append(key, this.addInfo[key])
        }
        addManageDocumentIssueRecycle(fd).then(res => {
          this.addLoading = false;
          if (res.code == 200) {
            this.$message.success('发放成功')
            this.addDialogVisible = false
            this.refreshTable()
          }
        })
      } else {
        let { documentCode, id, issueUser, recycleUser, receiveUser, name, version, documentState, issueCode, recycleCode, issueDate, recycleDate, issueNote, recycleNote } = this.addInfo
        // æ·»åŠ å›žæ”¶è®°å½•
        doManageDocumentIssueRecycle({
          documentCode,
          id,
          issueUser,
          recycleUser,
          receiveUser,
          name,
          version,
          documentState,
          issueCode,
          recycleCode,
          issueDate,
          recycleDate,
          issueNote,
          recycleNote
        }).then(res => {
          this.addLoading = false;
          if (res.code == 200) {
            this.$message.success('提交成功')
            this.addDialogVisible = false
            this.refreshTable()
          }
        })
      }
    },
    // æ·»åŠ å›žæ”¶
    handleUpdate(row) {
      this.addInfo = this.HaveJson(row)
      this.radio = '回收'
      this.addDialogVisible = true
    },
    // å®¡æ ¸
    handleCheck(row) {
      this.$confirm('是否审核通过?', '提示', {
        confirmButtonText: '通过',
        cancelButtonText: '不通过',
        type: 'warning',
        closeOnClickModal: false, // ç¦æ­¢ç‚¹å‡»é®ç½©å±‚关闭
        distinguishCancelAndClose: true,
        beforeClose: (action, instance, done) => {
          if (action === 'confirm') {
            // ç‚¹å‡»â€œç¡®å®šâ€æŒ‰é’®ï¼Œå…è®¸å…³é—­
            checkManageDocumentIssueRecycle({ id: row.id, documentState: '通过' }).then(res => {
              this.refreshTable()
              done();
              this.$message({
                type: 'success',
                message: '提交成功'
              })
            })
              .catch(err => {
              })
          } else if (action === 'cancel') {
            // ç‚¹å‡»â€œå–消”按钮,不允许关闭
            checkManageDocumentIssueRecycle({ id: row.id, documentState: '不通过' }).then(res => {
              this.refreshTable()
              done();
              this.$message({
                type: 'success',
                message: '提交成功'
              })
            })
              .catch(err => {
              })
          } else if (action === 'close') {
            // ç‚¹å‡»â€œÃ—”按钮,不允许关闭
            done();
            console.log("×按钮点击事件,不关闭弹框");
          }
        }
      })
    },
    handleChangeUpload(file, fileLists) {
      this.file = file
      this.$set(this.addInfo, 'name', file.name)
    },
    // æŸ¥çœ‹é™„ä»¶
    handleLook(row) {
      this.currentInfo = this.HaveJson(row)
      this.lookDialogVisible = true
    },
    handleDelete(row) {
      this.$confirm("是否删除该条数据?", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      })
        .then(() => {
          delManageDocumentIssueRecycle({ id: row.id }).then((res) => {
            if (res.code == 201) return;
            this.$message.success("删除成功");
            this.refresh();
          });
        })
        .catch(() => { });
    },
  }
}
</script>
<style scoped>
.title {
  height: 60px;
  line-height: 60px;
}
.search {
  background-color: #fff;
  height: 40px;
  display: flex;
  align-items: center;
  position: relative;
}
.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 {
  background-color: #fff;
  height: calc(100% - 60px - 80px);
  padding: 20px;
}
.btns {
  position: absolute;
  right: 20px;
  top: 5px;
}
</style>
src/views/CNAS/systemManagement/documentControl/components/FileChangeRequest.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,703 @@
<template>
  <!-- æ–‡ä»¶å˜æ›´ç”³è¯· -->
  <div class="file-change-request" style="height: 100%;">
    <div class="search">
      <div class="search_thing">
        <div class="search_label">申请文件编号:</div>
        <div class="search_input"><el-input v-model="queryParams.code" clearable placeholder="请输入" size="small"
            @keyup.enter.native="refreshTable()"></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="refreshTable()">查 è¯¢</el-button>
      </div>
      <div class="btns">
        <el-button size="small" type="primary"
          @click="addDialogVisible = true, addInfo = {}, currentFile = {}, title = '文件变更申请'">文件变更申请</el-button>
        <el-button :loading="outLoading" size="small" type="primary" @click="handleOut">导出</el-button>
      </div>
    </div>
    <div class="table">
      <lims-table :tableData="tableData" :column="column" :page="page" :tableLoading="tableLoading"
        :height="'calc(100vh - 290px)'" @pagination="pagination"></lims-table>
    </div>
    <el-dialog :title="title" :visible.sync="addDialogVisible" top="0vh" width="950px">
      <el-row>
        <el-col :span="12" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label"><span style="color:red;margin-right: 4px;">*</span>申请编号:</div>
            <div class="search_input"><el-input v-model="addInfo.code" :disabled="title == '审核'" clearable
                placeholder="请输入" size="small"></el-input></div>
          </div>
        </el-col>
        <el-col :span="12" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">审批人:</div>
            <div class="search_input">
              <el-select v-model="addInfo.checkUser" :disabled="title == '审核'" filterable size="small"
                style="width: 100%;">
                <el-option v-for="item in personList" :key="item.value" :label="item.label" :value="item.value">
                </el-option>
              </el-select>
            </div>
          </div>
        </el-col>
        <el-col :span="12" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">期望变更时间:</div>
            <div class="search_input">
              <el-date-picker v-model="addInfo.expectAlterDate" :disabled="title == '审核'" format="yyyy-MM-dd"
                placeholder="选择日期" size="small" style="width: 100%;" type="date" value-format="yyyy-MM-dd">
              </el-date-picker>
            </div>
          </div>
        </el-col>
        <el-col :span="12" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">实际变更时间:</div>
            <div class="search_input">
              <el-date-picker v-model="addInfo.actuallyAlterDate" :disabled="title == '审核'" format="yyyy-MM-dd"
                placeholder="选择日期" size="small" style="width: 100%;" type="date" value-format="yyyy-MM-dd">
              </el-date-picker>
            </div>
          </div>
        </el-col>
        <el-col :span="24" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">选择文件:</div>
            <div class="search_input">
              <el-select v-model="addInfo.alterBeforeCode" :disabled="title == '审核'" allow-create clearable filterable
                size="small" style="width: 100%;" @change="getCurrentFile">
                <el-option v-for="item in fileList" :key="item.documentCode" :label="item.title"
                  :value="item.documentCode">
                </el-option>
              </el-select>
            </div>
          </div>
        </el-col>
        <el-col :span="24">
          <h4 class="title">当前文件信息</h4>
        </el-col>
        <el-col :span="8" style="margin-bottom: 16px;">
          <div class="search_thing" style="width: 100%;">
            <div class="search_label">文件编号:</div>
            <div class="search_input"><el-input v-model="currentFile.documentCode" :disabled="title == '审核'" clearable
                placeholder="请输入" size="small"></el-input></div>
          </div>
        </el-col>
        <el-col :span="8" style="margin-bottom: 16px;">
          <div class="search_thing" style="width: 100%;">
            <div class="search_label">文件名称:</div>
            <div class="search_input"><el-input v-model="currentFile.name" :disabled="title == '审核'" clearable
                placeholder="请输入" size="small"></el-input></div>
          </div>
        </el-col>
        <el-col :span="8" style="margin-bottom: 16px;">
          <div class="search_thing" style="width: 100%;">
            <div class="search_label">文件版本:</div>
            <div class="search_input"><el-input v-model="currentFile.version" :disabled="title == '审核'" clearable
                placeholder="请输入" size="small"></el-input></div>
          </div>
        </el-col>
        <el-col :span="8" style="margin-bottom: 16px;">
          <div class="search_thing" style="width: 100%;">
            <div class="search_label">提交人:</div>
            <div class="search_input"><el-select v-model="currentFile.createUser" disabled filterable size="small"
                style="width: 100%;">
                <el-option v-for="item in personList" :key="item.value" :label="item.label" :value="item.value">
                </el-option>
              </el-select></div>
          </div>
        </el-col>
        <!-- <el-col :span="8" style="margin-bottom: 16px;">
          <div class="search_thing" style="width: 100%;">
            <div class="search_label">审核人:</div>
            <div class="search_input"><el-input size="small" placeholder="请输入" clearable v-model="addInfo.version" disabled></el-input></div>
          </div>
        </el-col>
        <el-col :span="8" style="margin-bottom: 16px;">
          <div class="search_thing" style="width: 100%;">
            <div class="search_label">作废人:</div>
            <div class="search_input"><el-input size="small" placeholder="请输入" clearable v-model="addInfo.version" disabled></el-input></div>
          </div>
        </el-col> -->
        <el-col :span="8" style="margin-bottom: 16px;">
          <div class="search_thing" style="width: 100%;">
            <div class="search_label">提交时间:</div>
            <div class="search_input"><el-input v-model="currentFile.createTime" clearable disabled placeholder="请输入"
                size="small"></el-input></div>
          </div>
        </el-col>
        <el-col :span="8" style="margin-bottom: 16px;">
          <div class="search_thing" style="width: 100%;">
            <div class="search_label">审核时间:</div>
            <div class="search_input"><el-input v-model="currentFile.effectiveDate" clearable disabled placeholder="请输入"
                size="small"></el-input></div>
          </div>
        </el-col>
        <!-- <el-col :span="8" style="margin-bottom: 16px;">
          <div class="search_thing" style="width: 100%;">
            <div class="search_label">作废时间:</div>
            <div class="search_input"><el-input size="small" placeholder="请输入" clearable v-model="addInfo.version" disabled></el-input></div>
          </div>
        </el-col> -->
        <el-col :span="8" style="margin-bottom: 16px;">
          <div class="search_thing" style="width: 100%;">
            <div class="search_label">文件状态:</div>
            <div class="search_input">
              <el-select v-model="currentFile.state" disabled size="small" style="width: 100%;">
                <el-option v-for="item in fileState" :key="item.value" :label="item.label" :value="item.value">
                </el-option>
              </el-select>
            </div>
          </div>
        </el-col>
        <!-- <el-col :span="8" style="margin-bottom: 16px;">
          <div class="search_thing" style="width: 100%;">
            <div class="search_label">文件说明:</div>
            <div class="search_input"><el-input size="small" placeholder="请输入" clearable v-model="addInfo.instructions" type="textarea"
              :rows="2" disabled></el-input></div>
          </div>
        </el-col> -->
        <el-col :span="24">
          <h4 class="title">文件变更申请</h4>
        </el-col>
        <el-col :span="8" style="margin-bottom: 16px;">
          <div class="search_thing" style="width: 100%;">
            <div class="search_label">变更后编号:</div>
            <div class="search_input"><el-input v-model="addInfo.alterAfterCode" :disabled="title == '审核'" clearable
                placeholder="请输入" size="small"></el-input></div>
          </div>
        </el-col>
        <el-col :span="8" style="margin-bottom: 16px;">
          <div class="search_thing" style="width: 100%;">
            <div class="search_label">变更后名称:</div>
            <div class="search_input"><el-input v-model="addInfo.alterAfterName" :disabled="title == '审核'" clearable
                placeholder="请输入" size="small"></el-input></div>
          </div>
        </el-col>
        <el-col :span="8" style="margin-bottom: 16px;">
          <div class="search_thing" style="width: 100%;">
            <div class="search_label">前一版本处理:</div>
            <div class="search_input">
              <el-select v-model="addInfo.method" :disabled="title == '审核'" size="small" style="width: 100%;">
                <el-option label="作废" value="作废"></el-option>
                <el-option label="存档不可用" value="存档不可用">
                </el-option>
              </el-select>
            </div>
          </div>
        </el-col>
        <el-col :span="8" style="margin-bottom: 16px;">
          <div class="search_thing" style="width: 100%;">
            <div class="search_label">变更后版本:</div>
            <div class="search_input"><el-input v-model="addInfo.alterAfterVersion" :disabled="title == '审核'" clearable
                placeholder="请输入" size="small"></el-input></div>
          </div>
        </el-col>
        <el-col :span="16" style="margin-bottom: 16px;">
          <div class="search_thing" style="width: 100%;">
            <div class="search_label">变更说明:</div>
            <div class="search_input"><el-input v-model="addInfo.alterNote" :disabled="title == '审核'" :rows="2"
                clearable placeholder="请输入" size="small" type="textarea"></el-input></div>
          </div>
        </el-col>
        <el-col v-if="title != '审核'" :span="24" style="margin-bottom: 16px;">
          <div class="search_thing" style="width: 100%;">
            <div class="search_label">相关附件:</div>
            <div class="search_input"><el-upload v-if="addDialogVisible" :auto-upload="false" :multiple="false"
                :on-change="handleChangeUpload" accept='.pdf' action="#" style="margin: 8px 0 0px 50px;">
                <el-button size="small" type="primary">上传附件</el-button>
              </el-upload></div>
          </div>
        </el-col>
        <UpPdfStamp v-if="title == '审核' && addDialogVisible" ref="UpPdfStamp" :isUpFile="false" @uploadPDF="uploadPDF">
        </UpPdfStamp>
      </el-row>
      <span v-if="title != '审核'" slot="footer" class="dialog-footer">
        <el-button @click="addDialogVisible = false">取 æ¶ˆ</el-button>
        <el-button :loading="addLoading" type="primary" @click="handleAdd">ç¡® å®š</el-button>
      </span>
      <span v-else slot="footer" class="dialog-footer">
        <el-button :loading="noCheckLoading" @click="handleCheckSub('不通过')">不通过</el-button>
        <el-button :loading="checkLoading" type="primary" @click="handleCheckSub('通过')">通 è¿‡</el-button>
      </span>
    </el-dialog>
    <el-dialog :visible.sync="lookDialogVisible" fullscreen title="查看附件" top="5vh" width="800px">
      <filePreview v-if="lookDialogVisible" :currentFile="{}" :fileUrl="javaApi + '/word/' + currentInfo.alterAfterUrl"
        style="height: 90vh;overflow-y: auto;" />
    </el-dialog>
  </div>
</template>
<script>
import limsTable from "@/components/Table/lims-table.vue";
import UpPdfStamp from '@/components/UpPdfStamp/index.vue'
import filePreview from '@/components/Preview/filePreview.vue'
import {
  selectUserCondition,
} from "@/api/system/user.js";
import {
  exportManageDocumentAlter,
  pageManageDocumentList,
  addManageDocumentAlter,
  doManageDocumentAlter,
  checkManageDocumentAlterPdf,
  checkManageDocumentAlter,
  delManageDocumentAlter,
  pageManageDocumentAlter,
} from '@/api/cnas/systemManagement/documentControl.js'
import { mapGetters } from "vuex";
export default {
  components: {
    limsTable,
    filePreview,
    UpPdfStamp,
  },
  computed: {
    ...mapGetters(["userId"]),
  },
  data() {
    return {
      title: '文件变更申请',
      noCheckLoading: false,
      checkLoading: false,
      addDialogVisible: false,
      addInfo: {},
      addPower: false,
      outPower: false,
      outLoading: false,
      personList: [],
      fileList: [],
      currentFile: {},
      fileState: [],
      file: null,
      addLoading: false,
      lookDialogVisible: false,
      currentInfo: {
      },
      type: null,
      fileName: null,
      queryParams: {},
      tableData: [],
      column: [
        { label: "申请编号", prop: "code" },
        { label: "申请人", prop: "createUserName", width: "120px" },
        {
          label: "变更说明",
          prop: "alterNote",
        },
        { label: "期望变更时间", prop: "expectAlterDate" },
        { label: "实际变更时间", prop: "actuallyAlterDate" },
        {
          label: "状态", prop: "state", dataType: "tag",
          formatData: (params) => {
            return params;
          },
          formatType: (params) => {
            if (params == '通过') {
              return 'success'
            } else {
              return 'danger'
            }
          },
        },
        {
          dataType: "action",
          fixed: "right",
          label: "操作",
          operation: [
            {
              name: "编辑",
              type: "text",
              clickFun: (row) => {
                this.handleUpdate(row);
              },
              disabled: (row, index) => {
                return row.state == '通过'
              }
            },
            {
              name: "删除",
              type: "text",
              clickFun: (row) => {
                this.handleDelete(row);
              },
              disabled: (row, index) => {
                return row.state == '通过'
              }
            },
            {
              name: "审核",
              type: "text",
              clickFun: (row) => {
                this.handleCheck(row);
              },
              disabled: (row, index) => {
                return row.checkUser != this.userId || row.state == '通过'
              }
            },
            {
              name: "查看附件",
              type: "text",
              clickFun: (row) => {
                this.handleLook(row);
              },
            },
            {
              name: "下载附件",
              type: "text",
              clickFun: (row) => {
                this.handleDown(row);
              },
            },
          ],
        },
      ],
      page: {
        total: 0,
        size: 10,
        current: 0,
      },
      tableLoading: false,
    }
  },
  mounted() {
    this.getList()
    this.getAuthorizedPerson()
    this.getFileList()
    this.selectEnumByCategory()
  },
  methods: {
    getPower() {
      let power = JSON.parse(sessionStorage.getItem('power'))
      let up = false
      let del = false
      let add = false
      let out = false
      for (var i = 0; i < power.length; i++) {
        if (power[i].menuMethod == 'addManageDocumentAlter') {
          up = true
        }
        if (power[i].menuMethod == 'addManageDocumentAlter') {
          add = true
        }
        if (power[i].menuMethod == 'delManageDocumentAlter') {
          del = true
        }
        if (power[i].menuMethod == 'exportManageDocumentAlter') {
          out = true
        }
      }
      if (!del) {
        this.componentData.do.splice(1, 1)
      }
      if (!up) {
        this.componentData.do.splice(0, 1)
      }
      this.addPower = add
      this.outPower = out
    },
    getList() {
      this.tableLoading = true;
      let param = { ...this.queryParams, ...this.page };
      delete param.total;
      pageManageDocumentAlter({ ...param })
        .then((res) => {
          this.tableLoading = false;
          if (res.code === 200) {
            this.tableData = res.data.records;
            this.page.total = res.data.total;
          }
        })
        .catch((err) => {
          this.tableLoading = false;
        });
    },
    pagination({ page, limit }) {
      this.page.current = page;
      this.page.size = limit;
      this.getList();
    },
    refresh() {
      this.queryParams = {};
      this.page.current = 1;
      this.getList();
    },
    refreshTable() {
      this.page.current = 1;
      this.getList();
    },
    // å¯¼å‡º
    handleOut() {
      this.outLoading = true
      exportManageDocumentAlter(this.queryParams).then(res => {
        this.outLoading = false
        const blob = new Blob([res], { type: 'application/octet-stream' });
        this.$download.saveAs(blob, '文件变更记录.xlsx')
      })
    },
    getAuthorizedPerson() {
      selectUserCondition().then(res => {
        let data = []
        res.data.forEach(a => {
          data.push({
            label: a.name,
            value: a.id
          })
        })
        this.personList = data
      })
    },
    // èŽ·å–æ–‡ä»¶åˆ—è¡¨--文件清单
    getFileList() {
      pageManageDocumentList({
        current: -1,
        size: -1
      }).then(res => {
        this.fileList = res.data.records.map(m => {
          m.title = m.documentCode + ':' + m.name
          return m
        })
      }).catch(err => { })
    },
    // å½“前文件
    getCurrentFile(e) {
      this.currentFile = this.fileList.find(m => m.documentCode == e)
      if (!this.currentFile) {
        this.currentFile = {}
      }
    },
    selectEnumByCategory() {
      // æ–‡ä»¶çŠ¶æ€
      this.getDicts("document_state").then((response) => {
        this.fileState = this.dictToValue(response.data);
      });
    },
    handleChangeUpload(file, fileLists) {
      this.file = file
      this.$set(this.addInfo, 'alterAfterName', file.name)
    },
    handleAdd() {
      if (!this.addInfo.code) return this.$message({ type: 'error', message: "请输入申请编号" })
      if (!this.addInfo.id) {
        // æ–°å¢ž
        let fd = new FormData();
        //文件信息中raw才是真的文件
        if (this.file) {
          fd.append("file", this.file.raw);
        }
        for (let m in this.addInfo) {
          fd.append(m, this.addInfo[m])
        }
        let { name, version, documentCode } = this.currentFile;
        fd.append("alterBeforeName", name);
        fd.append("alterBeforeVersion", version);
        // fd.append("alterBeforeCode",documentCode);
        this.addLoading = true
        addManageDocumentAlter(fd).then(res => {
          this.addLoading = false
          if (res.code == 200) {
            this.$message({
              type: 'success',
              message: '添加成功'
            })
            this.refreshTable()
            this.addDialogVisible = false
          } else {
            this.$message({
              type: 'error',
              message: '添加失败'
            })
          }
        })
      } else {
        // ä¿®æ”¹
        let fd = new FormData();
        //文件信息中raw才是真的文件
        if (this.file) {
          fd.append("file", this.file.raw);
        }
        let { name, version } = this.currentFile;
        fd.append("alterBeforeName", name);
        fd.append("alterBeforeVersion", version);
        let { code, checkUser, expectAlterDate, actuallyAlterDate, alterAfterCode, method, alterAfterVersion, alterNote, alterAfterName, id } = this.addInfo
        fd.append("code", code);
        fd.append("checkUser", checkUser);
        fd.append("expectAlterDate", expectAlterDate);
        fd.append("actuallyAlterDate", actuallyAlterDate);
        fd.append("alterAfterCode", alterAfterCode);
        fd.append("method", method);
        fd.append("alterAfterVersion", alterAfterVersion);
        fd.append("alterNote", alterNote);
        fd.append("alterAfterName", alterAfterName);
        fd.append("id", id);
        this.addLoading = true
        doManageDocumentAlter(fd).then(res => {
          this.addLoading = false
          if (res.code == 200) {
            this.$message({
              type: 'success',
              message: '修改成功'
            })
            this.refreshTable()
            this.addDialogVisible = false
          } else {
            this.$message({
              type: 'error',
              message: '修改失败'
            })
          }
        })
      }
    },
    // ç¼–辑
    handleUpdate(row) {
      this.title = '文件变更申请'
      this.addInfo = this.HaveJson(row)
      let alterBeforeCode = this.addInfo.alterBeforeCode
      this.getCurrentFile(alterBeforeCode)
      this.addDialogVisible = true
    },
    // é¢„览
    handleLook(row) {
      this.currentInfo = this.HaveJson(row)
      this.lookDialogVisible = true
    },
    // ä¸‹è½½é™„ä»¶
    handleDown(row) {
      if (!row.alterAfterUrl) return this.$message.warning('文件未上传')
      let url = this.javaApi + '/word/' + row.alterAfterUrl
      this.$download.saveAs(url, row.alterAfterUrl)
    },
    // æ‰“开审核弹框
    handleCheck(row) {
      this.title = '审核'
      this.fileName = row.alterAfterName
      if (!row.alterAfterUrl) return this.$message.warning('文件未上传')
      this.addInfo = this.HaveJson(row)
      let alterBeforeCode = this.addInfo.alterBeforeCode
      this.getCurrentFile(alterBeforeCode)
      this.addDialogVisible = true
      checkManageDocumentAlterPdf({ id: row.id }).then(res => {
        //
        const blob = new Blob([res]);
        const file = new File([blob], row.name, { type: 'application/pdf' })
        this.$refs.UpPdfStamp.lookFile(file)
        this.currentInfo = row
      }).catch(err => {
        console.log(err)
      })
    },
    // å®¡æ ¸ä¿å­˜
    async uploadPDF(pdfBlob) {
      const formData = new FormData();
      formData.append('file', pdfBlob, this.fileName + '.pdf'); // æ–‡ä»¶å­—段
      formData.append('id', this.currentInfo.id); // æ–‡ä»¶åå­—段
      formData.append('state', this.type); // æ–‡ä»¶åå­—段
      let res = await checkManageDocumentAlter(formData)
      this.checkLoading = false
      this.noCheckLoading = false
      if (res.code == 200) {
        this.$message({ message: '操作成功', type: 'success' });
        this.addDialogVisible = false;
        this.refreshTable()
        return true
      } else {
        this.$message({ message: '操作失败', type: 'error' });
        return false
      }
    },
    // æäº¤å®¡æ ¸
    handleCheckSub(type) {
      this.type = type
      if (type == '通过') {
        this.checkLoading = true
      } else {
        this.noCheckLoading = true
      }
      this.addLoading = true
      this.$refs['UpPdfStamp'].generatePDF()
    },
    handleDelete(row) {
      this.$confirm("是否删除该条数据?", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      })
        .then(() => {
          delManageDocumentAlter({ id: row.id }).then((res) => {
            if (res.code == 201) return;
            this.$message.success("删除成功");
            this.refresh();
          });
        })
        .catch(() => { });
    },
  }
}
</script>
<style scoped>
.title {
  height: 60px;
  line-height: 60px;
}
.search {
  background-color: #fff;
  height: 40px;
  display: flex;
  align-items: center;
  position: relative;
}
.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 {
  background-color: #fff;
  height: calc(100% - 60px - 80px);
  padding: 20px;
}
.btns {
  position: absolute;
  right: 20px;
  top: 5px;
}
h4.title {
  position: relative;
  height: 30px;
  line-height: 30px;
  box-sizing: border-box;
  padding-left: 16px;
  margin-left: 10px;
  margin-bottom: 10px;
}
h4.title::after {
  content: '';
  width: 4px;
  height: 20px;
  background: #3A7BFA;
  position: absolute;
  top: 5px;
  left: 0;
}
</style>
src/views/CNAS/systemManagement/documentControl/components/FileList.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,438 @@
<template>
  <!-- æ–‡ä»¶æ¸…单 -->
  <div class="file-list" style="height: 100%;">
    <div class="search">
      <div class="search_thing">
        <div class="search_label">文件名称:</div>
        <div class="search_input"><el-input size="small" placeholder="请输入" clearable v-model="queryParams.name"
            @keyup.enter.native="refreshTable()"></el-input></div>
      </div>
      <div class="search_thing">
        <div class="search_label">文件状态:</div>
        <div class="search_input">
          <el-select v-model="queryParams.state" size="small" @change="refreshTable()">
            <el-option :label="item.label" :value="item.value" v-for="(item, index) in fileState"
              :key="index"></el-option>
          </el-select>
        </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="refreshTable()">查 è¯¢</el-button>
      </div>
      <div class="btns" style="padding-left: 30px;">
        <el-upload :action="action" :multiple="false" accept='.xls,.xlsx' :headers="uploadHeader"
          :on-change="beforeUpload" :on-error="onError" ref='upload' :on-success="handleSuccessUp"
          :show-file-list="false">
          <el-button size="small" type="primary" :loading="upLoading">导入</el-button></el-upload>
      </div>
    </div>
    <div class="table">
      <lims-table :tableData="tableData" :column="column" :page="page" :tableLoading="tableLoading"
        :height="'calc(100vh - 290px)'" @pagination="pagination"></lims-table>
    </div>
    <el-dialog title="上传" :visible.sync="addDialogVisible" width="1000px" top="3vh">
      <UpPdfStamp ref="UpPdfStamp" v-if="addDialogVisible" @uploadPDF="uploadPDF" :isUpFile="true"
        @uploadPDFErr="uploadPDFErr"></UpPdfStamp>
      <span slot="footer" class="dialog-footer">
        <el-button @click="addDialogVisible = false">取 æ¶ˆ</el-button>
        <el-button type="primary" @click="handleAdd" v-loading="addLoading">ç¡® å®š</el-button>
      </span>
    </el-dialog>
    <el-dialog title="查看附件" :visible.sync="lookDialogVisible" width="800px" top="5vh" fullscreen>
      <filePreview v-if="lookDialogVisible" :fileUrl="javaApi + '/word/' + currentInfo.url" :currentFile="{}"
        style="max-height: 90vh;overflow-y: auto;" />
    </el-dialog>
    <!-- æ–°å¢ž/编辑 -->
    <el-dialog :title="title" :visible.sync="addDia" width="500px">
      <el-form :model="currentInfo" ref="currentInfoForm" :rules="rules" label-position="right" label-width="120px">
        <el-form-item label="文件编号" prop="documentCode">
          <el-input size="small" placeholder="请输入" clearable v-model="currentInfo.documentCode"></el-input>
        </el-form-item>
        <el-form-item label="类别" prop="type">
          <el-select v-model="currentInfo.type" size="small" clearable placeholder="请选择" style="width: 100%">
            <el-option v-for="item in fileType" :key="item.value" :label="item.label" :value="item.value">
            </el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="名称" prop="name">
          <el-input size="small" placeholder="请输入" clearable v-model="currentInfo.name">
          </el-input>
        </el-form-item>
        <el-form-item label="文件版本" prop="version">
          <el-input size="small" placeholder="请输入" clearable v-model="currentInfo.version">
          </el-input>
        </el-form-item>
        <el-form-item label="作者" prop="writer">
          <el-input size="small" placeholder="请输入" clearable v-model="currentInfo.writer">
          </el-input>
        </el-form-item>
        <el-form-item label="生效日期" prop="effectiveDate">
          <el-date-picker v-model="currentInfo.effectiveDate" format="yyyy-MM-dd" value-format="yyyy-MM-dd" type="date"
            size="small" placeholder="选择日期">
          </el-date-picker>
        </el-form-item>
        <el-form-item label="文件状态" prop="state">
          <el-select v-model="currentInfo.state" size="small" clearable placeholder="请选择" style="width: 100%">
            <el-option v-for="item in fileState" :key="item.value" :label="item.label" :value="item.value">
            </el-option>
          </el-select>
        </el-form-item>
      </el-form>
      <span slot="footer" class="dialog-footer">
        <el-button @click="addDia = false">取 æ¶ˆ</el-button>
        <el-button :loading="uploading" type="primary" @click="submitProduct('currentInfoForm')">ç¡® è®¤</el-button>
      </span>
    </el-dialog>
  </div>
</template>
<script>
import UpPdfStamp from '@/components/UpPdfStamp/index.vue'
import filePreview from '@/components/Preview/filePreview.vue'
import limsTable from "@/components/Table/lims-table.vue";
import {
  uploadFileManageDocumentList,
  pageManageDocumentList,
  delManageDocumentList,
  doManageDocumentList,
} from '@/api/cnas/systemManagement/documentControl.js'
export default {
  components: {
    UpPdfStamp,
    filePreview,
    limsTable,
  },
  data() {
    return {
      addDialogVisible: false,
      lookDialogVisible: false,
      addPower: false,
      upLoading: false,
      addLoading: false,
      currentInfo: {},
      fileType: [],
      fileState: [],
      title: '新增',
      queryParams: {},
      tableData: [],
      column: [
        { label: "文件编号", prop: "documentCode" },
        {
          label: "类别", prop: "type", width: "120px", dataType: "tag",
          formatData: (params) => {
            return this.fileType.find((m) => m.value == params).label;
          },
          formatType: (params) => {
            return this.fileType.find((m) => m.value == params).type;
          },
        },
        {
          label: "名称",
          prop: "name",
        },
        { label: "文件版本", prop: "version" },
        { label: "作者", prop: "writer" },
        { label: "生效日期", prop: "effectiveDate" },
        {
          label: "文件状态", prop: "state", dataType: "tag",
          formatData: (params) => {
            return this.fileState.find((m) => m.value == params).label;
          },
          formatType: (params) => {
            return this.fileState.find((m) => m.value == params).type;
          },
        },
        {
          dataType: "action",
          fixed: "right",
          label: "操作",
          operation: [
            {
              name: "编辑",
              type: "text",
              clickFun: (row) => {
                this.openAdd("编辑", row);
              },
            },
            {
              name: "上传",
              type: "text",
              clickFun: (row) => {
                this.handleUp(row);
              },
            },
            {
              name: "下载",
              type: "text",
              clickFun: (row) => {
                this.handleDown(row);
              },
            },
            {
              name: "查看附件",
              type: "text",
              clickFun: (row) => {
                this.handleLook(row);
              },
            },
            {
              name: "删除",
              type: "text",
              clickFun: (row) => {
                this.handleDelete(row);
              },
            },
          ],
        },
      ],
      page: {
        total: 0,
        size: 10,
        current: 0,
      },
      tableLoading: false,
      addDia: false,
      rules: {
        documentCode: [{ required: true, message: "请输入文件编号", trigger: "blur" }],
      },
      uploading: false,
    }
  },
  // ç”¨äºŽä¸Šä¼ æ–‡ä»¶çš„信息
  computed: {
    action() {
      return this.javaApi + '/manageDocumentList/exportManageDocumentList'
    }
  },
  mounted() {
    this.getList()
    this.selectEnumByCategory()
  },
  methods: {
    getList() {
      this.tableLoading = true;
      let param = { ...this.queryParams, ...this.page };
      delete param.total;
      pageManageDocumentList({ ...param })
        .then((res) => {
          this.tableLoading = false;
          if (res.code === 200) {
            this.tableData = res.data.records;
            this.page.total = res.data.total;
          }
        })
        .catch((err) => {
          this.tableLoading = false;
        });
    },
    pagination({ page, limit }) {
      this.page.current = page;
      this.page.size = limit;
      this.getList();
    },
    refreshTable() {
      this.page.current = 1;
      this.getList();
    },
    refresh() {
      this.queryParams = {};
      this.page.current = 1;
      this.getList();
    },
    openAdd(title, row) {
      this.title = title;
      if (row) {
        this.currentInfo = row;
      } else {
        this.currentInfo = {};
      }
      this.addDia = true;
    },
    // ä¸‹è½½æ–‡ä»¶
    handleDown(row) {
      if (!row.url) return this.$message.warning('文件未上传')
      let url = this.javaApi + '/word/' + row.url
      this.$download.saveAs(url, row.url);
    },
    // æŸ¥çœ‹æ–‡ä»¶
    handleLook(row) {
      if (!row.url) return this.$message.warning('文件未上传')
      this.currentInfo = row
      this.lookDialogVisible = true
    },
    getPower() {
      let power = JSON.parse(sessionStorage.getItem('power'))
      let up = false
      let upFile = false
      let add = false
      for (var i = 0; i < power.length; i++) {
        if (power[i].menuMethod == 'doManageDocumentList') {
          up = true
        }
        if (power[i].menuMethod == 'exportManageDocumentList') {
          add = true
        }
        if (power[i].menuMethod == 'uploadFileManageDocumentList') {
          upFile = true
        }
      }
      if (!upFile) {
        this.componentData.do.splice(1, 1)
      }
      if (!up) {
        this.componentData.do.splice(0, 1)
      }
      this.addPower = add
    },
    // ä¸Šä¼ æ–‡ä»¶
    handleUp(row) {
      this.currentInfo = row
      this.addDialogVisible = true;
    },
    // æäº¤ä¸Šä¼ 
    handleAdd() {
      this.addLoading = true
      this.$refs['UpPdfStamp'].generatePDF()
    },
    uploadPDFErr() {
      this.addLoading = false
    },
    beforeUpload(file) {
      if (file.size > 1024 * 1024 * 10) {
        this.$message.error('上传文件不超过10M');
        this.$refs.upload.clearFiles()
        return false;
      } else {
        // this.upLoading = true;
        return true;
      }
    },
    onError(err, file, fileList) {
      this.$message.error('上传失败')
      this.$refs.upload.clearFiles()
    },
    handleSuccessUp(response) {
      this.upLoading = false;
      if (response.code == 200) {
        this.$message.success('上传成功');
        this.refreshTable()
      }else {
        this.$message.error(response.msg);
      }
    },
    selectEnumByCategory() {
      // æ–‡ä»¶ç±»åˆ«
      this.getDicts("document_type").then((response) => {
        this.fileType = this.dictToValue(response.data);
      });
      // æ–‡ä»¶çŠ¶æ€
      this.getDicts("document_state").then((response) => {
        this.fileState = this.dictToValue(response.data);
      });
    },
    async uploadPDF(pdfBlob, fileName) {
      const formData = new FormData();
      formData.append('file', pdfBlob, fileName); // æ–‡ä»¶å­—段
      formData.append('id', this.currentInfo.id); // æ–‡ä»¶åå­—段
      try {
        let res = await uploadFileManageDocumentList(formData)
        this.addLoading = false
        if (res.code == 200) {
          this.$message({ message: '上传成功', type: 'success' });
          this.addDialogVisible = false;
          this.refreshTable()
          return true
        } else {
          this.$message({ message: '上传失败', type: 'error' });
          return false
        }
      } catch (e) {
        this.addLoading = false
      }
    },
    handleDelete(row) {
      this.$confirm("是否删除该条数据?", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      })
        .then(() => {
          delManageDocumentList({ id: row.id }).then((res) => {
            if (res.code == 201) return;
            this.$message.success("删除成功");
            this.refresh();
          });
        })
        .catch(() => { });
    },
    submitProduct(formName) {
      this.$refs[formName].validate((valid) => {
        if (valid) {
          this.uploading = true;
          doManageDocumentList(this.currentInfo)
            .then((res) => {
              this.uploading = false;
              if (res.code != 200) {
                return;
              }
              this.$message.success("提交成功");
              this.refresh();
              this.addDia = false;
            })
            .catch((err) => {
              this.uploading = false;
            });
        } else {
          return false;
        }
      });
    },
  }
}
</script>
<style scoped>
.title {
  height: 60px;
  line-height: 60px;
}
.search {
  background-color: #fff;
  height: 40px;
  display: flex;
  align-items: center;
  position: relative;
}
.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 {
  background-color: #fff;
  height: calc(100% - 60px - 80px);
  padding: 20px;
}
.btns {
  position: absolute;
  right: 20px;
  top: 5px;
}
</style>
src/views/CNAS/systemManagement/documentControl/components/FileObsoletionRequest.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,492 @@
<template>
  <!-- æ–‡ä»¶ä½œåºŸç”³è¯· -->
  <div class="file-obsoletion-request" style="height: 100%;">
    <div class="search">
      <div class="search_thing">
        <div class="search_label">文件编号:</div>
        <div class="search_input"><el-input v-model="queryParams.documentCode" clearable placeholder="请输入" size="small"
            @keyup.enter.native="refreshTable()"></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="refreshTable()">查 è¯¢</el-button>
      </div>
      <div class="btns" style="padding-left: 30px;">
        <el-button size="small" type="primary" @click="addDialogVisible = true, addInfo = {}">文件作废申请</el-button>
        <el-button :loading="outLoading" size="small" type="primary" @click="handleOut">导出</el-button>
      </div>
    </div>
    <div class="table">
      <lims-table :tableData="tableData" :column="column" :page="page" :tableLoading="tableLoading"
        :height="'calc(100vh - 290px)'" @pagination="pagination"></lims-table>
    </div>
    <el-dialog :visible.sync="addDialogVisible" title="文件作废申请" top="10vh" width="800px">
      <el-row>
        <el-col :span="12" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label"><span style="color:red;margin-right: 4px;">*</span>申请编号:</div>
            <div class="search_input">
              <el-select v-model="addInfo.documentCode" allow-create clearable filterable size="small"
                style="width: 100%;" @change="changeFileList">
                <el-option v-for="item in fileList" :key="item.documentCode" :label="item.documentCode"
                  :value="item.documentCode">
                </el-option>
              </el-select>
            </div>
          </div>
        </el-col>
        <el-col :span="12" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">审批人:</div>
            <div class="search_input">
              <el-select v-model="addInfo.checkUser" filterable size="small" style="width: 100%;">
                <el-option v-for="item in personList" :key="item.value" :label="item.label" :value="item.value">
                </el-option>
              </el-select>
            </div>
          </div>
        </el-col>
        <el-col :span="12" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">文件名称:</div>
            <div class="search_input"><el-input v-model="addInfo.name" clearable placeholder="请输入"
                size="small"></el-input></div>
          </div>
        </el-col>
        <el-col :span="12" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">文件版本:</div>
            <div class="search_input"><el-input v-model="addInfo.version" clearable placeholder="请输入"
                size="small"></el-input></div>
          </div>
        </el-col>
        <el-col :span="12" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">文件状态:</div>
            <div class="search_input">
              <el-select v-model="addInfo.state" size="small" style="width: 100%;">
                <el-option v-for="(item, index) in fileState" :key="index" :label="item.label"
                  :value="item.value"></el-option>
              </el-select>
            </div>
          </div>
        </el-col>
        <!-- <el-col :span="12" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">作废方式:</div>
            <div class="search_input">
              <el-select v-model="addInfo.method" size="small" style="width: 100%;">
                <el-option label="作废" value="作废"></el-option>
                <el-option label="无效" value="无效"></el-option>
              </el-select>
            </div>
          </div>
        </el-col> -->
        <el-col :span="12" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">期望作废时间:</div>
            <div class="search_input">
              <el-date-picker v-model="addInfo.expectCancelDate" format="yyyy-MM-dd" placeholder="选择日期" size="small"
                style="width: 100%;" type="date" value-format="yyyy-MM-dd">
              </el-date-picker>
            </div>
          </div>
        </el-col>
        <el-col :span="12" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">实际作废时间:</div>
            <div class="search_input">
              <el-date-picker v-model="addInfo.actuallyCancelDate" format="yyyy-MM-dd" placeholder="选择日期" size="small"
                style="width: 100%;" type="date" value-format="yyyy-MM-dd">
              </el-date-picker>
            </div>
          </div>
        </el-col>
        <el-col :span="12" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">作废说明:</div>
            <div class="search_input"><el-input v-model="addInfo.cancelNote" :rows="2" clearable placeholder="请输入"
                size="small" type="textarea"></el-input></div>
          </div>
        </el-col>
      </el-row>
      <span slot="footer" class="dialog-footer">
        <el-button @click="addDialogVisible = false">取 æ¶ˆ</el-button>
        <el-button :loading="addLoading" type="primary" @click="handleAdd">ç¡® å®š</el-button>
      </span>
    </el-dialog>
  </div>
</template>
<script>
import limsTable from "@/components/Table/lims-table.vue";
import {
  selectUserCondition,
} from "@/api/system/user.js";
import {
  addManageDocumentCancel,
  pageManageDocumentList,
  doManageDocumentCancel,
  checkManageDocumentCancel,
  exportManageDocumentCancel,
  delManageDocumentCancel,
  pageManageDocumentCancel,
} from '@/api/cnas/systemManagement/documentControl.js'
import { mapGetters } from "vuex";
export default {
  components: {
    limsTable
  },
  computed: {
    ...mapGetters(["userId"]),
  },
  data() {
    return {
      addPower: false,
      outPower: false,
      addInfo: {},
      addLoading: false,
      addDialogVisible: false,
      personList: [],
      fileList: [],
      outLoading: false,
      fileState: [],
      queryParams: {},
      tableData: [],
      column: [
        { label: "文件编号", prop: "documentCode" },
        { label: "申请人", prop: "createUserName", width: "120px" },
        {
          label: "作废说明",
          prop: "cancelNote",
        },
        { label: "期望作废时间", prop: "expectCancelDate" },
        { label: "实际作废日期", prop: "actuallyCancelDate" },
        {
          label: "作废状态", prop: "state", dataType: "tag",
          formatData: (params) => {
            return params;
          },
          formatType: (params) => {
            if (params == '通过') {
              return 'success'
            } else {
              return 'danger'
            }
          }
        },
        {
          dataType: "action",
          fixed: "right",
          label: "操作",
          operation: [
            {
              name: "编辑",
              type: "text",
              clickFun: (row) => {
                this.handleUpdate(row);
              },
              disabled: (row, index) => {
                return row.state == '通过'
              }
            },
            {
              name: "删除",
              type: "text",
              clickFun: (row) => {
                this.handleDelete(row);
              },
              disabled: (row, index) => {
                return row.state == '通过'
              }
            },
            {
              name: "审核",
              type: "text",
              clickFun: (row) => {
                this.handleCheck(row);
              },
              disabled: (row, index) => {
                return row.checkUser != this.userId || row.state == '通过'
              }
            },
          ],
        },
      ],
      page: {
        total: 0,
        size: 10,
        current: 0,
      },
      tableLoading: false,
    }
  },
  mounted() {
    this.getList()
    this.getAuthorizedPerson()
    this.getFileList()
    this.selectEnumByCategory()
  },
  methods: {
    getPower() {
      let power = JSON.parse(sessionStorage.getItem('power'))
      let out = false
      let del = false
      let add = false
      // let check = false
      for (var i = 0; i < power.length; i++) {
        if (power[i].menuMethod == 'exportManageDocumentCancel') {
          out = true
        }
        if (power[i].menuMethod == 'addManageDocumentCancel') {
          add = true
        }
        if (power[i].menuMethod == 'delManageDocumentCancel') {
          del = true
        }
        // if (power[i].menuMethod == 'checkManageDocumentControlled') {
        //   check = true
        // }
      }
      // if (!check) {
      //   this.componentData.do.splice(2, 1)
      // }
      if (!del) {
        this.componentData.do.splice(1, 1)
      }
      if (!add) {
        this.componentData.do.splice(0, 1)
      }
      this.addPower = add
      this.outPower = out
    },
    getList() {
      this.tableLoading = true;
      let param = { ...this.queryParams, ...this.page };
      delete param.total;
      pageManageDocumentCancel({ ...param })
        .then((res) => {
          this.tableLoading = false;
          if (res.code === 200) {
            this.tableData = res.data.records;
            this.page.total = res.data.total;
          }
        })
        .catch((err) => {
          this.tableLoading = false;
        });
    },
    pagination({ page, limit }) {
      this.page.current = page;
      this.page.size = limit;
      this.getList();
    },
    refresh() {
      this.queryParams = {};
      this.page.current = 1;
      this.getList();
    },
    refreshTable() {
      this.page.current = 1;
      this.getList();
    },
    selectEnumByCategory() {
      // æ–‡ä»¶çŠ¶æ€
      this.getDicts("document_state").then((response) => {
        this.fileState = this.dictToValue(response.data);
      });
    },
    // èŽ·å–äººå‘˜åˆ—è¡¨
    getAuthorizedPerson() {
      selectUserCondition().then(res => {
        let data = []
        res.data.forEach(a => {
          data.push({
            label: a.name,
            value: a.id
          })
        })
        this.personList = data
      })
    },
    // èŽ·å–æ–‡ä»¶åˆ—è¡¨
    getFileList() {
      pageManageDocumentList({
        current: -1,
        size: -1
      }).then(res => {
        this.fileList = res.data.records
      }).catch(err => { })
    },
    // æäº¤
    handleAdd() {
      if (!this.addInfo.documentCode) {
        this.$message.error('请输入申请编号')
        return false
      }
      this.addInfo.method = '作废'
      this.addLoading = true
      if (!this.addInfo.id) {
        // æ–°å¢ž
        addManageDocumentCancel(this.addInfo).then(res => {
          this.addLoading = false
          this.refreshTable()
          this.$message({
            type: 'success',
            message: '提交成功'
          })
          this.addDialogVisible = false
        }).catch(err => { })
      } else {
        // ç¼–辑
        doManageDocumentCancel({
          id: this.addInfo.id,
          method: '作废',
          documentCode: this.addInfo.documentCode,
          checkUser: this.addInfo.checkUser,
          name: this.addInfo.name,
          version: this.addInfo.version,
          documentState: this.addInfo.documentState,
          expectCancelDate: this.addInfo.expectCancelDate,
          actuallyCancelDate: this.addInfo.actuallyCancelDate,
          cancelNote: this.addInfo.cancelNote,
        }).then(res => {
          this.addLoading = false
          this.refreshTable()
          this.$message({
            type: 'success',
            message: '提交成功'
          })
          this.addDialogVisible = false
        }).catch(err => { })
      }
    },
    // é€‰ä¸­æ–‡ä»¶
    changeFileList(e) {
      if (e) {
        let obj = this.fileList.find(a => a.documentCode == e)
        if (obj) {
          this.addInfo.name = obj.name
          this.addInfo.version = obj.version
          this.addInfo.documentState = obj.state
        }
      }
    },
    handleUpdate(row) {
      this.addInfo = this.HaveJson(row)
      this.addDialogVisible = true
    },
    // å®¡æ ¸
    handleCheck(row) {
      this.$confirm('是否审核通过?', '提示', {
        confirmButtonText: '通过',
        cancelButtonText: '不通过',
        type: 'warning',
        closeOnClickModal: false, // ç¦æ­¢ç‚¹å‡»é®ç½©å±‚关闭
        distinguishCancelAndClose: true,
        beforeClose: (action, instance, done) => {
          if (action === 'confirm') {
            // ç‚¹å‡»â€œç¡®å®šâ€æŒ‰é’®ï¼Œå…è®¸å…³é—­
            checkManageDocumentCancel({ id: row.id, state: '通过' }).then(res => {
              this.refreshTable()
              done();
              this.$message({
                type: 'success',
                message: '提交成功'
              })
            })
              .catch(err => {
              })
          } else if (action === 'cancel') {
            // ç‚¹å‡»â€œå–消”按钮,不允许关闭
            checkManageDocumentCancel({ id: row.id, state: '不通过' }).then(res => {
              this.refreshTable()
              done();
              this.$message({
                type: 'success',
                message: '提交成功'
              })
            })
              .catch(err => {
              })
          } else if (action === 'close') {
            // ç‚¹å‡»â€œÃ—”按钮,不允许关闭
            done();
            console.log("×按钮点击事件,不关闭弹框");
          }
        }
      })
    },
    // å¯¼å‡º
    handleOut() {
      this.outLoading = true
      exportManageDocumentCancel(this.queryParams).then(res => {
        this.outLoading = false
        const blob = new Blob([res], { type: 'application/octet-stream' });
        this.$download.saveAs(blob, '文件作废表.xlsx')
      })
    },
    handleDelete(row) {
      this.$confirm("是否删除该条数据?", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      })
        .then(() => {
          delManageDocumentCancel({ id: row.id }).then((res) => {
            if (res.code == 201) return;
            this.$message.success("删除成功");
            this.refresh();
          });
        })
        .catch(() => { });
    },
  }
}
</script>
<style scoped>
.title {
  height: 60px;
  line-height: 60px;
}
.search {
  background-color: #fff;
  height: 40px;
  display: flex;
  align-items: center;
  position: relative;
}
.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 {
  background-color: #fff;
  height: calc(100% - 60px - 80px);
  padding: 20px;
}
.btns {
  position: absolute;
  right: 20px;
  top: 5px;
}
</style>
src/views/CNAS/systemManagement/documentControl/index.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,67 @@
<template>
  <div class="file-handling">
    <el-tabs type="border-card" v-model="activeName" style="height: 100%;">
      <el-tab-pane :label="item.name" :name="item.component" v-for="(item, index) in tabList" :key="index"
        style="height: 100%;">
        <component :is="item.component" :key="item.component"></component>
      </el-tab-pane>
    </el-tabs>
  </div>
</template>
<script>
import FileList from './components/FileList.vue'
import ControlledFileApplication from './components/ControlledFileApplication.vue'
import DistributionCollectionRecord from './components/DistributionCollectionRecord.vue'
import FileChangeRequest from './components/FileChangeRequest.vue'
import FileObsoletionRequest from './components/FileObsoletionRequest.vue'
export default {
  components: {
    FileList,
    ControlledFileApplication,
    DistributionCollectionRecord,
    FileChangeRequest,
    FileObsoletionRequest
  },
  data() {
    return {
      tabList: [
        {
          name: '文件清单',
          component: 'FileList'
        },
        {
          name: '文件受控申请',
          component: 'ControlledFileApplication'
        },
        {
          name: '发放回收记录',
          component: 'DistributionCollectionRecord'
        },
        {
          name: '文件变更申请',
          component: 'FileChangeRequest'
        },
        {
          name: '文件作废申请',
          component: 'FileObsoletionRequest'
        },
      ],
      activeName: 'FileList'
    };
  },
}
</script>
<style scoped>
.file-handling {
  margin-top: 10px;
  height: calc(100% - 20px);
}
>>>.el-tabs__content {
  height: 100%;
  padding: 0;
  padding-top: 10px;
}
</style>
src/views/CNAS/systemManagement/documentRecords/approvalRecord.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,513 @@
<template>
  <!-- æ–‡ä»¶å®¡æ‰¹è®°å½• -->
  <div class="DocumentApprovalRecords">
    <div class="search">
      <div class="search_thing">
        <div class="search_label">文件名称:</div>
        <div class="search_input"><el-input size="small" placeholder="请输入" clearable v-model="queryParams.documentName"
            @keyup.enter.native="refreshTable()"></el-input></div>
      </div>
      <div class="search_thing">
        <div class="search_label">文件编号:</div>
        <div class="search_input">
          <el-input size="small" placeholder="请输入" clearable v-model="queryParams.documentCode"
            @keyup.enter.native="refreshTable()"></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="refreshTable()">查 è¯¢</el-button>
      </div>
      <div class="btn">
        <el-button size="small" type="primary" @click="openAdd('新增')">新增</el-button>
        <el-upload :action="action" :multiple="false" :show-file-list="false" accept='.doc,.docx'
          :headers="uploadHeader" :on-change="beforeUpload" :on-error="onError" ref='upload'
          :on-success="handleSuccessUp" style="display:inline-block;margin-left: 20px;">
          <el-button type="primary" size="small">导入</el-button></el-upload>
        <el-button size="small" type="primary" @click="handleDown" :loading="outLoading"
          style="display:inline-block;margin-left: 20px;">导出</el-button>
      </div>
    </div>
    <div class="table">
      <lims-table :tableData="tableData" :column="column" :page="page" :tableLoading="tableLoading"
        :height="'calc(100vh - 290px)'" @pagination="pagination"></lims-table>
    </div>
    <!-- æ–°å¢ž/编辑 -->
    <el-dialog :title="title" :visible.sync="addDia" width="500px">
      <el-form :model="addForm" ref="addForm" :rules="addRules" label-position="right" label-width="120px">
        <el-form-item label="文件名称" prop="documentName">
          <el-input size="small" placeholder="请输入" clearable v-model="addForm.documentName"></el-input>
        </el-form-item>
        <el-form-item label="文件编号" prop="documentCode">
          <el-input size="small" placeholder="请输入" clearable v-model="addForm.documentCode">
          </el-input>
        </el-form-item>
        <el-form-item label="版/次" prop="documentVersion">
          <el-input size="small" placeholder="请输入" clearable v-model="addForm.documentVersion">
          </el-input>
        </el-form-item>
        <el-form-item label="编制" prop="writeUser">
          <el-select v-model="addForm.writeUser" size="small" clearable placeholder="请选择" style="width: 100%">
            <el-option v-for="item in personList" :key="item.value" :label="item.label" :value="item.value">
            </el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="审核" prop="checkUser">
          <el-select v-model="addForm.checkUser" size="small" clearable placeholder="请选择" style="width: 100%">
            <el-option v-for="item in personList" :key="item.value" :label="item.label" :value="item.value">
            </el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="批准" prop="ratifyUser">
          <el-select v-model="addForm.ratifyUser" size="small" clearable placeholder="请选择" style="width: 100%">
            <el-option v-for="item in personList" :key="item.value" :label="item.label" :value="item.value">
            </el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="批准日期" prop="ratifyDate">
          <el-date-picker v-model="addForm.ratifyDate" style="width: 100%" value-format="yyyy-MM-dd" ormat="yyyy-MM-dd"
            type="date" size="small"></el-date-picker>
        </el-form-item>
        <el-form-item label="备注" prop="remark">
          <el-input size="small" placeholder="请输入" type="textarea" :rows="2" clearable v-model="addForm.remarks">
          </el-input>
        </el-form-item>
      </el-form>
      <span slot="footer" class="dialog-footer">
        <el-button @click="addDia = false">取 æ¶ˆ</el-button>
        <el-button :loading="uploading" type="primary" @click="submitProduct('addForm')">ç¡® è®¤</el-button>
      </span>
    </el-dialog>
  </div>
</template>
<script>
import limsTable from "@/components/Table/lims-table.vue";
import {
  selectUserCondition,
} from "@/api/system/user.js";
import {
  addManageRecordCheck,
  doManageRecordCheck,
  exportOutManageRecordCheck,
  checkManageRecordCheck,
  ratifyManageRecordCheck,
  delManageRecordCheck,
  pageManageRecordCheck
} from '@/api/cnas/systemManagement/documentRecords.js'
export default {
  components: {
    limsTable
  },
  data() {
    return {
      addPower: true,
      outPower: true,
      upPower: true,
      outLoading: false,
      personList: [],
      queryParams: {},
      tableData: [],
      column: [
        { label: "文件名称", prop: "documentName" },
        { label: "文件编号", prop: "documentCode", width: "120px" },
        {
          label: "版/次",
          prop: "documentVersion",
        },
        { label: "编制", prop: "writeUser" },
        { label: "审核", prop: "checkUser" },
        { label: "批准", prop: "ratifyUser" },
        { label: "批准日期", prop: "ratifyDate" },
        { label: "备注", prop: "remark" },
        {
          dataType: "action",
          fixed: "right",
          label: "操作",
          operation: [
            {
              name: "编辑",
              type: "text",
              clickFun: (row) => {
                this.openAdd("编辑", row);
              },
              disabled: (row) => {
                return row.checkState == '通过' || row.ratifyState == '通过'
              },
            },
            {
              name: "审核",
              type: "text",
              clickFun: (row) => {
                this.handleCheck(row);
              },
              disabled: (row) => {
                return row.checkState == '通过' || row.ratifyState == '通过'
              },
            },
            {
              name: "批准",
              type: "text",
              clickFun: (row) => {
                this.handleApproval(row);
              },
              disabled: (row) => {
                return row.ratifyState == '通过'
              },
            },
            {
              name: "删除",
              type: "text",
              clickFun: (row) => {
                this.handleDelete(row);
              },
              disabled: (row) => {
                return row.checkState == '通过' || row.ratifyState == '通过'
              },
            },
          ],
        },
      ],
      page: {
        total: 0,
        size: 10,
        current: 0,
      },
      tableLoading: false,
      title: "新增",
      addDia: false,
      addForm: {},
      addRules: {
        documentName: [{ required: true, message: "请输入文件名称", trigger: "blur" }],
      },
      uploading: false,
    }
  },
  // ç”¨äºŽä¸Šä¼ æ–‡ä»¶çš„信息
  computed: {
    action() {
      return this.javaApi + '/manageRecordCheck/exportInManageRecordCheck'
    }
  },
  mounted() {
    this.getAuthorizedPerson()
  },
  methods: {
    getPower() {
      let power = JSON.parse(sessionStorage.getItem('power'))
      let add = false
      let del = false
      let up = false;
      let out = false;
      let check = false
      let ratify = false
      for (var i = 0; i < power.length; i++) {
        if (power[i].menuMethod == 'addManageRecordCheck') {
          add = true
        }
        if (power[i].menuMethod == 'delManageRecordCheck') {
          del = true
        }
        if (power[i].menuMethod == 'exportInManageRecordCheck') {
          up = true
        }
        if (power[i].menuMethod == 'checkManageRecordCheck') {
          check = true
        }
        if (power[i].menuMethod == 'ratifyManageRecordCheck') {
          ratify = true
        }
        if (power[i].menuMethod == 'exportOutManageRecordCheck') {
          out = true
        }
      }
      if (!ratify) {
        this.componentData.do.splice(3, 1)
      }
      if (!check) {
        this.componentData.do.splice(2, 1)
      }
      if (!add) {
        this.componentData.do.splice(1, 1)
      }
      if (!del) {
        this.componentData.do.splice(0, 1)
      }
      this.addPower = add
      this.outPower = out
      this.upPower = up
    },
    getList() {
      this.tableLoading = true;
      let param = { ...this.queryParams, ...this.page };
      delete param.total;
      pageManageRecordCheck({ ...param })
        .then((res) => {
          this.tableLoading = false;
          if (res.code === 200) {
            this.tableData = res.data.records;
            this.page.total = res.data.total;
          }
        })
        .catch((err) => {
          this.tableLoading = false;
        });
    },
    pagination({ page, limit }) {
      this.page.current = page;
      this.page.size = limit;
      this.getList();
    },
    refresh() {
      this.queryParams = {};
      this.page.current = 1;
      this.getList();
    },
    refreshTable() {
      this.page.current = 1;
      this.getList();
    },
    // æ–°å¢ž/编辑
    openAdd(title, row) {
      this.title = title
      if (row) {
        this.addForm = row
      } else {
        this.addForm = {}
      }
      this.addDia = true;
    },
    // å¯¼å‡º
    handleDown() {
      this.outLoading = true
      // queryParams
      exportOutManageRecordCheck(this.queryParams).then(res => {
        this.outLoading = false
        if (res.code == 201) return this.$message.error('导出失败')
        let url = this.javaApi + '/word/' + res.message
        this.$download.saveAs(url, '文件审批记录')
      })
    },
    getAuthorizedPerson() {
      selectUserCondition().then(res => {
        let data = []
        res.data.forEach(a => {
          data.push({
            label: a.name,
            value: a.id
          })
        })
        this.personList = data
        this.refreshTable()()
      })
    },
    // å®¡æ ¸
    handleCheck(row) {
      this.$confirm('是否审核通过?', '提示', {
        confirmButtonText: '通过',
        cancelButtonText: '不通过',
        type: 'warning',
        closeOnClickModal: false, // ç¦æ­¢ç‚¹å‡»é®ç½©å±‚关闭
        distinguishCancelAndClose: true,
        beforeClose: (action, instance, done) => {
          if (action === 'confirm') {
            // ç‚¹å‡»â€œç¡®å®šâ€æŒ‰é’®ï¼Œå…è®¸å…³é—­
            checkManageRecordCheck({ id: row.id, checkState: '通过' }).then(res => {
              if (res.code === 201) return
              this.refreshTable()
              done();
              this.$message({
                type: 'success',
                message: '提交成功'
              })
            })
              .catch(err => {
              })
          } else if (action === 'cancel') {
            // ç‚¹å‡»â€œå–消”按钮,不允许关闭
            checkManageRecordCheck({ id: row.id, checkState: '不通过' }).then(res => {
              if (res.code === 201) return
              this.refreshTable()
              done();
              this.$message({
                type: 'success',
                message: '提交成功'
              })
            })
              .catch(err => {
              })
            console.log("取消按钮点击事件,不关闭弹框");
          } else if (action === 'close') {
            // ç‚¹å‡»â€œÃ—”按钮,不允许关闭
            done();
            console.log("×按钮点击事件,不关闭弹框");
          }
        }
      })
    },
    // æ‰¹å‡†
    handleApproval(row) {
      this.$confirm('是否批准通过?', '提示', {
        confirmButtonText: '通过',
        cancelButtonText: '不通过',
        type: 'warning',
        closeOnClickModal: false, // ç¦æ­¢ç‚¹å‡»é®ç½©å±‚关闭
        distinguishCancelAndClose: true,
        beforeClose: (action, instance, done) => {
          if (action === 'confirm') {
            // ç‚¹å‡»â€œç¡®å®šâ€æŒ‰é’®ï¼Œå…è®¸å…³é—­
            ratifyManageRecordCheck({ id: row.id, ratifyState: '通过' }).then(res => {
              if (res.code === 201) return
              this.refreshTable()
              done();
              this.$message({
                type: 'success',
                message: '提交成功'
              })
            })
              .catch(err => {
              })
          } else if (action === 'cancel') {
            // ç‚¹å‡»â€œå–消”按钮,不允许关闭
            ratifyManageRecordCheck({ id: row.id, ratifyState: '不通过' }).then(res => {
              if (res.code === 201) return
              this.refreshTable()
              done();
              this.$message({
                type: 'success',
                message: '提交成功'
              })
            })
              .catch(err => {
              })
          } else if (action === 'close') {
            // ç‚¹å‡»â€œÃ—”按钮,不允许关闭
            done();
            console.log("×按钮点击事件,不关闭弹框");
          }
        }
      })
    },
    beforeUpload(file) {
      if (file.size > 1024 * 1024 * 10) {
        this.$message.error('上传文件不超过10M');
        this.$refs.upload.clearFiles()
        return false;
      } else {
        // this.upLoading = true;
        return true;
      }
    },
    onError(err, file, fileList) {
      this.$message.error('上传失败')
      this.$refs.upload.clearFiles()
    },
    handleSuccessUp(response) {
      this.upLoading = false;
      if (response.code == 200) {
        this.$message.success('上传成功');
        this.refreshTable()()
      } else {
        this.$message.error('上传失败');
      }
    },
    // æ–°å¢ž/修改
    submitProduct(formName) {
      this.$refs[formName].validate((valid) => {
        if (valid) {
          this.uploading = true;
          if (this.title == "新增") {
            addManageRecordCheck(this.addForm)
              .then((res) => {
                this.uploading = false;
                if (res.code != 200) {
                  return;
                }
                this.$message.success("提交成功");
                this.refresh();
                this.addDia = false;
              })
              .catch((err) => {
                this.uploading = false;
              });
          } else {
            doManageRecordCheck(this.addForm)
              .then((res) => {
                this.uploading = false;
                if (res.code != 200) {
                  return;
                }
                this.$message.success("提交成功");
                this.refresh();
                this.addDia = false;
              })
              .catch((err) => {
                this.uploading = false;
              });
          }
        } else {
          return false;
        }
      });
    },
    handleDelete(row) {
      this.$confirm("是否删除该条数据?", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      })
        .then(() => {
          delManageRecordCheck({ id: row.id }).then((res) => {
            if (res.code == 201) return;
            this.$message.success("删除成功");
            this.refresh();
          });
        })
        .catch(() => { });
    },
  }
}
</script>
<style scoped>
.search {
  background-color: #fff;
  height: 80px;
  display: flex;
  align-items: center;
  position: relative;
}
.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);
}
.btn {
  position: absolute;
  right: 16px;
  top: 20px;
}
.table {
  margin-top: 10px;
  background-color: #fff;
  height: calc(100% - 60px - 80px - 10px - 40px);
  padding: 20px;
}
</style>
src/views/CNAS/systemManagement/documentRecords/cancellationRecord.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,478 @@
<template>
  <!-- ä½œåºŸæ–‡ä»¶é”€æ¯è®°å½• -->
  <div class="ObsoleteDocumentDestructionRecords">
    <div class="search">
      <div class="search_thing">
        <div class="search_label">文件名称:</div>
        <div class="search_input"><el-input size="small" placeholder="请输入" clearable v-model="queryParams.documentName"
            @keyup.enter.native="refreshTable()"></el-input></div>
      </div>
      <div class="search_thing">
        <div class="search_label">文件编号:</div>
        <div class="search_input">
          <el-input size="small" placeholder="请输入" clearable v-model="queryParams.documentCode"
            @keyup.enter.native="refreshTable()"></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="refreshTable()">查 è¯¢</el-button>
      </div>
      <div class="btn">
        <el-button size="small" type="primary" @click="openAdd">新增</el-button>
        <el-upload :action="action" :multiple="false" :show-file-list="false" accept='.doc,.docx'
          :headers="uploadHeader" :on-change="beforeUpload" :on-error="onError" ref='upload'
          :on-success="handleSuccessUp" style="display:inline-block;margin-left: 20px;">
          <el-button type="primary" size="small">导入</el-button></el-upload>
        <el-button size="small" type="primary" @click="handleDown" :loading="outLoading"
          style="display:inline-block;margin-left: 20px;">导出</el-button>
      </div>
    </div>
    <div class="table">
      <lims-table :tableData="tableData" :column="column" :page="page" :tableLoading="tableLoading"
        :height="'calc(100vh - 260px)'" @pagination="pagination"></lims-table>
    </div>
    <el-dialog :title="title" :visible.sync="addDialogVisible" width="400px" top="6vh">
      <el-row>
        <el-col :span="24" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label"><span style="color: red;margin-left: 4px;">* </span>文件编号:</div>
            <div class="search_input">
              <el-select v-model="addInfo.documentCode" size="small" style="width: 100%;" @change="getCurrentFile"
                allow-create clearable filterable>
                <el-option v-for="item in fileList" :key="item.documentCode" :label="item.title"
                  :value="item.documentCode">
                </el-option>
              </el-select>
            </div>
          </div>
        </el-col>
        <el-col :span="24" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">文件名称:</div>
            <div class="search_input"><el-input size="small" placeholder="请输入" clearable
                v-model="addInfo.documentName"></el-input></div>
          </div>
        </el-col>
        <el-col :span="24" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">数量:</div>
            <div class="search_input"><el-input size="small" placeholder="请输入" clearable
                v-model="addInfo.qty"></el-input></div>
          </div>
        </el-col>
        <el-col :span="24" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">销毁原因:</div>
            <div class="search_input"><el-input size="small" placeholder="请输入" clearable
                v-model="addInfo.reason"></el-input></div>
          </div>
        </el-col>
        <el-col :span="24" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">备注:</div>
            <div class="search_input"><el-input size="small" placeholder="请输入" clearable v-model="addInfo.remark"
                type="textarea" :rows="2"></el-input></div>
          </div>
        </el-col>
      </el-row>
      <span slot="footer" class="dialog-footer">
        <el-button @click="addDialogVisible = false">取 æ¶ˆ</el-button>
        <el-button type="primary" @click="handleAdd" :loading="addLoading">ç¡® å®š</el-button>
      </span>
    </el-dialog>
  </div>
</template>
<script>
import limsTable from "@/components/Table/lims-table.vue";
import {
  selectUserCondition,
} from "@/api/system/user.js";
import {
  exportOutManageRecordCancel,
  addManageRecordCancel,
  doManageRecordCancel,
  ratifyManageRecordCancel,
  delManageRecordCancel,
  pageManageRecordCancel
} from '@/api/cnas/systemManagement/documentRecords.js'
import {
  pageManageDocumentList,
} from '@/api/cnas/systemManagement/documentControl.js'
export default {
  components: {
    limsTable
  },
  data() {
    return {
      addPower: true,
      outPower: true,
      upPower: true,
      outLoading: false,
      addLoading: false,
      addInfo: {},
      title: '新增',
      addInfo: {},
      addDialogVisible: false,
      fileList: [],
      personList: [],
      queryParams: {},
      tableData: [],
      column: [
        { label: "文件编号", prop: "documentCode" },
        { label: "文件名称", prop: "documentName", width: "120px" },
        {
          label: "数量",
          prop: "qty",
        },
        { label: "销毁原因", prop: "reason" },
        { label: "申请人", prop: "createUserName" },
        { label: "申请日期", prop: "createTime" },
        { label: "批准人", prop: "ratifyUserName" },
        { label: "批准日期", prop: "ratifyTime" },
        { label: "备注", prop: "remark" },
        {
          dataType: "action",
          fixed: "right",
          label: "操作",
          operation: [
            {
              name: "编辑",
              type: "text",
              clickFun: (row) => {
                this.handleEdit0(row);
              },
              disabled: (row) => {
                return row.ratifyState == '通过'
              },
            },
            {
              name: "批准",
              type: "text",
              clickFun: (row) => {
                this.handleRatify(row);
              },
              disabled: (row) => {
                return row.ratifyState == '通过'
              },
            },
            {
              name: "删除",
              type: "text",
              clickFun: (row) => {
                this.handleDelete(row);
              },
              disabled: (row) => {
                return row.ratifyState == '通过'
              },
            },
          ],
        },
      ],
      page: {
        total: 0,
        size: 10,
        current: 0,
      },
      tableLoading: false,
    }
  },
  // ç”¨äºŽä¸Šä¼ æ–‡ä»¶çš„信息
  computed: {
    action() {
      return this.javaApi + '/manageRecordCancel/exportInManageRecordCancel'
    }
  },
  mounted() {
    // this.entityCopy = this.HaveJson(this.componentData.entity);
    this.getList()
    this.getAuthorizedPerson()
    this.getFileList()
  },
  methods: {
    getPower() {
      let power = JSON.parse(sessionStorage.getItem('power'))
      let add = false
      let del = false
      let up = false;
      let out = false;
      let ratify = false
      for (var i = 0; i < power.length; i++) {
        if (power[i].menuMethod == 'addManageRecordCancel') {
          add = true
        }
        if (power[i].menuMethod == 'delManageRecordCancel') {
          del = true
        }
        if (power[i].menuMethod == 'exportInManageRecordCancel') {
          up = true
        }
        if (power[i].menuMethod == 'ratifyManageRecordCancel') {
          ratify = true
        }
        if (power[i].menuMethod == 'exportOutManageRecordCancel') {
          out = true
        }
      }
      if (!ratify) {
        this.componentData.do.splice(2, 1)
      }
      if (!add) {
        this.componentData.do.splice(1, 1)
      }
      if (!del) {
        this.componentData.do.splice(0, 1)
      }
      this.addPower = add
      this.outPower = out
      this.upPower = up
    },
    openAdd() {
      this.addInfo = {}
      this.title = '新增'
      this.addDialogVisible = true;
    },
    handleEdit0(row) {
      this.addInfo = row
      this.title = '修改'
      this.addDialogVisible = true;
    },
    // å¯¼å‡º
    handleDown() {
      this.outLoading = true
      exportOutManageRecordCancel(this.queryParams).then(res => {
        this.outLoading = false
        if (res.code == 201) return this.$message.error('导出失败')
        let url = this.javaApi + '/word/' + res.data
        this.$download.saveAs(url, "作废文件销毁记录");
      })
    },
    getList() {
      this.tableLoading = true;
      let param = { ...this.queryParams, ...this.page };
      delete param.total;
      pageManageRecordCancel({ ...param })
        .then((res) => {
          this.tableLoading = false;
          if (res.code === 200) {
            this.tableData = res.data.records;
            this.page.total = res.data.total;
          }
        })
        .catch((err) => {
          this.tableLoading = false;
        });
    },
    pagination({ page, limit }) {
      this.page.current = page;
      this.page.size = limit;
      this.getList();
    },
    refresh() {
      this.queryParams = {};
      this.page.current = 1;
      this.getList();
    },
    refreshTable() {
      this.page.current = 1;
      this.getList();
    },
    beforeUpload(file) {
      if (file.size > 1024 * 1024 * 10) {
        this.$message.error('上传文件不超过10M');
        this.$refs.upload.clearFiles()
        return false;
      } else {
        // this.upLoading = true;
        return true;
      }
    },
    onError(err, file, fileList) {
      this.$message.error('上传失败')
      this.$refs.upload.clearFiles()
    },
    handleSuccessUp(response) {
      this.upLoading = false;
      if (response.code == 200) {
        this.$message.success('上传成功');
        this.refreshTable()()
      } else {
        this.$message.error('上传失败');
      }
    },
    // èŽ·å–æ–‡ä»¶åˆ—è¡¨--文件清单
    getFileList() {
      pageManageDocumentList({
        current: -1,
        size: -1
      }).then(res => {
        this.fileList = res.data.records.map(m => {
          m.title = m.documentCode
          return m
        })
      }).catch(err => { })
    },
    handleAdd() {
      if (!this.addInfo.documentCode) return this.$message.error('请输入文件编号')
      this.addLoading = true
      let obj = {}
      if (this.title == '新增') {
        obj = this.HaveJson(this.addInfo)
      } else {
        let { id, documentCode, documentName, qty, reason, remark } = this.addInfo
        obj = { id, documentCode, documentName, qty, reason, remark }
      }
      if (this.title == '新增') {
        addManageRecordCancel(obj).then(res => {
          this.addLoading = false
          if (res.code == 201) {
            return
          }
          this.addDialogVisible = false
          this.$message({
            type: 'success',
            message: '操作成功!'
          });
          this.refreshTable()
        }).catch(err => { })
      } else {
        doManageRecordCancel(obj).then(res => {
          this.addLoading = false
          if (res.code == 201) {
            return
          }
          this.addDialogVisible = false
          this.$message({
            type: 'success',
            message: '操作成功!'
          });
          this.refreshTable()
        }).catch(err => { })
      }
    },
    getCurrentFile(e) {
      let obj = this.fileList.find(m => m.documentCode == e)
      if (obj) {
        this.$set(this.addInfo, 'documentName', obj.name)
      }
    },
    getAuthorizedPerson() {
      selectUserCondition().then(res => {
        let data = []
        res.data.forEach(a => {
          data.push({
            label: a.name,
            value: a.id
          })
        })
        this.personList = data
      })
    },
    handleRatify(row) {
      this.$confirm('是否批准通过?', '提示', {
        confirmButtonText: '通过',
        cancelButtonText: '不通过',
        type: 'warning',
        closeOnClickModal: false, // ç¦æ­¢ç‚¹å‡»é®ç½©å±‚关闭
        distinguishCancelAndClose: true,
        beforeClose: (action, instance, done) => {
          if (action === 'confirm') {
            // ç‚¹å‡»â€œç¡®å®šâ€æŒ‰é’®ï¼Œå…è®¸å…³é—­
            ratifyManageRecordCancel({ id: row.id, ratifyState: '通过' }).then(res => {
              if (res.code === 201) return
              this.refreshTable()
              done();
              this.$message({
                type: 'success',
                message: '提交成功'
              })
            })
              .catch(err => {
              })
          } else if (action === 'cancel') {
            // ç‚¹å‡»â€œå–消”按钮,不允许关闭
            ratifyManageRecordCancel({ id: row.id, ratifyState: '不通过' }).then(res => {
              if (res.code === 201) return
              this.refreshTable()
              done();
              this.$message({
                type: 'success',
                message: '提交成功'
              })
            })
              .catch(err => {
              })
            console.log("取消按钮点击事件,不关闭弹框");
          } else if (action === 'close') {
            // ç‚¹å‡»â€œÃ—”按钮,不允许关闭
            done();
            console.log("×按钮点击事件,不关闭弹框");
          }
        }
      })
    },
    handleDelete(row) {
      this.$confirm("是否删除该条数据?", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      })
        .then(() => {
          delManageRecordCancel({ id: row.id }).then((res) => {
            if (res.code == 201) return;
            this.$message.success("删除成功");
            this.refresh();
          });
        })
        .catch(() => { });
    },
  }
}
</script>
<style scoped>
.title {
  height: 60px;
  line-height: 60px;
}
.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;
  height: calc(100% - 60px - 80px - 10px - 40px);
  padding: 20px;
  padding-top: 0;
}
.btn {
  position: absolute;
  right: 20px;
  top: 16px;
}
</style>
src/views/CNAS/systemManagement/documentRecords/distributionCollectionRecord.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,522 @@
<template>
  <!-- æ‰€æœ‰æ–‡ä»¶ï¼ˆå†…、外部文件)的发放与回收记录 -->
  <div class="DistributionRetrievalRecordsAllDocuments">
    <div class="search">
      <div class="search_thing">
        <div class="search_label">文件名称:</div>
        <div class="search_input"><el-input size="small" placeholder="请输入" clearable v-model="queryParams.documentName"
            @keyup.enter.native="refreshTable()"></el-input></div>
      </div>
      <div class="search_thing">
        <div class="search_label">文件编号:</div>
        <div class="search_input">
          <el-input size="small" placeholder="请输入" clearable v-model="queryParams.documentCode"
            @keyup.enter.native="refreshTable()"></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="refreshTable()">查 è¯¢</el-button>
      </div>
      <div class="btn">
        <el-button size="small" type="primary" @click="openAdd">新增</el-button>
        <el-upload :action="action" :multiple="false" :show-file-list="false" accept='.doc,.docx'
          :headers="uploadHeader" :on-change="beforeUpload" :on-error="onError" ref='upload'
          :on-success="handleSuccessUp" style="display:inline-block;margin-left: 20px;">
          <el-button type="primary" size="small">导入</el-button></el-upload>
        <el-button size="small" type="primary" @click="handleDown" :loading="outLoading"
          style="display:inline-block;margin-left: 20px;">导出</el-button>
      </div>
    </div>
    <div class="table">
      <lims-table :tableData="tableData" :column="column" :page="page" :tableLoading="tableLoading"
        :height="'calc(100vh - 260px)'" @pagination="pagination"></lims-table>
    </div>
    <el-dialog :title="title" :visible.sync="addDialogVisible" width="400px" top="6vh">
      <el-row>
        <el-col :span="24" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label"><span style="color: red;margin-left: 4px;">* </span>文件编号:</div>
            <div class="search_input">
              <el-select v-model="addInfo.documentCode" size="small" style="width: 100%;" @change="getCurrentFile"
                allow-create clearable filterable>
                <el-option v-for="item in fileList" :key="item.documentCode" :label="item.title"
                  :value="item.documentCode">
                </el-option>
              </el-select>
            </div>
          </div>
        </el-col>
        <el-col :span="24" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">文件名称:</div>
            <div class="search_input"><el-input size="small" placeholder="请输入" clearable
                v-model="addInfo.documentName"></el-input></div>
          </div>
        </el-col>
        <el-col :span="24" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">版号:</div>
            <div class="search_input"><el-input size="small" placeholder="请输入" clearable
                v-model="addInfo.documentVersion"></el-input></div>
          </div>
        </el-col>
        <el-col :span="24" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">份数:</div>
            <div class="search_input"><el-input size="small" placeholder="请输入" clearable
                v-model="addInfo.pages"></el-input></div>
          </div>
        </el-col>
        <el-col :span="24" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">文件类别:</div>
            <div class="search_input">
              <el-select v-model="addInfo.documentType" placeholder="请选择" size="small" style="width: 100%;">
                <el-option v-for="item in fileType" :key="item.value" :label="item.label" :value="item.value">
                </el-option>
              </el-select>
            </div>
          </div>
        </el-col>
        <el-col :span="24" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">分发号:</div>
            <div class="search_input"><el-input size="small" placeholder="请输入" clearable
                v-model="addInfo.number"></el-input></div>
          </div>
        </el-col>
        <el-col :span="24" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">接受人:</div>
            <div class="search_input">
              <el-select v-model="addInfo.receiveUser" placeholder="请选择" size="small" style="width: 100%;"
                filterable="">
                <el-option v-for="item in personList" :key="item.value" :label="item.label" :value="item.value">
                </el-option>
              </el-select>
            </div>
          </div>
        </el-col>
        <el-col :span="24" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">接收部门:</div>
            <div class="search_input">
              <el-select v-model="addInfo.departLims" placeholder="请选择" size="small" style="width: 100%;">
                <el-option v-for="item in list" :key="item.name" :label="item.name" :value="item.name">
                </el-option>
              </el-select>
            </div>
          </div>
        </el-col>
        <el-col :span="24" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">接受日期:</div>
            <div class="search_input">
              <el-date-picker v-model="addInfo.receiveDate" type="date" size="small" placeholder="选择日期"
                format="yyyy-MM-dd" value-format="yyyy-MM-dd" style="width: 100%;">
              </el-date-picker>
            </div>
          </div>
        </el-col>
      </el-row>
      <span slot="footer" class="dialog-footer">
        <el-button @click="addDialogVisible = false">取 æ¶ˆ</el-button>
        <el-button type="primary" @click="handleAdd" :loading="addLoading">ç¡® å®š</el-button>
      </span>
    </el-dialog>
  </div>
</template>
<script>
import limsTable from "@/components/Table/lims-table.vue";
import {
  getYearAndMonthAndDays
} from '@/utils/date'
import {
  selectUserCondition,
} from "@/api/system/user.js";
import {
  exportOutManageRecordIssueRecycle,
  doManageRecordIssueRecycle,
  addManageRecordIssueRecycle,
  selectCNSAPersonTree,
  pageManageRecordIssueRecycle,
  delManageRecordIssueRecycle,
} from '@/api/cnas/systemManagement/documentRecords.js'
import {
  pageManageDocumentList,
} from '@/api/cnas/systemManagement/documentControl.js'
import { mapGetters } from "vuex";
export default {
  components: {
    limsTable
  },
  data() {
    return {
      addPower: true,
      outPower: true,
      upPower: true,
      outLoading: false,
      addLoading: false,
      title: '新增',
      addDialogVisible: false,
      addInfo: {},
      personList: [],
      fileType: [],
      fileList: [],
      list: [],
      queryParams: {},
      tableData: [],
      column: [
        { label: "文件编号", prop: "documentCode" },
        { label: "文件名称", prop: "documentName", width: "120px" },
        {
          label: "版号",
          prop: "documentVersion",
        },
        { label: "份数", prop: "pages" },
        { label: "文件类别", prop: "documentType" },
        { label: "分发号", prop: "number" },
        { label: "接受人", prop: "receiveUserName" },
        { label: "接收部门", prop: "departLims" },
        { label: "接受日期", prop: "receiveDate" },
        { label: "签收人", prop: "signedUserName" },
        { label: "签收日期", prop: "signedDate" },
        {
          dataType: "action",
          fixed: "right",
          label: "操作",
          operation: [
            {
              name: "编辑",
              type: "text",
              clickFun: (row) => {
                this.handleEdit(row);
              },
              disabled: (row) => {
                return !!row.signedUser
              },
            },
            {
              name: "回收",
              type: "text",
              clickFun: (row) => {
                this.handleBack(row);
              },
              disabled: (row) => {
                return !!row.signedUser
              },
            },
            {
              name: "删除",
              type: "text",
              clickFun: (row) => {
                this.handleDelete(row);
              },
              disabled: (row) => {
                return !!row.signedUser
              },
            },
          ],
        },
      ],
      page: {
        total: 0,
        size: 10,
        current: 0,
      },
      tableLoading: false,
    }
  },
  // ç”¨äºŽä¸Šä¼ æ–‡ä»¶çš„信息
  computed: {
    action() {
      return this.javaApi + '/manageRecordIssueRecycle/exportInManageRecordIssueRecycle'
    },
    ...mapGetters(["userId"]),
  },
  mounted() {
    // this.entityCopy = this.HaveJson(this.componentData.entity);
    this.getList()
    this.getAuthorizedPerson()
    this.selectEnumByCategory()
    this.getFileList()
    // TODO éƒ¨é—¨æŽ¥å£éœ€è¦é‡å†™
    // this.selectTreeList()
  },
  methods: {
    getPower() {
      let power = JSON.parse(sessionStorage.getItem('power'))
      let add = false
      let del = false
      let up = false;
      let out = false;
      let edit = false
      for (var i = 0; i < power.length; i++) {
        if (power[i].menuMethod == 'addManageRecordIssueRecycle') {
          add = true
        }
        if (power[i].menuMethod == 'delManageRecordIssueRecycle') {
          del = true
        }
        if (power[i].menuMethod == 'exportInManageRecordIssueRecycle') {
          up = true
        }
        if (power[i].menuMethod == 'doManageRecordIssueRecycle') {
          edit = true
        }
        if (power[i].menuMethod == 'exportOutManageRecordIssueRecycle') {
          out = true
        }
      }
      if (!add) {
        this.componentData.do.splice(2, 1)
      }
      if (!add) {
        this.componentData.do.splice(1, 1)
      }
      if (!del) {
        this.componentData.do.splice(0, 1)
      }
      this.addPower = add
      this.outPower = out
      this.upPower = up
    },
    // æ–°å¢ž
    openAdd() {
      // this.$refs.ValueTable.openAddDia(this.$api.manageRecordIssueRecycle.addManageRecordIssueRecycle);
      this.addInfo = {}
      this.title = '新增'
      this.addDialogVisible = true;
    },
    handleEdit(row) {
      this.addInfo = row
      this.title = '编辑'
      this.addDialogVisible = true;
    },
    // å¯¼å‡º
    handleDown() {
      this.outLoading = true
      exportOutManageRecordIssueRecycle(this.queryParams).then(res => {
        this.outLoading = false
        if (res.code == 201) return this.$message.error('导出失败')
        let url = this.javaApi + '/word/' + res.data
        this.$download.saveAs(url, '文件发放与回收记录')
      })
    },
    getList() {
      this.tableLoading = true;
      let param = { ...this.queryParams, ...this.page };
      delete param.total;
      pageManageRecordIssueRecycle({ ...param })
        .then((res) => {
          this.tableLoading = false;
          if (res.code === 200) {
            this.tableData = res.data.records;
            this.page.total = res.data.total;
          }
        })
        .catch((err) => {
          this.tableLoading = false;
        });
    },
    pagination({ page, limit }) {
      this.page.current = page;
      this.page.size = limit;
      this.getList();
    },
    refresh() {
      this.queryParams = {};
      this.page.current = 1;
      this.getList();
    },
    refreshTable() {
      this.page.current = 1;
      this.getList();
    },
    getAuthorizedPerson() {
      selectUserCondition().then(res => {
        let data = []
        res.data.forEach(a => {
          data.push({
            label: a.name,
            value: a.id
          })
        })
        this.personList = data
      })
    },
    beforeUpload(file) {
      if (file.size > 1024 * 1024 * 10) {
        this.$message.error('上传文件不超过10M');
        this.$refs.upload.clearFiles()
        return false;
      } else {
        // this.upLoading = true;
        return true;
      }
    },
    onError(err, file, fileList) {
      this.$message.error('上传失败')
      this.$refs.upload.clearFiles()
    },
    handleSuccessUp(response) {
      this.upLoading = false;
      if (response.code == 200) {
        this.$message.success('上传成功');
        this.refreshTable()()
      } else {
        this.$message.error('上传失败');
      }
    },
    selectEnumByCategory() {
      // æ–‡ä»¶ç±»åˆ«
      this.getDicts("document_type").then((response) => {
        this.fileType = this.dictToValue(response.data);
      });
    },
    // èŽ·å–æ–‡ä»¶åˆ—è¡¨--文件清单
    getFileList() {
      pageManageDocumentList({
        current: -1,
        size: -1
      }).then(res => {
        this.fileList = res.data.records.map(m => {
          m.title = m.documentCode
          return m
        })
      }).catch(err => { })
    },
    getCurrentFile(e) {
      let obj = this.fileList.find(m => m.documentCode == e)
      if (obj) {
        this.$set(this.addInfo, 'documentName', obj.name)
        this.$set(this.addInfo, 'documentVersion', obj.version)
        this.$set(this.addInfo, 'documentType', obj.type)
      }
    },
    handleAdd() {
      if (!this.addInfo.documentCode) return this.$message.error('请输入文件编号')
      this.addLoading = true
      let obj = {}
      if (this.title == '新增') {
        obj = this.HaveJson(this.addInfo)
      } else {
        let { id, documentCode, documentName, documentVersion, pages, documentType, number, receiveUser, receiveDate, departLims } = this.addInfo
        obj = { id, documentCode, documentName, documentVersion, pages, documentType, number, receiveUser, receiveDate, departLims }
      }
      if (this.title == '新增') {
        addManageRecordIssueRecycle(obj).then(res => {
          this.addLoading = false
          if (res.code == 201) {
            return
          }
          this.addDialogVisible = false
          this.$message({
            type: 'success',
            message: '操作成功!'
          });
          this.refreshTable()
        }).catch(err => { })
      } else {
        doManageRecordIssueRecycle(obj).then(res => {
          this.addLoading = false
          if (res.code == 201) {
            return
          }
          this.addDialogVisible = false
          this.$message({
            type: 'success',
            message: '操作成功!'
          });
          this.refreshTable()
        }).catch(err => { })
      }
    },
    // å›žæ”¶
    handleBack(row) {
      this.$confirm('是否确认回收?', "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning"
      }).then(() => {
        let obj = {}
        let { id, documentCode, documentName, documentVersion, pages, documentType, number, receiveUser, receiveDate, departLims } = row
        obj = { id, documentCode, documentName, documentVersion, pages, documentType, number, receiveUser, receiveDate, departLims, signedDate: getYearAndMonthAndDays(), signedUser: this.userId }
        doManageRecordIssueRecycle(obj).then(res => {
          this.addLoading = false
          if (res.code == 201) {
            return
          }
          this.addDialogVisible = false
          this.$message({
            type: 'success',
            message: '操作成功!'
          });
          this.refreshTable()
        }).catch(err => { })
      }).catch(() => { })
    },
    // æŸ¥è¯¢æ ‘形列表
    selectTreeList() {
      selectCNSAPersonTree().then((res) => {
        this.list = res.data[0].children;
      });
    },
    handleDelete(row) {
      this.$confirm("是否删除该条数据?", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      })
        .then(() => {
          delManageRecordIssueRecycle({ id: row.id }).then((res) => {
            if (res.code == 201) return;
            this.$message.success("删除成功");
            this.refresh();
          });
        })
        .catch(() => { });
    },
  }
}
</script>
<style scoped>
.title {
  height: 60px;
  line-height: 60px;
}
.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;
  height: calc(100% - 60px - 80px - 10px - 40px);
  padding: 20px;
  padding-top: 0;
}
</style>
src/views/CNAS/systemManagement/documentRecords/outDocumenRecordt.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,540 @@
<template>
  <!-- å¤–来文件确认记录 -->
  <div class="ExternalDocumentConfirmationRecords">
    <el-tabs type="border-card" v-model="activeName" style="height: 100%;">
      <el-tab-pane label="填写" name="填写" style="height: 100%;">
        <div style="display: flex;align-items: center;justify-content: flex-end;margin-right: 20px;">
          <el-button size="small" type="primary" @click="openAdd('新增')" style="margin-left: 20px;">新增</el-button>
          <el-upload :action="action" :multiple="false" :show-file-list="false" accept='.doc,.docx'
            :headers="uploadHeader" :on-change="beforeUpload" :on-error="onError" ref='upload'
            :on-success="handleSuccessUp" style="display:inline-block;margin-left: 20px;">
            <el-button size="small" type="primary" :loading="upLoading">导入</el-button></el-upload>
        </div>
        <div class="table" style="height: calc(100% - 200px)">
          <!-- <ValueTable ref="ValueTable0" :url="$api.manageRecordTotal.pageManageRecordVerify"
            :componentData="componentData0" :key="upIndex0" :delUrl="$api.manageRecordTotal.delManageRecordVerify"
            :upUrl="$api.manageRecordTotal.doManageRecordVerify" /> -->
          <lims-table :tableData="tableData0" :column="column0" :page="page0" :tableLoading="tableLoading0"
            :height="'calc(100vh - 270px)'" @pagination="pagination0"></lims-table>
        </div>
      </el-tab-pane>
      <el-tab-pane label="历史记录" name="历史记录" style="height: 100%;">
        <div class="search">
          <div class="search_thing">
            <div class="search_label">年:</div>
            <div class="search_input">
              <el-date-picker v-model="queryParams.year" type="year" placeholder="选择年" format="yyyy" value-format="yyyy"
                size="small" @change="refreshTable()">
              </el-date-picker>
            </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="refreshTable()">查 è¯¢</el-button>
          </div>
        </div>
        <div class="table">
          <lims-table :tableData="tableData" :column="column" :page="page" :tableLoading="tableLoading"
            :height="'calc(100vh - 280px)'" @pagination="pagination"></lims-table>
        </div>
      </el-tab-pane>
    </el-tabs>
    <!-- è¯¦æƒ…/下载/审核 -->
    <el-dialog :title="title0" :visible.sync="lookDialogVisible" width="800px" :class="{ downPdf: title0 == '下载' }"
      :modal="title0 != '下载'" top="5vh">
      <filePreview v-if="lookDialogVisible" :fileUrl="javaApi + '/word/' + currentInfo.url" :currentFile="{}"
        style="max-height: 70vh;overflow-y: auto;" />
      <span slot="footer" class="dialog-footer" v-if="title0 == '审核' || title0 == '批准'">
        <el-button @click="submitCheck('不通过')" :loading="noCheckLoading">不通过</el-button>
        <el-button type="primary" @click="submitCheck('通过')" :loading="checkLoading">通 è¿‡</el-button>
      </span>
    </el-dialog>
    <!-- æ–°å¢ž/编辑 -->
    <el-dialog :title="title" :visible.sync="addDia" width="500px">
      <el-form :model="addForm" ref="addForm" :rules="addRules" label-position="right" label-width="120px">
        <el-form-item label="外来文件名称" prop="documentName">
          <el-input size="small" placeholder="请输入" clearable v-model="addForm.documentName"></el-input>
        </el-form-item>
        <el-form-item label="文件编号" prop="documentCode">
          <el-input size="small" placeholder="请输入" clearable v-model="addForm.documentCode">
          </el-input>
        </el-form-item>
        <el-form-item label="标准规范名称" prop="standardName">
          <el-input size="small" placeholder="请输入" clearable v-model="addForm.standardName">
          </el-input>
        </el-form-item>
        <el-form-item label="标准号" prop="standardCode">
          <el-input size="small" placeholder="请输入" clearable v-model="addForm.standardCode">
          </el-input>
        </el-form-item>
        <el-form-item label="生效日期" prop="effectiveDate">
          <el-date-picker v-model="addForm.effectiveDate" format="yyyy-MM-dd" placeholder="选择日期" size="small"
            style="width: 100%" type="date" value-format="yyyy-MM-dd">
          </el-date-picker>
        </el-form-item>
        <el-form-item label="作废日期" prop="cancelDate">
          <el-date-picker v-model="addForm.cancelDate" format="yyyy-MM-dd" placeholder="选择日期" size="small"
            style="width: 100%" type="date" value-format="yyyy-MM-dd">
          </el-date-picker>
        </el-form-item>
        <el-form-item label="备注" prop="note">
          <el-input size="small" placeholder="请输入" type="textarea" :rows="2" clearable v-model="addForm.note">
          </el-input>
        </el-form-item>
      </el-form>
      <span slot="footer" class="dialog-footer">
        <el-button @click="addDia = false">取 æ¶ˆ</el-button>
        <el-button :loading="uploading" type="primary" @click="submitProduct('addForm')">ç¡® è®¤</el-button>
      </span>
    </el-dialog>
  </div>
</template>
<script>
import limsTable from "@/components/Table/lims-table.vue";
import filePreview from '@/components/Preview/filePreview.vue'
import {
  addManageRecordVerify,
  pageManageRecordVerify,
  submitManageRecordTotal,
  ratifyManageRecordTotal,
  delManageRecordVerify,
  pageManageRecordTotal,
  doManageRecordVerify
} from '@/api/cnas/systemManagement/documentRecords.js'
export default {
  components: {
    filePreview,
    limsTable,
  },
  data() {
    return {
      title0: '查看',
      activeName: '填写',
      lookDialogVisible: false,
      noCheckLoading: false,
      checkLoading: false,
      addPower: true,
      upPower: true,
      currentInfo: {},
      upLoading: false,
      queryParams: {},
      tableData: [],
      column: [
        { label: "年份", prop: "year" },
        { label: "总数量", prop: "totalNum", width: "120px" },
        {
          label: "拟制人",
          prop: "submitUserName",
        },
        { label: "拟制日期", prop: "submitDate" },
        { label: "批准人", prop: "ratifyUserName" },
        { label: "批准日期", prop: "ratifyDate" },
        { label: "批准结果", prop: "ratifyState" },
        {
          dataType: "action",
          fixed: "right",
          label: "操作",
          operation: [
            {
              name: "查看",
              type: "text",
              clickFun: (row) => {
                this.handleLook(row);
              },
              disabled: (row) => {
                return !row.url
              },
            },
            {
              name: "下载",
              type: "text",
              clickFun: (row) => {
                this.handleDown0(row);
              },
              disabled: (row) => {
                return !row.url
              },
            },
            {
              name: "提交",
              type: "text",
              clickFun: (row) => {
                this.handleSubmit(row);
              },
              disabled: (row) => {
                return !!row.submitUserName
              },
            },
            {
              name: "批准",
              type: "text",
              clickFun: (handleApproval) => {
                this.handleSubmit(row);
              },
              disabled: (row) => {
                return !row.submitUserName || !!row.ratifyUserName
              },
            },
          ],
        },
      ],
      page: {
        total: 0,
        size: 10,
        current: 0,
      },
      tableLoading: false,
      tableData0: [],
      column0: [
        { label: "外来文件名称", prop: "documentName" },
        { label: "文件编号", prop: "documentCode", width: "120px" },
        {
          label: "标准规范名称",
          prop: "standardName",
        },
        { label: "标准号", prop: "standardCode" },
        { label: "生效日期", prop: "effectiveDate" },
        { label: "作废日期", prop: "cancelDate" },
        { label: "备注", prop: "note" },
        {
          dataType: "action",
          fixed: "right",
          label: "操作",
          operation: [
            {
              name: "编辑",
              type: "text",
              clickFun: (row) => {
                this.openAdd("编辑", row);
              },
            },
            {
              name: "删除",
              type: "text",
              clickFun: (row) => {
                this.handleDelete(row);
              },
            },
          ],
        },
      ],
      page0: {
        total: 0,
        size: 10,
        current: 0,
      },
      tableLoading0: false,
      title: '新增',
      addForm: {},
      addDia: false,
      addRules: {
        documentName: [{ required: true, message: "请输入外来文件名称", trigger: "blur" }],
        documentCode: [
          { required: true, message: "请输入文件编号", trigger: "blur" },
        ],
      },
      uploading: false,
    }
  },
  // ç”¨äºŽä¸Šä¼ æ–‡ä»¶çš„信息
  computed: {
    action() {
      return this.javaApi + '/manageRecordVerify/exportManageRecordVerify'
    }
  },
  mounted() {
    // this.entityCopy = this.HaveJson(this.componentData.entity);
    this.getList()
    this.getList0()
  },
  methods: {
    getPower() {
      let power = JSON.parse(sessionStorage.getItem('power'))
      let add = false
      let del = false
      let up = false;
      let sub = false
      let ratify = false
      for (var i = 0; i < power.length; i++) {
        if (power[i].menuMethod == 'addManageRecordVerify') {
          add = true
        }
        if (power[i].menuMethod == 'delManageRecordVerify') {
          del = true
        }
        if (power[i].menuMethod == 'exportManageRecordVerify') {
          up = true
        }
        if (power[i].menuMethod == 'submitManageRecordTotal') {
          sub = true
        }
        if (power[i].menuMethod == 'ratifyManageRecordTotal') {
          ratify = true
        }
      }
      if (!ratify) {
        this.componentData.do.splice(3, 1)
      }
      if (!sub) {
        this.componentData.do.splice(2, 1)
      }
      if (!del) {
        this.componentData0.do.splice(1, 1)
      }
      if (!add) {
        this.componentData0.do.splice(0, 1)
      }
      this.addPower = add
      this.upPower = up
    },
    openAdd(title, row) {
      this.title = title;
      if (row) {
        this.addForm = row;
      } else {
        this.addForm = {};
      }
      this.addDia = true;
    },
    getList() {
      this.tableLoading = true;
      let param = { ...this.queryParams, ...this.page };
      delete param.total;
      pageManageRecordTotal({ ...param })
        .then((res) => {
          this.tableLoading = false;
          if (res.code === 200) {
            this.tableData = res.data.records;
            this.page.total = res.data.total;
          }
        })
        .catch((err) => {
          this.tableLoading = false;
        });
    },
    pagination({ page, limit }) {
      this.page.current = page;
      this.page.size = limit;
      this.getList();
    },
    getList0() {
      this.tableLoading0 = true;
      let param = { ...this.page0 };
      delete param.total;
      pageManageRecordVerify({ ...param })
        .then((res) => {
          this.tableLoading0 = false;
          if (res.code === 200) {
            this.tableData0 = res.data.records;
            this.page0.total = res.data.total;
          }
        })
        .catch((err) => {
          this.tableLoading0 = false;
        });
    },
    pagination0({ page, limit }) {
      this.pag0.current = page;
      this.page0.size = limit;
      this.getList0();
    },
    refresh() {
      this.queryParams = {};
      this.page.current = 1;
      this.getList();
    },
    refreshTable() {
      this.page.current = 1;
      this.getList();
    },
    beforeUpload(file) {
      if (file.size > 1024 * 1024 * 10) {
        this.$message.error('上传文件不超过10M');
        this.$refs.upload.clearFiles()
        return false;
      } else {
        // this.upLoading = true;
        return true;
      }
    },
    onError(err, file, fileList) {
      this.$message.error('上传失败')
      this.$refs.upload.clearFiles()
    },
    handleSuccessUp(response) {
      this.upLoading = false;
      if (response.code == 200) {
        this.$message.success('上传成功');
        this.getList0();
      } else {
        this.$message.error('上传失败');
      }
    },
    submitCheck(type) { },
    // æŸ¥çœ‹
    handleLook(row) {
      this.title0 = '查看'
      this.commonFun(row)
    },
    // å…¬ç”¨æ–¹æ³•
    commonFun(row, callbanck) {
      this.currentInfo = row
      pageManageRecordVerify({
        current: -1,
        size: -1,
        manageRecordTotalId: row.id
      }).then(res => {
        this.currentInfo.arr = res.data.records
        this.lookDialogVisible = true
        if (callbanck) {
          callbanck()
        }
      }).catch(err => { });
    },
    handleDown0(row) {
      let url = this.javaApi + '/word/' + row.url
      this.$download.saveAs(url, '外来文件确认记录')
    },
    // æäº¤
    handleSubmit(row) {
      this.$confirm('是否提交 ' + row.year + ' å¹´çš„æ•°æ®', '提交', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        submitManageRecordTotal({
          id: row.id
        }).then(res => {
          this.$message({
            type: 'success',
            message: '提交成功!'
          });
          this.refreshTable()()
        }).catch(err => { });
      })
    },
    // æ‰¹å‡†
    handleApproval(row) {
      this.title0 = '批准'
      this.commonFun(row)
    },
    // æäº¤å®¡æ ¸/批准
    submitCheck(state) {
      if (state == '通过') {
        this.checkLoading = true
      } else {
        this.noCheckLoading = true
      }
      ratifyManageRecordTotal({
        id: this.currentInfo.id,
        ratifyState: state
      }).then(res => {
        this.checkLoading = false
        this.noCheckLoading = false
        if (res.code === 201) return
        this.$message({
          type: 'success',
          message: '操作成功!'
        });
        this.refreshTable()()
        this.lookDialogVisible = false
      }).catch(err => { });
    },
    handleDelete(row) {
      this.$confirm("是否删除该条数据?", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      })
        .then(() => {
          delManageRecordVerify({ id: row.id }).then((res) => {
            if (res.code == 201) return;
            this.$message.success("删除成功");
            this.getList0()
          });
        })
        .catch(() => { });
    },
    submitProduct(formName) {
      this.$refs[formName].validate((valid) => {
        if (valid) {
          this.uploading = true;
          if (this.title == "新增") {
            addManageRecordVerify(this.addForm)
              .then((res) => {
                this.uploading = false;
                if (res.code != 200) {
                  return;
                }
                this.$message.success("提交成功");
                this.getList0()
                this.addDia = false;
              })
              .catch((err) => {
                this.uploading = false;
              });
          } else {
            doManageRecordVerify(this.addForm)
              .then((res) => {
                this.uploading = false;
                if (res.code != 200) {
                  return;
                }
                this.$message.success("提交成功");
                this.getList0()
                this.addDia = false;
              })
              .catch((err) => {
                this.uploading = false;
              });
          }
        } else {
          return false;
        }
      });
    },
  }
}
</script>
<style scoped>
.title {
  height: 60px;
  line-height: 60px;
}
.search {
  background-color: #fff;
  height: 40px;
  display: flex;
  align-items: center;
  position: relative;
}
.search_thing {
  width: 350px;
  display: flex;
  align-items: center;
}
.search_label {
  width: 30px;
  font-size: 14px;
  text-align: right;
}
.search_input {
  width: calc(100% - 110px);
}
.table {
  background-color: #fff;
  height: 100%;
  margin-top: 10px;
}
>>>.el-tabs__content {
  height: 100%;
}
</style>
src/views/CNAS/systemManagement/documentRecords/regularReviewsRecord.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,743 @@
<template>
  <!-- æ–‡ä»¶å®šæœŸå®¡æŸ¥è®°å½• -->
  <div class="PeriodicDocumentReviewRecords">
    <el-tabs type="border-card" v-model="activeName" style="height: 100%;">
      <el-tab-pane label="填写" name="填写" style="height: 100%;">
        <div class="search">
          <div class="search_thing">
            <div class="search_label">文件名称:</div>
            <div class="search_input"><el-input size="small" placeholder="请输入" clearable
                v-model="queryParams.documentName" @keyup.enter.native="refreshTable()"></el-input></div>
          </div>
          <div class="search_thing">
            <div class="search_label">文件编号:</div>
            <div class="search_input">
              <el-input size="small" placeholder="请输入" clearable v-model="queryParams.documentCode"
                @keyup.enter.native="refreshTable()"></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="refreshTable()">查 è¯¢</el-button>
          </div>
          <div class="btns">
            <el-button size="small" type="primary" @click="openAdd" v-if="addPower">新增</el-button>
            <el-upload :action="action" :multiple="false" :show-file-list="false" accept='.doc,.docx'
              :headers="uploadHeader" :on-change="beforeUpload" :on-error="onError" ref='upload' v-if="upPower"
              :on-success="handleSuccessUp" style="display:inline-block;margin-left: 20px;">
              <el-button type="primary" size="small">导入</el-button></el-upload>
          </div>
        </div>
        <div class="table">
          <lims-table :tableData="tableData" :column="column" :page="page" :tableLoading="tableLoading"
            :height="'calc(100vh - 290px)'" @pagination="pagination"></lims-table>
        </div>
      </el-tab-pane>
      <el-tab-pane label="历史记录" name="历史记录" style="height: 100%;">
        <div class="search">
          <div class="search_thing">
            <div class="search_label">年:</div>
            <div class="search_input">
              <el-date-picker v-model="queryParams0.year" type="year" placeholder="选择年" format="yyyy"
                value-format="yyyy" size="small" @change="refreshTable(1)">
              </el-date-picker>
            </div>
          </div>
          <div class="search_thing" style="padding-left: 30px;">
            <el-button size="small" @click="refresh(1)">重 ç½®</el-button>
            <el-button size="small" type="primary" @click="refreshTable(1)">查 è¯¢</el-button>
          </div>
        </div>
        <div class="table">
          <lims-table :tableData="tableData0" :column="column0" :page="page0" :tableLoading="tableLoading"
            :height="'calc(100vh - 290px)'" @pagination="pagination0"></lims-table>
        </div>
      </el-tab-pane>
    </el-tabs>
    <el-dialog :title="title" :visible.sync="addDialogVisible" width="400px" top="6vh">
      <el-row>
        <el-col :span="24" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label"><span style="color: red;margin-left: 4px;">* </span>文件编号:</div>
            <div class="search_input">
              <el-select v-model="addInfo.documentCode" size="small" style="width: 100%;" @change="getCurrentFile"
                allow-create clearable filterable>
                <el-option v-for="item in fileList" :key="item.documentCode" :label="item.title"
                  :value="item.documentCode">
                </el-option>
              </el-select>
            </div>
          </div>
        </el-col>
        <el-col :span="24" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">文件名称:</div>
            <div class="search_input"><el-input size="small" placeholder="请输入" clearable
                v-model="addInfo.documentName"></el-input></div>
          </div>
        </el-col>
        <el-col :span="24" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">版本号:</div>
            <div class="search_input"><el-input size="small" placeholder="请输入" clearable
                v-model="addInfo.documentVersion"></el-input></div>
          </div>
        </el-col>
        <el-col :span="24" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">修订号:</div>
            <div class="search_input"><el-input size="small" placeholder="请输入" clearable
                v-model="addInfo.revision"></el-input></div>
          </div>
        </el-col>
        <el-col :span="24" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">适宜性:</div>
            <div class="search_input">
              <el-select v-model="addInfo.suitability" placeholder="请选择" size="small" style="width: 100%;">
                <el-option v-for="item in typeList" :key="item.value" :label="item.label" :value="item.value">
                </el-option>
              </el-select>
            </div>
          </div>
        </el-col>
        <el-col :span="24" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">备注:</div>
            <div class="search_input"><el-input size="small" placeholder="请输入" clearable v-model="addInfo.remark"
                type="textarea" :rows="2"></el-input></div>
          </div>
        </el-col>
      </el-row>
      <span slot="footer" class="dialog-footer">
        <el-button @click="addDialogVisible = false">取 æ¶ˆ</el-button>
        <el-button type="primary" @click="handleAdd" :loading="addLoading">ç¡® å®š</el-button>
      </span>
    </el-dialog>
    <!-- è¯¦æƒ…/审核 -->
    <el-dialog :title="title0" :visible.sync="lookDialogVisible" width="800px" top="5vh">
      <filePreview v-if="lookDialogVisible" :fileUrl="javaApi + '/word/' + currentInfo.url" :currentFile="{}"
        style="max-height: 70vh;overflow-y: auto;" />
      <span slot="footer" class="dialog-footer" v-if="title0 == '审核' || title0 == '批准'">
        <el-button @click="submitCheck('不通过')" :loading="noCheckLoading">不通过</el-button>
        <el-button type="primary" @click="submitCheck('通过')" :loading="checkLoading">通 è¿‡</el-button>
      </span>
    </el-dialog>
  </div>
</template>
<script>
import limsTable from "@/components/Table/lims-table.vue";
import filePreview from '@/components/Preview/filePreview.vue'
import {
  exportOutManageRecordIntervals,
  addManageRecordIntervals,
  doManageRecordIntervals,
  ratifyManageRecordIntervalsTotal,
  submitManageRecordIntervalsTotal,
  pageManageRecordIntervals,
  pageManageRecordIntervalsTotal,
  delManageRecordIntervals,
} from '@/api/cnas/systemManagement/documentRecords.js'
import {
  pageManageDocumentList,
} from '@/api/cnas/systemManagement/documentControl.js'
export default {
  components: {
    limsTable,
    filePreview
  },
  data() {
    return {
      activeName: '填写',
      title0: '新增',
      addPower: true,
      outPower: true,
      upPower: true,
      outLoading: false,
      addLoading: false,
      lookDialogVisible: false,
      noCheckLoading: false,
      checkLoading: false,
      componentData: {
        entity: {
          documentName: null,
          documentCode: null,
          orderBy: {
            field: 'id',
            order: 'desc'
          }
        },
        isIndex: true,
        showSelect: false,
        select: false,
        // selectMethod: 'handleChangeTask',
        do: [{
          id: 'handleEdit',
          font: '修改',
          type: 'text',
          method: 'handleEdit',
          field: [],
        }, {
          id: 'delete',
          font: '删除',
          type: 'text',
          method: 'doDiy',
        }],
        tagField: {
          // documentType:{
          //   select: []
          // },
          // receiveUserName:{
          //   select: []
          // },
        },
        selectField: {
          // documentType:{
          //   select: []
          // },
          // receiveUserName:{
          //   select: []
          // },
        },
        addUpload: ['signatoryUrl'],
        requiredAdd: [],
        requiredUp: [],
        datePicker: ['receiveDate'],
        noHead: ['signedUserName', 'signedDate', 'departLims'],//不参与新增编辑的字段
        needSort: [],
        inputType: ''
      },
      componentData0: {
        entity: {
          year: null,
          orderBy: {
            field: 'id',
            order: 'desc'
          }
        },
        isIndex: true,
        showSelect: false,
        select: false,
        do: [{
          id: 'handleLook',
          font: '查看',
          type: 'text',
          method: 'handleLook',
          disabFun: (row, index) => {
            return !row.url
          }
        }, {
          id: 'handleDown0',
          font: '下载',
          type: 'text',
          method: 'handleDown0',
          disabFun: (row, index) => {
            return !row.url
          }
        },
        {
          id: 'handleSubmit',
          font: '提交',
          type: 'text',
          method: 'handleSubmit',
          disabFun: (row, index) => {
            return !!row.submitUserName
          }
        }, {
          id: 'handleApproval',
          font: '批准',
          type: 'text',
          method: 'handleApproval',
          disabFun: (row, index) => {
            return !row.submitUserName || !!row.ratifyUserName
          }
        }],
        tagField: {},
        selectField: {},
        requiredAdd: [],
        requiredUp: [],
        needSort: [],
        inputType: ''
      },
      entityCopy: {},
      entityCopy0: {},
      upIndex: 0,
      addInfo: {},
      title: '新增',
      addInfo: {},
      addDialogVisible: false,
      fileList: [],
      typeList: [],
      currentInfo: {},
      queryParams: {},
      tableData: [],
      column: [
        { label: "文件名称", prop: "documentName" },
        { label: "文件编号", prop: "documentCode", width: "120px" },
        {
          label: "版本号",
          prop: "documentVersion",
        },
        { label: "修订号", prop: "revision" },
        { label: "适宜性", prop: "suitability" },
        { label: "备注", prop: "remark" },
        {
          dataType: "action",
          fixed: "right",
          label: "操作",
          operation: [
            {
              name: "编辑",
              type: "text",
              clickFun: (row) => {
                this.handleEdit(row);
              },
            },
            {
              name: "删除",
              type: "text",
              clickFun: (row) => {
                this.handleDelete(row);
              },
            },
          ],
        },
      ],
      page: {
        total: 0,
        size: 10,
        current: 0,
      },
      tableLoading: false,
      queryParams0: {},
      tableData0: [],
      column0: [
        { label: "年份", prop: "year" },
        { label: "总数量", prop: "totalNum", width: "120px" },
        {
          label: "拟制人",
          prop: "submitUserName",
        },
        { label: "拟制日期", prop: "submitDate" },
        { label: "批准人", prop: "ratifyUserName" },
        { label: "批准日期", prop: "ratifyDate" },
        { label: "批准结果", prop: "ratifyState" },
        {
          dataType: "action",
          fixed: "right",
          label: "操作",
          operation: [
            {
              name: "查看",
              type: "text",
              clickFun: (row) => {
                this.handleLook(row);
              },
              disabled: (row) => {
                return !row.url
              },
            },
            {
              name: "下载",
              type: "text",
              clickFun: (row) => {
                this.handleDown0(row);
              },
              disabled: (row) => {
                return !row.url
              },
            },
            {
              name: "提交",
              type: "text",
              clickFun: (row) => {
                this.handleSubmit(row);
              },
              disabled: (row) => {
                return !!row.submitUserName && row.ratifyState != '不通过'
              },
            },
            {
              name: "批准",
              type: "text",
              clickFun: (row) => {
                this.handleApproval(row);
              },
              disabled: (row) => {
                return (!row.submitUserName || !!row.ratifyUserName) && row.ratifyState != '不通过'
              },
            },
          ],
        },
      ],
      page0: {
        total: 0,
        size: 10,
        current: 0,
      },
    }
  },
  // ç”¨äºŽä¸Šä¼ æ–‡ä»¶çš„信息
  computed: {
    action() {
      return this.javaApi + '/manageRecordIntervals/exportInManageRecordIntervals'
    }
  },
  mounted() {
    // this.entityCopy = this.HaveJson(this.componentData.entity);
    // this.entityCopy0 = this.HaveJson(this.componentData0.entity);
    this.getList()
    this.getList0()
    this.getFileList()
    this.selectEnumByCategory()
  },
  methods: {
    getPower() {
      let power = JSON.parse(sessionStorage.getItem('power'))
      let add = false
      let del = false
      let up = false;
      let out = false;
      let submit = false
      let ratify = false
      for (var i = 0; i < power.length; i++) {
        if (power[i].menuMethod == 'addManageRecordIntervals') {
          add = true
        }
        if (power[i].menuMethod == 'delManageRecordIntervals') {
          del = true
        }
        if (power[i].menuMethod == 'exportInManageRecordIntervals') {
          up = true
        }
        if (power[i].menuMethod == 'exportOutManageRecordIntervals') {
          out = true
        }
        if (power[i].menuMethod == 'submitManageRecordIntervalsTotal') {
          submit = true
        }
        if (power[i].menuMethod == 'ratifyManageRecordIntervalsTotal') {
          ratify = true
        }
      }
      if (!ratify) {
        this.componentData0.do.splice(3, 1)
      }
      if (!submit) {
        this.componentData0.do.splice(2, 1)
      }
      if (!add) {
        this.componentData.do.splice(1, 1)
      }
      if (!del) {
        this.componentData.do.splice(0, 1)
      }
      this.addPower = add
      this.outPower = out
      this.upPower = up
    },
    // æ–°å¢ž
    openAdd() {
      // this.$refs.ValueTable.openAddDia(this.$api.manageRecordIssueRecycle.addManageRecordIssueRecycle);
      this.addInfo = {}
      this.title = '新增'
      this.addDialogVisible = true;
    },
    // å¯¼å‡º
    handleDown() {
      this.outLoading = true
      exportOutManageRecordIntervals(this.queryParams).then(res => {
        this.outLoading = false
        if (res.code == 201) return this.$message.error('导出失败')
        let url = this.javaApi + 'word/' + res.message
        this.$download.saveAs(url, "文件定期审查记录");
      })
    },
    getList() {
      this.tableLoading = true;
      let param = { ...this.queryParams, ...this.page };
      delete param.total;
      pageManageRecordIntervals({ ...param })
        .then((res) => {
          this.tableLoading = false;
          if (res.code === 200) {
            this.tableData = res.data.records;
            this.page.total = res.data.total;
          }
        })
        .catch((err) => {
          this.tableLoading = false;
        });
    },
    pagination({ page, limit }) {
      this.page.current = page;
      this.page.size = limit;
      this.getList();
    },
    getList0() {
      this.tableLoading = true;
      let param = { ...this.queryParams0, ...this.page0 };
      delete param.total;
      pageManageRecordIntervalsTotal({ ...param })
        .then((res) => {
          this.tableLoading = false;
          if (res.code === 200) {
            this.tableData0 = res.data.records;
            this.page0.total = res.data.total;
          }
        })
        .catch((err) => {
          this.tableLoading = false;
        });
    },
    pagination0({ page, limit }) {
      this.page0.current = page;
      this.page0.size = limit;
      this.getList0();
    },
    refreshTable(num) {
      if (num) {
        this.page0.current = 1;
        this.getList0();
      } else {
        this.page.current = 1;
        this.getList();
      }
    },
    refresh(num) {
      if (num) {
        this.queryParams0 = {};
        this.page0.current = 1;
        this.getList0();
      } else {
        this.queryParams = {};
        this.page.current = 1;
        this.getList();
      }
    },
    beforeUpload(file) {
      if (file.size > 1024 * 1024 * 10) {
        this.$message.error('上传文件不超过10M');
        this.$refs.upload.clearFiles()
        return false;
      } else {
        // this.upLoading = true;
        return true;
      }
    },
    onError(err, file, fileList) {
      this.$message.error('上传失败')
      this.$refs.upload.clearFiles()
    },
    handleSuccessUp(response) {
      this.upLoading = false;
      if (response.code == 200) {
        this.$message.success('上传成功');
        this.refreshTable()()
      } else {
        this.$message.error('上传失败');
      }
    },
    getCurrentFile(e) {
      let obj = this.fileList.find(m => m.documentCode == e)
      if (obj) {
        this.$set(this.addInfo, 'documentName', obj.name)
        this.$set(this.addInfo, 'documentVersion', obj.version)
        // this.addInfo.documentName = obj.name
        // this.addInfo.documentVersion = obj.version
      }
    },
    // èŽ·å–æ–‡ä»¶åˆ—è¡¨--文件清单
    getFileList() {
      pageManageDocumentList({
        current: -1,
        size: -1
      }).then(res => {
        this.fileList = res.data.records.map(m => {
          m.title = m.documentCode
          return m
        })
      }).catch(err => { })
    },
    selectEnumByCategory() {
      // æ–‡ä»¶ç±»åˆ«
      this.getDicts("suitability").then((response) => {
        this.typeList = this.dictToValue(response.data);
      });
    },
    // æäº¤
    handleAdd() {
      if (!this.addInfo.documentCode) return this.$message.error('请输入文件编号')
      this.addLoading = true
      let obj = {}
      if (this.title == '新增') {
        obj = this.HaveJson(this.addInfo)
      } else {
        let { id, documentCode, documentName, documentVersion, revision, suitability, remark } = this.addInfo
        obj = { id, documentCode, documentName, documentVersion, revision, suitability, remark }
      }
      if (this.title == '新增') {
        addManageRecordIntervals(obj).then(res => {
          this.addLoading = false
          if (res.code == 201) {
            return
          }
          this.addDialogVisible = false
          this.$message({
            type: 'success',
            message: '操作成功!'
          });
          this.refreshTable()
        }).catch(err => { })
      } else {
        doManageRecordIntervals(obj).then(res => {
          this.addLoading = false
          if (res.code == 201) {
            return
          }
          this.addDialogVisible = false
          this.$message({
            type: 'success',
            message: '操作成功!'
          });
          this.refreshTable()
        }).catch(err => { })
      }
    },
    // ä¿®æ”¹
    handleEdit(row) {
      this.addInfo = row
      this.title = '编辑'
      this.addDialogVisible = true;
    },
    submitCheck(state) {
      if (state == '通过') {
        this.checkLoading = true
      } else {
        this.noCheckLoading = true
      }
      ratifyManageRecordIntervalsTotal({
        id: this.currentInfo.id,
        ratifyState: state
      }).then(res => {
        this.checkLoading = false
        if (res.code == 201) {
          return
        }
        this.noCheckLoading = false
        this.$message({
          type: 'success',
          message: '操作成功!'
        });
        this.refreshTable(1);
        this.lookDialogVisible = false
      }).catch(err => { });
    },
    // æŸ¥çœ‹
    handleLook(row) {
      this.title0 = '查看'
      this.commonFun(row)
    },
    commonFun(row, callbanck) {
      this.currentInfo = row
      this.lookDialogVisible = true
      if (callbanck) {
        callbanck()
      }
    },
    handleDown0(row) {
      let url = this.javaApi + '/word/' + row.url
      this.$download.saveAs(url, "所有文件定期检查记录");
    },
    // æäº¤
    handleSubmit(row) {
      this.$confirm('是否提交 ' + row.year + ' å¹´çš„æ•°æ®', '提交', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        submitManageRecordIntervalsTotal({
          id: row.id
        }).then(res => {
          if (res.code === 201) return
          this.$message({
            type: 'success',
            message: '提交成功!'
          });
          this.refreshTable(1);
        }).catch(err => { });
      })
    },
    // æ‰¹å‡†
    handleApproval(row) {
      this.title0 = '批准'
      this.commonFun(row)
    },
    handleDelete(row) {
      this.$confirm("是否删除该条数据?", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      })
        .then(() => {
          delManageRecordIntervals({ id: row.id }).then((res) => {
            if (res.code == 201) return;
            this.$message.success("删除成功");
            this.refreshTable();
          });
        })
        .catch(() => { });
    },
  }
}
</script>
<style scoped>
.title {
  height: 60px;
  line-height: 60px;
}
.search {
  background-color: #fff;
  height: 40px;
  display: flex;
  align-items: center;
  position: relative;
}
.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;
  height: calc(100% - 60px - 140px);
  padding: 20px;
  padding-top: 0;
}
>>>.el-tabs__content {
  height: 100%;
}
.btns {
  position: absolute;
  right: 20px;
  top: 5px;
}
</style>
src/views/CNAS/systemManagement/documentRecords/revisionRecord.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,867 @@
<template>
  <!-- æ–‡ä»¶ä¿®è®¢ç”³è¯·å®¡æ‰¹è®°å½• -->
  <div class="DocumentRevisionRequestApprovalRecords">
    <div class="search">
      <div class="search_thing">
        <div class="search_label">文件编号:</div>
        <div class="search_input">
          <el-input size="small" placeholder="请输入" clearable v-model="queryParams.documentCode"
            @keyup.enter.native="refreshTable()"></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="refreshTable()">查 è¯¢</el-button>
      </div>
      <div class="btn">
        <el-button size="small" type="primary" @click="openAdd" v-if="addPower">新增</el-button>
        <el-button size="small" type="primary" @click="handleDown" :loading="outLoading" v-if="outPower"
          style="display:inline-block;margin-left: 20px;">导出</el-button>
      </div>
    </div>
    <div class="table">
      <lims-table :tableData="tableData" :column="column" :page="page" :tableLoading="tableLoading"
        :height="'calc(100vh - 260px)'" @pagination="pagination"></lims-table>
    </div>
    <el-dialog :title="title" :visible.sync="addDialogVisible" width="800px" top="6vh">
      <el-row>
        <el-col :span="12" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">申请类型:</div>
            <div class="search_input">
              <el-radio-group v-model="addInfo.method" size="small" :disabled="title.includes('意见')">
                <el-radio label="修订">修订</el-radio>
                <el-radio label="作废">作废</el-radio>
              </el-radio-group>
            </div>
          </div>
        </el-col>
        <el-col :span="12" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label"><span style="color: red;margin-left: 4px;">* </span>文件编号:</div>
            <div class="search_input">
              <el-select v-model="addInfo.documentCode" size="small" style="width: 100%;" @change="getCurrentFile"
                allow-create clearable filterable :disabled="title.includes('意见')">
                <el-option v-for="item in fileList" :key="item.documentCode" :label="item.title"
                  :value="item.documentCode">
                </el-option>
              </el-select>
            </div>
          </div>
        </el-col>
        <el-col :span="12" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">文件名称:</div>
            <div class="search_input"><el-input size="small" placeholder="请输入" clearable v-model="addInfo.documentName"
                :disabled="title.includes('意见')"></el-input></div>
          </div>
        </el-col>
        <el-col :span="12" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">章节号:</div>
            <div class="search_input"><el-input size="small" placeholder="请输入" clearable v-model="addInfo.capter"
                :disabled="title.includes('意见')"></el-input></div>
          </div>
        </el-col>
        <el-col :span="12" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">页码:</div>
            <div class="search_input"><el-input size="small" placeholder="请输入" clearable v-model="addInfo.pages"
                :disabled="title.includes('意见')"></el-input></div>
          </div>
        </el-col>
        <el-col :span="12" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">修改次数:</div>
            <div class="search_input"><el-input size="small" placeholder="请输入" clearable v-model="addInfo.number"
                :disabled="title.includes('意见')"></el-input></div>
          </div>
        </el-col>
        <el-col :span="12" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">修改前版本号:</div>
            <div class="search_input"><el-input size="small" placeholder="请输入" clearable v-model="addInfo.beforeVersion"
                :disabled="title.includes('意见')"></el-input></div>
          </div>
        </el-col>
        <el-col :span="12" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">修改后版本号:</div>
            <div class="search_input"><el-input size="small" placeholder="请输入" clearable v-model="addInfo.afterVersion"
                :disabled="title.includes('意见')"></el-input></div>
          </div>
        </el-col>
        <el-col :span="12" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">修订人:</div>
            <div class="search_input">
              <el-select v-model="addInfo.alterUser" placeholder="请选择" size="small" style="width: 100%;" filterable
                :disabled="title.includes('意见')">
                <el-option v-for="item in personList" :key="item.value" :label="item.label" :value="item.value">
                </el-option>
              </el-select>
            </div>
          </div>
        </el-col>
        <el-col :span="12" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">原分发部门:</div>
            <div class="search_input">
              <el-select v-model="addInfo.beforeDepart" placeholder="请选择" size="small" style="width: 100%;"
                :disabled="title.includes('意见')">
                <el-option v-for="item in list" :key="item.name" :label="item.name" :value="item.name">
                </el-option>
              </el-select>
            </div>
          </div>
        </el-col>
        <el-col :span="12" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">修订后分发部门:</div>
            <div class="search_input">
              <el-select v-model="addInfo.afterDepart" placeholder="请选择" size="small" style="width: 100%;"
                :disabled="title.includes('意见')">
                <el-option v-for="item in list" :key="item.name" :label="item.name" :value="item.name">
                </el-option>
              </el-select>
            </div>
          </div>
        </el-col><el-col :span="12" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">日期:</div>
            <div class="search_input">
              <el-date-picker v-model="addInfo.date" type="date" size="small" placeholder="选择日期" format="yyyy-MM-dd"
                value-format="yyyy-MM-dd" style="width: 100%;">
              </el-date-picker>
            </div>
          </div>
        </el-col>
        <el-col :span="24" style="margin-bottom: 16px;">
          <div class="search_thing" style="width: 90%;">
            <div class="search_label">修改内容:</div>
            <div class="search_input"><el-input size="small" placeholder="请输入" clearable v-model="addInfo.alterThing"
                type="textarea" :rows="2" :disabled="title.includes('意见')"></el-input></div>
          </div>
        </el-col>
        <el-col :span="24" style="margin-bottom: 16px;">
          <div class="search_thing" style="width: 90%;">
            <div class="search_label">变化原因:</div>
            <div class="search_input"><el-input size="small" placeholder="请输入" clearable v-model="addInfo.reason"
                type="textarea" :rows="2" :disabled="title.includes('意见')"></el-input></div>
          </div>
        </el-col>
        <el-col :span="12" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">上传附件:</div>
            <div class="search_input"><el-upload style="margin: 8px 0 0px 50px;" action="#" :auto-upload="false"
                :multiple="false" accept='.pdf' :on-change="handleChangeUpload"
                v-if="addDialogVisible && !title.includes('意见')">
                <el-button size="small" type="primary">上传附件</el-button>
              </el-upload></div>
          </div>
        </el-col>
        <el-col :span="12" style="margin-bottom: 16px;" v-if="title.includes('意见')">
          <div class="search_thing">
            <div class="search_label">申请部门主管意见:</div>
            <div class="search_input"><el-input size="small" placeholder="请输入" clearable v-model="addInfo.applicant"
                type="textarea" :rows="2" :disabled="title != '申请部门主管意见'"></el-input></div>
          </div>
        </el-col>
        <el-col :span="12" style="margin-bottom: 16px;" v-if="title.includes('意见')">
          <div class="search_thing">
            <div class="search_label">原定制部门意见:</div>
            <div class="search_input"><el-input size="small" placeholder="请输入" clearable v-model="addInfo.formulation"
                type="textarea" :rows="2" :disabled="title != '原定制部门意见'"></el-input></div>
          </div>
        </el-col>
        <el-col :span="12" style="margin-bottom: 16px;" v-if="title.includes('意见')">
          <div class="search_thing">
            <div class="search_label">原审核部门意见:</div>
            <div class="search_input"><el-input size="small" placeholder="请输入" clearable v-model="addInfo.audit"
                type="textarea" :rows="2" :disabled="title != '原审核部门意见'"></el-input></div>
          </div>
        </el-col>
      </el-row>
      <span slot="footer" class="dialog-footer">
        <el-button @click="addDialogVisible = false">取 æ¶ˆ</el-button>
        <el-button type="primary" @click="handleAdd" :loading="addLoading">ç¡® å®š</el-button>
      </span>
    </el-dialog>
    <el-dialog :title="title0" :visible.sync="detailDialogVisible" width="900px" top="20px"
      :class="{ downPdf: title0 == '下载' }" :modal="title0 != '下载'">
      <div style="max-height: 75vh;overflow-y: auto;">
        <div id="dialogBody">
          <h4 style="display: flex;align-items: center;flex-direction: column;justify-content: center;">
            <span style="font-size: 20px;">文件更改/作废申请表</span>
            <span>Application for alteration/cancellation of Document</span>
          </h4>
          <p style="display: flex;justify-content: space-between;margin-top: 16px;">
            <span>{{ currentInfo.documentCode }}</span>
            <span>{{ currentInfo.method }}</span>
          </p>
          <table border="1" class="tables" cellpadding="10">
            <tr>
              <td>
                <p>申请部门</p>
                <p class="en">Application department</p>
              </td>
              <td>{{ currentInfo.createUserDepart }}</td>
              <td>
                <p>申请人</p>
                <p>Proposer</p>
              </td>
              <td>{{ currentInfo.createUserName }}</td>
              <td>
                <p>申请时间</p>
                <p class="en">Application date</p>
              </td>
              <td>{{ currentInfo.createTime }}</td>
            </tr>
            <tr>
              <td>
                <p>文件名称</p>
                <p class="en">File name</p>
              </td>
              <td colspan="3">{{ currentInfo.documentName }}</td>
              <td>
                <p>文件编号</p>
                <p class="en">Document number</p>
              </td>
              <td>{{ currentInfo.documentCode }}</td>
            </tr>
            <tr>
              <td>
                <p>修改前版次</p>
                <p class="en">Modify previous editions</p>
              </td>
              <td colspan="2">{{ currentInfo.beforeVersion }}</td>
              <td>
                <p>修改后版次</p>
                <p class="en">Revised edition</p>
              </td>
              <td colspan="2">{{ currentInfo.afterVersion }}</td>
            </tr>
            <tr>
              <td>
                <p>变化原因</p>
                <p class="en">Changing reason</p>
              </td>
              <td colspan="5">
                <div class="user-content">
                  <p style="text-align: left;line-height: 26px;">{{ currentInfo.reason }}</p>
                </div>
              </td>
            </tr>
            <tr>
              <td>
                <p>原文内容</p>
                <p class="en">Original content</p>
              </td>
              <td colspan="2">见附件</td>
              <td>
                <p>拟修订内容</p>
                <p class="en">Content be revised</p>
              </td>
              <td colspan="2">{{ currentInfo.alterThing }}</td>
            </tr>
            <tr>
              <td>
                <p>修订后分发部门</p>
                <p class="en">Distribute to the department after revision</p>
              </td>
              <td colspan="2">{{ currentInfo.afterDepart }}</td>
              <td>
                <p>原分放部门</p>
                <p class="en">The original distribution department</p>
              </td>
              <td colspan="2">{{ currentInfo.beforeDepart }}</td>
            </tr>
            <tr>
              <td>
                <p>申请部门主管意见</p>
                <p class="en">Opinion of the head of the applicant department</p>
              </td>
              <td colspan="2">
                <p>原制定部门意见</p>
                <p class="en">Original formulation of the department's opinion</p>
              </td>
              <td colspan="2">
                <p>原审核部门意见</p>
                <p class="en">Opinion of the original audit department</p>
              </td>
              <td>
                <p>批准</p>
                <p class="en">Ratify</p>
              </td>
            </tr>
            <tr>
              <td>
                {{ currentInfo.applicant }}
              </td>
              <td colspan="2">
                {{ currentInfo.formulation }}
              </td>
              <td colspan="2">
                {{ currentInfo.audit }}
              </td>
              <td>
                <img :src="javaApi + 'img/' + currentInfo.ratifyUserUrl" style="width: 100%;" alt="批准人签名">
              </td>
            </tr>
          </table>
        </div>
      </div>
    </el-dialog>
    <el-dialog title="文件预览" :visible.sync="lookDialogVisible" width="800px" top="5vh" fullscreen>
      <h4>修订内容</h4>
      <filePreview v-if="lookDialogVisible" :fileUrl="javaApi + '/word/' + currentInfo.afterUrl" :currentFile="{}" />
      <h4>原内容</h4>
      <filePreview v-if="lookDialogVisible" :fileUrl="javaApi + '/word/' + currentInfo.beforeUrl" :currentFile="{}" />
    </el-dialog>
  </div>
</template>
<script>
import limsTable from "@/components/Table/lims-table.vue";
import { exportHtmlToPDF } from '@/utils/downHtmlToPDF'
import filePreview from '@/components/Preview/filePreview.vue'
import {
  exportOutManageRecordAudit,
  addManageRecordAudit,
  doManageRecordAudit,
  selectCNSAPersonTree,
  ratifyManageRecordAudit,
  pageManageRecordAudit,
  delManageRecordAudit,
} from '@/api/cnas/systemManagement/documentRecords.js'
import {
  pageManageDocumentList,
} from '@/api/cnas/systemManagement/documentControl.js'
import {
  selectUserCondition,
} from "@/api/system/user.js";
export default {
  components: {
    filePreview,
    limsTable
  },
  data() {
    return {
      addPower: true,
      outPower: true,
      outLoading: false,
      lookDialogVisible: false,
      addLoading: false,
      title: '新增',
      addInfo: {
        method: '修订',
      },
      addDialogVisible: false,
      detailDialogVisible: false,
      fileList: [],
      personList: [],
      list: [],
      file: null,
      title0: '查看',
      currentInfo: {},
      queryParams: {},
      tableData: [],
      column: [
        { label: "文件编号", prop: "documentCode" },
        { label: "章节号", prop: "capter", width: "120px" },
        {
          label: "页码",
          prop: "pages",
        },
        { label: "修订次数", prop: "number" },
        { label: "修改前版本号", prop: "beforeVersion" },
        { label: "修改后版本号", prop: "afterVersion" },
        { label: "修改内容", prop: "alterThing" },
        { label: "修订人", prop: "alterUserName" },
        { label: "批准人", prop: "ratifyUserName" },
        { label: "日期", prop: "date" },
        {
          dataType: "action",
          fixed: "right",
          label: "操作",
          operation: [
            {
              name: "查看",
              type: "text",
              clickFun: (row) => {
                this.handleLook(row);
              },
            },
            {
              name: "文件预览",
              type: "text",
              clickFun: (row) => {
                this.handleLook0(row);
              },
            },
            {
              name: "下载",
              type: "text",
              clickFun: (row) => {
                this.handleOut(row);
              },
            },
            {
              name: "删除",
              type: "text",
              clickFun: (row) => {
                this.handleDelete(row);
              },
              disabled: (row) => {
                return !!row.ratifyUser
              },
            },
            {
              name: "编辑",
              type: "text",
              clickFun: (row) => {
                this.handleEdit(row);
              },
              disabled: (row) => {
                return !!row.ratifyUser
              },
            },
            {
              name: "批准",
              type: "text",
              clickFun: (row) => {
                this.handleRatify(row);
              },
              disabled: (row) => {
                return !!row.ratifyUser
              },
            },
            {
              name: "申请意见",
              type: "text",
              clickFun: (row) => {
                this.handlework0(row);
              },
              disabled: (row) => {
                return !!row.ratifyUser
              },
            },
            {
              name: "原定制意见",
              type: "text",
              clickFun: (row) => {
                this.handlework1(row);
              },
              disabled: (row) => {
                return !!row.ratifyUser
              },
            },
            {
              name: "原审核意见",
              type: "text",
              clickFun: (row) => {
                this.handlework2(row);
              },
              disabled: (row) => {
                return !!row.ratifyUser
              },
            },
          ],
        },
      ],
      page: {
        total: 0,
        size: 10,
        current: 0,
      },
      tableLoading: false,
    }
  },
  mounted() {
    this.getList()
    this.getFileList()
    this.getAuthorizedPerson()
    this.selectTreeList()
  },
  methods: {
    getPower() {
      let power = JSON.parse(sessionStorage.getItem('power'))
      let add = false
      let del = false
      let out = false;
      let ratify = false
      let audit1 = false
      let audit2 = false
      let audit3 = false
      for (var i = 0; i < power.length; i++) {
        if (power[i].menuMethod == 'addManageRecordAudit') {
          add = true
        }
        if (power[i].menuMethod == 'delManageRecordAudit') {
          del = true
        }
        if (power[i].menuMethod == 'ratifyManageRecordAudit') {
          ratify = true
        }
        if (power[i].menuMethod == 'exportOutManageRecordAudit') {
          out = true
        }
        if (power[i].menuMethod == 'manageRecordAudit1') {
          audit1 = true
        }
        if (power[i].menuMethod == 'manageRecordAudit2') {
          audit2 = true
        }
        if (power[i].menuMethod == 'manageRecordAudit3') {
          audit3 = true
        }
      }
      if (!audit3) {
        this.componentData.do.splice(8, 1)
      }
      if (!audit2) {
        this.componentData.do.splice(7, 1)
      }
      if (!audit1) {
        this.componentData.do.splice(6, 1)
      }
      if (!ratify) {
        this.componentData.do.splice(5, 1)
      }
      if (!add) {
        this.componentData.do.splice(4, 1)
      }
      if (!del) {
        this.componentData.do.splice(3, 1)
      }
      this.addPower = add
      this.outPower = out
    },
    openAdd() {
      this.addInfo = {
        method: '修订',
      }
      this.title = '新增'
      this.addDialogVisible = true;
    },
    // å¯¼å‡º
    handleDown() {
      this.outLoading = true
      exportOutManageRecordAudit(this.queryParams).then(res => {
        this.outLoading = false
        if (res.code == 201) return this.$message.error('导出失败')
        let url = this.javaApi + '/word/' + res.data
        this.$download.saveAs(url, "文件修订表");
      })
    },
    getList() {
      this.tableLoading = true;
      let param = { ...this.queryParams, ...this.page };
      delete param.total;
      pageManageRecordAudit({ ...param })
        .then((res) => {
          this.tableLoading = false;
          if (res.code === 200) {
            this.tableData = res.data.records;
            this.page.total = res.data.total;
          }
        })
        .catch((err) => {
          this.tableLoading = false;
        });
    },
    pagination({ page, limit }) {
      this.page.current = page;
      this.page.size = limit;
      this.getList();
    },
    refresh() {
      this.queryParams = {};
      this.page.current = 1;
      this.getList();
    },
    refreshTable() {
      this.page.current = 1;
      this.getList();
    },
    // èŽ·å–æ–‡ä»¶åˆ—è¡¨--文件清单
    getFileList() {
      pageManageDocumentList({
        current: -1,
        size: -1
      }).then(res => {
        this.fileList = res.data.records.map(m => {
          m.title = m.documentCode
          return m
        })
      }).catch(err => { })
    },
    getCurrentFile(e) { },
    handleAdd() {
      if (!this.addInfo.documentCode) return this.$message({ type: 'error', message: "请输入文件编号" })
      if (!this.addInfo.id) {
        // æ–°å¢ž
        let fd = new FormData();
        //文件信息中raw才是真的文件
        if (this.file) {
          fd.append("file", this.file.raw);
        }
        for (let m in this.addInfo) {
          fd.append(m, this.addInfo[m])
        }
        this.addLoading = true
        addManageRecordAudit(fd).then(res => {
          this.addLoading = false
          if (res.code == 200) {
            this.$message({
              type: 'success',
              message: '添加成功'
            })
            this.refreshTable()
            this.addDialogVisible = false
          } else {
            this.$message({
              type: 'error',
              message: '添加失败'
            })
          }
        })
      } else {
        // ä¿®æ”¹
        let { id, method, documentCode, documentName, capter, pages, beforeVersion, afterVersion, alterUser, alterThing, reason, beforeDepart, afterDepart, number, applicant, formulation, audit, date } = this.addInfo
        let fd = new FormData();
        //文件信息中raw才是真的文件
        if (this.file) {
          fd.append("file", this.file.raw);
        }
        let obj = { id, method, documentCode, documentName, capter, pages, beforeVersion, afterVersion, alterUser, alterThing, reason, beforeDepart, afterDepart, number, applicant, formulation, audit, date }
        for (let m in obj) {
          if (this.addInfo[m]) {
            fd.append(m, this.addInfo[m])
          }
        }
        this.addLoading = true
        doManageRecordAudit(fd).then(res => {
          this.addLoading = false
          if (res.code == 200) {
            this.refreshTable()
            this.addDialogVisible = false
          } else {
            this.$message({
              type: 'error',
              message: '添加失败'
            })
          }
        })
      }
    },
    getAuthorizedPerson() {
      selectUserCondition().then(res => {
        let data = []
        res.data.forEach(a => {
          data.push({
            label: a.name,
            value: a.id
          })
        })
        this.personList = data
      })
    },
    // æŸ¥è¯¢æ ‘形列表
    selectTreeList() {
      selectCNSAPersonTree().then((res) => {
        this.list = res.data[0].children;
      });
    },
    handleChangeUpload(file, fileLists) {
      this.file = file
      // this.$set(this.addInfo,'name',file.name)
    },
    handleEdit(row) {
      this.addInfo = row
      this.title = '修改'
      this.addDialogVisible = true;
    },
    // å®¡æ‰¹
    handleRatify(row) {
      this.$confirm('是否批准通过?', '批准', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      })
        .then(() => {
          ratifyManageRecordAudit({ id: row.id }).then(res => {
            if (res.code === 201) {
              return;
            }
            this.$message.success('操作成功');
            this.refreshTable();
          })
            .catch(e => {
              this.$message.error('操作失败');
            });
        })
        .catch(() => {
        });
    },
    handlework0(row) {
      this.addInfo = row
      this.title = '申请部门主管意见'
      this.addDialogVisible = true;
    },
    handlework1(row) {
      this.addInfo = row
      this.title = '原定制部门意见'
      this.addDialogVisible = true;
    },
    handlework2(row) {
      this.addInfo = row
      this.title = '原审核部门意见'
      this.addDialogVisible = true;
    },
    handleLook(row) {
      this.title0 = '查看'
      this.currentInfo = row
      this.detailDialogVisible = true;
    },
    handleOut(row) {
      this.currentInfo = row
      this.title0 = '下载'
      this.detailDialogVisible = true;
      setTimeout(() => {
        this.$nextTick(() => {
          const element = document.getElementById("dialogBody");
          exportHtmlToPDF(element, '文件' + row.method + '申请表').then(res => {
            this.detailDialogVisible = false;
          })
        })
      }, 500);
    },
    handleLook0(row) {
      this.currentInfo = row;
      this.lookDialogVisible = true
    },
    handleDelete(row) {
      this.$confirm("是否删除该条数据?", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      })
        .then(() => {
          delManageRecordAudit({ id: row.id }).then((res) => {
            if (res.code == 201) return;
            this.$message.success("删除成功");
            this.refresh();
          });
        })
        .catch(() => { });
    },
  }
}
</script>
<style scoped>
.title {
  height: 60px;
  line-height: 60px;
}
.search {
  background-color: #fff;
  height: 80px;
  display: flex;
  align-items: center;
  position: relative;
}
.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;
  height: calc(100% - 60px - 80px - 10px - 40px);
  padding: 20px;
  padding-top: 0;
}
.tables {
  table-layout: fixed;
  width: 100%;
  margin-top: 10px;
  border-collapse: collapse;
}
.tables td {
  height: 40px;
  width: 100px;
  text-align: center;
  font-size: 14px;
  word-wrap: break-word;
  white-space: normal;
}
.en {
  font-size: 12px;
  word-break: break-word;
  /* è‡ªåŠ¨æ–­è¡Œ */
  overflow-wrap: break-word;
  /* é˜²æ­¢æº¢å‡º */
  white-space: normal;
  /* é»˜è®¤æ¢è¡Œ */
}
.heads td {
  border: 1px dashed black;
  /* å•元格的虚线 */
  padding: 8px;
  text-align: left;
}
.downPdf {
  opacity: 0 !important;
}
h4.title {
  position: relative;
  height: 30px;
  line-height: 30px;
  box-sizing: border-box;
  padding-left: 16px;
  margin-left: 10px;
  margin-bottom: 10px;
}
h4.title::after {
  content: '';
  width: 4px;
  height: 20px;
  background: #3A7BFA;
  position: absolute;
  top: 5px;
  left: 0;
}
>>>.el-dialog__body {
  height: auto;
}
.btn {
  position: absolute;
  right: 20px;
  top: 16px;
}
</style>
src/views/CNAS/systemManagement/internalAuditManagement/components/ViewTestRecord.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,176 @@
<template>
  <div>
    <el-dialog :visible.sync="filesDialogVisible" title="附件" width="80%" @closed="closeFilesLook">
      <div style="display: flex;justify-content: space-between;">
        <el-upload ref='upload' :action="fileAction" :auto-upload="true" :before-upload="fileBeforeUpload"
          :data="{ correctId: info.correctId }" :headers="uploadHeader" :on-error="onError"
          :on-success="handleSuccessUp" :show-file-list="false"
          accept='.jpg,.jpeg,.png,.gif,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.pdf,.zip,.rar' style="width: 80px !important;">
          <el-button size="small" style="height: 38px" type="primary">附件上传</el-button>
        </el-upload>
      </div>
      <div>
        <limsTable ref="yearTable" :column="columnData" :height="'calc(100vh - 30em)'" :highlightCurrentRow="true"
          :table-data="tableData" :table-loading="tableLoading" style="margin-top: 0.5em;" :page="page">
        </limsTable>
      </div>
    </el-dialog>
    <el-dialog :visible.sync="lookDialogVisible" fullscreen title="查看附件" top="5vh" width="800px">
      <filePreview v-if="lookDialogVisible" :currentFile="{}" :fileUrl="javaApi + '/word/' + currentInfo.fileUrl"
        style="height: 90vh;overflow-y: auto;" />
    </el-dialog>
  </div>
</template>
<script>
import limsTable from "@/components/Table/lims-table.vue";
import filePreview from '@/components/Preview/filePreview.vue'
import {
  getInternalCorrectFileList,
  delInternalCorrectFile,
} from '@/api/cnas/systemManagement/internalAuditManagement.js'
export default {
  name: 'ViewTestRecord',
  // import å¼•入的组件需要注入到对象中才能使用
  components: { filePreview, limsTable },
  data() {
    // è¿™é‡Œå­˜æ”¾æ•°æ®
    return {
      filesDialogVisible: false,
      tableLoading: false,
      filesLookInfo: {},
      columnData: [
        {
          label: '文件名称',
          prop: 'fileName',
          minWidth: '150px'
        },
        {
          dataType: 'action',
          minWidth: '100',
          label: '操作',
          fixed: 'right',
          operation: [
            {
              name: '预览',
              type: 'text',
              clickFun: (row) => {
                this.handleLook(row)
              }
            },
            {
              name: '下载',
              type: 'text',
              clickFun: (row) => {
                this.upload(row)
              }
            },
            {
              name: '删除',
              type: 'text',
              color: '#f56c6c',
              clickFun: (row) => {
                this.delete(row)
              }
            }
          ]
        }
      ],
      tableData: [],
      info: {},
      currentInfo: {},
      lookDialogVisible: false,
      page: {
        total: 0,
        size: -1,
        current: -1,
      },
    };
  },
  // æ–¹æ³•集合
  methods: {
    openDia(row) {
      this.filesDialogVisible = true
      this.info = row
      this.searchTableList()
    },
    // æŸ¥è¯¢é™„件列表
    searchTableList() {
      this.tableLoading = true
      getInternalCorrectFileList({ correctId: this.info.correctId }).then(res => {
        this.tableLoading = false
        if (res.code === 201) return
        this.tableData = res.data
      }).catch(err => {
        this.tableLoading = false
        console.log('err---', err);
      })
    },
    closeFilesLook() {
      this.filesDialogVisible = false
    },
    // æŸ¥çœ‹æ–‡ä»¶
    handleLook(row) {
      this.currentInfo = row
      this.lookDialogVisible = true
    },
    // ä¸‹è½½
    upload(row) {
      let url = '';
      if (row.type == 1) {
        url = this.javaApi + '/img/' + row.fileUrl
        this.$download.saveAs(url, row.fileName)
      } else {
        url = this.javaApi + '/word/' + row.fileUrl
        this.$download.saveAs(url, row.fileName)
      }
    },
    // åˆ é™¤
    delete(row) {
      this.tableLoading = true
      delInternalCorrectFile({ correctFileId: row.correctFileId }).then(res => {
        this.tableLoading = false
        if (res.code === 201) return
        this.$message.success('删除成功')
        this.searchTableList()
      }).catch(err => {
        this.tableLoading = false
        console.log('err---', err);
      })
    },
    // ä¸Šä¼ éªŒè¯
    fileBeforeUpload(file) {
      let flag = true
      if (file.size > 1024 * 1024 * 10) {
        this.$message.error('上传文件不超过10M');
        this.$refs.upload.clearFiles()
        flag = false
      }
      if (!flag) {
        return Promise.reject(flag); //正确的终止
      }
    },
    onError(err, file, fileList, type) {
      this.$message.error('上传失败')
      this.$refs.upload.clearFiles()
    },
    handleSuccessUp(response,) {
      this.upLoading = false;
      if (response.code == 200) {
        this.$message.success('上传成功');
        this.searchTableList()
      } else {
        this.$message.error(response.message);
      }
    },
  },
  computed: {
    fileAction() {
      return this.javaApi + '/internalCorrect/uploadInternalCorrectFile'
    }
  },
};
</script>
<style scoped></style>
src/views/CNAS/systemManagement/internalAuditManagement/components/auditInspection.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,253 @@
<template>
  <div>
    <div class="search-background">
      <span class="search-group">
        <span style="width: 160px">受审部门:</span>
        <el-input v-model="searchForm.department" clearable size="small"></el-input>
        <el-button size="medium" style="margin-left: 10px" @click="resetSearchForm">重 ç½®</el-button>
        <el-button size="medium" type="primary" @click="searchList">查 è¯¢</el-button>
      </span>
      <span class="search-group">
        <el-button size="medium" type="primary" @click="openFormDia('add')">新 å¢ž</el-button>
      </span>
    </div>
    <div class="table">
      <limsTable :column="tableColumn" :height="'calc(100vh - 23em)'" :table-data="tableData"
        :table-loading="tableLoading" style="padding: 0 10px;margin-bottom: 16px" :page="page" @pagination="pagination">
      </limsTable>
    </div>
    <audit-inspection-dia v-if="auditInspectionDia" ref="auditInspectionDia"
      @closeImplementDia="closeImplementDia"></audit-inspection-dia>
  </div>
</template>
<script>
import limsTable from "@/components/Table/lims-table.vue";
import AuditInspectionDia from './auditInspectionDia.vue';
import {
  pageInternalCheck,
  delInternalCheck,
  exportInternalCheck
} from '@/api/cnas/systemManagement/internalAuditManagement.js'
export default {
  name: 'auditInspection',
  // import å¼•入的组件需要注入到对象中才能使用
  components: { AuditInspectionDia, limsTable },
  data() {
    // è¿™é‡Œå­˜æ”¾æ•°æ®
    return {
      searchForm: {
        department: '',
      },
      tableColumn: [
        {
          label: '受审部门',
          prop: 'department',
        },
        {
          label: '部门负责人',
          prop: 'departmentHead',
        },
        {
          label: '审核员',
          prop: 'auditor',
        },
        {
          label: '审核日期',
          prop: 'reviewDate',
        }, {
          dataType: 'tag',
          label: '批准状态',
          prop: 'ratifyStatus',
          minWidth: '100',
          formatData: (params) => {
            if (params === 0) {
              return '不批准';
            } else if (params === 1) {
              return '批准';
            } else {
              return null;
            }
          },
          formatType: (params) => {
            if (params === 0) {
              return 'danger';
            } else if (params === 1) {
              return 'success';
            } else {
              return null;
            }
          }
        }, {
          label: '批准内容',
          prop: 'ratifyRemark',
          minWidth: '140'
        },
        {
          dataType: 'action',
          minWidth: '220',
          label: '操作',
          operation: [
            {
              name: '导出',
              type: 'text',
              clickFun: (row) => {
                this.handleDown(row)
              },
              disabled: (row) => {
                if (row.ratifyStatus === 1) {
                  return false
                } else {
                  return true
                }
              },
            },
            {
              name: '编辑',
              type: 'text',
              clickFun: (row) => {
                this.openFormDia('edit', row);
              },
              disabled: (row) => {
                if (row.ratifyStatus === 1) {
                  return true
                } else {
                  return false
                }
              },
            },
            {
              name: '批准',
              type: 'text',
              clickFun: (row) => {
                this.openFormDia('ratify', row);
              },
              disabled: (row) => {
                if (row.ratifyStatus === 1) {
                  return true
                } else {
                  return false
                }
              },
            },
            {
              name: '删除',
              type: 'text',
              color: '#f56c6c',
              clickFun: (row) => {
                this.delPlan(row)
              },
              disabled: (row) => {
                if (row.ratifyStatus === 1) {
                  return true
                } else {
                  return false
                }
              },
            }
          ]
        }
      ],
      tableData: [],
      tableLoading: false,
      page: {
        size: 20,
        current: 1,
        total: 0,
      },
      auditInspectionDia: false
    };
  },
  mounted() {
    this.searchList()
  },
  // æ–¹æ³•集合
  methods: {
    // æŸ¥è¯¢åˆ—表
    searchList() {
      const entity = this.searchForm
      const page = this.page
      this.tableLoading = true
      pageInternalCheck({ ...entity, ...page }).then(res => {
        this.tableLoading = false
        if (res.code === 201) return
        this.tableData = res.data.records
        this.page.total = res.data.total
      }).catch(err => {
        console.log('err---', err);
        this.tableLoading = false
      })
    },
    // æ–°å¢žï¼Œç¼–辑,批准弹框
    openFormDia(type, row) {
      this.auditInspectionDia = true
      this.$nextTick(() => {
        this.$refs.auditInspectionDia.openDia(type, row)
      })
    },
    closeImplementDia() {
      this.auditInspectionDia = false
      this.searchList()
    },
    // é‡ç½®æŸ¥è¯¢æ¡ä»¶
    resetSearchForm() {
      this.searchForm.department = '';
      this.searchList()
    },
    // åˆ é™¤
    delPlan(row) {
      this.$confirm('此操作将永久删除该数据, æ˜¯å¦ç»§ç»­?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        this.tableLoading = true
        delInternalCheck({ checkId: row.checkId }).then(res => {
          this.tableLoading = false
          if (res.code === 201) return
          this.$message.success('删除成功')
          this.searchList()
        }).catch(err => {
          this.tableLoading = false
          console.log('err---', err);
        })
      }).catch(() => {
        this.$message({
          type: 'info',
          message: '已取消删除'
        });
      });
    },
    // å¯¼å‡º
    handleDown(row) {
      exportInternalCheck({ checkId: row.checkId }).then(res => {
        this.outLoading = false
        const blob = new Blob([res], { type: 'application/msword' });
        this.$download.saveAs(blob, '内审检查' + '.docx');
      })
    },
    pagination({ page, limit }) {
      this.page.current = page;
      this.page.size = limit;
      this.searchList();
    },
  }
};
</script>
<style scoped>
.search-background {
  width: 100%;
  height: 60px;
  line-height: 60px;
  display: flex;
  justify-content: space-between;
}
.search-group {
  display: flex;
  align-items: center;
  margin: 0 20px;
}
</style>
src/views/CNAS/systemManagement/internalAuditManagement/components/auditInspectionDia.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,231 @@
<template>
  <div>
    <el-dialog v-loading="diaLoading" :close-on-click-modal="false" :close-on-press-escape="false"
      :visible.sync="formDia" title="内部审核实施计划" width="80%" @close="closeImplementDia">
      <el-form ref="form" :model="form" :rules="rules" label-width="auto">
        <el-col :span="12">
          <el-form-item label="受审部门" prop="department">
            <el-input v-model="form.department" :disabled="operationType === 'ratify'" clearable
              size="small"></el-input>
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="部门负责人" prop="departmentHead">
            <el-input v-model="form.departmentHead" :disabled="operationType === 'ratify'" clearable
              size="small"></el-input>
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="审核员" prop="auditor">
            <el-input v-model="form.auditor" :disabled="operationType === 'ratify'" clearable size="small"></el-input>
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="审核日期" prop="reviewDate">
            <el-date-picker v-model="form.reviewDate" :disabled="operationType === 'ratify'" clearable
              format="yyyy-MM-dd" placeholder="选择日期" size="small" style="width: 100%" type="date"
              value-format="yyyy-MM-dd">
            </el-date-picker>
          </el-form-item>
        </el-col>
      </el-form>
      <div v-if="operationType !== 'ratify'" style="text-align: right;margin-bottom: 10px">
        <el-button size="small" type="primary" @click="addRow">添加</el-button>
        <el-button size="small" type="danger" @click="clearTable">清空</el-button>
      </div>
      <el-table :data="checkDetailList" border height="300" style="width: 100%">
        <el-table-column align="center" label="序号" type="index" width="60" />
        <el-table-column header-align="center" label="涉及要素和质量体系文件条款" prop="element">
          <template slot-scope="{row}">
            <el-input v-model="row.element" :disabled="operationType === 'ratify'" size="small" />
          </template>
        </el-table-column>
        <el-table-column header-align="center" label="审核内容" prop="content">
          <template slot-scope="{row}">
            <el-input v-model="row.content" :disabled="operationType === 'ratify'" size="small" />
          </template>
        </el-table-column>
        <el-table-column header-align="center" label="审核方式" prop="method">
          <template slot-scope="{row}">
            <el-input v-model="row.method" :disabled="operationType === 'ratify'" size="small" />
          </template>
        </el-table-column>
        <el-table-column header-align="center" label="审核结果记录" prop="resultRecords" width="180">
          <template slot-scope="{row}">
            <el-input v-model="row.resultRecords" :disabled="operationType === 'ratify'" size="small" />
          </template>
        </el-table-column>
        <el-table-column header-align="center" label="不符合性质" prop="nonNature" width="180">
          <template slot-scope="{row}">
            <el-input v-model="row.nonNature" :disabled="operationType === 'ratify'" size="small" />
          </template>
        </el-table-column>
      </el-table>
      <span slot="footer" class="dialog-footer">
        <el-button v-if="operationType === 'ratify'" :loading="loading" @click="ratify(0)">不批准</el-button>
        <el-button v-if="operationType === 'ratify'" :loading="loading" type="primary" @click="ratify(1)">批
          å‡†</el-button>
        <el-button v-if="operationType !== 'ratify'" @click="closeImplementDia">取 æ¶ˆ</el-button>
        <el-button v-if="operationType !== 'ratify'" :loading="loading" type="primary" @click="handleEdit">提
          äº¤</el-button>
      </span>
    </el-dialog>
    <el-dialog :visible.sync="approvalDialog" title="批准" width="30%" @close="approvalDialog = false">
      <span>
        æ‰¹å‡†å¤‡æ³¨ï¼š
        <el-input v-model="ratifyRemark" type="textarea"></el-input>
      </span>
      <span slot="footer" class="dialog-footer">
        <el-button :loading="approvalLoading" @click="approvalDialog = false">取 æ¶ˆ</el-button>
        <el-button :loading="approvalLoading" type="primary" @click="handleApproval(0)">ç¡® å®š</el-button>
      </span>
    </el-dialog>
  </div>
</template>
<script>
import {
  getInternalCheckOne,
  addInternalCheck,
  updateInternalCheck,
  ratifyInternalCheck,
} from '@/api/cnas/systemManagement/internalAuditManagement.js'
export default {
  name: 'auditInspectionDia',
  // import å¼•入的组件需要注入到对象中才能使用
  components: {},
  data() {
    // è¿™é‡Œå­˜æ”¾æ•°æ®
    return {
      formDia: false,
      diaLoading: false,
      loading: false,
      form: {
        department: '',
        departmentHead: '',
        auditor: '',
        reviewDate: '',
      },
      rules: {
        department: [{ required: true, message: '请填写受审部门', trigger: 'blur' }],
        departmentHead: [{ required: true, message: '请填写部门负责人', trigger: 'blur' }],
        auditor: [{ required: true, message: '请填写审核员', trigger: 'blur' }],
        reviewDate: [{ required: true, message: '请填写审核日期', trigger: 'blur' }],
      },
      checkDetailList: [],
      operationType: '',
      approvalDialog: false,
      approvalLoading: false,
      ratifyRemark: '',
    };
  },
  // æ–¹æ³•集合
  methods: {
    // æ‰“开弹框
    openDia(type, row) {
      this.formDia = true
      this.operationType = type
      if (type !== 'add') {
        this.searchInfo(row)
      }
    },
    // æŸ¥è¯¢è¯¦æƒ…
    searchInfo(row) {
      this.diaLoading = true
      getInternalCheckOne({ checkId: row.checkId }).then(res => {
        this.diaLoading = false
        if (res.code === 201) return
        this.form = res.data
        this.checkDetailList = this.form.checkDetailList
      }).catch(err => {
        console.log(err)
        this.diaLoading = false
      })
    },
    // æäº¤å¼¹æ¡†æ•°æ®
    handleEdit() {
      this.$refs['form'].validate((valid) => {
        if (valid) {
          if (this.checkDetailList.length === 0) {
            this.$message.warning('请添加表格数据')
            return
          }
          this.loading = true
          const internalCheckDto = this.HaveJson(this.form)
          internalCheckDto.checkDetailList = this.HaveJson(this.checkDetailList)
          if (this.operationType === 'add') {
            addInternalCheck(internalCheckDto).then(res => {
              this.loading = false
              if (res.code === 201) return
              this.$message.success('操作成功')
              this.closeImplementDia()
            }).catch(err => {
              console.log('err---', err);
              this.loading = false
            })
          } else if (this.operationType === 'edit') {
            updateInternalCheck(internalCheckDto).then(res => {
              this.loading = false
              if (res.code === 201) return
              this.$message.success('操作成功')
              this.closeImplementDia()
            }).catch(err => {
              console.log('err---', err);
              this.loading = false
            })
          }
        } else {
          console.log('error submit!!');
          return false;
        }
      });
    },
    ratify(ratifyStatus) {
      // ä¸æ‰¹å‡†éœ€è¦å¡«å†™æ‰¹å‡†å†…容
      if (ratifyStatus === 0) {
        this.approvalDialog = true
      } else {
        this.handleApproval(ratifyStatus)
      }
    },
    // æäº¤æ‰¹å‡†ä¿¡æ¯
    handleApproval(ratifyStatus) {
      this.approvalLoading = true
      const internalCheckDto = this.HaveJson(this.form)
      internalCheckDto.ratifyStatus = ratifyStatus
      internalCheckDto.ratifyRemark = ratifyStatus === 0 ? this.ratifyRemark : ''
      ratifyInternalCheck(internalCheckDto).then(res => {
        if (res.code === 200) {
          this.$message.success('提交成功!');
          this.approvalDialog = false
          this.closeImplementDia(this.departId);
        }
        this.approvalLoading = false
      }).catch(() => {
        this.approvalLoading = false
      })
    },
    // å¢žåŠ è¡¨æ ¼è¡Œæ•°æ®
    addRow() {
      this.checkDetailList.push({
        element: '',
        content: '',
        method: '',
        resultRecords: '',
        nonNature: '',
      })
    },
    // æ¸…空表格数据
    clearTable() {
      this.checkDetailList = []
    },
    closeImplementDia() {
      this.$refs.form.resetFields();
      this.formDia = false
      this.$emit('closeImplementDia')
    },
  }
};
</script>
<style scoped></style>
src/views/CNAS/systemManagement/internalAuditManagement/components/auditMeetingSign.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,201 @@
<template>
  <div>
    <div class="search-background">
      <span class="search-group">
        <span style="width: 160px">时间:</span>
        <el-input v-model="searchForm.meetingDate" clearable size="small"></el-input>
        <el-button size="medium" style="margin-left: 10px" @click="resetSearchForm">重 ç½®</el-button>
        <el-button size="medium" type="primary" @click="searchList">查 è¯¢</el-button>
      </span>
      <span class="search-group">
        <el-button size="medium" type="primary" @click="openFormDia('add')">新 å¢ž</el-button>
      </span>
    </div>
    <div class="table">
      <limsTable :column="tableColumn" :height="'calc(100vh - 23em)'" :table-data="tableData"
        :table-loading="tableLoading" style="padding: 0 10px;margin-bottom: 16px" :page="page" @pagination="pagination">
      </limsTable>
    </div>
    <audit-meeting-sign-dia v-if="auditMeetingSignDia" ref="auditMeetingSignDia"
      @closeYearDia="closeYearDia"></audit-meeting-sign-dia>
  </div>
</template>
<script>
import limsTable from "@/components/Table/lims-table.vue";
import AuditMeetingSignDia from './auditMeetingSignDia.vue';
import {
  pageInternalMeeting,
  delInternalMeeting,
  exportInternalMeeting,
} from '@/api/cnas/systemManagement/internalAuditManagement.js'
export default {
  name: 'auditMeetingSign',
  // import å¼•入的组件需要注入到对象中才能使用
  components: { AuditMeetingSignDia, limsTable },
  data() {
    // è¿™é‡Œå­˜æ”¾æ•°æ®
    return {
      searchForm: {
        meetingDate: '',
      },
      tableColumn: [
        {
          label: '时间',
          prop: 'meetingDate',
          minWidth: '100'
        },
        {
          label: '主持人',
          prop: 'compere',
          minWidth: '100'
        },
        {
          label: '地点',
          prop: 'place',
          minWidth: '100'
        },
        {
          label: '会议主题',
          prop: 'subject',
          minWidth: '100'
        },
        {
          label: '参会人员',
          prop: 'participantName',
          minWidth: '120'
        },
        {
          dataType: 'action',
          fixed: 'right',
          minWidth: '220',
          label: '操作',
          operation: [
            {
              name: '导出',
              type: 'text',
              clickFun: (row) => {
                this.handleDown(row)
              }
            },
            {
              name: '编辑',
              type: 'text',
              clickFun: (row) => {
                this.openFormDia('edit', row);
              },
            },
            {
              name: '删除',
              type: 'text',
              color: '#f56c6c',
              clickFun: (row) => {
                this.delPlan(row)
              }
            }
          ]
        }
      ],
      tableData: [],
      tableLoading: false,
      page: {
        size: 20,
        current: 1,
        total: 0,
      },
      auditMeetingSignDia: false,
    };
  },
  mounted() {
    this.searchList()
  },
  // æ–¹æ³•集合
  methods: {
    // æŸ¥è¯¢åˆ—表
    searchList() {
      const entity = this.searchForm
      const page = this.page
      this.tableLoading = true
      pageInternalMeeting({ ...entity, ...page }).then(res => {
        this.tableLoading = false
        if (res.code === 201) return
        this.tableData = res.data.records
        this.page.total = res.data.total
      }).catch(err => {
        console.log('err---', err);
        this.tableLoading = false
      })
    },
    // æ–°å¢žï¼Œç¼–辑弹框
    openFormDia(type, row) {
      this.auditMeetingSignDia = true
      this.$nextTick(() => {
        this.$refs.auditMeetingSignDia.openDia(type, row)
      })
    },
    closeYearDia() {
      this.auditMeetingSignDia = false
      this.searchList()
    },
    // é‡ç½®æŸ¥è¯¢æ¡ä»¶
    resetSearchForm() {
      this.searchForm.meetingDate = '';
      this.searchList()
    },
    // åˆ é™¤
    delPlan(row) {
      this.$confirm('此操作将永久删除该数据, æ˜¯å¦ç»§ç»­?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        this.tableLoading = true
        delInternalMeeting({ meetingId: row.meetingId }).then(res => {
          this.tableLoading = false
          if (res.code === 201) return
          this.$message.success('删除成功')
          this.searchList()
        }).catch(err => {
          this.tableLoading = false
          console.log('err---', err);
        })
      }).catch(() => {
        this.$message({
          type: 'info',
          message: '已取消删除'
        });
      });
    },
    // å¯¼å‡º
    handleDown(row) {
      exportInternalMeeting({ meetingId: row.meetingId }).then(res => {
        this.outLoading = false
        const blob = new Blob([res], { type: 'application/msword' });
        this.$download.saveAs(blob, '内审会议签到' + '.docx');
      })
    },
    pagination({ page, limit }) {
      this.page.current = page;
      this.page.size = limit;
      this.searchList();
    },
  }
};
</script>
<style scoped>
.search-background {
  width: 100%;
  height: 60px;
  line-height: 60px;
  display: flex;
  justify-content: space-between;
}
.search-group {
  display: flex;
  align-items: center;
  margin: 0 20px;
}
</style>
src/views/CNAS/systemManagement/internalAuditManagement/components/auditMeetingSignDia.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,183 @@
<template>
  <div>
    <el-dialog v-loading="diaLoading" :close-on-click-modal="false" :close-on-press-escape="false"
      :visible.sync="formDia" title="内审会议签到表" width="1000px" @close="closeYearDia">
      <el-form ref="form" :model="form" :rules="rules" label-position="top" label-width="auto">
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="时间" prop="meetingDate">
              <el-date-picker v-model="form.meetingDate" clearable 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="compere">
              <el-input v-model="form.compere" clearable size="small"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="地点" prop="place">
              <el-input v-model="form.place" clearable size="small"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="会议主题" prop="subject">
              <el-input v-model="form.subject" clearable size="small"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item label="参会人员" prop="participant">
              <el-select v-model="form.participant" clearable filterable multiple placeholder="请选择" size="small"
                style="width: 100%;">
                <el-option v-for="(item, i) in personList" :key="i" :label="item.label" :value="item.value">
                </el-option>
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <span slot="footer" class="dialog-footer">
        <el-button @click="closeYearDia">取 æ¶ˆ</el-button>
        <el-button :loading="loading" type="primary" @click="handleEdit">提 äº¤</el-button>
      </span>
    </el-dialog>
  </div>
</template>
<script>
import {
  selectUserCondition,
} from "@/api/system/user.js";
import {
  getInternalMeetingOne,
  addInternalMeeting,
  updateInternalMeeting,
} from '@/api/cnas/systemManagement/internalAuditManagement.js'
export default {
  name: 'auditMeetingSignDia',
  // import å¼•入的组件需要注入到对象中才能使用
  components: {},
  data() {
    // è¿™é‡Œå­˜æ”¾æ•°æ®
    return {
      formDia: false,
      diaLoading: false,
      loading: false,
      form: {
        meetingDate: '',
        compere: '',
        place: '',
        subject: '',
        participant: [],
      },
      rules: {
        meetingDate: [{ required: true, message: '请填写会议时间', trigger: 'blur' }],
        compere: [{ required: true, message: '请填写主持人', trigger: 'blur' }],
        place: [{ required: true, message: '请填写地点', trigger: 'blur' }],
        subject: [{ required: true, message: '请填写会议主题', trigger: 'blur' }],
        participant: [{ required: true, message: '请选择参加人员', trigger: 'change' }],
      },
      operationType: '',
      personList: []
    };
  },
  mounted() {
  },
  // æ–¹æ³•集合
  methods: {
    // æ‰“开弹框
    openDia(type, row) {
      this.formDia = true
      this.operationType = type
      this.getAuthorizedPerson()
      if (type !== 'add') {
        this.searchInfo(row)
      }
    },
    // æŸ¥è¯¢è¯¦æƒ…
    searchInfo(row) {
      this.diaLoading = true
      getInternalMeetingOne({ meetingId: row.meetingId }).then(res => {
        this.diaLoading = false
        if (res.code === 201) return
        this.form = res.data
        this.form.participant = this.form.participant.split(',').map(Number)
      }).catch(err => {
        console.log(err)
        this.diaLoading = false
      })
    },
    // æäº¤å¼¹æ¡†æ•°æ®
    handleEdit() {
      this.$refs['form'].validate((valid) => {
        if (valid) {
          this.loading = true
          const internalMeeting = this.HaveJson(this.form)
          internalMeeting.participant = internalMeeting.participant.join(',')
          if (this.operationType === 'add') {
            addInternalMeeting(internalMeeting).then(res => {
              this.loading = false
              if (res.code === 201) return
              this.$message.success('操作成功')
              this.closeYearDia()
            }).catch(err => {
              console.log('err---', err);
              this.loading = false
            })
          } else if (this.operationType === 'edit') {
            updateInternalMeeting(internalMeeting).then(res => {
              this.loading = false
              if (res.code === 201) return
              this.$message.success('操作成功')
              this.closeYearDia()
            }).catch(err => {
              console.log('err---', err);
              this.loading = false
            })
          }
        } else {
          console.log('error submit!!');
          return false;
        }
      });
    },
    closeYearDia() {
      this.$refs.form.resetFields();
      this.formDia = false
      this.$emit('closeYearDia')
    },
    getAuthorizedPerson() {
      selectUserCondition().then(res => {
        let data = []
        res.data.forEach(a => {
          data.push({
            label: a.name,
            value: a.id
          })
        })
        this.personList = data
      })
    },
  }
};
</script>
<style scoped>
.table {
  table-layout: fixed;
  width: 100%;
  margin-top: 10px;
}
.table td {
  height: 34px;
  width: 100px;
  text-align: center;
  font-size: 14px;
  word-wrap: break-word;
  white-space: normal;
  padding: 4px;
}
</style>
src/views/CNAS/systemManagement/internalAuditManagement/components/auditReport.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,311 @@
<template>
  <div>
    <div class="search-background">
      <span class="search-group">
        <span style="width: 160px">审核目的:</span>
        <el-input v-model="searchForm.purposes" clearable size="small"></el-input>
        <el-button size="medium" style="margin-left: 10px" @click="resetSearchForm">重 ç½®</el-button>
        <el-button size="medium" type="primary" @click="searchList">查 è¯¢</el-button>
      </span>
      <span class="search-group">
        <el-button size="medium" type="primary" @click="openFormDia('add')">新 å¢ž</el-button>
      </span>
    </div>
    <div class="table">
      <limsTable :column="tableColumn" :height="'calc(100vh - 23em)'" :table-data="tableData"
        :table-loading="tableLoading" style="padding: 0 10px;margin-bottom: 16px" :page="page" @pagination="pagination">
      </limsTable>
    </div>
    <audit-report-dia v-if="auditReportDia" ref="auditReportDia"
      @closeImplementDia="closeImplementDia"></audit-report-dia>
  </div>
</template>
<script>
import limsTable from "@/components/Table/lims-table.vue";
import AuditReportDia from './auditReportDia.vue';
import {
  delInternalReport,
  pageInternalReport,
  exportInternalReport,
} from '@/api/cnas/systemManagement/internalAuditManagement.js'
export default {
  name: 'auditReport',
  // import å¼•入的组件需要注入到对象中才能使用
  components: { AuditReportDia, limsTable },
  data() {
    // è¿™é‡Œå­˜æ”¾æ•°æ®
    return {
      searchForm: {
        purposes: '',
      },
      tableColumn: [
        {
          label: '审核目的',
          prop: 'purposes',
        },
        {
          label: '审核依据',
          prop: 'basis',
        },
        {
          label: '审核日期',
          prop: 'reviewDate',
        },
        {
          label: '审核方法',
          prop: 'method',
        },
        {
          label: '审核范围',
          prop: 'scope',
        },
        {
          label: '审核责任者',
          prop: 'responsible',
        },
        {
          label: '审核组长',
          prop: 'leader',
        },
        {
          label: '审核员',
          prop: 'auditor',
        },
        {
          label: '审核组分工情况',
          prop: 'division',
        },
        {
          dataType: 'tag',
          label: '审核状态',
          prop: 'examineStatus',
          minWidth: '100',
          formatData: (params) => {
            if (params === 0) {
              return '不通过';
            } else if (params === 1) {
              return '通过';
            } else {
              return null;
            }
          },
          formatType: (params) => {
            if (params === 0) {
              return 'danger';
            } else if (params === 1) {
              return 'success';
            } else {
              return null;
            }
          }
        },
        {
          label: '审核内容',
          prop: 'examineRemark',
          minWidth: '140'
        },
        {
          dataType: 'tag',
          label: '质量负责人状态',
          prop: 'qualityStatus',
          minWidth: '100',
          formatData: (params) => {
            if (params === 0) {
              return '不通过';
            } else if (params === 1) {
              return '通过';
            } else {
              return null;
            }
          },
          formatType: (params) => {
            if (params === 0) {
              return 'danger';
            } else if (params === 1) {
              return 'success';
            } else {
              return null;
            }
          }
        },
        {
          label: '质量负责人意见',
          prop: 'qualityRemark',
          minWidth: '140'
        },
        {
          dataType: 'action',
          minWidth: '220',
          fixed: 'right',
          label: '操作',
          operation: [
            {
              name: '导出',
              type: 'text',
              clickFun: (row) => {
                this.handleDown(row)
              }
            },
            {
              name: '编辑',
              type: 'text',
              clickFun: (row) => {
                this.openFormDia('edit', row);
              },
              disabled: (row) => {
                if (row.examineStatus === 1 || row.examineStatus === 1) {
                  return true
                } else {
                  return false
                }
              },
            },
            {
              name: '审核',
              type: 'text',
              clickFun: (row) => {
                this.openFormDia('examine', row);
              },
              disabled: (row) => {
                if (row.examineStatus === 1) {
                  return true
                } else {
                  return false
                }
              },
            },
            {
              name: '意见',
              type: 'text',
              clickFun: (row) => {
                this.openFormDia('ratify', row);
              },
              disabled: (row) => {
                if (row.qualityStatus === 1 || row.examineStatus === 0 || row.examineStatus === null) {
                  return true
                } else {
                  return false
                }
              },
            },
            {
              name: '删除',
              type: 'text',
              color: '#f56c6c',
              clickFun: (row) => {
                this.delPlan(row)
              },
              disabled: (row) => {
                if (row.qualityStatus === 1) {
                  return true
                } else {
                  return false
                }
              },
            }
          ]
        }
      ],
      tableData: [],
      tableLoading: false,
      page: {
        size: 20,
        current: 1,
        total: 0,
      },
      auditReportDia: false
    };
  },
  mounted() {
    this.searchList()
  },
  // æ–¹æ³•集合
  methods: {
    // æŸ¥è¯¢åˆ—表
    searchList() {
      const entity = this.searchForm
      const page = this.page
      this.tableLoading = true
      pageInternalReport({ ...entity, ...page }).then(res => {
        this.tableLoading = false
        if (res.code === 201) return
        this.tableData = res.data.records
        this.page.total = res.data.total
      }).catch(err => {
        console.log('err---', err);
        this.tableLoading = false
      })
    },
    // æ–°å¢žï¼Œç¼–辑,批准弹框
    openFormDia(type, row) {
      this.auditReportDia = true
      this.$nextTick(() => {
        this.$refs.auditReportDia.openDia(type, row)
      })
    },
    closeImplementDia() {
      this.auditReportDia = false
      this.searchList()
    },
    // é‡ç½®æŸ¥è¯¢æ¡ä»¶
    resetSearchForm() {
      this.searchForm.purposes = '';
      this.searchList()
    },
    // åˆ é™¤
    delPlan(row) {
      this.$confirm('此操作将永久删除该数据, æ˜¯å¦ç»§ç»­?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        this.tableLoading = true
        delInternalReport({ reportId: row.reportId }).then(res => {
          this.tableLoading = false
          if (res.code === 201) return
          this.$message.success('删除成功')
          this.searchList()
        }).catch(err => {
          this.tableLoading = false
          console.log('err---', err);
        })
      }).catch(() => {
        this.$message({
          type: 'info',
          message: '已取消删除'
        });
      });
    },
    // å¯¼å‡º
    handleDown(row) {
      exportInternalReport({ reportId: row.reportId }).then(res => {
        this.outLoading = false
        const blob = new Blob([res], { type: 'application/msword' });
        this.$download.saveAs(blob, '内审报告' + '.docx');
      })
    },
    pagination({ page, limit }) {
      this.page.current = page;
      this.page.size = limit;
      this.searchList();
    },
  }
};
</script>
<style scoped>
.search-background {
  width: 100%;
  height: 60px;
  line-height: 60px;
  display: flex;
  justify-content: space-between;
}
.search-group {
  display: flex;
  align-items: center;
  margin: 0 20px;
}
</style>
src/views/CNAS/systemManagement/internalAuditManagement/components/auditReportDia.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,333 @@
<template>
  <div>
    <el-dialog v-loading="diaLoading" :close-on-click-modal="false" :close-on-press-escape="false"
      :visible.sync="formDia" title="内部审核报告" width="80%" @close="closeImplementDia">
      <el-form ref="form" :model="form" :rules="rules" label-position="top" label-width="auto">
        <el-row :gutter="20">
          <el-col :span="24">
            <el-form-item label="审核目的" prop="purposes">
              <el-input v-model="form.purposes" :disabled="operationType === 'examine' || operationType === 'ratify'"
                clearable size="small"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="审核依据" prop="basis">
              <el-input v-model="form.basis" :disabled="operationType === 'examine' || operationType === 'ratify'"
                clearable size="small"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="审核日期" prop="reviewDate">
              <el-date-picker v-model="form.reviewDate"
                :disabled="operationType === 'examine' || operationType === 'ratify'" clearable format="yyyy-MM-dd"
                placeholder="选择日期" size="small" style="width: 100%" type="date" value-format="yyyy-MM-dd">
              </el-date-picker>
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item label="审核方法" prop="method">
              <el-input v-model="form.method" :disabled="operationType === 'examine' || operationType === 'ratify'"
                clearable size="small"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item label="审核范围" prop="scope">
              <el-input v-model="form.scope" :disabled="operationType === 'examine' || operationType === 'ratify'"
                clearable size="small"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="审核责任者" prop="responsible">
              <el-input v-model="form.responsible" :disabled="operationType === 'examine' || operationType === 'ratify'"
                clearable size="small"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="审核组长" prop="leader">
              <el-input v-model="form.leader" :disabled="operationType === 'examine' || operationType === 'ratify'"
                clearable size="small"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item label="审核员" prop="auditor">
              <el-input v-model="form.auditor" :disabled="operationType === 'examine' || operationType === 'ratify'"
                clearable size="small"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item label="审核组分工情况" prop="division">
              <el-input v-model="form.division" :disabled="operationType === 'examine' || operationType === 'ratify'"
                clearable size="small"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item label="审核概况" prop="overview">
              <el-input v-model="form.overview" :disabled="operationType === 'examine' || operationType === 'ratify'"
                :rows="3" clearable size="small" type="textarea"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item label="内审组对中心管理体系的结论性评价" prop="conclusion">
              <el-input v-model="form.conclusion" :disabled="operationType === 'examine' || operationType === 'ratify'"
                :rows="3" clearable size="small" type="textarea"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item label="改进意见" prop="suggest">
              <el-input v-model="form.suggest" :disabled="operationType === 'examine' || operationType === 'ratify'"
                :rows="3" clearable size="small" type="textarea"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item label="预计受审核部门完成纠正措施所需时间" prop="actionDate">
              <el-input v-model="form.actionDate" :disabled="operationType === 'examine' || operationType === 'ratify'"
                :rows="3" clearable size="small" type="textarea"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item label="不符合情况整改总体跟进确认人" prop="followUser">
              <el-input v-model="form.followUser" :disabled="operationType === 'examine' || operationType === 'ratify'"
                :rows="3" clearable size="small" type="textarea"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item label="不符合情况整改总体跟进确认记录" prop="followRecord">
              <el-input v-model="form.followRecord"
                :disabled="operationType === 'examine' || operationType === 'ratify'" :rows="3" clearable size="small"
                type="textarea"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item label="本报告发放范围" prop="reportScope">
              <el-input v-model="form.reportScope" :disabled="operationType === 'examine' || operationType === 'ratify'"
                :rows="3" clearable size="small" type="textarea"></el-input>
            </el-form-item>
          </el-col>
          <el-col v-if="operationType === 'ratify'" :span="24">
            <el-form-item label="质量负责人意见" prop="qualityRemark">
              <el-input v-model="form.qualityRemark" :rows="3" clearable size="small" type="textarea"></el-input>
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <span slot="footer" class="dialog-footer">
        <el-button v-if="operationType === 'examine'" :loading="loading" @click="examine(0)">不通过</el-button>
        <el-button v-if="operationType === 'examine'" :loading="loading" type="primary" @click="examine(1)">通
          è¿‡</el-button>
        <el-button v-if="operationType === 'ratify'" :loading="loading" @click="handleApproval(0)">不批准</el-button>
        <el-button v-if="operationType === 'ratify'" :loading="loading" type="primary" @click="handleApproval(1)">批
          å‡†</el-button>
        <el-button v-if="operationType !== 'ratify' && operationType !== 'examine'" @click="closeImplementDia">取
          æ¶ˆ</el-button>
        <el-button v-if="operationType !== 'ratify' && operationType !== 'examine'" :loading="loading" type="primary"
          @click="handleEdit">提 äº¤</el-button>
      </span>
    </el-dialog>
    <el-dialog :visible.sync="examineDialog" title="审核" width="30%" @close="examineDialog = false">
      <span>
        å®¡æ ¸å¤‡æ³¨ï¼š
        <el-input v-model="examineRemark" type="textarea"></el-input>
      </span>
      <span slot="footer" class="dialog-footer">
        <el-button :loading="examineLoading" @click="examineDialog = false">取 æ¶ˆ</el-button>
        <el-button :loading="examineLoading" type="primary" @click="handleExamine(0)">ç¡® å®š</el-button>
      </span>
    </el-dialog>
    <el-dialog :visible.sync="approvalDialog" title="批准" width="30%" @close="approvalDialog = false">
      <span>
        æ‰¹å‡†å¤‡æ³¨ï¼š
        <el-input v-model="qualityRemark" type="textarea"></el-input>
      </span>
      <span slot="footer" class="dialog-footer">
        <el-button :loading="approvalLoading" @click="approvalDialog = false">取 æ¶ˆ</el-button>
        <el-button :loading="approvalLoading" type="primary" @click="handleApproval(0)">ç¡® å®š</el-button>
      </span>
    </el-dialog>
  </div>
</template>
<script>
import {
  getInternalReportOne,
  addInternalReport,
  updateInternalReport,
  examineInternalReport,
  qualityInternalReport,
} from '@/api/cnas/systemManagement/internalAuditManagement.js'
export default {
  name: 'auditReportDia',
  // import å¼•入的组件需要注入到对象中才能使用
  components: {},
  data() {
    // è¿™é‡Œå­˜æ”¾æ•°æ®
    return {
      formDia: false,
      diaLoading: false,
      loading: false,
      form: {
        purposes: '',
        basis: '',
        reviewDate: '',
        method: '',
        scope: '',
        responsible: '',
        leader: '',
        auditor: '',
        division: '',
        overview: '',
        conclusion: '',
        suggest: '',
        actionDate: '',
        followUser: '',
        followRecord: '',
        reportScope: '',
        qualityRemark: '',
      },
      rules: {
        purposes: [{ required: true, message: '请填写审核目的', trigger: 'blur' }],
        basis: [{ required: true, message: '请填写审核依据', trigger: 'blur' }],
        reviewDate: [{ required: true, message: '请填写审核日期', trigger: 'change' }],
        method: [{ required: true, message: '请填写审核方法', trigger: 'blur' }],
        scope: [{ required: true, message: '请填写审核范围', trigger: 'blur' }],
        responsible: [{ required: true, message: '请填写审核责任者', trigger: 'blur' }],
        leader: [{ required: true, message: '请填写审核组长', trigger: 'blur' }],
        auditor: [{ required: true, message: '请填写审核员', trigger: 'blur' }],
        division: [{ required: true, message: '请填写审核组分工情况', trigger: 'blur' }],
        overview: [{ required: true, message: '请填写审核概况', trigger: 'blur' }],
        conclusion: [{ required: true, message: '请填写', trigger: 'blur' }],
        suggest: [{ required: true, message: '请填写', trigger: 'blur' }],
        actionDate: [{ required: true, message: '请填写', trigger: 'blur' }],
        followUser: [{ required: true, message: '请填写', trigger: 'blur' }],
        followRecord: [{ required: true, message: '请填写', trigger: 'blur' }],
        reportScope: [{ required: true, message: '请填写', trigger: 'blur' }],
        qualityRemark: [{ required: true, message: '请填写', trigger: 'blur' }],
      },
      operationType: '',
      approvalDialog: false,
      approvalLoading: false,
      examineDialog: false,
      examineLoading: false,
      qualityRemark: '',
      examineRemark: '',
    };
  },
  mounted() {
  },
  // æ–¹æ³•集合
  methods: {
    // æ‰“开弹框
    openDia(type, row) {
      this.formDia = true
      this.operationType = type
      if (type !== 'add') {
        this.searchInfo(row)
      }
    },
    // æŸ¥è¯¢è¯¦æƒ…
    searchInfo(row) {
      this.diaLoading = true
      getInternalReportOne({ reportId: row.reportId }).then(res => {
        this.diaLoading = false
        if (res.code === 201) return
        this.form = res.data
      }).catch(err => {
        console.log(err)
        this.diaLoading = false
      })
    },
    // æäº¤å¼¹æ¡†æ•°æ®
    handleEdit() {
      this.$refs['form'].validate((valid) => {
        if (valid) {
          this.loading = true
          const internalReport = this.HaveJson(this.form)
          if (this.operationType === 'add') {
            addInternalReport(internalReport).then(res => {
              this.loading = false
              if (res.code === 201) return
              this.$message.success('操作成功')
              this.closeImplementDia()
            }).catch(err => {
              console.log('err---', err);
              this.loading = false
            })
          } else if (this.operationType === 'edit') {
            updateInternalReport(internalReport).then(res => {
              this.loading = false
              if (res.code === 201) return
              this.$message.success('操作成功')
              this.closeImplementDia()
            }).catch(err => {
              console.log('err---', err);
              this.loading = false
            })
          }
        } else {
          console.log('error submit!!');
          return false;
        }
      });
    },
    // å®¡æ ¸æµç¨‹
    examine(examineStatus) {
      if (examineStatus === 0) {
        this.examineDialog = true
      } else {
        this.handleExamine(examineStatus)
      }
    },
    handleExamine(examineStatus) {
      this.examineLoading = true
      const internalReport = this.HaveJson(this.form)
      internalReport.examineStatus = examineStatus
      examineInternalReport(internalReport).then(res => {
        if (res.code === 200) {
          this.$message.success('提交成功!');
          this.approvalDialog = false
          this.closeImplementDia(this.departId);
        }
        this.examineLoading = false
      }).catch(() => {
        this.examineLoading = false
      })
    },
    // æäº¤å®¡æ ¸ä¿¡æ¯
    handleApproval(qualityStatus) {
      this.approvalLoading = true
      const internalReport = this.HaveJson(this.form)
      internalReport.qualityStatus = qualityStatus
      qualityInternalReport(internalReport).then(res => {
        if (res.code === 200) {
          this.$message.success('提交成功!');
          this.approvalDialog = false
          this.closeImplementDia(this.departId);
        }
        this.approvalLoading = false
      }).catch(() => {
        this.approvalLoading = false
      })
    },
    closeImplementDia() {
      this.$refs.form.resetFields();
      this.formDia = false
      this.$emit('closeImplementDia')
    },
  }
};
</script>
<style scoped>
>>>.el-dialog {
  margin: 6vh auto 50px !important;
}
>>>.el-dialog__body {
  max-height: 42em;
  overflow-y: auto;
}
>>>.is-required {
  margin-bottom: 6px;
}
</style>
src/views/CNAS/systemManagement/internalAuditManagement/components/correctiveAction.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,181 @@
<template>
  <div>
    <div class="search-background">
      <span class="search-group">
        <span style="width: 200px">不合格描述:</span>
        <el-input v-model="searchForm.raiseResult" clearable size="small"></el-input>
        <el-button size="medium" style="margin-left: 10px" @click="resetSearchForm">重 ç½®</el-button>
        <el-button size="medium" type="primary" @click="searchList">查 è¯¢</el-button>
      </span>
      <span class="search-group">
        <el-button size="medium" type="primary" @click="openFormDia('add')">新 å¢ž</el-button>
      </span>
    </div>
    <div class="table">
      <limsTable :column="tableColumn" :height="'calc(100vh - 23em)'" :table-data="tableData"
        :table-loading="tableLoading" style="padding: 0 10px;margin-bottom: 16px" :page="page" @pagination="pagination">
      </limsTable>
    </div>
    <corrective-action-d-ia v-if="correctiveActionDIa" ref="correctiveActionDIa"
      @closeRectifyDia="closeRectifyDia"></corrective-action-d-ia>
    <view-test-record v-if="viewTestRecordDialog" ref="viewTestRecordDialog"></view-test-record>
  </div>
</template>
<script>
import TableCard from '@/components/TableCard/index.vue';
import limsTable from "@/components/Table/lims-table.vue";
import CorrectiveActionDIa from './correctiveActionDIa.vue';
import ViewTestRecord from './ViewTestRecord.vue';
import {
  pageInternalCorrect,
  exportInternalCorrect,
} from '@/api/cnas/systemManagement/internalAuditManagement.js'
export default {
  name: 'correctiveAction',
  // import å¼•入的组件需要注入到对象中才能使用
  components: { CorrectiveActionDIa, limsTable, TableCard, ViewTestRecord },
  data() {
    // è¿™é‡Œå­˜æ”¾æ•°æ®
    return {
      searchForm: {
        raiseResult: '',
      },
      tableColumn: [
        {
          label: '不合格或偏离事实的描述',
          prop: 'raiseResult',
          minWidth: '100'
        },
        {
          label: '原因分析',
          prop: 'causeResult',
          minWidth: '100'
        },
        {
          label: '纠正措施',
          prop: 'correctResult',
          minWidth: '100'
        },
        {
          label: '实施验证结果',
          prop: 'validationResult',
          minWidth: '100'
        },
        {
          dataType: 'action',
          minWidth: '220',
          label: '操作',
          operation: [
            {
              name: '导出',
              type: 'text',
              clickFun: (row) => {
                this.handleDown(row)
              }
            },
            {
              name: '纠正',
              type: 'text',
              clickFun: (row) => {
                this.openFormDia('rectify', row);
              },
            },
            {
              name: '查看附件',
              type: 'text',
              clickFun: (row) => {
                this.viewFiles(row);
              },
            },
          ]
        }
      ],
      tableData: [],
      tableLoading: false,
      page: {
        size: 20,
        current: 1,
        total: 0,
      },
      correctiveActionDIa: false,
      viewTestRecordDialog: false,
    };
  },
  mounted() {
    this.searchList()
  },
  // æ–¹æ³•集合
  methods: {
    // æŸ¥è¯¢åˆ—表
    searchList() {
      const entity = {
        raiseResult: this.searchForm.raiseResult,
      }
      const page = this.page
      this.tableLoading = true
      pageInternalCorrect({ ...entity, ...page }).then(res => {
        this.tableLoading = false
        if (res.code === 201) return
        this.tableData = res.data.records
        this.page.total = res.data.total
      }).catch(err => {
        console.log('err---', err);
        this.tableLoading = false
      })
    },
    // é‡ç½®æŸ¥è¯¢æ¡ä»¶
    resetSearchForm() {
      this.searchForm.raiseResult = '';
      this.searchList()
    },
    // æŸ¥çœ‹é™„ä»¶
    viewFiles(row) {
      this.viewTestRecordDialog = true
      this.$nextTick(() => {
        this.$refs.viewTestRecordDialog.openDia(row)
      })
    },
    openFormDia(type, row) {
      this.correctiveActionDIa = true
      this.$nextTick(() => {
        this.$refs.correctiveActionDIa.openDia(type, row)
      })
    },
    // å¯¼å‡º
    handleDown(row) {
      exportInternalCorrect({ correctId: row.correctId }).then(res => {
        this.outLoading = false
        const blob = new Blob([res], { type: 'application/msword' });
        this.$download.saveAs(blob, '内审纠正措施' + '.docx');
      })
    },
    closeRectifyDia() {
      this.correctiveActionDIa = false
      this.searchList()
    },
    pagination({ page, limit }) {
      this.page.current = page;
      this.page.size = limit;
      this.searchList();
    },
  }
};
</script>
<style scoped>
.search-background {
  width: 100%;
  height: 60px;
  line-height: 60px;
  display: flex;
  justify-content: space-between;
}
.search-group {
  display: flex;
  align-items: center;
  margin: 0 20px;
}
</style>
src/views/CNAS/systemManagement/internalAuditManagement/components/correctiveActionDIa.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,409 @@
<template>
  <div>
    <el-dialog :close-on-click-modal="false" :close-on-press-escape="false" :visible.sync="formDia" title="纠正措施处理单"
      width="60%" @close="closeRectifyDia">
      <el-steps :active="currentStep" align-center finish-status="success">
        <el-step title="不合格或偏离事实的描述" @click.native="setStep(0)"></el-step>
        <el-step title="原因分析" @click.native="setStep(1)"></el-step>
        <el-step title="纠正措施" @click.native="setStep(2)"></el-step>
        <el-step title="实施验证结果" @click.native="setStep(3)"></el-step>
      </el-steps>
      <div>
        <table border="1" cellspacing="10" class="tables">
          <tr v-if="showStep === 0">
            <td class="td-title">
              <p><span class="required-span">* </span>不合格或偏离事实的描述:</p>
            </td>
            <td class="td-info" colspan="3">
              <el-input v-if="showStep === 0 && currentStep === 0" v-model="form.raiseResult" :rows="4"
                placeholder="请输入内容" size="small" type="textarea">
              </el-input>
              <span v-if="showStep === 0 && currentStep !== 0" class="td-info1"> {{ form.raiseResult }}</span>
            </td>
          </tr>
          <tr v-if="showStep === 0">
            <td v-if="currentStep === 0" class="td-title">
              <p><span class="required-span">* </span>请选择下一步负责人:</p>
            </td>
            <td v-if="currentStep === 0" class="td-info" colspan="3">
              <el-select v-model="form.causeUserId" clearable filterable placeholder="请选择" size="small">
                <el-option v-for="(item, i) in personList" :key="i" :label="item.label" :value="item.value">
                </el-option>
              </el-select>
            </td>
          </tr>
          <tr v-if="showStep === 0 && currentStep !== 0">
            <td class="td-title">
              <p>提出人:</p>
            </td>
            <td class="td-info">
              {{ form.raiseUserName }}
            </td>
            <td class="td-title">
              <p>提出部门:</p>
            </td>
            <td class="td-info">
              {{ form.raiseDepartment }}
            </td>
          </tr>
          <tr v-if="showStep === 0 && currentStep !== 0">
            <td class="td-title">
              <p>日期:</p>
            </td>
            <td class="td-info" colspan="3">
              {{ form.raiseTime }}
            </td>
          </tr>
          <tr v-if="showStep === 1">
            <td class="td-title">
              <p><span class="required-span">* </span>原因分析:</p>
            </td>
            <td class="td-info" colspan="3">
              <el-input v-if="showStep === 1 && currentStep === 1" v-model="form.causeResult" :rows="5"
                placeholder="请输入内容" size="small" type="textarea">
              </el-input>
              <span v-if="showStep === 1 && currentStep !== 1" class="td-info1"> {{ form.causeResult }}</span>
            </td>
          </tr>
          <tr v-if="showStep === 1 && currentStep !== 1">
            <td class="td-title">
              <p>原因分析人:</p>
            </td>
            <td class="td-info">
              {{ form.causeUserName }}
            </td>
            <td class="td-title">
              <p>责任部门:</p>
            </td>
            <td class="td-info">
              {{ form.causeDepartment }}
            </td>
          </tr>
          <tr v-if="showStep === 1 && currentStep !== 1">
            <td class="td-title">
              <p>原因分析日期:</p>
            </td>
            <td class="td-info" colspan="3">
              {{ form.causeTime }}
            </td>
          </tr>
          <tr v-if="showStep === 1">
            <td v-if="currentStep === 1" class="td-title">
              <p><span class="required-span">* </span>请选择下一步负责人:</p>
            </td>
            <td v-if="currentStep === 1" class="td-info" colspan="3">
              <el-select v-model="form.correctUserId" clearable filterable placeholder="请选择" size="small">
                <el-option v-for="(item, i) in personList" :key="i" :label="item.label" :value="item.value">
                </el-option>
              </el-select>
            </td>
          </tr>
          <tr v-if="showStep === 2">
            <td class="td-title">
              <p><span class="required-span">* </span>纠正措施:</p>
            </td>
            <td class="td-info" colspan="3">
              <el-input v-if="showStep === 2 && currentStep === 2" v-model="form.correctResult" :rows="5"
                placeholder="请输入内容" size="small" type="textarea">
              </el-input>
              <span v-if="showStep === 2 && currentStep !== 2" class="td-info1"> {{ form.correctResult }}</span>
            </td>
          </tr>
          <tr v-if="showStep === 2">
            <td class="td-title">
              <p>提出要求部门确认:</p>
            </td>
            <td class="td-info" colspan="3">
              <el-input v-if="showStep === 2 && currentStep === 2" v-model="form.raiseDepartmentAffirm" :rows="5"
                placeholder="请输入内容" size="small" type="textarea">
              </el-input>
              <span v-if="showStep === 2 && currentStep !== 2" class="td-info1"> {{ form.raiseDepartmentAffirm }}</span>
            </td>
          </tr>
          <tr v-if="showStep === 2 && currentStep !== 2">
            <td class="td-title">
              <p>纠正人:</p>
            </td>
            <td class="td-info">
              {{ form.correctUserName }}
            </td>
            <td class="td-title">
              <p>责任部门:</p>
            </td>
            <td class="td-info">
              {{ form.correctDepartment }}
            </td>
          </tr>
          <tr v-if="showStep === 2 && currentStep !== 2">
            <td class="td-title">
              <p>纠正日期:</p>
            </td>
            <td class="td-info" colspan="3">
              {{ form.correctTime }}
            </td>
          </tr>
          <tr v-if="showStep === 2">
            <td v-if="currentStep === 2" class="td-title">
              <p><span class="required-span">* </span>请选择下一步负责人:</p>
            </td>
            <td v-if="currentStep === 2" class="td-info" colspan="3">
              <el-select v-model="form.validationUserId" clearable filterable placeholder="请选择" size="small">
                <el-option v-for="(item, i) in personList" :key="i" :label="item.label" :value="item.value">
                </el-option>
              </el-select>
            </td>
          </tr>
          <tr v-if="showStep === 3">
            <td class="td-title">
              <p><span class="required-span">* </span>实施验证结果:</p>
            </td>
            <td class="td-info" colspan="3">
              <el-input v-if="showStep === 3 && currentStep === 3" v-model="form.validationResult" :rows="5"
                placeholder="请输入内容" size="small" type="textarea">
              </el-input>
              <span v-if="showStep === 3 && currentStep !== 3" class="td-info1"> {{ form.validationResult }}</span>
            </td>
          </tr>
          <tr v-if="showStep === 3 && currentStep !== 3">
            <td class="td-title">
              <p>验证人:</p>
            </td>
            <td class="td-info">
              {{ form.validationUserName }}
            </td>
            <td class="td-title">
              <p>责任部门:</p>
            </td>
            <td class="td-info">
              {{ form.validationDepartment }}
            </td>
          </tr>
          <tr v-if="showStep === 3 && currentStep !== 3">
            <td class="td-title">
              <p>验证日期:</p>
            </td>
            <td class="td-info" colspan="3">
              {{ form.validationTime }}
            </td>
          </tr>
        </table>
      </div>
      <span slot="footer" class="dialog-footer">
        <el-button @click="closeRectifyDia">取 æ¶ˆ</el-button>
        <el-button v-if="currentStep !== 4" :loading="editLoad" type="primary" @click="handleEdit">提 äº¤</el-button>
      </span>
    </el-dialog>
  </div>
</template>
<script>
import {
  getInternalCorrect,
  addInternalCorrect,
} from '@/api/cnas/systemManagement/internalAuditManagement.js'
import {
  selectUserCondition,
} from "@/api/system/user.js";
export default {
  name: 'correctiveActionDIa',
  // import å¼•入的组件需要注入到对象中才能使用
  components: {},
  data() {
    // è¿™é‡Œå­˜æ”¾æ•°æ®
    return {
      formDia: false,
      currentStep: 0,
      showStep: 0,
      form: {
        superviseDetailsId: '',
        raiseResult: '',
        vdeRaiseResult: '',
        causeUserId: '',
        raiseUserName: '',
        raiseDepartment: '',
        raiseTime: '',
        causeResult: '',
        causeUserName: '',
        causeDepartment: '',
        causeTime: '',
        correctUserId: '',
        correctResult: '',
        raiseDepartmentAffirm: '',
        correctUserName: '',
        correctDepartment: '',
        correctTime: '',
        validationUserId: '',
        validationResult: '',
        validationUserName: '',
        validationDepartment: '',
        validationTime: '',
      },
      editLoad: false,
      personList: [],
      supervisedUserList: [],
    };
  },
  mounted() {
  },
  // æ–¹æ³•集合
  methods: {
    openDia(type, row) {
      this.formDia = true
      if (type !== 'add') {
        this.searchInfo(row)
        this.form.superviseDetailsId = row.superviseDetailsId
      }
      this.getAuthorizedPerson() // èŽ·å–äººå‘˜åˆ—è¡¨
      this.getSupervisedUserList() // èŽ·å–å½“å‰éƒ¨é—¨äººå‘˜
    },
    // æŸ¥è¯¢ç›‘控计划详情实施信息
    searchInfo(row) {
      this.form.qualityMonitorDetailsId = row.qualityMonitorDetailsId
      getInternalCorrect({ correctId: row.correctId }).then(res => {
        if (res.code === 201) return
        if (res.data.superviseDetailsCorrectId === null) {
          this.showStep = 0
          this.currentStep = 0
        } else {
          this.form = res.data
          if (res.data.isFinish === 0) {
            if (res.data.causeUserId) {
              this.showStep = 1
              this.currentStep = 1
            }
            if (res.data.correctUserId) {
              this.showStep = 2
              this.currentStep = 2
            }
            if (res.data.validationUserId) {
              this.showStep = 3
              this.currentStep = 3
            }
          } else {
            this.currentStep = 4
            this.showStep = 3
          }
        }
      }).catch(err => {
        console.log('err---', err);
      })
    },
    // æäº¤
    handleEdit() {
      if (this.currentStep === 0) {
        if (!this.form.raiseResult) {
          this.$message.warning('请填写不合格描述')
          return
        }
        if (!this.form.causeUserId) {
          this.$message.warning('请选择下一步负责人')
          return
        }
      } else if (this.currentStep === 1) {
        if (!this.form.causeResult) {
          this.$message.warning('请填写原因分析')
          return
        }
        if (!this.form.correctUserId) {
          this.$message.warning('请选择下一步负责人')
          return
        }
      } else if (this.currentStep === 2) {
        if (!this.form.correctResult) {
          this.$message.warning('请填写纠正措施')
          return
        }
        if (!this.form.validationUserId) {
          this.$message.warning('请选择下一步负责人')
          return
        }
      } else if (this.currentStep === 3) {
        if (!this.form.validationResult) {
          this.$message.warning('请填写实施验证结果')
          return
        }
      }
      this.editLoad = true
      this.form.supervisedTime = ''
      this.form.flowType = this.currentStep
      addInternalCorrect(this.form).then(res => {
        this.editLoad = false
        if (res.code === 201) return
        this.$message.success('提交成功')
        this.closeRectifyDia()
      }).catch(err => {
        console.log('err---', err);
        this.editLoad = false
      })
    },
    // å…³é—­å¼¹æ¡†
    closeRectifyDia() {
      this.formDia = false
      this.$emit('closeRectifyDia')
    },
    setStep(step) {
      this.showStep = step
    },
    getAuthorizedPerson() {
      selectUserCondition().then(res => {
        let data = []
        res.data.forEach(a => {
          data.push({
            label: a.name,
            value: a.id
          })
        })
        this.personList = data
      })
    },
    getSupervisedUserList() {
      selectUserCondition({ type: 2 }).then(res => {
        let data = []
        res.data.forEach(a => {
          data.push({
            label: a.name,
            value: a.id
          })
        })
        this.supervisedUserList = data
      })
    },
  }
};
</script>
<style scoped>
>>>.el-dialog {
  margin: 10vh auto 50px !important;
}
.tables {
  table-layout: fixed;
  width: 100%;
  margin-top: 10px;
}
.td-title {
  height: 40px;
  width: 170px;
  text-align: center;
  font-size: 14px;
  word-wrap: break-word;
  white-space: normal;
  padding: 6px;
}
.td-info {
  padding: 6px;
}
.td-info1 {
  display: inline-block;
  width: 100%;
  text-align: left;
  font-size: 14px;
  word-wrap: break-word;
  white-space: normal;
}
</style>
src/views/CNAS/systemManagement/internalAuditManagement/components/implementPlanDia.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,307 @@
<template>
  <div>
    <el-dialog v-loading="diaLoading" :close-on-click-modal="false" :close-on-press-escape="false"
      :visible.sync="formDia" title="内部审核实施计划" width="80%" @close="closeImplementDia">
      <el-form ref="form" :model="form" :rules="rules" label-width="auto">
        <el-col :span="24">
          <el-form-item label="审核目的" prop="purposes">
            <el-input v-model="form.purposes" :disabled="operationType === 'ratify'" clearable size="small"></el-input>
          </el-form-item>
        </el-col>
        <el-col :span="24">
          <el-form-item label="审核性质" prop="nature">
            <el-input v-model="form.nature" :disabled="operationType === 'ratify'" clearable size="small"></el-input>
          </el-form-item>
        </el-col>
        <el-col :span="24">
          <el-form-item label="审核范围" prop="scope">
            <el-input v-model="form.scope" :disabled="operationType === 'ratify'" clearable size="small"></el-input>
          </el-form-item>
        </el-col>
        <el-col :span="24">
          <el-form-item label="审核依据" prop="basis">
            <el-input v-model="form.basis" :disabled="operationType === 'ratify'" clearable size="small"></el-input>
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="审核组长" prop="teamLeader">
            <el-input v-model="form.teamLeader" :disabled="operationType === 'ratify'" clearable
              size="small"></el-input>
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="内审员" prop="internalAuditor">
            <el-input v-model="form.internalAuditor" :disabled="operationType === 'ratify'" clearable
              size="small"></el-input>
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="审核日期" prop="reviewDate">
            <el-date-picker v-model="form.reviewDate" :disabled="operationType === 'ratify'" clearable
              format="yyyy-MM-dd" placeholder="选择日期" size="small" 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="auditMethod">
            <el-input v-model="form.auditMethod" :disabled="operationType === 'ratify'" clearable
              size="small"></el-input>
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="首次会议时间" prop="firstMeetingTime">
            <el-date-picker v-model="form.firstMeetingTime" :disabled="operationType === 'ratify'" clearable
              format="yyyy-MM-dd" placeholder="选择日期" size="small" 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="lastMeetingTime">
            <el-date-picker v-model="form.lastMeetingTime" :disabled="operationType === 'ratify'" clearable
              format="yyyy-MM-dd" placeholder="选择日期" size="small" 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="submitTime">
            <el-date-picker v-model="form.submitTime" :disabled="operationType === 'ratify'" clearable
              format="yyyy-MM-dd" placeholder="选择日期" size="small" 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="submitScope">
            <el-input v-model="form.submitScope" :disabled="operationType === 'ratify'" clearable
              size="small"></el-input>
          </el-form-item>
        </el-col>
      </el-form>
      <div v-if="operationType !== 'ratify'" style="text-align: right;margin-bottom: 10px">
        <el-button size="small" type="primary" @click="addRow">添加</el-button>
        <el-button size="small" type="danger" @click="clearTable">清空</el-button>
      </div>
      <el-table :data="implementDetailList" border height="300" style="width: 100%">
        <el-table-column align="center" label="序号" type="index" width="60" />
        <el-table-column header-align="center" label="时间" prop="implement">
          <template slot-scope="{row}">
            <el-input v-model="row.implement" :disabled="operationType === 'ratify'" size="small" />
          </template>
        </el-table-column>
        <el-table-column header-align="center" label="受审核部门" prop="department">
          <template slot-scope="{row}">
            <el-input v-model="row.department" :disabled="operationType === 'ratify'" size="small" />
          </template>
        </el-table-column>
        <el-table-column header-align="center" label="责任人" prop="responsible">
          <template slot-scope="{row}">
            <el-input v-model="row.responsible" :disabled="operationType === 'ratify'" size="small" />
          </template>
        </el-table-column>
        <el-table-column header-align="center" label="审核员" prop="auditor" width="180">
          <template slot-scope="{row}">
            <el-input v-model="row.auditor" :disabled="operationType === 'ratify'" size="small" />
          </template>
        </el-table-column>
        <el-table-column header-align="center" label="审核内容" prop="reviewContent" width="180">
          <template slot-scope="{row}">
            <el-input v-model="row.reviewContent" :disabled="operationType === 'ratify'" size="small" />
          </template>
        </el-table-column>
      </el-table>
      <span slot="footer" class="dialog-footer">
        <el-button v-if="operationType === 'ratify'" :loading="loading" @click="ratify(0)">不批准</el-button>
        <el-button v-if="operationType === 'ratify'" :loading="loading" type="primary" @click="ratify(1)">批
          å‡†</el-button>
        <el-button v-if="operationType !== 'ratify'" @click="closeImplementDia">取 æ¶ˆ</el-button>
        <el-button v-if="operationType !== 'ratify'" :loading="loading" type="primary" @click="handleEdit">提
          äº¤</el-button>
      </span>
    </el-dialog>
    <el-dialog :visible.sync="approvalDialog" title="批准" width="30%" @close="approvalDialog = false">
      <span>
        æ‰¹å‡†å¤‡æ³¨ï¼š
        <el-input v-model="ratifyRemark" type="textarea"></el-input>
      </span>
      <span slot="footer" class="dialog-footer">
        <el-button :loading="approvalLoading" @click="approvalDialog = false">取 æ¶ˆ</el-button>
        <el-button :loading="approvalLoading" type="primary" @click="handleApproval(0)">ç¡® å®š</el-button>
      </span>
    </el-dialog>
  </div>
</template>
<script>
import {
  getInternalImplementOne,
  addInternalImplement,
  updateInternalImplement,
  ratifyInternalImplement,
} from '@/api/cnas/systemManagement/internalAuditManagement.js'
export default {
  name: 'implementPlanDia',
  // import å¼•入的组件需要注入到对象中才能使用
  components: {},
  data() {
    // è¿™é‡Œå­˜æ”¾æ•°æ®
    return {
      formDia: false,
      diaLoading: false,
      loading: false,
      form: {
        purposes: '',
        nature: '',
        scope: '',
        basis: '',
        teamLeader: '',
        internalAuditor: '',
        reviewDate: '',
        auditMethod: '',
        firstMeetingTime: '',
        lastMeetingTime: '',
        submitTime: '',
        submitScope: '',
      },
      rules: {
        purposes: [{ required: true, message: '请填写审核目的', trigger: 'blur' }],
        nature: [{ required: true, message: '请填写审核性质', trigger: 'blur' }],
        scope: [{ required: true, message: '请填写审核范围', trigger: 'blur' }],
        basis: [{ required: true, message: '请填写审核依据', trigger: 'blur' }],
        teamLeader: [{ required: true, message: '请填写审核组长', trigger: 'blur' }],
        internalAuditor: [{ required: true, message: '请填写内审员', trigger: 'blur' }],
        reviewDate: [{ required: true, message: '请填写审核时间', trigger: 'blur' }],
        auditMethod: [{ required: true, message: '请填写审核方法', trigger: 'blur' }],
        firstMeetingTime: [{ required: true, message: '请填写首次会议时间', trigger: 'blur' }],
        lastMeetingTime: [{ required: true, message: '请填写末次会议时间', trigger: 'blur' }],
        submitTime: [{ required: true, message: '请填写审核报告提交日期', trigger: 'blur' }],
        submitScope: [{ required: true, message: '请填写审核报告发放范围', trigger: 'blur' }],
      },
      implementDetailList: [],
      operationType: '',
      approvalDialog: false,
      approvalLoading: false,
      ratifyRemark: '',
    };
  },
  // æ–¹æ³•集合
  methods: {
    // æ‰“开弹框
    openDia(type, row) {
      this.formDia = true
      this.operationType = type
      if (type !== 'add') {
        this.searchInfo(row)
      }
    },
    // æŸ¥è¯¢è¯¦æƒ…
    searchInfo(row) {
      this.diaLoading = true
      getInternalImplementOne({ implementId: row.implementId }).then(res => {
        this.diaLoading = false
        if (res.code === 201) return
        this.form = res.data
        this.implementDetailList = this.form.implementDetailList
      }).catch(err => {
        console.log(err)
        this.diaLoading = false
      })
    },
    // æäº¤å¼¹æ¡†æ•°æ®
    handleEdit() {
      this.$refs['form'].validate((valid) => {
        if (valid) {
          if (this.implementDetailList.length === 0) {
            this.$message.warning('请添加表格数据')
            return
          }
          this.loading = true
          const internalImplementDto = this.HaveJson(this.form)
          internalImplementDto.implementDetailList = this.HaveJson(this.implementDetailList)
          if (this.operationType === 'add') {
            addInternalImplement(internalImplementDto).then(res => {
              this.loading = false
              if (res.code === 201) return
              this.$message.success('操作成功')
              this.closeImplementDia()
            }).catch(err => {
              console.log('err---', err);
              this.loading = false
            })
          } else if (this.operationType === 'edit') {
            updateInternalImplement(internalImplementDto).then(res => {
              this.loading = false
              if (res.code === 201) return
              this.$message.success('操作成功')
              this.closeImplementDia()
            }).catch(err => {
              console.log('err---', err);
              this.loading = false
            })
          }
        } else {
          console.log('error submit!!');
          return false;
        }
      });
    },
    ratify(ratifyStatus) {
      // ä¸æ‰¹å‡†éœ€è¦å¡«å†™æ‰¹å‡†å†…容
      if (ratifyStatus === 0) {
        this.approvalDialog = true
      } else {
        this.handleApproval(ratifyStatus)
      }
    },
    // æäº¤æ‰¹å‡†ä¿¡æ¯
    handleApproval(ratifyStatus) {
      this.approvalLoading = true
      const internalImplementDto = this.HaveJson(this.form)
      internalImplementDto.ratifyStatus = ratifyStatus
      internalImplementDto.ratifyRemark = ratifyStatus === 0 ? this.ratifyRemark : ''
      ratifyInternalImplement(internalImplementDto).then(res => {
        if (res.code === 200) {
          this.$message.success('提交成功!');
          this.approvalDialog = false
          this.closeImplementDia(this.departId);
        }
        this.approvalLoading = false
      }).catch(() => {
        this.approvalLoading = false
      })
    },
    // å¢žåŠ è¡¨æ ¼è¡Œæ•°æ®
    addRow() {
      this.implementDetailList.push({
        implement: '',
        department: '',
        responsible: '',
        auditor: '',
        reviewContent: '',
      })
    },
    // æ¸…空表格数据
    clearTable() {
      this.implementDetailList = []
    },
    closeImplementDia() {
      this.$refs.form.resetFields();
      this.formDia = false
      this.$emit('closeImplementDia')
    },
  }
};
</script>
<style scoped>
>>>.el-dialog {
  margin: 10vh auto 50px !important;
}
>>>.el-dialog__body {
  max-height: 38em;
  overflow-y: auto;
}
</style>
src/views/CNAS/systemManagement/internalAuditManagement/components/implementationPlan.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,291 @@
<template>
  <div>
    <div class="search-background">
      <span class="search-group">
        <span style="width: 160px">审核目的:</span>
        <el-input v-model="searchForm.purposes" clearable size="small"></el-input>
        <el-button size="medium" style="margin-left: 10px" @click="resetSearchForm">重 ç½®</el-button>
        <el-button size="medium" type="primary" @click="searchList">查 è¯¢</el-button>
      </span>
      <span class="search-group">
        <el-button size="medium" type="primary" @click="openFormDia('add')">新 å¢ž</el-button>
      </span>
    </div>
    <div class="table">
      <limsTable :column="tableColumn" :height="'calc(100vh - 23em)'" :table-data="tableData"
        :table-loading="tableLoading" style="padding: 0 10px;margin-bottom: 16px" @pagination="pagination" :page="page">
      </limsTable>
    </div>
    <implement-plan-dia v-if="implementPlanDia" ref="implementPlanDia"
      @closeImplementDia="closeImplementDia"></implement-plan-dia>
  </div>
</template>
<script>
import {
  pageInternalImplement,
  delInternalImplement,
  exportInternalImplement,
} from '@/api/cnas/systemManagement/internalAuditManagement.js'
import limsTable from "@/components/Table/lims-table.vue";
import ImplementPlanDia from './implementPlanDia.vue';
export default {
  name: 'implementationPlan',
  // import å¼•入的组件需要注入到对象中才能使用
  components: { ImplementPlanDia, limsTable },
  data() {
    // è¿™é‡Œå­˜æ”¾æ•°æ®
    return {
      searchForm: {
        purposes: '',
      },
      tableColumn: [
        {
          label: '审核目的',
          prop: 'purposes',
          minWidth: '100'
        },
        {
          label: '审核性质',
          prop: 'nature',
          minWidth: '100'
        },
        {
          label: '审核范围',
          prop: 'scope',
          minWidth: '100'
        },
        {
          label: '审核依据',
          prop: 'basis',
          minWidth: '100'
        },
        {
          label: '审核组长',
          prop: 'teamLeader',
          minWidth: '100'
        },
        {
          label: '内审员',
          prop: 'internalAuditor',
          minWidth: '100',
        },
        {
          label: '审核日期',
          prop: 'reviewDate',
          minWidth: '100',
        },
        {
          label: '审核方法',
          prop: 'auditMethod',
          minWidth: '100',
        },
        {
          label: '首次会议时间',
          prop: 'firstMeetingTime',
          minWidth: '100',
        },
        {
          label: '末次会议时间',
          prop: 'lastMeetingTime',
          minWidth: '100',
        },
        {
          label: '审核报告提交日期',
          prop: 'submitTime',
          minWidth: '100',
        },
        {
          label: '审核报告发放范围',
          prop: 'submitScope',
          minWidth: '100',
        }, {
          dataType: 'tag',
          label: '批准状态',
          prop: 'ratifyStatus',
          minWidth: '100',
          formatData: (params) => {
            if (params === 0) {
              return '不批准';
            } else if (params === 1) {
              return '批准';
            } else {
              return null;
            }
          },
          formatType: (params) => {
            if (params === 0) {
              return 'danger';
            } else if (params === 1) {
              return 'success';
            } else {
              return null;
            }
          }
        }, {
          label: '批准内容',
          prop: 'ratifyRemark',
          minWidth: '100'
        },
        {
          dataType: 'action',
          minWidth: '220',
          fixed: 'right',
          label: '操作',
          operation: [
            {
              name: '导出',
              type: 'text',
              clickFun: (row) => {
                this.handleDown(row)
              }
            },
            {
              name: '编辑',
              type: 'text',
              clickFun: (row) => {
                this.openFormDia('edit', row);
              },
              disabled: (row) => {
                if (row.ratifyStatus === 1) {
                  return true
                } else {
                  return false
                }
              },
            },
            {
              name: '批准',
              type: 'text',
              clickFun: (row) => {
                this.openFormDia('ratify', row);
              },
              disabled: (row) => {
                if (row.ratifyStatus === 1) {
                  return true
                } else {
                  return false
                }
              },
            },
            {
              name: '删除',
              type: 'text',
              color: '#f56c6c',
              clickFun: (row) => {
                this.delPlan(row)
              },
              disabled: (row) => {
                if (row.ratifyStatus === 1) {
                  return true
                } else {
                  return false
                }
              },
            }
          ]
        }
      ],
      tableData: [],
      tableLoading: false,
      page: {
        size: 20,
        current: 1,
        total: 0,
      },
      implementPlanDia: false,
    };
  },
  mounted() {
    this.searchList()
  },
  // æ–¹æ³•集合
  methods: {
    // æŸ¥è¯¢åˆ—表
    searchList() {
      const entity = this.searchForm
      const page = this.page
      this.tableLoading = true
      pageInternalImplement({ ...entity, ...page }).then(res => {
        this.tableLoading = false
        if (res.code === 201) return
        this.tableData = res.data.records
        this.page.total = res.data.total
      }).catch(err => {
        console.log('err---', err);
        this.tableLoading = false
      })
    },
    // æ–°å¢žï¼Œç¼–辑,批准弹框
    openFormDia(type, row) {
      this.implementPlanDia = true
      this.$nextTick(() => {
        this.$refs.implementPlanDia.openDia(type, row)
      })
    },
    closeImplementDia() {
      this.implementPlanDia = false
      this.searchList()
    },
    // é‡ç½®æŸ¥è¯¢æ¡ä»¶
    resetSearchForm() {
      this.searchForm.purposes = '';
      this.searchList()
    },
    // åˆ é™¤
    delPlan(row) {
      this.$confirm('此操作将永久删除该数据, æ˜¯å¦ç»§ç»­?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        this.tableLoading = true
        delInternalImplement({ implementId: row.implementId }).then(res => {
          this.tableLoading = false
          if (res.code === 201) return
          this.$message.success('删除成功')
          this.searchList()
        }).catch(err => {
          this.tableLoading = false
          console.log('err---', err);
        })
      }).catch(() => {
        this.$message({
          type: 'info',
          message: '已取消删除'
        });
      });
    },
    // å¯¼å‡º
    handleDown(row) {
      exportInternalImplement({ implementId: row.implementId }).then(res => {
        this.outLoading = false
        const blob = new Blob([res], { type: 'application/msword' });
        this.$download.saveAs(blob, '内审实施计划' + '.docx');
      })
    },
    pagination({ page, limit }) {
      this.page.current = page;
      this.page.size = limit;
      this.searchList();
    },
  }
};
</script>
<style scoped>
.search-background {
  width: 100%;
  height: 60px;
  line-height: 60px;
  display: flex;
  justify-content: space-between;
}
.search-group {
  display: flex;
  align-items: center;
  margin: 0 20px;
}
</style>
src/views/CNAS/systemManagement/internalAuditManagement/components/yearPlan.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,313 @@
<template>
  <div>
    <div class="search-background">
      <span class="search-group">
        <span style="width: 160px">内审目的:</span>
        <el-input v-model="searchForm.purpose" clearable size="small"></el-input>
        <el-button size="medium" style="margin-left: 10px" @click="resetSearchForm">重 ç½®</el-button>
        <el-button size="medium" type="primary" @click="searchList">查 è¯¢</el-button>
      </span>
      <span class="search-group">
        <el-button size="medium" type="primary" @click="openFormDia('add')">新 å¢ž</el-button>
      </span>
    </div>
    <div class="table">
      <limsTable :column="tableColumn" :height="'calc(100vh - 23em)'" :table-data="tableData"
        :table-loading="tableLoading" style="padding: 0 10px;margin-bottom: 16px" @pagination="pagination" :page="page">
      </limsTable>
    </div>
    <year-plan-dia v-if="yearPlanDia" ref="yearPlanDia" @closeYearDia="closeYearDia"></year-plan-dia>
  </div>
</template>
<script>
import limsTable from "@/components/Table/lims-table.vue";
import YearPlanDia from './yearPlanDia.vue';
import {
  pageInternalPlan,
  delInternalPlan,
  exportInternalPlan,
} from '@/api/cnas/systemManagement/internalAuditManagement.js'
export default {
  name: 'yearPlan',
  // import å¼•入的组件需要注入到对象中才能使用
  components: { YearPlanDia, limsTable },
  data() {
    // è¿™é‡Œå­˜æ”¾æ•°æ®
    return {
      searchForm: {
        purpose: '',
      },
      tableColumn: [
        {
          label: '内审目的',
          prop: 'purpose',
          minWidth: '100'
        },
        {
          label: '内审范围',
          prop: 'scope',
          minWidth: '100'
        },
        {
          label: '内审依据',
          prop: 'basis',
          minWidth: '100'
        },
        {
          label: '组长',
          prop: 'leader',
          minWidth: '100'
        },
        {
          label: '组员',
          prop: 'crew',
          minWidth: '100'
        },
        {
          dataType: 'tag',
          label: '审核状态',
          prop: 'examineStatus',
          minWidth: '100',
          formatData: (params) => {
            if (params === 0) {
              return '不通过';
            } else if (params === 1) {
              return '通过';
            } else {
              return null;
            }
          },
          formatType: (params) => {
            if (params === 0) {
              return 'danger';
            } else if (params === 1) {
              return 'success';
            } else {
              return null;
            }
          }
        }, {
          label: '审核内容',
          prop: 'examineRemark',
          minWidth: '100'
        }, {
          label: '审核人',
          prop: 'examineUserName',
          minWidth: '100'
        }, {
          label: '审核日期',
          prop: 'examineTime',
          minWidth: '160'
        }, {
          dataType: 'tag',
          label: '批准状态',
          prop: 'ratifyStatus',
          minWidth: '100',
          formatData: (params) => {
            if (params === 0) {
              return '不批准';
            } else if (params === 1) {
              return '批准';
            } else {
              return null;
            }
          },
          formatType: (params) => {
            if (params === 0) {
              return 'danger';
            } else if (params === 1) {
              return 'success';
            } else {
              return null;
            }
          }
        }, {
          label: '批准内容',
          prop: 'ratifyRemark',
          minWidth: '100'
        }, {
          label: '批准人',
          prop: 'ratifyUserName',
          minWidth: '100'
        }, {
          label: '批准日期',
          prop: 'ratifyTime',
          minWidth: '160'
        },
        {
          dataType: 'action',
          fixed: 'right',
          minWidth: '220',
          label: '操作',
          operation: [
            {
              name: '导出',
              type: 'text',
              clickFun: (row) => {
                this.handleDown(row)
              }
            },
            {
              name: '编辑',
              type: 'text',
              clickFun: (row) => {
                this.openFormDia('edit', row);
              },
              disabled: (row) => {
                if (row.ratifyStatus === 1) {
                  return true
                } else {
                  return false
                }
              },
            },
            {
              name: '审核',
              type: 'text',
              clickFun: (row) => {
                this.openFormDia('examine', row);
              },
              disabled: (row) => {
                if (row.examineStatus === 1) {
                  return true
                } else {
                  return false
                }
              },
            },
            {
              name: '批准',
              type: 'text',
              clickFun: (row) => {
                this.openFormDia('ratify', row);
              },
              disabled: (row) => {
                if (row.ratifyStatus === 1 || row.examineStatus === 0 || row.examineStatus === null) {
                  return true
                } else {
                  return false
                }
              },
            },
            {
              name: '删除',
              type: 'text',
              color: '#f56c6c',
              clickFun: (row) => {
                this.delPlan(row)
              },
              disabled: (row) => {
                if (row.ratifyStatus === 1) {
                  return true
                } else {
                  return false
                }
              },
            }
          ]
        }
      ],
      tableData: [],
      tableLoading: false,
      page: {
        size: 20,
        current: 1,
        total: 0,
      },
      yearPlanDia: false,
    };
  },
  mounted() {
    this.searchList()
  },
  // æ–¹æ³•集合
  methods: {
    // æŸ¥è¯¢åˆ—表
    searchList() {
      const entity = this.searchForm
      const page = this.page
      this.tableLoading = true
      pageInternalPlan({ ...entity, ...page }).then(res => {
        this.tableLoading = false
        if (res.code === 201) return
        this.tableData = res.data.records
        this.page.total = res.data.total
      }).catch(err => {
        console.log('err---', err);
        this.tableLoading = false
      })
    },
    // åˆ é™¤
    delPlan(row) {
      this.$confirm('此操作将永久删除该数据, æ˜¯å¦ç»§ç»­?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        this.tableLoading = true
        delInternalPlan({ planId: row.planId }).then(res => {
          this.tableLoading = false
          if (res.code === 201) return
          this.$message.success('删除成功')
          this.searchList()
        }).catch(err => {
          this.tableLoading = false
          console.log('err---', err);
        })
      }).catch(() => {
        this.$message({
          type: 'info',
          message: '已取消删除'
        });
      });
    },
    // æ–°å¢žï¼Œç¼–辑,批准弹框
    openFormDia(type, row) {
      this.yearPlanDia = true
      this.$nextTick(() => {
        this.$refs.yearPlanDia.openDia(type, row)
      })
    },
    // å¯¼å‡º
    handleDown(row) {
      exportInternalPlan({ planId: row.planId }).then(res => {
        this.outLoading = false
        const blob = new Blob([res], { type: 'application/msword' });
        this.$download.saveAs(blob, '内审年度计划' + '.docx');
      })
    },
    closeYearDia() {
      this.yearPlanDia = false
      this.searchList()
    },
    // é‡ç½®æŸ¥è¯¢æ¡ä»¶
    resetSearchForm() {
      this.searchForm.purpose = '';
      this.searchList()
    },
    pagination({ page, limit }) {
      this.page.current = page;
      this.page.size = limit;
      this.searchList();
    },
  }
};
</script>
<style scoped>
.search-background {
  width: 100%;
  height: 60px;
  line-height: 60px;
  display: flex;
  justify-content: space-between;
}
.search-group {
  display: flex;
  align-items: center;
  margin: 0 20px;
}
</style>
src/views/CNAS/systemManagement/internalAuditManagement/components/yearPlanDia.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,342 @@
<template>
  <div>
    <el-dialog v-loading="diaLoading" :close-on-click-modal="false" :close-on-press-escape="false"
      :visible.sync="formDia" title="内部审核年度计划" width="1000px" @close="closeYearDia">
      <el-form ref="form" :model="form" :rules="rules" label-position="top" label-width="auto">
        <el-row :gutter="20">
          <el-col :span="24">
            <el-form-item label="内审目的" prop="purpose">
              <el-input v-model="form.purpose" :disabled="operationType === 'examine' || operationType === 'ratify'"
                :rows="3" clearable size="small" type="textarea"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item label="内审范围" prop="scope">
              <el-input v-model="form.scope" :disabled="operationType === 'examine' || operationType === 'ratify'"
                :rows="3" clearable size="small" type="textarea"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item label="内审依据" prop="basis">
              <el-input v-model="form.basis" :disabled="operationType === 'examine' || operationType === 'ratify'"
                clearable size="small"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="组长" prop="leader">
              <el-input v-model="form.leader" :disabled="operationType === 'examine' || operationType === 'ratify'"
                clearable size="small"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="组员" prop="crew">
              <el-input v-model="form.crew" :disabled="operationType === 'examine' || operationType === 'ratify'"
                clearable size="small"></el-input>
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <table border="1" cellspacing="10" class="table">
        <tr>
          <td class="div-with-line">
            <span style="float: left;">部门</span>
            <span style="float: right;">月份</span>
          </td>
          <th v-for="(item, index) in dic1" :key="index">{{ item }}</th>
        </tr>
        <tr v-for="(item, index) in planDetailList" :key="index">
          <td>{{ item.department }}</td>
          <th>
            <el-input v-model="item.january" :disabled="operationType === 'examine' || operationType === 'ratify'"
              clearable size="small"></el-input>
          </th>
          <th>
            <el-input v-model="item.february" :disabled="operationType === 'examine' || operationType === 'ratify'"
              clearable size="small"></el-input>
          </th>
          <th>
            <el-input v-model="item.march" :disabled="operationType === 'examine' || operationType === 'ratify'"
              clearable size="small"></el-input>
          </th>
          <th>
            <el-input v-model="item.april" :disabled="operationType === 'examine' || operationType === 'ratify'"
              clearable size="small"></el-input>
          </th>
          <th>
            <el-input v-model="item.may" :disabled="operationType === 'examine' || operationType === 'ratify'" clearable
              size="small"></el-input>
          </th>
          <th>
            <el-input v-model="item.june" :disabled="operationType === 'examine' || operationType === 'ratify'"
              clearable size="small"></el-input>
          </th>
          <th>
            <el-input v-model="item.july" :disabled="operationType === 'examine' || operationType === 'ratify'"
              clearable size="small"></el-input>
          </th>
          <th>
            <el-input v-model="item.august" :disabled="operationType === 'examine' || operationType === 'ratify'"
              clearable size="small"></el-input>
          </th>
          <th>
            <el-input v-model="item.september" :disabled="operationType === 'examine' || operationType === 'ratify'"
              clearable size="small"></el-input>
          </th>
          <th>
            <el-input v-model="item.october" :disabled="operationType === 'examine' || operationType === 'ratify'"
              clearable size="small"></el-input>
          </th>
          <th>
            <el-input v-model="item.november" :disabled="operationType === 'examine' || operationType === 'ratify'"
              clearable size="small"></el-input>
          </th>
          <th>
            <el-input v-model="item.december" :disabled="operationType === 'examine' || operationType === 'ratify'"
              clearable size="small"></el-input>
          </th>
        </tr>
      </table>
      <span slot="footer" class="dialog-footer">
        <el-button v-if="operationType === 'examine'" :loading="loading" @click="examine(0)">不通过</el-button>
        <el-button v-if="operationType === 'examine'" :loading="loading" type="primary" @click="examine(1)">通
          è¿‡</el-button>
        <el-button v-if="operationType === 'ratify'" :loading="loading" @click="approval(0)">不批准</el-button>
        <el-button v-if="operationType === 'ratify'" :loading="loading" type="primary" @click="handleApproval(1)">批
          å‡†</el-button>
        <el-button v-if="operationType !== 'ratify' && operationType !== 'examine'" @click="closeYearDia">取
          æ¶ˆ</el-button>
        <el-button v-if="operationType !== 'ratify' && operationType !== 'examine'" :loading="loading" type="primary"
          @click="handleEdit">提 äº¤</el-button>
      </span>
    </el-dialog>
    <el-dialog :visible.sync="examineDialog" title="审核" width="30%" @close="examineDialog = false">
      <span>
        å®¡æ ¸å¤‡æ³¨ï¼š
        <el-input v-model="examineRemark" type="textarea"></el-input>
      </span>
      <span slot="footer" class="dialog-footer">
        <el-button :loading="examineLoading" @click="examineDialog = false">取 æ¶ˆ</el-button>
        <el-button :loading="examineLoading" type="primary" @click="handleExamine(0)">ç¡® å®š</el-button>
      </span>
    </el-dialog>
    <el-dialog :visible.sync="approvalDialog" title="批准" width="30%" @close="approvalDialog = false">
      <span>
        æ‰¹å‡†å¤‡æ³¨ï¼š
        <el-input v-model="ratifyRemark" type="textarea"></el-input>
      </span>
      <span slot="footer" class="dialog-footer">
        <el-button :loading="approvalLoading" @click="approvalDialog = false">取 æ¶ˆ</el-button>
        <el-button :loading="approvalLoading" type="primary" @click="handleApproval(0)">ç¡® å®š</el-button>
      </span>
    </el-dialog>
  </div>
</template>
<script>
import {
  getInternalPlanOne,
  addInternalPlan,
  updateInternalPlan,
  examineInternalPlan,
  ratifyInternalPlan,
} from '@/api/cnas/systemManagement/internalAuditManagement.js'
export default {
  name: 'yearPlanDia',
  // import å¼•入的组件需要注入到对象中才能使用
  components: {},
  data() {
    // è¿™é‡Œå­˜æ”¾æ•°æ®
    return {
      formDia: false,
      diaLoading: false,
      loading: false,
      form: {
        purpose: '',
        scope: '',
        basis: '',
        leader: '',
        crew: '',
      },
      rules: {
        purpose: [{ required: true, message: '请填写内审目的', trigger: 'blur' }],
        scope: [{ required: true, message: '请填写内审范围', trigger: 'blur' }],
        basis: [{ required: true, message: '请填写内审依据', trigger: 'blur' }],
        leader: [{ required: true, message: '请填写组长', trigger: 'blur' }],
        crew: [{ required: true, message: '请填写组员', trigger: 'blur' }],
      },
      operationType: '',
      approvalDialog: false,
      approvalLoading: false,
      examineDialog: false,
      examineLoading: false,
      ratifyRemark: '',
      examineRemark: '',
      dic1: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],
      planDetailList: [{ department: '装备电缆实验室' }, { department: '通信产品实验室' }, { department: '电力产品实验室' }, { department: '储能产品实验室' }, { department: '射频线缆实验室' }],
    };
  },
  mounted() {
  },
  // æ–¹æ³•集合
  methods: {
    // æ‰“开弹框
    openDia(type, row) {
      this.formDia = true
      this.operationType = type
      if (type !== 'add') {
        this.searchInfo(row)
      }
    },
    // æŸ¥è¯¢è¯¦æƒ…
    searchInfo(row) {
      this.diaLoading = true
      getInternalPlanOne({ planId: row.planId }).then(res => {
        this.diaLoading = false
        if (res.code === 201) return
        this.form = res.data
        this.planDetailList = this.form.planDetailList
      }).catch(err => {
        console.log(err)
        this.diaLoading = false
      })
    },
    // æäº¤å¼¹æ¡†æ•°æ®
    handleEdit() {
      this.$refs['form'].validate((valid) => {
        if (valid) {
          this.loading = true
          const internalPlan = this.HaveJson(this.form)
          internalPlan.planDetailList = this.HaveJson(this.planDetailList)
          if (this.operationType === 'add') {
            addInternalPlan(internalPlan).then(res => {
              this.loading = false
              if (res.code === 201) return
              this.$message.success('操作成功')
              this.closeYearDia()
            }).catch(err => {
              console.log('err---', err);
              this.loading = false
            })
          } else if (this.operationType === 'edit') {
            updateInternalPlan(internalPlan).then(res => {
              this.loading = false
              if (res.code === 201) return
              this.$message.success('操作成功')
              this.closeYearDia()
            }).catch(err => {
              console.log('err---', err);
              this.loading = false
            })
          }
        } else {
          console.log('error submit!!');
          return false;
        }
      });
    },
    // å®¡æ ¸æµç¨‹
    examine(examineStatus) {
      if (examineStatus === 0) {
        this.examineDialog = true
      } else {
        this.handleExamine(examineStatus)
      }
    },
    handleExamine(examineStatus) {
      this.examineLoading = true
      const internalReport = this.HaveJson(this.form)
      internalReport.examineStatus = examineStatus
      internalReport.examineRemark = this.examineRemark
      examineInternalPlan(internalReport).then(res => {
        if (res.code === 200) {
          this.$message.success('提交成功!');
          this.approvalDialog = false
          this.closeYearDia(this.departId);
        }
        this.examineLoading = false
      }).catch(() => {
        this.examineLoading = false
      })
    },
    // æäº¤æ‰¹å‡†ä¿¡æ¯
    approval(ratifyStatus) {
      if (ratifyStatus === 0) {
        this.approvalDialog = true
      } else {
        this.handleApproval(ratifyStatus)
      }
    },
    handleApproval(ratifyStatus) {
      this.approvalLoading = true
      const internalReport = this.HaveJson(this.form)
      internalReport.ratifyStatus = ratifyStatus
      internalReport.ratifyRemark = this.ratifyRemark
      ratifyInternalPlan(internalReport).then(res => {
        if (res.code === 200) {
          this.$message.success('提交成功!');
          this.approvalDialog = false
          this.closeYearDia(this.departId);
        }
        this.approvalLoading = false
      }).catch(() => {
        this.approvalLoading = false
      })
    },
    closeYearDia() {
      this.$refs.form.resetFields();
      this.formDia = false
      this.$emit('closeYearDia')
    },
  }
};
</script>
<style scoped>
>>>.el-dialog {
  margin: 6vh auto 50px !important;
}
>>>.el-dialog__body {
  max-height: 42em;
  overflow-y: auto;
}
>>>.is-required {
  margin-bottom: 6px;
}
.table {
  width: 100%;
  margin-top: 20px;
}
.table th {
  width: 70px;
}
.table td {
  width: 70px;
  height: 70px;
  text-align: center;
}
.div-with-line {
  width: 70px;
  height: 70px;
  position: relative;
  /*overflow: hidden; /* éšè—æº¢å‡ºå†…容 */
}
.div-with-line::after {
  content: '';
  position: absolute;
  bottom: 0;
  height: 1px;
  background-color: #000000;
  left: 50%;
  transform: translateX(-50%) rotate(45deg);
  transform-origin: center 50%;
  top: 50%;
  width: 100px;
}
</style>
src/views/CNAS/systemManagement/internalAuditManagement/index.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,57 @@
<template>
  <div class="main">
    <el-tabs v-model="activeName" class="tab-panel" type="border-card">
      <el-tab-pane label="年度计划" name="yearPlan">
        <year-plan></year-plan>
      </el-tab-pane>
      <el-tab-pane label="内部实施计划" name="implementationPlan">
        <implementation-plan></implementation-plan>
      </el-tab-pane>
      <el-tab-pane label="内审会议签到" name="meetingSignIn">
        <audit-meeting-sign></audit-meeting-sign>
      </el-tab-pane>
      <el-tab-pane label="内审检查" name="auditInspection">
        <audit-inspection></audit-inspection>
      </el-tab-pane>
      <el-tab-pane label="纠正措施" name="correctiveAction">
        <corrective-action></corrective-action>
      </el-tab-pane>
      <el-tab-pane label="内审报告" name="auditReport">
        <audit-report></audit-report>
      </el-tab-pane>
    </el-tabs>
  </div>
</template>
<script>
import YearPlan from './components/yearPlan.vue';
import implementationPlan from './components/implementationPlan.vue';
import AuditInspection from './components/auditInspection.vue';
import AuditReport from './components/auditReport.vue';
import AuditMeetingSign from './components/auditMeetingSign.vue';
import CorrectiveAction from './components/correctiveAction.vue';
export default {
  name: 'InternalAuditManagement',
  // import å¼•入的组件需要注入到对象中才能使用
  components: { CorrectiveAction, AuditMeetingSign, AuditReport, AuditInspection, YearPlan, implementationPlan },
  data() {
    // è¿™é‡Œå­˜æ”¾æ•°æ®
    return {
      activeName: 'yearPlan',
    };
  },
  // æ–¹æ³•集合
  methods: {}
};
</script>
<style scoped>
.main {
  padding: 15px 0;
}
.tab-panel {
  background: #fff;
}
</style>
src/views/CNAS/systemManagement/managementReview/components/managementFormDIa.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,246 @@
<template>
  <div>
    <el-dialog v-loading="diaLoading" :close-on-click-modal="false" :close-on-press-escape="false"
      :visible.sync="formDia" title="管理评审计划" width="80%" @close="closeImplementDia">
      <el-form ref="form" :model="form" :rules="rules" label-position="right" label-width="auto">
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="评审时间" prop="reviewTime">
              <el-date-picker v-model="form.reviewTime" :disabled="operationType === 'ratify'" clearable
                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="judgingLocation">
              <el-input v-model="form.judgingLocation" :disabled="operationType === 'ratify'" clearable
                size="small"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item label="评审目的" prop="judgingPurpose">
              <el-input v-model="form.judgingPurpose" :disabled="operationType === 'ratify'" clearable
                size="small"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item label="评审方式" prop="judgingMethod">
              <el-input v-model="form.judgingMethod" :disabled="operationType === 'ratify'" clearable
                size="small"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item label="参加人员" prop="participants">
              <!-- <el-input v-model="form.participants" :disabled="operationType === 'ratify'" clearable size="small"></el-input> -->
              <el-select v-model="form.participants" size="small" style="width: 100%;" filterable
                :disabled="operationType === 'ratify'" clearable multiple>
                <el-option v-for="item in personList" :key="item.value" :label="item.label" :value="item.value">
                </el-option>
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item label="评审范围" prop="judgingScope">
              <el-input v-model="form.judgingScope" :disabled="operationType === 'ratify'" clearable
                size="small"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item label="评审依据" prop="judgingBasis">
              <el-input v-model="form.judgingBasis" :disabled="operationType === 'ratify'" :rows="3" clearable
                size="small" type="textarea"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item label="评审主要内容" prop="mainContext">
              <el-input v-model="form.mainContext" :disabled="operationType === 'ratify'" :rows="3" clearable
                size="small" type="textarea"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item label="准备工作要求" prop="preparationRequirements">
              <el-input v-model="form.preparationRequirements" :disabled="operationType === 'ratify'" :rows="3"
                clearable size="small" type="textarea"></el-input>
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <span slot="footer" class="dialog-footer">
        <el-button @click="closeImplementDia">取 æ¶ˆ</el-button>
        <el-button v-if="operationType === 'ratify'" :loading="loading" type="primary" @click="handleApproval(1)">批
          å‡†</el-button>
        <el-button v-if="operationType !== 'ratify'" :loading="loading" type="primary" @click="handleEdit">提
          äº¤</el-button>
      </span>
    </el-dialog>
    <el-dialog :visible.sync="approvalDialog" title="批准" width="30%" @close="approvalDialog = false">
      <span>
        æ‰¹å‡†å¤‡æ³¨ï¼š
        <el-input v-model="qualityRemark" type="textarea"></el-input>
      </span>
      <span slot="footer" class="dialog-footer">
        <el-button :loading="approvalLoading" @click="approvalDialog = false">取 æ¶ˆ</el-button>
        <el-button :loading="approvalLoading" type="primary" @click="handleApproval(0)">ç¡® å®š</el-button>
      </span>
    </el-dialog>
  </div>
</template>
<script>
import {
  addReviewProgram,
  modifyReviewProgram,
} from '@/api/cnas/systemManagement/managementReview.js'
import { dateFormat } from '@/utils/date'
import {
  selectUserCondition,
} from "@/api/system/user.js";
import { mapGetters } from "vuex";
export default {
  name: 'managementFormDIa',
  // import å¼•入的组件需要注入到对象中才能使用
  components: {},
  data() {
    // è¿™é‡Œå­˜æ”¾æ•°æ®
    return {
      formDia: false,
      diaLoading: false,
      loading: false,
      form: {
        id: '',
        reviewTime: '',
        judgingLocation: '',
        judgingPurpose: '',
        judgingMethod: '',
        participants: [],
        judgingScope: '',
        judgingBasis: '',
        mainContext: '',
        preparationRequirements: '',
      },
      rules: {
        reviewTime: [{ required: true, message: '请选择评审时间', trigger: 'blur' }],
        judgingLocation: [{ required: true, message: '请填写评审地点', trigger: 'blur' }],
        judgingPurpose: [{ required: true, message: '请填写评审目的', trigger: 'blur' }],
        judgingMethod: [{ required: true, message: '请填写评审方式', trigger: 'blur' }],
        participants: [{ required: true, message: '请填写参加人员', trigger: 'change' }],
        judgingScope: [{ required: true, message: '请填写评审范围', trigger: 'blur' }],
        judgingBasis: [{ required: true, message: '请填写评审依据', trigger: 'blur' }],
        mainContext: [{ required: true, message: '请填写评审主要内容', trigger: 'blur' }],
        preparationRequirements: [{ required: true, message: '请填写准备工作要求', trigger: 'blur' }],
      },
      operationType: '',
      approvalDialog: false,
      approvalLoading: false,
      qualityRemark: '',
      personList: [],
    };
  },
  computed: {
    ...mapGetters(['nickName'])
  },
  mounted() {
    this.getAuthorizedPerson()
  },
  // æ–¹æ³•集合
  methods: {
    // æ‰“开弹框
    openDia(type, row) {
      this.formDia = true
      this.operationType = type
      if (type !== 'add') {
        this.form = row
        this.form.participants = row.participants ? row.participants.split(',').map(m => Number(m)) : []
      }
    },
    // æŸ¥è¯¢è¯¦æƒ…
    // searchInfo (row) {
    //   this.diaLoading = true
    //   this.$axios(this.$api.internalReport.getInternalReportOne + '?reportId=' + row.reportId).then(res => {
    //     this.diaLoading = false
    //     if (res.code === 201) return
    //     this.form = res.data
    //   }).catch(err => {
    //     console.log(err)
    //     this.diaLoading = false
    //   })
    // },
    // æäº¤å¼¹æ¡†æ•°æ®
    handleEdit() {
      this.$refs['form'].validate((valid) => {
        if (valid) {
          this.loading = true
          const internalReport = this.HaveJson(this.form)
          internalReport.participants = internalReport.participants.join(',')
          if (this.operationType === 'add') {
            addReviewProgram(internalReport).then(res => {
              this.loading = false
              if (res.code === 201) return
              this.$message.success('操作成功')
              this.closeImplementDia()
            }).catch(err => {
              console.log('err---', err);
              this.loading = false
            })
          } else if (this.operationType === 'edit') {
            modifyReviewProgram(internalReport).then(res => {
              this.loading = false
              if (res.code === 201) return
              this.$message.success('操作成功')
              this.closeImplementDia()
            }).catch(err => {
              console.log('err---', err);
              this.loading = false
            })
          }
        } else {
          console.log('error submit!!');
          return false;
        }
      });
    },
    // æäº¤æ‰¹å‡†ä¿¡æ¯
    handleApproval(qualityStatus) {
      this.approvalLoading = true
      const internalReport = this.HaveJson(this.form)
      internalReport.approve = this.nickName
      internalReport.approveDate = dateFormat(new Date())
      internalReport.participants = internalReport.participants.join(',')
      modifyReviewProgram(internalReport).then(res => {
        if (res.code === 200) {
          this.$message.success('提交成功!');
          this.approvalDialog = false
          this.closeImplementDia(this.departId);
        }
        this.approvalLoading = false
      }).catch(() => {
        this.approvalLoading = false
      })
    },
    closeImplementDia() {
      this.$refs.form.resetFields();
      this.formDia = false
      this.$emit('closeImplementDia')
    },
    getAuthorizedPerson() {
      selectUserCondition().then(res => {
        let data = []
        res.data.forEach(a => {
          data.push({
            label: a.name,
            value: a.id
          })
        })
        this.personList = data
      })
    },
  }
};
</script>
<style scoped>
>>>.el-dialog {
  margin: 6vh auto 50px !important;
}
</style>
src/views/CNAS/systemManagement/managementReview/components/managementReviewPlan.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,306 @@
<template>
  <div>
    <div class="search-background">
      <span class="search-group">
        <span style="width: 160px">评审地点:</span>
        <el-input v-model="searchForm.judgingLocation" clearable size="small"></el-input>
        <el-button size="medium" style="margin-left: 10px" @click="resetSearchForm">重 ç½®</el-button>
        <el-button size="medium" type="primary" @click="searchList">查 è¯¢</el-button>
      </span>
      <span class="search-group">
        <el-button size="medium" type="primary" @click="openFormDia('add')">新 å¢ž</el-button>
      </span>
    </div>
    <div class="table">
      <limsTable :column="tableColumn" :height="'calc(100vh - 23em)'" :table-data="tableData"
        :table-loading="tableLoading" style="padding: 0 10px;margin-bottom: 16px" :page="page" @pagination="pagination">
      </limsTable>
    </div>
    <management-form-d-ia v-if="managementFormDIa" ref="managementFormDIa"
      @closeImplementDia="closeImplementDia"></management-form-d-ia>
    <el-dialog :visible.sync="listDialogVisible" title="文件查看" top="15vh" width="400px">
      <div style="max-height:60vh;overflow-y: auto;">
        <p v-for="(item, index) in fileList" :key="index">
          <span>{{ item.fileName }}</span>
          <el-button icon="el-icon-view" size="small" style="margin-left: 20px;" type="text"
            @click="lookFile(item.url, item.fileName)">预览</el-button>
          <el-button icon="el-icon-bottom" size="small" style="margin-left: 20px;" type="text"
            @click="handleDown0(item.url, item.fileName)">下载</el-button>
        </p>
      </div>
    </el-dialog>
    <el-dialog :visible.sync="lookDialogVisible" fullscreen title="查看附件" top="5vh" width="800px">
      <filePreview v-if="lookDialogVisible" :currentFile="{}" :fileUrl="javaApi + '/word/' + currentInfo.url"
        style="height: 90vh;overflow-y: auto;" />
    </el-dialog>
  </div>
</template>
<script>
import limsTable from "@/components/Table/lims-table.vue";
import ManagementFormDIa from './managementFormDIa.vue';
import filePreview from "@/components/Preview/filePreview.vue";
import {
  addReviewProgramFile,
  selectReviewProgramFile,
  getPageReviewProgram,
  deleteReviewProgram,
  exportReviewProgram,
} from '@/api/cnas/systemManagement/managementReview.js'
export default {
  name: 'managementReviewPlan',
  // import å¼•入的组件需要注入到对象中才能使用
  components: { ManagementFormDIa, limsTable, filePreview },
  data() {
    // è¿™é‡Œå­˜æ”¾æ•°æ®
    return {
      searchForm: {
        judgingLocation: '',
      },
      listDialogVisible: false,
      lookDialogVisible: false,
      fileList: [],
      currentInfo: {},
      tableColumn: [
        {
          label: '评审时间',
          prop: 'reviewTime',
        },
        {
          label: '评审地点',
          prop: 'judgingLocation',
        },
        {
          label: '评审目的',
          prop: 'judgingPurpose',
        },
        {
          label: '评审方式',
          prop: 'judgingMethod',
        },
        {
          label: '评审范围',
          prop: 'judgingScope',
        },
        // {
        //   dataType: 'tag',
        //   label: '批准状态',
        //   prop: 'approve',
        //   minWidth: '100',
        //   formatData: (params) => {
        //     if (params === 0) {
        //       return '不通过';
        //     } else if (params === 1) {
        //       return '通过';
        //     } else {
        //       return null;
        //     }
        //   },
        //   formatType: (params) => {
        //     if (params === 0) {
        //       return 'danger';
        //     } else if (params === 1) {
        //       return 'success';
        //     } else {
        //       return null;
        //     }
        //   }
        // },
        {
          dataType: 'action',
          minWidth: '110',
          label: '操作',
          operation: [
            {
              name: '编辑',
              type: 'text',
              clickFun: (row) => {
                this.openFormDia('edit', row);
              },
              disabled: (row) => {
                return !!row.approve
              },
            },
            {
              name: '上传',
              type: 'upload',
              multiple: true,
              limit: 20,
              accept: '.doc,.docx,.xls,.xlsx,.jpg,.jpeg,.png,.pdf',
              clickFun: async (row, file, fileList) => {
                const formData = new FormData();
                formData.append('file', file.raw); // æ–‡ä»¶å­—段
                formData.append('id', row.id); // æ–‡ä»¶åå­—段
                let res = await addReviewProgramFile(formData)
                if (res.code == 200) {
                  this.$message({ message: '上传成功', type: 'success' });
                  // this.searchList()
                  return
                } else {
                  this.$message({ message: '上传失败', type: 'error' });
                  return
                }
              },
              disabled: (row) => {
                return !!row.approve
              },
            },
            {
              name: '查看附件',
              type: 'text',
              clickFun: (row) => {
                selectReviewProgramFile({ id: row.id }).then(res => {
                  this.listDialogVisible = true;
                  this.fileList = res.data.fileList
                });
              },
            },
            {
              name: '批准',
              type: 'text',
              clickFun: (row) => {
                this.openFormDia('ratify', row);
              },
              disabled: (row) => {
                return !!row.approve
              },
            },
            {
              name: '删除',
              type: 'text',
              color: '#f56c6c',
              clickFun: (row) => {
                this.delPlan(row)
              },
              disabled: (row) => {
                if (row.qualityStatus === 1) {
                  return true
                } else {
                  return false
                }
              },
            },
            {
              name: '下载',
              type: 'text',
              clickFun: (row) => {
                this.handleDown(row)
              }
            },
          ]
        }
      ],
      tableData: [],
      tableLoading: false,
      page: {
        size: 20,
        current: 1,
        total: 0,
      },
      managementFormDIa: false,
    };
  },
  mounted() {
    this.searchList()
  },
  // æ–¹æ³•集合
  methods: {
    // æŸ¥è¯¢åˆ—表
    searchList() {
      this.tableLoading = true
      getPageReviewProgram({
        judgingLocation: this.searchForm.judgingLocation,
        pages: this.page.current,
        size: this.page.size
      }).then(res => {
        this.tableLoading = false
        if (res.code === 201) return
        this.tableData = res.data.records
        this.page.total = res.data.total
      }).catch(err => {
        console.log('err---', err);
        this.tableLoading = false
      })
    },
    // æ–°å¢žï¼Œç¼–辑,批准弹框
    openFormDia(type, row) {
      this.managementFormDIa = true
      this.$nextTick(() => {
        this.$refs.managementFormDIa.openDia(type, row)
      })
    },
    closeImplementDia() {
      this.managementFormDIa = false
      this.searchList()
    },
    // é‡ç½®æŸ¥è¯¢æ¡ä»¶
    resetSearchForm() {
      this.searchForm.judgingLocation = '';
      this.searchList()
    },
    // åˆ é™¤
    delPlan(row) {
      this.$confirm('此操作将永久删除该数据, æ˜¯å¦ç»§ç»­?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        this.tableLoading = true
        deleteReviewProgram({ id: row.id }).then(res => {
          this.tableLoading = false
          if (res.code === 201) return
          this.$message.success('删除成功')
          this.searchList()
        }).catch(err => {
          this.tableLoading = false
          console.log('err---', err);
        })
      }).catch(() => {
        this.$message({
          type: 'info',
          message: '已取消删除'
        });
      });
    },
    // åˆ†é¡µ
    pagination({ page, limit }) {
      this.page.current = page;
      this.page.size = limit;
      this.searchList();
    },
    handleDown(row) {
      exportReviewProgram({ id: row.id }).then(res => {
        const blob = new Blob([res], { type: 'application/octet-stream' });
        this.$download.saveAs(blob, '评审计划.docx');
      })
    },
    lookFile(url, name) {
      this.currentInfo.url = url
      this.currentInfo.name = name
      this.lookDialogVisible = true
    },
    handleDown0(url, name) {
      if (!url) return this.$message.warning('文件未上传')
      let url0 = this.javaApi + '/word/' + url
      this.$download.saveAs(url0, name);
    }
  }
};
</script>
<style scoped>
.search-background {
  width: 100%;
  height: 60px;
  line-height: 60px;
  display: flex;
  justify-content: space-between;
}
.search-group {
  display: flex;
  align-items: center;
  margin: 0 20px;
}
</style>
src/views/CNAS/systemManagement/managementReview/components/meetingRecords.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,196 @@
<template>
  <div>
    <div class="search-background">
      <span class="search-group">
        <span style="width: 160px">会议地点:</span>
        <el-input v-model="searchForm.place" clearable size="small"></el-input>
        <el-button size="medium" style="margin-left: 10px" @click="resetSearchForm">重 ç½®</el-button>
        <el-button size="medium" type="primary" @click="searchList">查 è¯¢</el-button>
      </span>
      <span class="search-group">
        <el-button size="medium" type="primary" @click="openFormDia('add')">新 å¢ž</el-button>
      </span>
    </div>
    <div class="table">
      <limsTable :column="tableColumn" :height="'calc(100vh - 23em)'" :table-data="tableData"
        :table-loading="tableLoading" style="padding: 0 10px;margin-bottom: 16px" :page="page" @pagination="pagination">
      </limsTable>
    </div>
    <meeting-records-dia v-if="meetingRecordsDia" ref="meetingRecordsDia"
      @closeYearDia="closeYearDia"></meeting-records-dia>
  </div>
</template>
<script>
import limsTable from "@/components/Table/lims-table.vue";
import MeetingRecordsDia from './meetingRecordsDia.vue';
import ManagementFormDIa from './managementFormDIa.vue';
import {
  getPageMeeting,
  deleteMeeting,
  exportMeeting,
} from '@/api/cnas/systemManagement/managementReview.js'
export default {
  name: 'meetingRecords',
  // import å¼•入的组件需要注入到对象中才能使用
  components: { ManagementFormDIa, MeetingRecordsDia, limsTable },
  data() {
    // è¿™é‡Œå­˜æ”¾æ•°æ®
    return {
      searchForm: {
        place: '',
      },
      tableColumn: [
        {
          label: '时间',
          prop: 'meetingTime',
          minWidth: '100'
        },
        {
          label: '主持人',
          prop: 'compere',
          minWidth: '100'
        },
        {
          label: '会议地点',
          prop: 'place',
          minWidth: '100'
        },
        {
          label: '会议内容摘要',
          prop: 'content',
          minWidth: '100'
        },
        {
          dataType: 'action',
          minWidth: '120',
          label: '操作',
          operation: [
            {
              name: '编辑',
              type: 'text',
              clickFun: (row) => {
                this.openFormDia('edit', row);
              },
            },
            {
              name: '删除',
              type: 'text',
              color: '#f56c6c',
              clickFun: (row) => {
                this.delPlan(row)
              }
            },
            {
              name: '下载',
              type: 'text',
              clickFun: (row) => {
                this.handleDown(row)
              }
            },
          ]
        }
      ],
      tableData: [],
      tableLoading: false,
      page: {
        size: 20,
        current: 1,
        total: 0,
      },
      meetingRecordsDia: false
    };
  },
  mounted() {
    this.searchList()
  },
  // æ–¹æ³•集合
  methods: {
    // æŸ¥è¯¢åˆ—表
    searchList() {
      this.tableLoading = true
      getPageMeeting({ place: this.searchForm.place, pages: this.page.current, size: this.page.size }).then(res => {
        this.tableLoading = false
        if (res.code === 201) return
        this.tableData = res.data.records
        this.page.total = res.data.total
      }).catch(err => {
        console.log('err---', err);
        this.tableLoading = false
      })
    },
    // æ–°å¢žï¼Œç¼–辑弹框
    openFormDia(type, row) {
      this.meetingRecordsDia = true
      this.$nextTick(() => {
        this.$refs.meetingRecordsDia.openDia(type, row)
      })
    },
    closeYearDia() {
      this.meetingRecordsDia = false
      this.searchList()
    },
    // é‡ç½®æŸ¥è¯¢æ¡ä»¶
    resetSearchForm() {
      this.searchForm.place = '';
      this.searchList()
    },
    // åˆ é™¤
    delPlan(row) {
      this.$confirm('此操作将永久删除该数据, æ˜¯å¦ç»§ç»­?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        this.tableLoading = true
        deleteMeeting({ id: row.id }).then(res => {
          this.tableLoading = false
          if (res.code === 201) return
          this.$message.success('删除成功')
          this.searchList()
        }).catch(err => {
          this.tableLoading = false
          console.log('err---', err);
        })
      }).catch(() => {
        this.$message({
          type: 'info',
          message: '已取消删除'
        });
      });
    },
    pagination({ page, limit }) {
      this.page.current = page;
      this.page.size = limit;
      this.searchList();
    },
    handleDown(row) {
      exportMeeting({ 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, '会议记录.docx');
      })
    },
  }
};
</script>
<style scoped>
.search-background {
  width: 100%;
  height: 60px;
  line-height: 60px;
  display: flex;
  justify-content: space-between;
}
.search-group {
  display: flex;
  align-items: center;
  margin: 0 20px;
}
</style>
src/views/CNAS/systemManagement/managementReview/components/meetingRecordsDia.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,158 @@
<template>
  <div>
    <el-dialog v-loading="diaLoading" :close-on-click-modal="false" :close-on-press-escape="false"
      :visible.sync="formDia" title="管理评审会议记录" width="1000px" @close="closeYearDia">
      <el-form ref="form" :model="form" :rules="rules" label-position="top" label-width="auto">
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="时间" prop="meetingTime">
              <el-date-picker v-model="form.meetingTime" clearable 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="place">
              <el-input v-model="form.place" clearable size="small"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="主持人" prop="compere">
              <el-input v-model="form.compere" clearable size="small"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="会议内容摘要" prop="content">
              <el-input v-model="form.content" clearable size="small"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item label="参会人员" prop="participant">
              <el-select v-model="form.participant" clearable filterable multiple placeholder="请选择" size="small"
                style="width: 100%;">
                <el-option v-for="(item, i) in personList" :key="i" :label="item.label" :value="item.value">
                </el-option>
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <span slot="footer" class="dialog-footer">
        <el-button @click="closeYearDia">取 æ¶ˆ</el-button>
        <el-button :loading="loading" type="primary" @click="handleEdit">提 äº¤</el-button>
      </span>
    </el-dialog>
  </div>
</template>
<script>
import {
  addMeeting,
  modifyMeeting,
} from '@/api/cnas/systemManagement/managementReview.js'
import {
  selectUserCondition,
} from "@/api/system/user.js";
export default {
  name: 'meetingRecordsDia',
  // import å¼•入的组件需要注入到对象中才能使用
  components: {},
  data() {
    // è¿™é‡Œå­˜æ”¾æ•°æ®
    return {
      formDia: false,
      diaLoading: false,
      loading: false,
      form: {
        id: '',
        meetingTime: '',
        compere: '',
        place: '',
        content: '',
        participant: [],
      },
      rules: {
        meetingTime: [{ required: true, message: '请填写会议时间', trigger: 'blur' }],
        compere: [{ required: true, message: '请填写主持人', trigger: 'blur' }],
        place: [{ required: true, message: '请填写地点', trigger: 'blur' }],
        content: [{ required: true, message: '请填写会议内容摘要', trigger: 'blur' }],
        participant: [{ required: true, message: '请选择参加人员', trigger: 'change' }],
      },
      operationType: '',
      personList: []
    };
  },
  mounted() {
  },
  // æ–¹æ³•集合
  methods: {
    // æ‰“开弹框
    openDia(type, row) {
      this.operationType = type
      this.getAuthorizedPerson()
      if (type !== 'add') {
        this.form = row
        this.form.participant = row.participant.split(',').map(a => {
          a = Number(a)
          return a
        })
      }
      this.formDia = true
    },
    // æäº¤å¼¹æ¡†æ•°æ®
    handleEdit() {
      this.$refs['form'].validate((valid) => {
        if (valid) {
          this.loading = true
          const internalMeeting = this.HaveJson(this.form)
          internalMeeting.participant = internalMeeting.participant.join(',')
          if (this.operationType === 'add') {
            addMeeting(internalMeeting).then(res => {
              this.loading = false
              if (res.code === 201) return
              this.$message.success('操作成功')
              this.closeYearDia()
            }).catch(err => {
              console.log('err---', err);
              this.loading = false
            })
          } else if (this.operationType === 'edit') {
            modifyMeeting(internalMeeting).then(res => {
              this.loading = false
              if (res.code === 201) return
              this.$message.success('操作成功')
              this.closeYearDia()
            }).catch(err => {
              console.log('err---', err);
              this.loading = false
            })
          }
        } else {
          console.log('error submit!!');
          return false;
        }
      });
    },
    closeYearDia() {
      this.$refs.form.resetFields();
      this.formDia = false
      this.$emit('closeYearDia')
    },
    getAuthorizedPerson() {
      selectUserCondition().then(res => {
        let data = []
        res.data.forEach(a => {
          data.push({
            label: a.name,
            value: a.id
          })
        })
        this.personList = data
      })
    },
  }
};
</script>
<style scoped></style>
src/views/CNAS/systemManagement/managementReview/components/reviewReport.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,266 @@
<template>
  <div>
    <div class="search-background">
      <span class="search-group">
        <span style="width: 160px">地点:</span>
        <el-input v-model="searchForm.place" clearable size="small"></el-input>
        <el-button size="medium" style="margin-left: 10px" @click="resetSearchForm">重 ç½®</el-button>
        <el-button size="medium" type="primary" @click="searchList">查 è¯¢</el-button>
      </span>
      <span class="search-group">
        <el-button size="medium" type="primary" @click="openFormDia('add')">新 å¢ž</el-button>
      </span>
    </div>
    <div class="table">
      <limsTable :column="tableColumn" :height="'calc(100vh - 23em)'" :table-data="tableData"
        :table-loading="tableLoading" style="padding: 0 10px;margin-bottom: 16px" :page="page" @pagination="pagination">
      </limsTable>
    </div>
    <review-report-dia v-if="reviewReportDia" ref="reviewReportDia" @closeYearDia="closeYearDia"></review-report-dia>
  </div>
</template>
<script>
import limsTable from "@/components/Table/lims-table.vue";
import ReviewReportDia from './reviewReportDia.vue';
import {
  getPageReviewReport,
  deleteReviewReport,
  exportReviewReport,
  modifyReviewReport,
} from '@/api/cnas/systemManagement/managementReview.js'
import { mapGetters } from "vuex";
export default {
  name: 'reviewReport',
  // import å¼•入的组件需要注入到对象中才能使用
  components: { ReviewReportDia, limsTable },
  data() {
    // è¿™é‡Œå­˜æ”¾æ•°æ®
    return {
      searchForm: {
        place: '',
      },
      tableColumn: [
        {
          label: '目的',
          prop: 'objective',
          minWidth: '100'
        },
        {
          label: '地点',
          prop: 'place',
          minWidth: '100'
        },
        {
          label: '主持人',
          prop: 'compere',
          minWidth: '100'
        },
        {
          label: '记录人',
          prop: 'recordPeople',
          minWidth: '100'
        },
        {
          label: '日期',
          prop: 'date',
          minWidth: '100'
        },
        {
          label: '页次',
          prop: 'page',
          minWidth: '100'
        },
        {
          label: '评审方式',
          prop: 'judgingMethod',
          minWidth: '100'
        },
        {
          label: '评审依据',
          prop: 'reviewBasis',
          minWidth: '100'
        },
        {
          dataType: 'action',
          minWidth: '160',
          label: '操作',
          operation: [
            {
              name: '编辑',
              type: 'text',
              clickFun: (row) => {
                this.openFormDia('edit', row);
              },
              disabled: (row) => {
                return !!row.audit || !!row.approval
              }
            },
            {
              name: '审核',
              type: 'text',
              clickFun: (row) => {
                this.$confirm('确定审核通过?', '提示', {
                  confirmButtonText: '确定',
                  cancelButtonText: '取消',
                  type: 'warning'
                }).then(() => {
                  this.submit('audit', row)
                }).catch(() => {
                });
              },
              disabled: (row) => {
                return !!row.audit
              }
            },
            {
              name: '批准',
              type: 'text',
              clickFun: (row) => {
                this.$confirm('确定批准通过?', '提示', {
                  confirmButtonText: '确定',
                  cancelButtonText: '取消',
                  type: 'warning'
                }).then(() => {
                  this.submit('approval', row)
                }).catch(() => {
                });
              },
              disabled: (row) => {
                return !row.audit || !!row.approval
              }
            },
            {
              name: '删除',
              type: 'text',
              color: '#f56c6c',
              clickFun: (row) => {
                this.delPlan(row)
              }
            },
            {
              name: '下载',
              type: 'text',
              clickFun: (row) => {
                this.handleDown(row)
              }
            },
          ]
        }
      ],
      tableData: [],
      tableLoading: false,
      page: {
        size: 20,
        current: 1,
        total: 0,
      },
      reviewReportDia: false,
    };
  },
  computed: {
    ...mapGetters(['nickName'])
  },
  mounted() {
    this.searchList()
  },
  // æ–¹æ³•集合
  methods: {
    // æŸ¥è¯¢åˆ—表
    searchList() {
      this.tableLoading = true
      getPageReviewReport({ place: this.searchForm.place, pages: this.page.current, size: this.page.size }).then(res => {
        this.tableLoading = false
        if (res.code === 201) return
        this.tableData = res.data.records
        this.page.total = res.data.total
      }).catch(err => {
        console.log('err---', err);
        this.tableLoading = false
      })
    },
    // æ–°å¢žï¼Œç¼–辑弹框
    openFormDia(type, row) {
      this.reviewReportDia = true
      this.$nextTick(() => {
        this.$refs.reviewReportDia.openDia(type, row)
      })
    },
    closeYearDia() {
      this.reviewReportDia = false
      this.searchList()
    },
    // é‡ç½®æŸ¥è¯¢æ¡ä»¶
    resetSearchForm() {
      this.searchForm.place = '';
      this.searchList()
    },
    // åˆ é™¤
    delPlan(row) {
      this.$confirm('此操作将永久删除该数据, æ˜¯å¦ç»§ç»­?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        this.tableLoading = true
        deleteReviewReport({ id: row.id }).then(res => {
          this.tableLoading = false
          if (res.code === 201) return
          this.$message.success('删除成功')
          this.searchList()
        }).catch(err => {
          this.tableLoading = false
          console.log('err---', err);
        })
      }).catch(() => {
        this.$message({
          type: 'info',
          message: '已取消删除'
        });
      });
    },
    pagination({ page, limit }) {
      this.page.current = page;
      this.page.size = limit;
      this.searchList();
    },
    handleDown(row) {
      exportReviewReport({ 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, '评审报告.docx');
      })
    },
    submit(type, row) {
      let obj = row
      obj[type] = this.nickNamee;
      modifyReviewReport(obj).then(res => {
        if (res.code === 201) return
        this.$message.success('操作成功')
        this.searchList()
      }).catch(err => {
        console.log('err---', err);
      })
    }
  }
};
</script>
<style scoped>
.search-background {
  width: 100%;
  height: 60px;
  line-height: 60px;
  display: flex;
  justify-content: space-between;
}
.search-group {
  display: flex;
  align-items: center;
  margin: 0 20px;
}
</style>
src/views/CNAS/systemManagement/managementReview/components/reviewReportDia.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,259 @@
<template>
  <div>
    <el-dialog v-loading="diaLoading" :close-on-click-modal="false" :close-on-press-escape="false"
      :visible.sync="formDia" title="管理评审会议记录" width="1000px" @close="closeYearDia">
      <el-form ref="form" :model="form" :rules="rules" label-position="top" label-width="auto">
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="目的" prop="objective">
              <el-input v-model="form.objective" clearable size="small"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="地点" prop="place">
              <el-input v-model="form.place" clearable size="small"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="主持人" prop="compere">
              <el-input v-model="form.compere" clearable size="small"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="记录人" prop="recordPeople">
              <el-input v-model="form.recordPeople" clearable size="small"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="日期" prop="date">
              <el-date-picker v-model="form.date" clearable 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="page">
              <el-input v-model="form.page" clearable size="small"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="评审方式" prop="judgingMethod">
              <el-input v-model="form.judgingMethod" clearable size="small"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="评审依据" prop="reviewBasis">
              <el-input v-model="form.reviewBasis" clearable size="small"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item label="出席人员" prop="attendess">
              <!-- <el-input v-model="form.attendess    " clearable size="small"></el-input> -->
              <el-select v-model="form.attendess" size="small" style="width: 100%;" filterable clearable multiple>
                <el-option v-for="item in personList" :key="item.value" :label="item.label" :value="item.value">
                </el-option>
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item label="评审输入情况" prop="reviewInputs">
              <el-input v-model="form.reviewInputs" clearable size="small"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item label="评审过程概况" prop="reviewProcess">
              <el-input v-model="form.reviewProcess" clearable size="small"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item label="主要议题概述" prop="mainTopic">
              <el-input v-model="form.mainTopic" :rows="5" clearable placeholder="请输入内容,可输入几千字" size="small"
                type="textarea">
              </el-input>
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item label="事项" prop="matters">
              <el-input v-model="form.matters" clearable size="small"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item label="负责人" prop="head">
              <el-input v-model="form.head" clearable size="small"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item label="完成日期" prop="completionDate">
              <el-date-picker v-model="form.completionDate" clearable 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="24">
            <el-form-item label="跟踪确认人" prop="trackingConfirmed">
              <el-input v-model="form.trackingConfirmed" clearable size="small"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item label="跟踪情况确认记录" prop="follerUp">
              <el-input v-model="form.follerUp" clearable size="small"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item label="体系评价" prop="overallEvaluation">
              <el-input v-model="form.overallEvaluation" clearable size="small"></el-input>
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <span slot="footer" class="dialog-footer">
        <el-button @click="closeYearDia">取 æ¶ˆ</el-button>
        <el-button :loading="loading" type="primary" @click="handleEdit">提 äº¤</el-button>
      </span>
    </el-dialog>
  </div>
</template>
<script>
import {
  addReviewReport,
  modifyReviewReport,
} from '@/api/cnas/systemManagement/managementReview.js'
import {
  selectUserCondition,
} from "@/api/system/user.js";
export default {
  name: 'reviewReportDia',
  // import å¼•入的组件需要注入到对象中才能使用
  components: {},
  data() {
    // è¿™é‡Œå­˜æ”¾æ•°æ®
    return {
      formDia: false,
      diaLoading: false,
      loading: false,
      form: {
        id: '',
        objective: '',
        place: '',
        compere: '',
        recordPeople: '',
        date: '',
        page: '',
        judgingMethod: '',
        reviewBasis: '',
        attendess: [],
        reviewInputs: '',
        reviewProcess: '',
        mainTopic: '',
        matters: '',
        head: '',
        completionDate: '',
        trackingConfirmed: '',
        follerUp: '',
        overallEvaluation: '',
      },
      rules: {
        objective: [{ required: true, message: '请填写目的', trigger: 'blur' }],
        place: [{ required: true, message: '请填写地点', trigger: 'blur' }],
        compere: [{ required: true, message: '请填写主持人', trigger: 'blur' }],
        recordPeople: [{ required: true, message: '请填写记录人', trigger: 'blur' }],
        date: [{ required: true, message: '请选择日期', trigger: 'change' }],
        completionDate: [{ required: true, message: '请选择完成日期', trigger: 'change' }],
        page: [{ required: true, message: '请填写页次', trigger: 'blur' }],
        judgingMethod: [{ required: true, message: '请填写评审方式', trigger: 'blur' }],
        reviewBasis: [{ required: true, message: '请填写评审依据', trigger: 'blur' }],
        attendess: [{ required: true, message: '请填写出席人员', trigger: 'change' }],
        reviewInputs: [{ required: true, message: '请填写评审输入情况', trigger: 'blur' }],
        reviewProcess: [{ required: true, message: '请填写评审输入情况', trigger: 'blur' }],
        mainTopic: [{ required: true, message: '请填写主要议题概述', trigger: 'blur' }],
        matters: [{ required: true, message: '请填写主要议题概述', trigger: 'blur' }],
        head: [{ required: true, message: '请填写负责人', trigger: 'blur' }],
        trackingConfirmed: [{ required: true, message: '请填写跟踪确认人', trigger: 'blur' }],
        follerUp: [{ required: true, message: '请填写跟踪确认人', trigger: 'blur' }],
        overallEvaluation: [{ required: true, message: '请填写体系评价', trigger: 'blur' }],
      },
      operationType: '',
      personList: []
    };
  },
  mounted() {
  },
  // æ–¹æ³•集合
  methods: {
    // æ‰“开弹框
    openDia(type, row) {
      this.formDia = true
      this.operationType = type
      this.getAuthorizedPerson()
      if (type !== 'add') {
        this.form = row
        this.form.attendess = this.form.attendess ? this.form.attendess.split(',').map(m => Number(m)) : []
      }
    },
    // æäº¤å¼¹æ¡†æ•°æ®
    handleEdit() {
      this.$refs['form'].validate((valid) => {
        if (valid) {
          this.loading = true
          const internalMeeting = this.HaveJson(this.form)
          internalMeeting.attendess = internalMeeting.attendess ? internalMeeting.attendess.join(',') : ''
          if (this.operationType === 'add') {
            addReviewReport(internalMeeting).then(res => {
              this.loading = false
              if (res.code === 201) return
              this.$message.success('操作成功')
              this.closeYearDia()
            }).catch(err => {
              console.log('err---', err);
              this.loading = false
            })
          } else if (this.operationType === 'edit') {
            modifyReviewReport(internalMeeting).then(res => {
              this.loading = false
              if (res.code === 201) return
              this.$message.success('操作成功')
              this.closeYearDia()
            }).catch(err => {
              console.log('err---', err);
              this.loading = false
            })
          }
        } else {
          console.log('error submit!!');
          return false;
        }
      });
    },
    closeYearDia() {
      this.$refs.form.resetFields();
      this.formDia = false
      this.$emit('closeYearDia')
    },
    getAuthorizedPerson() {
      selectUserCondition().then(res => {
        let data = []
        res.data.forEach(a => {
          data.push({
            label: a.name,
            value: a.id
          })
        })
        this.personList = data
      })
    },
  }
};
</script>
<style scoped>
>>>.el-dialog {
  margin: 4vh auto 50px !important;
}
>>>.el-dialog__body {
  max-height: 600px;
  overflow-y: auto;
}
</style>
src/views/CNAS/systemManagement/managementReview/index.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,48 @@
<template>
  <div class="main">
    <el-tabs v-model="activeName" class="tab-panel" type="border-card">
      <el-tab-pane label="管理评审计划" name="yearPlan">
        <management-review-plan></management-review-plan>
      </el-tab-pane>
      <el-tab-pane label="会议记录" name="implementationPlan">
        <meeting-records></meeting-records>
      </el-tab-pane>
      <el-tab-pane label="评审报告" name="meetingSignIn">
        <review-report></review-report>
      </el-tab-pane>
    </el-tabs>
  </div>
</template>
<script>
import ManagementReviewPlan from './components/managementReviewPlan.vue';
import MeetingRecords from './components/meetingRecords.vue';
import ReviewReport from './components/reviewReport.vue';
export default {
  name: 'a9-management-review',
  // import å¼•入的组件需要注入到对象中才能使用
  components: { ReviewReport, MeetingRecords, ManagementReviewPlan },
  data() {
    // è¿™é‡Œå­˜æ”¾æ•°æ®
    return {
      activeName: 'yearPlan',
    };
  },
  mounted() {
  },
  // æ–¹æ³•集合
  methods: {}
};
</script>
<style scoped>
.main {
  padding: 15px 0;
}
.tab-panel {
  background: #fff;
}
</style>
src/views/CNAS/systemManagement/measuresDealRisks/components/hazardIdentificationRiskAssessment.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,331 @@
<template>
  <div style="padding: 10px">
    <div class="header">
      <span></span>
      <div style="min-width: 200px">
        <el-button type="primary" size="small" @click="addFun">新 å¢ž</el-button>
        <el-button type="primary" size="small" @click="approvalFun">审 æ‰¹</el-button>
        <el-button type="primary" size="small" @click="approveFun">批 å‡†</el-button>
        <el-upload style="display: inline-block; padding: 0 6px" :headers="uploadHeader" :action="action"
          :on-error="onError" :show-file-list="false" :on-success="onSuccess">
          <el-button size="small" type="primary">导 å…¥</el-button>
        </el-upload>
        <el-button size="small" @click="openDownloadDia">导出</el-button>
      </div>
    </div>
    <el-table :data="tableData" style="width: 100%" height="calc(100vh - 18em)" key="table1">
      <el-table-column type="index" label="序号" width="120">
        <template v-slot="scope">
          <span>{{ (page.current - 1) * page.size + scope.$index + 1 }}</span>
        </template>
      </el-table-column>
      <el-table-column prop="venue" label="地点/活动" min-width="180"></el-table-column>
      <el-table-column prop="hazard" label="危险因素" width="testDate" min-width="180"></el-table-column>
      <el-table-column prop="accidents" label="可能导致的事故" min-width="180"></el-table-column>
      <el-table-column prop="injury" label="对人可能造成的危害" min-width="180"></el-table-column>
      <el-table-column label="风险评价" align="center" min-width="180">
        <template>
          <el-table-column prop="riskL" label="L" min-width="80"></el-table-column>
          <el-table-column prop="riskE" label="E" min-width="80"></el-table-column>
          <el-table-column prop="riskC" label="C" min-width="80"></el-table-column>
          <el-table-column prop="riskD" label="D" min-width="80"></el-table-column>
        </template>
      </el-table-column>
      <el-table-column prop="level" label="风险等级" min-width="180"></el-table-column>
      <el-table-column prop="measures" label="控制措施" min-width="180"></el-table-column>
      <el-table-column prop="editorName" label="编制人姓名" min-width="180"></el-table-column>
      <el-table-column prop="editorDate" label="编制日期" min-width="180"></el-table-column>
      <el-table-column prop="approvalName" label="审批人姓名" min-width="180"></el-table-column>
      <el-table-column prop="approvalDate" label="审批日期" min-width="180"></el-table-column>
      <el-table-column prop="approvalStatus" label="审批状态" min-width="180">
        <template #default="{ row }">
          {{ row.approvalStatus === 1 ? '通过' : row.approvalStatus === 2 ? '不通过' : '' }}
        </template>
      </el-table-column>
      <el-table-column prop="approveName" label="批准人姓名" min-width="180"></el-table-column>
      <el-table-column prop="approveStatus" label="批准状态" min-width="180">
        <template #default="{ row }">
          {{ row.approveStatus === 1 ? '通过' : row.approveStatus === 2 ? '不通过' : '' }}
        </template>
      </el-table-column>
      <el-table-column prop="approveDate" label="批准日期" min-width="180"></el-table-column>
      <el-table-column fixed="right" label="操作" width="100">
        <template v-slot="scope">
          <el-button type="text" size="small" @click="editClick(scope.row)">编辑</el-button>
          <el-button @click="deleteClick(scope.row)" type="text" size="small">删除</el-button>
        </template>
      </el-table-column>
    </el-table>
    <el-pagination :current-page="1" :page-size="page.size" :page-sizes="[10, 20, 30, 50, 100]" :total="page.total"
      layout="->,total, sizes, prev, pager, next, jumper" @size-change="handleSizeChange"
      @current-change="handleCurrentChange">
    </el-pagination>
    <el-dialog title="提示" :visible.sync="dialogVisible" width="50%">
      <el-form ref="form" :model="form" label-width="120px">
        <el-row>
          <el-col :span="12">
            <el-form-item label="地点/活动">
              <el-input v-model="form.venue" size="small"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="危险因素">
              <el-input v-model="form.hazard" size="small"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="可能导致的事故">
              <el-input v-model="form.accidents" size="small"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="对人可能造成的危害" label-width="140px">
              <el-input v-model="form.injury" size="small"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="风险评价/L">
              <el-input v-model="form.riskL" size="small"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="风险评价/E">
              <el-input v-model="form.riskE" size="small"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="风险评价/C">
              <el-input v-model="form.riskC" size="small"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="风险评价/D">
              <el-input v-model="form.riskD" size="small"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="风险等级">
              <el-input v-model="form.level" size="small"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="控制措施">
              <el-input v-model="form.measures" size="small"></el-input>
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <span slot="footer" class="dialog-footer">
        <el-button @click="dialogVisible = false">取 æ¶ˆ</el-button>
        <el-button type="primary" @click="addApi" :loading="loading">ç¡® å®š</el-button>
      </span>
    </el-dialog>
  </div>
</template>
<script>
import { getToken } from "@/utils/auth";
import {
  getPageResults,
  dangerousRiskApproval,
  hazardIdentificationAndRiskApproval,
  removeRiskFactors,
  addNewRiskFactors,
  exportHazardFactorIdentification,
} from '@/api/cnas/systemManagement/measuresDealRisks.js'
import { mapGetters } from "vuex";
export default {
  data() {
    return {
      dialogVisible: false,
      form: {},
      page: {
        total: 0,
        size: 10,
        current: 1,
      },
      tableData: [],
      loading: false
    }
  },
  computed: {
    action() {
      return this.javaApi + '/manageRiskAssessmentResults/riskAssessmentImport'
    },
    ...mapGetters(["userId"]),
  },
  methods: {
    handleSizeChange(val) {
      this.page.size = val;
      this.initData();
    },
    handleCurrentChange(val) {
      this.page.current = val;
      this.initData();
    },
    // åˆ†é¡µè¡¨æ ¼åˆå§‹åŒ–
    initData() {
      this.tableData = []
      getPageResults(this.page).then(res => {
        if (res.code === 201) return;
        this.tableData = res.data.records;
        this.page.total = res.data.total;
      });
    },
    // å®¡æ‰¹
    approvalFun() {
      this.$confirm('是否审批通过?', '提示', {
        confirmButtonText: '通过',
        cancelButtonText: '不通过',
        type: 'warning',
        closeOnClickModal: false, // ç¦æ­¢ç‚¹å‡»é®ç½©å±‚关闭
        distinguishCancelAndClose: true,
        beforeClose: (action, instance, done) => {
          if (action === 'confirm') {
            this.approvalApi(this.userId, 1)
            done();
          } else if (action === 'cancel') {
            this.approvalApi(this.userId, 2)
            done();
          } else if (action === 'close') {
            // ç‚¹å‡»â€œÃ—”按钮,不允许关闭
            done();
          }
        }
      })
    },
    // å®¡æ‰¹æŽ¥å£
    approvalApi(userId, status) {
      dangerousRiskApproval({ approval: userId, status: status }).then(res => {
        if (res.code === 201) return;
        this.initData()
        this.$message({
          type: 'success',
          message: '操作成功!'
        });
      });
    },
    // æ‰¹å‡†
    approveFun() {
      this.$confirm('是否批准通过?', '提示', {
        confirmButtonText: '通过',
        cancelButtonText: '不通过',
        type: 'warning',
        closeOnClickModal: false, // ç¦æ­¢ç‚¹å‡»é®ç½©å±‚关闭
        distinguishCancelAndClose: true,
        beforeClose: (action, instance, done) => {
          if (action === 'confirm') {
            this.approveApi(this.userId, 1)
            done();
          } else if (action === 'cancel') {
            this.approveApi(this.userId, 2)
            done();
          } else if (action === 'close') {
            // ç‚¹å‡»â€œÃ—”按钮,不允许关闭
            done();
          }
        }
      })
    },
    // æ‰¹å‡†æŽ¥å£
    approveApi(userId, status) {
      hazardIdentificationAndRiskApproval({ approve: userId, status: status }).then(res => {
        if (res.code === 201) return;
        this.initData()
        this.$message({
          type: 'success',
          message: '操作成功!'
        });
      });
    },
    // æ–‡ä»¶ä¸Šä¼ å¤±è´¥
    onError() {
      this.$message({
        type: 'error',
        message: '操作失败!'
      });
    },
    // æ–‡ä»¶ä¸Šä¼ æˆåŠŸ
    onSuccess(response) {
      if (response.code == 201) {
        this.$message({
          type: 'error',
          message: response.message,
        });
        return
      }
      this.initData()
      this.$message({
        type: 'success',
        message: '操作成功!'
      });
    },
    addFun() {
      this.form = {}
      this.dialogVisible = true
    },
    // åˆ é™¤
    deleteClick(row) {
      this.$confirm('此操作将永久删除该数据, æ˜¯å¦ç»§ç»­?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        removeRiskFactors({ id: row.id }).then(res => {
          if (res.code === 201) return;
          this.initData()
          this.$message({
            type: 'success',
            message: '操作成功!'
          });
        });
      }).catch(() => {
        this.$message({
          type: 'info',
          message: '已取消删除'
        });
      });
    },
    addApi() {
      this.loading = true
      addNewRiskFactors(this.form).then(res => {
        if (res.code === 201) return;
        this.dialogVisible = false
        this.loading = false
        this.initData()
        this.$message({
          type: 'success',
          message: '操作成功!'
        });
      }).catch(err => {
        this.loading = false
      });
    },
    // ç¼–辑
    editClick(row) {
      this.form = { ...row }
      this.dialogVisible = true
    },
    // å¯¼å‡º
    openDownloadDia() {
      exportHazardFactorIdentification().then(res => {
        this.outLoading = false
        const blob = new Blob([res], { type: 'application/msword' });
        this.$download.saveAs(blob, '危险因素辨识与风险评价结果一览' + '.docx');
      })
    },
  },
  mounted() {
    this.initData()
  },
}
</script>
<style scoped>
.header {
  height: 3em;
  width: 100%;
  display: flex;
  justify-content: space-between;
}
</style>
src/views/CNAS/systemManagement/measuresDealRisks/components/listRiskAnalysisControlPlans.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,298 @@
<template>
  <div style="padding: 10px">
    <div class="header">
      <div></div>
      <div style="min-width: 200px">
        <el-button type="primary" size="small" @click="addFun">新 å¢ž</el-button>
        <el-button type="primary" size="small" @click="approvalFun">审 æ‰¹</el-button>
        <el-button type="primary" size="small" @click="approveFun">批 å‡†</el-button>
        <el-upload style="display: inline-block; padding: 0 6px" :action="action" :headers="uploadHeader"
          :on-error="onError" :show-file-list="false" :on-success="onSuccess">
          <el-button size="small" type="primary">导 å…¥</el-button>
        </el-upload>
        <el-button size="small" @click="openDownloadDia">导出</el-button>
      </div>
    </div>
    <el-table :data="tableData" style="width: 100%" height="calc(100vh - 18em)" key="table0">
      <el-table-column type="index" label="序号" width="120">
        <template v-slot="scope">
          <span>{{ (search.current - 1) * search.size + scope.$index + 1 }}</span>
        </template>
      </el-table-column>
      <el-table-column prop="jobActivity" label="作业活动" min-width="180"></el-table-column>
      <el-table-column prop="category" label="风险因素类别" width="testDate" min-width="180"></el-table-column>
      <el-table-column prop="description" label="风险因素描述" min-width="180"></el-table-column>
      <el-table-column prop="result" label="可导致的事故" min-width="180"></el-table-column>
      <el-table-column prop="intolerable" label="是否不可承受风险" min-width="180"></el-table-column>
      <el-table-column prop="plan" label="控制计划" min-width="180"></el-table-column>
      <el-table-column prop="editorName" label="编制人姓名" min-width="180"></el-table-column>
      <el-table-column prop="editorDate" label="编制日期" min-width="180"></el-table-column>
      <el-table-column prop="approvalName" label="审批姓名" min-width="180"></el-table-column>
      <el-table-column prop="approvalDate" label="审批日期" min-width="180"></el-table-column>
      <el-table-column prop="approvalStatus" label="审批状态" min-width="180">
        <template #default="{ row }">
          {{ row.approvalStatus === 1 ? '通过' : row.approvalStatus === 2 ? '不通过' : '' }}
        </template>
      </el-table-column>
      <el-table-column prop="approveName" label="批准姓名" min-width="180"></el-table-column>
      <el-table-column prop="approveStatus" label="批准状态" min-width="180">
        <template #default="{ row }">
          {{ row.approveStatus === 1 ? '通过' : row.approveStatus === 2 ? '不通过' : '' }}
        </template>
      </el-table-column>
      <el-table-column prop="approveDate" label="批准人日期" min-width="180"></el-table-column>
      <el-table-column fixed="right" label="操作" width="100">
        <template v-slot="scope">
          <el-button type="text" size="small" @click="editClick(scope.row)">编辑</el-button>
          <el-button @click="deleteClick(scope.row)" type="text" size="small">删除</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>
    <el-dialog title="提示" :visible.sync="dialogVisible" width="50%">
      <el-form ref="form" :model="form" label-width="120px">
        <el-row>
          <el-col :span="12">
            <el-form-item label="作业活动">
              <el-input v-model="form.jobActivity" size="small"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="风险因素类别">
              <el-input v-model="form.category" size="small"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="风险因素描述">
              <el-input v-model="form.description" size="small"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="可导致的事故">
              <el-input v-model="form.result" size="small"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="是否不可承受风险" label-width="130px">
              <el-input v-model="form.intolerable" size="small"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="控制计划">
              <el-input v-model="form.plan" size="small"></el-input>
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <span slot="footer" class="dialog-footer">
        <el-button @click="dialogVisible = false">取 æ¶ˆ</el-button>
        <el-button type="primary" @click="addApi" :loading="loading">ç¡® å®š</el-button>
      </span>
    </el-dialog>
  </div>
</template>
<script>
import {
  getPageList,
  riskAnalysisApprovalOfControlPlanChecklist,
  approvalOfControlPlanChecklist,
  deleteSignificantRiskFactorAnalysis,
  analysisOfMajorRiskFactorsAdded,
  exportSignificantRiskFactors,
} from '@/api/cnas/systemManagement/measuresDealRisks.js'
import { mapGetters } from "vuex";
export default {
  data() {
    return {
      dialogVisible: false,
      form: {},
      loading: false,
      search: {
        size: 20,
        current: 1,
        total: 0
      },
      tableData: [],
    }
  },
  computed: {
    action() {
      return this.javaApi + '/manageControlPlanList/importControlPlanList'
    },
    ...mapGetters(["userId"]),
  },
  methods: {
    handleSizeChange(val) {
      this.search.size = val;
      this.initData();
    },
    handleCurrentChange(val) {
      this.search.current = val;
      this.initData();
    },
    initData() {
      getPageList(this.search).then(res => {
        if (res.code === 201) return;
        this.tableData = res.data.records;
        this.search.total = res.data.total;
      });
    },
    // å®¡æ‰¹
    approvalFun() {
      this.$confirm('是否审批通过?', '提示', {
        confirmButtonText: '通过',
        cancelButtonText: '不通过',
        type: 'warning',
        closeOnClickModal: false, // ç¦æ­¢ç‚¹å‡»é®ç½©å±‚关闭
        distinguishCancelAndClose: true,
        beforeClose: (action, instance, done) => {
          if (action === 'confirm') {
            this.approvalApi(this.userId, 1)
            done();
          } else if (action === 'cancel') {
            this.approvalApi(this.userId, 2)
            done();
          } else if (action === 'close') {
            // ç‚¹å‡»â€œÃ—”按钮,不允许关闭
            done();
          }
        }
      })
    },
    // å®¡æ‰¹æŽ¥å£
    approvalApi(userId, status) {
      riskAnalysisApprovalOfControlPlanChecklist({ approval: userId, status }).then(res => {
        if (res.code === 201) return;
        this.initData()
        this.$message({
          type: 'success',
          message: '操作成功!'
        });
      });
    },
    // æ‰¹å‡†
    approveFun() {
      this.$confirm('是否批准通过?', '提示', {
        confirmButtonText: '通过',
        cancelButtonText: '不通过',
        type: 'warning',
        closeOnClickModal: false, // ç¦æ­¢ç‚¹å‡»é®ç½©å±‚关闭
        distinguishCancelAndClose: true,
        beforeClose: (action, instance, done) => {
          if (action === 'confirm') {
            this.approveApi(this.userId, 1)
            done();
          } else if (action === 'cancel') {
            this.approveApi(this.userId, 2)
            done();
          } else if (action === 'close') {
            // ç‚¹å‡»â€œÃ—”按钮,不允许关闭
            done();
          }
        }
      })
    },
    // æ‰¹å‡†æŽ¥å£
    approveApi(userId, status) {
      approvalOfControlPlanChecklist({ approve: userId, status }).then(res => {
        if (res.code === 201) return;
        this.initData()
        this.$message({
          type: 'success',
          message: '操作成功!'
        });
      });
    },
    onError() {
      this.$message({
        type: 'error',
        message: '操作失败!'
      });
    },
    onSuccess(response) {
      if (response.code == 201) {
        this.$message({
          type: 'error',
          message: response.message,
        });
        return
      }
      this.initData()
      this.$message({
        type: 'success',
        message: '操作成功!'
      });
    },
    addFun() {
      this.form = {}
      this.dialogVisible = true
    },
    // åˆ é™¤
    deleteClick(row) {
      this.$confirm('此操作将永久删除该数据, æ˜¯å¦ç»§ç»­?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        deleteSignificantRiskFactorAnalysis({ id: row.id }).then(res => {
          if (res.code === 201) return;
          this.initData()
          this.$message({
            type: 'success',
            message: '操作成功!'
          });
        });
      }).catch(() => {
        this.$message({
          type: 'info',
          message: '已取消删除'
        });
      });
    },
    addApi() {
      this.loading = true
      analysisOfMajorRiskFactorsAdded(this.form).then(res => {
        if (res.code === 201) return;
        this.dialogVisible = false
        this.loading = false
        this.initData()
        this.$message({
          type: 'success',
          message: '操作成功!'
        });
      }).catch(err => {
        this.loading = false
      });
    },
    // ç¼–辑
    editClick(row) {
      this.form = { ...row }
      this.dialogVisible = true
    },
    // å¯¼å‡º
    openDownloadDia() {
      exportSignificantRiskFactors().then(res => {
        this.outLoading = false
        const blob = new Blob([res], { type: 'application/msword' });
        this.$download.saveAs(blob, '重大风险因素分析及控制计划清单' + '.docx');
      })
    },
  },
  mounted() {
    this.initData()
  },
}
</script>
<style scoped>
.header {
  height: 3em;
  width: 100%;
  display: flex;
  justify-content: space-between;
}
</style>
src/views/CNAS/systemManagement/measuresDealRisks/index.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,39 @@
<template>
  <div class="main">
    <el-tabs v-model="activeName" type="border-card" :lazy="true">
      <el-tab-pane label="危险因素辨识与风险评价结果一览" name="危险因素辨识与风险评价结果一览">
        <HazardIdentificationRiskAssessment v-if="activeName === '危险因素辨识与风险评价结果一览'" />
      </el-tab-pane>
      <el-tab-pane label="重大风险因素分析及控制计划清单" name="重大风险因素分析及控制计划清单">
        <listRiskAnalysisControlPlans v-if="activeName === '重大风险因素分析及控制计划清单'" />
      </el-tab-pane>
    </el-tabs>
  </div>
</template>
<script>
import HazardIdentificationRiskAssessment
  from "./components/hazardIdentificationRiskAssessment.vue";
import listRiskAnalysisControlPlans
  from "./components//listRiskAnalysisControlPlans.vue";
export default {
  components: { HazardIdentificationRiskAssessment, listRiskAnalysisControlPlans },
  data() {
    return {
      activeName: '危险因素辨识与风险评价结果一览',
    }
  }
}
</script>
<style scoped>
.main {
  width: 100%;
}
/deep/ .el-tabs--border-card>.el-tabs__content {
  height: calc(100vh - 9em);
  padding: 0;
}
</style>
src/views/standard/model/index.vue
@@ -4,77 +4,29 @@
      <div class="search_thing">
        <div class="search_label">模板名称:</div>
        <div class="search_input">
          <el-input
            v-model="queryParams.name"
            clearable
            placeholder="请输入"
            size="small"
            @keyup.enter.native="refreshTable()"
          ></el-input>
          <el-input v-model="queryParams.name" clearable placeholder="请输入" size="small"
            @keyup.enter.native="refreshTable()"></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="refreshTable()"
          >查 è¯¢</el-button
        >
        <el-button size="small" type="primary" @click="refreshTable()">查 è¯¢</el-button>
      </div>
      <div class="btn">
        <el-button
          v-if="checkPermi(['standard:model:add'])"
          size="small"
          type="primary"
          @click="openAdd"
          >新增</el-button
        >
        <!-- <el-button
          v-if="checkPermi(['standard:model:copy'])"
          size="small"
          @click="copyTemplate"
          >复制模版</el-button
        > -->
        <el-button v-if="checkPermi(['standard:model:add'])" size="small" type="primary" @click="openAdd">新增</el-button>
      </div>
    </div>
    <lims-table
      :tableData="tableData"
      :column="column"
      :page="page"
      :tableLoading="tableLoading"
      :height="'calc(100vh - 240px)'"
      style="padding: 20px; padding-top: 0"
      @pagination="pagination"
    ></lims-table>
    <el-dialog
      :before-close="isClose"
      :close-on-click-modal="false"
      :close-on-press-escape="false"
      :visible.sync="isShow"
      title="模板编制"
      width="85%"
    >
    <lims-table :tableData="tableData" :column="column" :page="page" :tableLoading="tableLoading"
      :height="'calc(100vh - 240px)'" style="padding: 20px; padding-top: 0" @pagination="pagination"></lims-table>
    <el-dialog :before-close="isClose" :close-on-click-modal="false" :close-on-press-escape="false"
      :visible.sync="isShow" title="模板编制" width="85%">
      <div v-if="isShow" style="width: 100%; height: 82vh; overflow: auto">
        <Excel
          v-loading="loading"
          :data="row.thing"
          :execlTitle="row.name"
        ></Excel>
        <Excel v-loading="loading" :data="row.thing" :execlTitle="row.name"></Excel>
      </div>
    </el-dialog>
    <el-dialog
      :before-close="closeCopyTem"
      :close-on-click-modal="false"
      :close-on-press-escape="false"
      :visible.sync="isShowCopyTem"
      :title="title"
      width="35%"
    >
      <el-form
        ref="copyForm"
        :model="copyForm"
        :rules="copyFormRules"
        label-position="right"
        label-width="80px"
      >
    <el-dialog :before-close="closeCopyTem" :close-on-click-modal="false" :close-on-press-escape="false"
      :visible.sync="isShowCopyTem" :title="title" width="35%">
      <el-form ref="copyForm" :model="copyForm" :rules="copyFormRules" label-position="right" label-width="80px">
        <el-form-item label="模版编号" prop="number">
          <el-input v-model="copyForm.number" clearable size="small"></el-input>
        </el-form-item>
@@ -87,12 +39,7 @@
      </el-form>
      <span slot="footer" class="dialog-footer">
        <el-button @click="closeCopyTem">取 æ¶ˆ</el-button>
        <el-button
          :loading="submitCopyInfoLoading"
          type="primary"
          @click="submitCopyInfo"
          >ç¡® å®š</el-button
        >
        <el-button :loading="submitCopyInfoLoading" type="primary" @click="submitCopyInfo">ç¡® å®š</el-button>
      </span>
    </el-dialog>
  </div>
@@ -103,7 +50,6 @@
import Excel from "@/components/Excel/luckysheet.vue";
import {
  selectStandardTemplatePageList,
  copyStandardTemplate,
  addStandardTemplate,
  upStandardTemplate,
  delStandardTemplate,
@@ -178,16 +124,6 @@
              },
            },
            {
              name: "复制模板",
              type: "text",
              clickFun: (row) => {
                this.copyTemplate(row);
              },
              showHide: (row) => {
                return this.checkPermi(["standard:model:copy"]);
              },
            },
            {
              name: "模板编制",
              type: "text",
              clickFun: (row) => {
@@ -234,8 +170,9 @@
          this.tableLoading = false;
        });
    },
    pagination(current, size) {
      this.page.current = current;
    pagination({ page, limit }) {
      this.page.current = page;
      this.page.size = limit;
      this.getList();
    },
    refreshTable(e) {
@@ -251,12 +188,6 @@
      this.title = "新增";
      this.copyForm = {};
      this.isShowCopyTem = true;
    },
    // å¤åˆ¶æ¨¡ç‰ˆ
    copyTemplate(row) {
      this.title = "复制模版";
      this.isShowCopyTem = true;
      this.copyForm.id = row.id;
    },
    // æ–°å¢ž/编辑/复制模板
    submitCopyInfo() {
@@ -300,20 +231,6 @@
                  this.submitCopyInfoLoading = false;
                });
              break;
            case "复制模版":
              copyStandardTemplate(params)
                .then((res) => {
                  if (res.code == 201) return;
                  this.isShowCopyTem = false;
                  this.submitCopyInfoLoading = false;
                  this.$message.success("复制成功");
                  this.refreshTable("page");
                })
                .catch((err) => {
                  console.log("copyTemplate----", err);
                  this.submitCopyInfoLoading = false;
                });
              break;
          }
        } else {
          console.log("error submit!!");
@@ -339,7 +256,7 @@
            this.refreshTable("page");
          });
        })
        .catch(() => {});
        .catch(() => { });
    },
    templateWrite(row) {
      getEditTemplatePreparation({ id: row.id }).then((res) => {
@@ -363,7 +280,7 @@
        .then(() => {
          this.closed();
        })
        .catch(() => {});
        .catch(() => { });
    },
    closed() {
      this.loading = true;
@@ -455,6 +372,7 @@
.search_input {
  width: calc(100% - 110px);
}
.btn {
  position: absolute;
  right: 14px;
vue.config.js
@@ -36,7 +36,7 @@
    proxy: {
      // detail: https://cli.vuejs.org/config/#devserver-proxy
      [process.env.VUE_APP_BASE_API]: {
        target: `http://127.0.0.1:8002`,
        target: `http://192.168.0.104:8002`,
        changeOrigin: true,
        pathRewrite: {
          ["^" + process.env.VUE_APP_BASE_API]: "",