瀏覽代碼

Merge branch 'master' of http://8.136.199.33:3000/eta_front/eta_front

Karsa 10 月之前
父節點
當前提交
10ceaa640a
共有 59 個文件被更改,包括 3343 次插入472 次删除
  1. 225 0
      src/api/modules/approve.js
  2. 二進制
      src/assets/img/approve_m/approve.png
  3. 二進制
      src/assets/img/approve_m/future-icon.png
  4. 3 0
      src/assets/img/approve_m/future-icon.svg
  5. 二進制
      src/assets/img/approve_m/passed-icon.png
  6. 10 0
      src/assets/img/approve_m/passed-icon.svg
  7. 3 0
      src/assets/img/approve_m/passed-msg.svg
  8. 二進制
      src/assets/img/approve_m/passed.png
  9. 二進制
      src/assets/img/approve_m/pending.png
  10. 二進制
      src/assets/img/approve_m/process-icon.png
  11. 6 0
      src/assets/img/approve_m/process-icon.svg
  12. 3 0
      src/assets/img/approve_m/process-msg.svg
  13. 二進制
      src/assets/img/approve_m/reject-icon.png
  14. 3 0
      src/assets/img/approve_m/reject-icon.svg
  15. 10 0
      src/assets/img/approve_m/reject-msg.svg
  16. 二進制
      src/assets/img/approve_m/reject.png
  17. 二進制
      src/assets/img/approve_m/return-icon.png
  18. 5 0
      src/assets/img/approve_m/return-icon.svg
  19. 3 0
      src/assets/img/approve_m/return-msg.svg
  20. 二進制
      src/assets/img/approve_m/return.png
  21. 二進制
      src/assets/img/approve_m/select.png
  22. 二進制
      src/assets/img/approve_m/start.png
  23. 146 0
      src/components/notificationMsg.vue
  24. 65 0
      src/mixins/reportApproveConfig.js
  25. 27 0
      src/routes/modules/approveRoutes.js
  26. 12 0
      src/routes/modules/oldRoutes.js
  27. 23 3
      src/utils/buttonConfig.js
  28. 7 2
      src/views/Home.vue
  29. 386 0
      src/views/approve_manage/approveDetail.vue
  30. 194 0
      src/views/approve_manage/approveEdit.vue
  31. 311 0
      src/views/approve_manage/approveList.vue
  32. 162 0
      src/views/approve_manage/approveSetting.vue
  33. 112 0
      src/views/approve_manage/components/flowEdiotr.vue
  34. 44 0
      src/views/approve_manage/components/flowNode/addNode.vue
  35. 280 0
      src/views/approve_manage/components/flowNode/approveNode.vue
  36. 26 0
      src/views/approve_manage/components/flowNode/endNode.vue
  37. 43 0
      src/views/approve_manage/components/flowNode/startNode.vue
  38. 81 0
      src/views/approve_manage/components/rejectDialog.vue
  39. 60 0
      src/views/approve_manage/components/timeLine.vue
  40. 120 0
      src/views/approve_manage/components/timeLineItem.vue
  41. 185 0
      src/views/approve_manage/components/treeTransfer.vue
  42. 95 0
      src/views/approve_manage/config/tableConfig.js
  43. 39 0
      src/views/approve_manage/css/nodeStyle.scss
  44. 6 0
      src/views/approve_manage/css/pageStyle.scss
  45. 31 0
      src/views/approve_manage/mixins/approveMixins.js
  46. 3 4
      src/views/dataEntry_manage/databaseList.vue
  47. 3 3
      src/views/predictEdb_manage/mixins/mixin.js
  48. 0 1
      src/views/predictEdb_manage/predictEdb.vue
  49. 23 7
      src/views/report_manage/addreportNew.vue
  50. 23 7
      src/views/report_manage/editreportNew.vue
  51. 31 11
      src/views/report_manage/mixins/messagePush.js
  52. 50 15
      src/views/report_manage/reportEn/reportEditor.vue
  53. 126 94
      src/views/report_manage/reportEn/reportlist.vue
  54. 24 9
      src/views/report_manage/reportdtl.vue
  55. 129 131
      src/views/report_manage/reportlist.vue
  56. 41 16
      src/views/smartReport/editReport.vue
  57. 12 2
      src/views/smartReport/reportDetail.vue
  58. 116 166
      src/views/smartReport/reportList.vue
  59. 36 1
      src/views/system_manage/etaBaseConfig.vue

+ 225 - 0
src/api/modules/approve.js

@@ -0,0 +1,225 @@
+import http from "@/api/http.js"
+
+export const approveInterence = {
+    /**
+     * 获取审批流列表
+     * @param {Object} params 
+     * @param {Number} params.PageSize
+     * @param {Number} params.CurrentIndex
+     * @param {Number} params.ReportType 报告类型:1-中文研报;2-英文研报;3-智能研报
+     * @param {Number} params.ClassifyFirstId 关联报告一级分类ID
+     * @param {Number} params.ClassifySecondId 关联报告二级分类ID
+     * @param {String} params.Keyword
+     * @param {Number} params.SortRule 排序方式: 1-正序; 2-倒序(默认)
+     * @returns 
+     */
+    getApproveFlowList(params){
+        return http.get("/report_approve/flow/list",params)
+    },
+    /**
+     * 获取报告分类树
+     * @param {Object} params 
+     * @param {Number} params.ReportApproveFlowId 审批流ID(非必填)
+     * @returns 
+     */
+    getReportClassifyTree(params){
+        return http.get("/report_approve/report/classify_tree",params)
+    },
+    /**
+     * 删除审批流
+     * @param {Object} params 
+     * @param {Number} params.ReportApproveFlowId
+     * @returns 
+     */
+    deleteApproveFlow(params){
+        return http.post("/report_approve/flow/remove",params)
+    },
+    /**
+     * 获取审批流详情
+     * @param {Object} params 
+     * @param {Number} params.ReportApproveFlowId
+     * @returns 
+     */
+    getApproveFlowDetail(params){
+        return http.get("/report_approve/flow/detail",params)
+    },
+    /**
+     * 新增审批流
+     * @param {Object} params 
+     * @param {String} params.FlowName 审批流名称
+     * @param {Number} params.ReportType 报告类型:1-中文研报;2-英文研报;3-智能研报
+     * @param {Number} params.ClassifyFirstId 一级分类ID
+     * @param {Number} params.ClassifySecondId 二级分类ID
+     * @param {Object[]} params.Nodes 审批节点
+     * @param {Number} params.Nodes[].ApproveType 审批类型:1-依次审批;2-会签;3-或签
+     * @param {Object[]} params.Nodes[].Users 审批人信息
+     * @param {String} params.Nodes[].Users[].UserType 审批人类型: user-用户; role-角色
+     * @param {Number} params.Nodes[].Users[].UserId 用户/角色ID
+     * @param {String} params.Nodes[].Users[].UserName 用户/角色姓名
+     * @param {String} params.Nodes[].Users[].Sort 依次审批时的排序
+     * @returns 
+     */
+    addNewApproveFlow(params){
+        return http.post("/report_approve/flow/add",params)
+    },
+    /**
+     * 编辑审批流
+     * @param {Object} params 
+     * @param {Number} params.ReportApproveFlowId 审批流Id
+     * 其他参数同上
+     * @returns 
+     */
+    editApproveFlow(params){
+        return http.post("/report_approve/flow/edit",params)
+    },
+
+
+    /**
+     * 获取审批列表
+     * @param {Object} params 
+     * @param {Number} params.PageSize
+     * @param {Number} params.CurrentIndex
+     * @param {Number} params.ReportType 报告类型:1-中文研报;2-英文研报;3-智能研报
+     * @param {Number} params.ClassifyFirstId 报告的倒数第二级id
+     * @param {Number} params.ClassifySecondId 报告的倒数第一级id
+     * @param {String} params.Keyword
+     * @param {Number} params.SortRule 排序方式: 1-正序; 2-倒序(默认)
+     * @param {Number} params.SortField 排序字段:1-提交时间;2-处理时间;3-审批时间
+     * @param {Number} params.ListType 列表类型:1-待处理;2-已处理;3-我发起的
+     * @param {Number} params.ApproveState 审批状态:1-待审批;2-已审批/已通过;3-已驳回;4-已撤回/已撤销
+     * @param {Number} params.TimeType 时间类型:1-提交时间;2-处理时间;3-审批时间
+     * @param {String} params.StartTime 开始时间
+     * @param {String} params.EndTime 结束时间
+     * @returns 
+     */
+    getApproveList(params){
+        return http.get("/report_approve/list",params)
+    },
+    /**
+     * 获取审批详情
+     * @param {Object} params
+     * @param {Number} params.ReportApproveId
+     * @returns 
+     */
+    getApproveDetail(params){
+        return http.get("/report_approve/detail",params)
+    },
+    /**
+     * 审批消息通知
+     * @param {Object} params 
+     * @param {Number} params.PageSize
+     * @param {Number} params.CurrentIndex
+     * @returns 
+     */
+    getApproveMsgList(params){
+        return http.get("/report_approve/message/list",params)
+    },
+    /**
+     * 消息通知已读
+     * @param {Object} params 
+     * @param {Number} params.MessageId
+     * @returns 
+     */
+    readApproveMsg(params){
+        return http.post("/report_approve/message/read",params)
+    },
+    /**
+     * 撤销审批
+     * @param {Object} params 
+     * @param {Number} params.ReportApproveId
+     * @returns 
+     */
+    cancelApprove(params){
+        return http.post("/report_approve/cancel",params)
+    },
+    /**
+     * 通过审批
+     * @param {Object} params 
+     * @param {Number} params.ReportApproveId
+     * @returns 
+     */
+    passApprove(params){
+        return http.post("/report_approve/approve",params)
+    },
+    /**
+     * 驳回审批
+     * @param {Object} params 
+     * @param {Number} params.ReportApproveId
+     * @param {String} params.ApproveRemark
+     * @returns 
+     */
+    rejectApprove(params){
+        return http.post("/report_approve/refuse",params)
+    },
+    /**
+     * 校验研报分类是否有审批流
+     * @param {Object} params 
+     * @param {Number} params.ReportType 报告类型:1-中文研报;2-英文研报;3-智能研报
+     * @param {Number} params.ClassifyFirstId 倒数第二级分类的id
+     * @param {Number} params.ClassifySecondId 倒数第一级分类的id
+     * @returns 
+     */
+    checkClassifyApprove(params){
+        return http.post("/report_approve/classify/check_open",params)
+    },
+
+
+
+
+    /*------------研报审批接口----------- */
+    /**
+     * 中文研报提交审批
+     * @param {Object} params 
+     * @param {Number} params.ReportId
+     * @returns 
+     */
+    reportCnSubmit(params){
+        return http.post("/report/approve/submit",params)
+    },
+    /**
+     * 中文研报撤销审批
+     * @param {Object} params 
+     * @param {Number} params.ReportId
+     * @returns 
+     */
+    reportCnCancel(params){
+        return http.post("/report/approve/cancel",params)
+    },
+    /**
+     * 英文研报提交审批
+     * @param {Object} params 
+     * @param {Number} params.ReportId
+     * @returns 
+     */
+    reportEnSubmit(params){
+        return http.post("/english_report/approve/submit",params)
+    },
+    /**
+     * 英文研报撤销审批
+     * @param {Object} params 
+     * @param {Number} params.ReportId
+     * @returns 
+     */
+    reportEnCancel(params){
+        return http.post("/english_report/approve/cancel",params)
+    },
+    /**
+     * 智能研报提交审批
+     * @param {Object} params 
+     * @param {Number} params.ReportId
+     * @returns 
+     */
+    reportSmartSubmit(params){
+        return http.post("/smart_report/approve/submit",params)
+    },
+    /**
+     * 智能研报撤销审批
+     * @param {Object} params 
+     * @param {Number} params.ReportId
+     * @returns 
+     */
+    reportSmartCancel(params){
+        return http.post("/smart_report/approve/cancel",params)
+    },
+
+}

二進制
src/assets/img/approve_m/approve.png


二進制
src/assets/img/approve_m/future-icon.png


+ 3 - 0
src/assets/img/approve_m/future-icon.svg

@@ -0,0 +1,3 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<circle cx="8" cy="8" r="7" stroke="#C0C4CC" stroke-width="2"/>
+</svg>

二進制
src/assets/img/approve_m/passed-icon.png


+ 10 - 0
src/assets/img/approve_m/passed-icon.svg

@@ -0,0 +1,10 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<g clip-path="url(#clip0_2561_11064)">
+<path d="M0 8C0 3.58179 3.58179 0 8 0C12.4182 0 16 3.58179 16 8C16 12.4182 12.4182 16 8 16C3.58179 16 0 12.4182 0 8ZM6.55172 11.0411C6.65221 11.1447 6.78931 11.2048 6.9336 11.2086C7.0779 11.2123 7.2179 11.1593 7.32359 11.061L12.5661 6.18703C12.6724 6.08722 12.735 5.94935 12.7399 5.80357C12.7449 5.65779 12.692 5.51596 12.5927 5.40911C12.4934 5.30227 12.3558 5.23909 12.2101 5.2334C12.0643 5.22771 11.9222 5.27997 11.8149 5.37876L6.98483 9.9029L4.71724 7.56469C4.66696 7.51198 4.60675 7.46975 4.54006 7.44043C4.47338 7.41111 4.40155 7.39529 4.32872 7.39387C4.25589 7.39246 4.1835 7.40548 4.11573 7.43219C4.04795 7.4589 3.98614 7.49876 3.93386 7.54948C3.88157 7.6002 3.83985 7.66077 3.81109 7.7277C3.78233 7.79463 3.76712 7.86659 3.76632 7.93943C3.76552 8.01227 3.77915 8.08455 3.80642 8.15209C3.8337 8.21964 3.87408 8.28111 3.92524 8.33297L6.552 11.0411H6.55172Z" fill="#0052D9"/>
+</g>
+<defs>
+<clipPath id="clip0_2561_11064">
+<rect width="16" height="16" fill="white"/>
+</clipPath>
+</defs>
+</svg>

+ 3 - 0
src/assets/img/approve_m/passed-msg.svg

@@ -0,0 +1,3 @@
+<svg width="19" height="19" viewBox="0 0 19 19" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M9.50115 0C4.25336 0 0 4.25284 0 9.5C0 14.7472 4.25336 19 9.50115 19C14.7489 19 19 14.7449 19 9.4977C19 4.25054 14.7444 0 9.50115 0ZM14.0439 7.59633L10.3922 11.1855L8.62384 12.9147C8.61695 12.9239 8.60776 12.933 8.59628 12.9445C8.5825 12.9583 8.56642 12.9721 8.55034 12.9859C8.44011 13.0915 8.29542 13.1489 8.14155 13.1489H8.11628C7.95552 13.1489 7.80624 13.0892 7.696 12.979C7.67992 12.9652 7.66614 12.9514 7.65236 12.9399C7.64318 12.9307 7.63629 12.9239 7.6294 12.9147L4.68053 9.96616C4.44168 9.72734 4.45775 9.32318 4.71498 9.06599C4.84588 8.9351 5.02043 8.86162 5.19727 8.86162C5.35803 8.86162 5.50731 8.92132 5.61755 9.03155L8.13006 11.5438L9.4644 10.2394L13.1183 6.65023C13.2286 6.5423 13.3756 6.48489 13.534 6.48489C13.7132 6.48489 13.89 6.56067 14.0209 6.69386C14.2735 6.95564 14.2873 7.3598 14.0439 7.59633Z" fill="#68BB8D"/>
+</svg>

二進制
src/assets/img/approve_m/passed.png


二進制
src/assets/img/approve_m/pending.png


二進制
src/assets/img/approve_m/process-icon.png


+ 6 - 0
src/assets/img/approve_m/process-icon.svg

@@ -0,0 +1,6 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<circle cx="8" cy="8" r="7" fill="white" stroke="#0052D9" stroke-width="2"/>
+<circle cx="4" cy="8.5" r="1.5" fill="#0052D9"/>
+<circle cx="8" cy="8.5" r="1.5" fill="#0052D9"/>
+<circle cx="12" cy="8.5" r="1.5" fill="#0052D9"/>
+</svg>

+ 3 - 0
src/assets/img/approve_m/process-msg.svg

@@ -0,0 +1,3 @@
+<svg width="19" height="19" viewBox="0 0 19 19" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M9.5 0C4.25327 0 0 4.25324 0 9.50002C0 12.894 1.81074 16.0301 4.75 17.7273C7.68945 19.4242 11.3107 19.4242 14.25 17.7273C17.1895 16.0303 19 12.8942 19 9.50002C19.0002 4.25343 14.7467 0 9.5 0ZM9.5 14.7779C8.91712 14.7779 8.44444 14.3053 8.44444 13.7224C8.44444 13.3454 8.64566 12.9968 8.97222 12.8083C9.29879 12.6198 9.70122 12.6198 10.0278 12.8083C10.3543 12.9968 10.5556 13.3454 10.5556 13.7224C10.5556 14.3051 10.0831 14.7779 9.5 14.7779ZM10.5556 10.5556C10.5556 11.1888 10.1333 11.6111 9.5 11.6111C8.86667 11.6111 8.44444 11.1888 8.44444 10.5556V5.27788C8.44444 4.64459 8.86667 4.22234 9.5 4.22234C10.1333 4.22234 10.5556 4.64459 10.5556 5.27788V10.5556Z" fill="#E98F36"/>
+</svg>

二進制
src/assets/img/approve_m/reject-icon.png


+ 3 - 0
src/assets/img/approve_m/reject-icon.svg

@@ -0,0 +1,3 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M0 7.93442C0.036889 5.7137 0.851645 3.75612 2.51279 2.18473C4.14539 0.640302 6.11295 -0.0867217 8.35598 0.00822671C10.511 0.0994046 12.3505 0.946285 13.8273 2.5179C15.3632 4.15237 16.0877 6.11726 15.9915 8.35695C15.8993 10.5061 15.0568 12.3422 13.4922 13.8175C11.8572 15.3593 9.89104 16.0873 7.6479 15.9917C5.49497 15.8998 3.6592 15.0518 2.18102 13.4843C0.735039 11.951 0.0268387 10.1078 0 7.93442ZM7.19038 7.98972C7.168 8.01406 7.15441 8.02971 7.1399 8.04434C6.69461 8.48983 6.24909 8.93521 5.80368 9.38081C5.46322 9.72142 5.12266 10.062 4.78278 10.4031C4.62677 10.5596 4.57172 10.747 4.62471 10.962C4.68981 11.2261 4.95203 11.4084 5.21859 11.3856C5.37289 11.3724 5.49612 11.3054 5.60347 11.1979C6.38351 10.4164 7.16423 9.63573 7.94484 8.85489C7.96071 8.839 7.97716 8.82392 8.01348 8.78907C8.02684 8.81352 8.03392 8.83797 8.04968 8.85374C8.82812 9.63401 9.60781 10.413 10.3861 11.1935C10.5262 11.3339 10.6882 11.4011 10.8888 11.3838C11.1686 11.3595 11.4141 11.0681 11.3896 10.7885C11.3755 10.6285 11.31 10.4993 11.1977 10.3872C10.4339 9.62464 9.6712 8.86083 8.90818 8.09747C8.80505 7.99418 8.80493 7.99429 8.90749 7.89169C9.67188 7.12696 10.4359 6.36189 11.201 5.59784C11.3367 5.46233 11.4045 5.30466 11.3859 5.11042C11.3538 4.77553 11.0216 4.53764 10.6937 4.61397C10.5534 4.64653 10.4503 4.73097 10.3522 4.82923C9.58337 5.60013 8.81316 6.36966 8.04454 7.1409C8.00776 7.17781 7.98801 7.17895 7.95055 7.14113C7.57515 6.76271 7.19781 6.38623 6.82104 6.00929C6.41195 5.60002 6.0032 5.19029 5.59353 4.78159C5.41857 4.607 5.2106 4.55181 4.9775 4.63751C4.58931 4.78021 4.47145 5.27975 4.78963 5.59499C5.46014 6.25928 6.12528 6.92918 6.79294 7.59645C6.92291 7.72659 7.0547 7.85558 7.19038 7.98972Z" fill="#AD352F"/>
+</svg>

+ 10 - 0
src/assets/img/approve_m/reject-msg.svg

@@ -0,0 +1,10 @@
+<svg width="19" height="19" viewBox="0 0 19 19" fill="none" xmlns="http://www.w3.org/2000/svg">
+<g clip-path="url(#clip0_5316_6053)">
+<path d="M9.5 19C4.25362 19 0 14.7464 0 9.5C0 4.25362 4.25362 0 9.5 0C14.7464 0 19 4.25362 19 9.5C19 14.7464 14.7464 19 9.5 19ZM9.5 8.38058L5.57808 4.45708C5.50453 4.38405 5.41731 4.32621 5.32141 4.28688C5.2255 4.24756 5.12279 4.2275 5.01914 4.22787C4.91548 4.22824 4.81292 4.24902 4.71729 4.28903C4.62167 4.32903 4.53487 4.38749 4.46183 4.46104C4.38799 4.53391 4.32929 4.62067 4.28911 4.71631C4.24892 4.81195 4.22804 4.9146 4.22767 5.01834C4.22731 5.12209 4.24745 5.22488 4.28696 5.3208C4.32647 5.41673 4.38455 5.5039 4.45787 5.57729L8.38058 9.5L4.45708 13.4219C4.38405 13.4955 4.32621 13.5827 4.28688 13.6786C4.24756 13.7745 4.2275 13.8772 4.22787 13.9809C4.22824 14.0845 4.24902 14.1871 4.28903 14.2827C4.32903 14.3783 4.38749 14.4651 4.46104 14.5382C4.53391 14.612 4.62067 14.6707 4.71631 14.7109C4.81195 14.7511 4.9146 14.772 5.01834 14.7723C5.12209 14.7727 5.22488 14.7525 5.3208 14.713C5.41673 14.6735 5.5039 14.6154 5.57729 14.5421L9.5 10.6194L13.4219 14.5421C13.4955 14.6152 13.5827 14.673 13.6786 14.7123C13.7745 14.7517 13.8772 14.7717 13.9809 14.7713C14.0845 14.771 14.1871 14.7502 14.2827 14.7102C14.3783 14.6702 14.4651 14.6117 14.5382 14.5382C14.612 14.4653 14.6707 14.3785 14.7109 14.2829C14.7511 14.1873 14.772 14.0846 14.7723 13.9809C14.7727 13.8771 14.7525 13.7743 14.713 13.6784C14.6735 13.5825 14.6154 13.4953 14.5421 13.4219L10.6194 9.5L14.5421 5.57808C14.6152 5.50453 14.673 5.41731 14.7123 5.32141C14.7517 5.2255 14.7717 5.12279 14.7713 5.01914C14.771 4.91548 14.7502 4.81292 14.7102 4.71729C14.6702 4.62167 14.6117 4.53487 14.5382 4.46183C14.4653 4.38799 14.3785 4.32929 14.2829 4.28911C14.1873 4.24892 14.0846 4.22804 13.9809 4.22767C13.8771 4.22731 13.7743 4.24745 13.6784 4.28696C13.5825 4.32647 13.4953 4.38455 13.4219 4.45787L9.5 8.38058Z" fill="#D81E06"/>
+</g>
+<defs>
+<clipPath id="clip0_5316_6053">
+<rect width="19" height="19" fill="white"/>
+</clipPath>
+</defs>
+</svg>

二進制
src/assets/img/approve_m/reject.png


二進制
src/assets/img/approve_m/return-icon.png


+ 5 - 0
src/assets/img/approve_m/return-icon.svg

@@ -0,0 +1,5 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<circle cx="8" cy="8" r="8" fill="#999999"/>
+<path d="M6.21355 4.34426C6.26948 4.28793 6.34477 4.255 6.42411 4.25215C6.50345 4.24931 6.5809 4.27677 6.64072 4.32896C6.70055 4.38115 6.73827 4.45416 6.74622 4.53315C6.75418 4.61214 6.73177 4.6912 6.68355 4.75426L6.65563 4.78635L5.10855 6.33301L6.65563 7.87968C6.70906 7.9331 6.74133 8.00407 6.74646 8.07945C6.75159 8.15483 6.72924 8.22951 6.68355 8.28968L6.65563 8.32176C6.60221 8.3752 6.53124 8.40746 6.45586 8.4126C6.38048 8.41773 6.3058 8.39538 6.24563 8.34968L6.21355 8.32176L4.44605 6.55385C4.39262 6.50043 4.36035 6.42946 4.35521 6.35408C4.35008 6.2787 4.37243 6.20402 4.41813 6.14385L4.44605 6.11218L6.21355 4.34426Z" fill="white" stroke="white" stroke-width="0.3"/>
+<path d="M9.25023 6.02051C9.87811 6.01989 10.4811 6.26579 10.9296 6.70528C11.378 7.14477 11.636 7.74273 11.648 8.3705C11.66 8.99827 11.4251 9.60566 10.9938 10.062C10.5625 10.5183 9.96934 10.7871 9.3419 10.8105L9.25023 10.8122H4.6669C4.58772 10.8122 4.5115 10.7821 4.45365 10.728C4.3958 10.674 4.36062 10.6 4.35522 10.521C4.34982 10.442 4.37461 10.3639 4.42458 10.3025C4.47454 10.241 4.54596 10.2009 4.6244 10.1901L4.6669 10.1872H9.25023C9.71244 10.1872 10.1563 10.0064 10.4871 9.68358C10.8179 9.36073 11.0093 8.92135 11.0205 8.45927C11.0317 7.99719 10.8618 7.54905 10.5471 7.21054C10.2323 6.87204 9.79773 6.67001 9.33606 6.64759L9.25023 6.64551H4.6669C4.58772 6.64548 4.5115 6.61541 4.45365 6.56135C4.3958 6.5073 4.36062 6.4333 4.35522 6.35431C4.34982 6.27532 4.37461 6.19722 4.42458 6.1358C4.47454 6.07438 4.54596 6.03422 4.6244 6.02343L4.6669 6.02051H9.25023Z" fill="white" stroke="white" stroke-width="0.3"/>
+</svg>

+ 3 - 0
src/assets/img/approve_m/return-msg.svg

@@ -0,0 +1,3 @@
+<svg width="20" height="18" viewBox="0 0 20 18" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M12.6234 14.45C12.4885 14.45 12.3592 14.4018 12.2638 14.316C12.1685 14.2302 12.1149 14.1138 12.1149 13.9924C12.1149 13.871 12.1685 13.7546 12.2638 13.6688C12.3592 13.583 12.4885 13.5348 12.6234 13.5348C14.2122 13.5348 15.5047 12.3715 15.5047 10.9416C15.5047 9.51163 14.2122 8.34834 12.6234 8.34834H5.21424L8.66102 11.4501C8.75106 11.5369 8.80011 11.6518 8.79783 11.7705C8.79555 11.8893 8.74211 12.0026 8.64879 12.0865C8.55547 12.1705 8.42957 12.2185 8.29765 12.2205C8.16572 12.2225 8.0381 12.1783 7.94169 12.0972L3.26746 7.89071L7.94169 3.6839C8.03708 3.59805 8.16646 3.54982 8.30136 3.54982C8.43626 3.54982 8.56563 3.59805 8.66102 3.6839C8.7564 3.76975 8.80999 3.88618 8.80999 4.00759C8.80999 4.129 8.7564 4.24544 8.66102 4.33129L5.21424 7.43308H12.6234C14.7729 7.43308 16.5217 9.00702 16.5217 10.9416C16.5217 12.8761 14.7729 14.45 12.6234 14.45ZM10 0C4.48576 0 0 4.03749 0 9C0 13.9625 4.48576 18 10 18C15.5139 18 20 13.9625 20 9C20 4.03749 15.5139 0 10 0Z" fill="#797979"/>
+</svg>

二進制
src/assets/img/approve_m/return.png


二進制
src/assets/img/approve_m/select.png


二進制
src/assets/img/approve_m/start.png


+ 146 - 0
src/components/notificationMsg.vue

@@ -0,0 +1,146 @@
+<template>
+    <!-- 消息通知 -->
+    <el-popover
+        placement="bottom"
+        width="443"
+        trigger="click" v-model="visible">
+        <div class="notifation-wrap">
+            <!-- 防止tabs在popover前渲染,会导致tab选中状态不正确 -->
+            <el-tabs v-model="activeName" v-if="visible">
+                <el-tab-pane :label="`研报审批(${UnreadTotal})`" name="first"></el-tab-pane>
+            </el-tabs>
+            <div class="massage-list" v-if="visible">
+                <div class="message-item" :class="{'IsRead':item.IsRead}" v-for="item in msgList" :key="item.Id" @click="readMsg(item)">
+                    <span class="icon">
+                        <img :src="require(`@/assets/img/approve_m/${approveState[item.ApproveState]||'process'}-msg.svg`)" alt="">
+                    </span>
+                    <div class="info">
+                        <div class="head">
+                            <span class="title">{{item.Content}}</span>
+                            <span class="time">{{item.CreateTime}}</span>
+                        </div>
+                        <div class="content">{{item.Remark||''}}&nbsp;</div>
+                    </div>
+                </div>
+                <tableNoData v-if="!msgList.length" text="暂无消息"></tableNoData>
+            </div>
+            <el-button type="text" class="close-btn" @click="visible=false">关闭</el-button>
+        </div>
+        <span slot="reference" @click="visible = !visible" class="msg-btn">
+            <svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
+                <path d="M16.7344 15.4904L15.2941 12.9564V7.84847C15.2941 5.89142 13.8231 3.77337 11.6786 2.99732C11.5741 1.96012 10.8811 1.20374 9.97287 1.20374C9.06595 1.20374 8.37036 1.96014 8.26717 2.99732C6.12392 3.77337 4.65292 5.8914 4.65292 7.84847V12.9564L3.14258 15.6146C3.04183 15.7903 3.04429 16.0054 3.14504 16.1799C3.24581 16.3544 3.43263 16.4601 3.63415 16.4601H7.22871C7.49293 17.7357 8.62233 18.6967 9.97289 18.6967C11.3247 18.6967 12.4541 17.7357 12.7171 16.4601H16.3116C16.3215 16.4601 16.3288 16.4601 16.3374 16.4601C16.6508 16.4601 16.904 16.2082 16.904 15.8948C16.904 15.7362 16.8401 15.5925 16.7344 15.4904ZM9.97287 2.33803C10.1769 2.33803 10.3415 2.49286 10.4472 2.7239C10.2899 2.70792 10.1375 2.67106 9.97287 2.67106C9.8082 2.67106 9.65583 2.70792 9.49851 2.7239C9.60422 2.49284 9.76889 2.33803 9.97287 2.33803ZM9.97287 17.5636C9.25396 17.5636 8.65303 17.1016 8.41951 16.4601H11.5262C11.2927 17.1015 10.693 17.5636 9.97287 17.5636ZM4.60745 15.3282L5.71102 13.3853C5.76015 13.3017 5.78719 13.2034 5.78719 13.1051V7.84847C5.78719 5.93934 7.57648 3.80413 9.97287 3.80413C12.3692 3.80413 14.161 5.93934 14.161 7.84847V13.1051C14.161 13.2034 14.1868 13.3017 14.2347 13.3853L15.3395 15.3282H4.60745Z" fill="currentColor"/>
+            </svg>
+            <div class="unread" v-if="UnreadTotal">{{UnreadTotal>99?'99+':UnreadTotal}}</div>
+        </span>
+    </el-popover>
+</template>
+
+<script>
+import {approveInterence} from '@/api/modules/approve.js';
+export default {
+    data() {
+        this.approveState=['','process','passed','reject','return',]
+        return {
+            activeName:'first',
+            visible:false,
+            msgList:[],
+            UnreadTotal:0
+        };
+    },
+    watch:{
+        visible(val){
+            if(val){
+                this.getMsgList()
+            }
+        }
+    },
+    methods:{
+        readMsg(msg){
+            const {ApproveState,ReportApproveId,Id} = msg
+            approveInterence.readApproveMsg({
+                MessageId:Id
+            }).then(res=>{
+                if(res.Ret!==200) return 
+                this.getMsgList()
+            })
+            const type = ApproveState===1?'approve':ApproveState===4?'detail':'myself'
+            this.$router.push({
+                path:'/approveDetail',
+                query:{
+                    type,
+                    approveId:ReportApproveId
+                }
+            })
+        },
+        getMsgList(){
+            approveInterence.getApproveMsgList({
+                CurrentIndex:1,
+                PageSize:1000
+            }).then(res=>{
+                if(res.Ret!==200) return 
+                this.msgList = res.Data.List||[]
+                this.UnreadTotal = res.Data.UnreadTotal||0
+            })
+        }
+    }
+};
+</script>
+
+<style lang="scss">
+.notifation-wrap{
+    position:relative;
+    .massage-list{
+        padding: 0 10px;
+        max-height: 320px;
+        overflow-y: auto;
+        .message-item{
+            cursor: pointer;
+            display: flex;
+            padding: 5px 0;
+            border-bottom: 1px solid #E4E7ED;
+            color:#333;
+            &.IsRead{
+                color:#999;
+            }
+            .icon{
+                width:40px;
+                display: flex;
+                align-items: flex-start;
+                justify-content: center;
+            }
+            .info{
+                flex:1;
+                .head{
+                    display: flex;
+                    justify-content: space-between;
+                }
+
+            }
+        }
+    }
+    .close-btn{
+        position:absolute;
+        top:0;
+        right:0;
+        box-sizing: border-box;
+    }
+}
+.msg-btn{
+    cursor: pointer;
+    display: inline-block;
+    width: 50px;
+    text-align: center;
+    position: relative;
+    .unread{
+        position: absolute;
+        width:23px;
+        height:14px;
+        color:#fff;
+        background-color:#AD352F;
+        border-radius: 40px;
+        top:-4px;
+        right:4px;
+        font-size: 12px;
+    }
+}
+</style>

+ 65 - 0
src/mixins/reportApproveConfig.js

@@ -0,0 +1,65 @@
+/*
+    研报及审批配置,涉及到:
+    智能研报
+    中文研报(除晨周报)
+    英文研报
+    审批流配置
+    审批管理
+    审批详情
+ */
+import {etaBaseConfigInterence} from '@/api/modules/etaBaseConfigApi.js';
+import {approveInterence} from '@/api/modules/approve.js';
+export default{
+    data(){
+        return{
+            ReportApproveType:'',
+            IsReportApprove:false,
+            pageLoading:false,
+            hasApproveFlow:false,
+            checkLoading:false,
+        }
+    },
+    computed:{
+        //是否开启审批流
+        isApprove(){
+            return this.IsReportApprove
+        },
+        //是否开启了ETA审批流
+        isETAApprove(){
+            return this.IsReportApprove&&this.ReportApproveType==='eta'
+        },
+        //是否开启了接口审批
+        isOtherApprove(){
+            return this.IsReportApprove&&this.ReportApproveType==='other'
+        },
+    },
+    methods:{
+        async getBaseConfig(){
+            //从基本配置中获取是否开启审批流的数据
+            this.pageLoading = true
+            const res = await etaBaseConfigInterence.getBaseConfig()
+            this.pageLoading = false
+            if(res.Ret!==200) return
+            const {IsReportApprove='',ReportApproveType=''} = res.Data
+            this.IsReportApprove = IsReportApprove==='true'?true:false,
+            this.ReportApproveType = ReportApproveType
+        },
+        //检查是否有审批流
+        checkClassifyNameArr(type=1,classify=[]){
+            this.checkLoading=true
+            let params = {
+                ReportType:type,
+                ClassifyFirstId:classify[classify.length-2]||0,
+                ClassifySecondId:classify[classify.length-1]||0,
+            }
+            approveInterence.checkClassifyApprove(params).then(res=>{
+                this.checkLoading=false
+                if(res.Ret!==200) return 
+                this.hasApproveFlow = res.Data||false
+            })
+        },
+    },
+    mounted(){
+        this.getBaseConfig()
+    }
+}

+ 27 - 0
src/routes/modules/approveRoutes.js

@@ -0,0 +1,27 @@
+const home = r => require.ensure([], () => r(require('@/views/Home.vue')), 'Home'); //主页
+export default [
+    {
+        path:'/',
+        component:home,
+        name:'审批管理',
+        hidden:false,
+        icon_path: require('@/assets/img/home/data_ic.png'),
+        children:[{
+            path:'approveList',
+            name:'审批列表',
+            component:()=>import('@/views/approve_manage/approveList.vue'),
+            hidden:false
+        },{
+            path:'approveDetail',
+            name:'审批详情',
+            component:()=>import('@/views/approve_manage/approveDetail.vue'),
+            hidden:false,
+            meta: {
+                pathFrom: "approveList",
+                pathName: "审批列表",
+                keepAlive: false,
+              },
+        }
+        ]
+    }
+]

+ 12 - 0
src/routes/modules/oldRoutes.js

@@ -323,6 +323,18 @@ export default [
         name: "外部链接配置",
         hidden: true,
       },
+      {
+        path: "approveSetting",
+        component: () => import("@/views/approve_manage/approveSetting.vue"),
+        name: "审批流配置",
+        hidden: true,
+      },
+      {
+        path: "approveEdit",
+        component: () => import("@/views/approve_manage/approveEdit.vue"),
+        name: "编辑审批流",
+        hidden:true,
+      },
       {
         path: "dataSourceAccountList",
         component: () => import("@/views/dataSource_manage/accountList.vue"),

+ 23 - 3
src/utils/buttonConfig.js

@@ -631,7 +631,7 @@ export const baseConfigPermission = {
     etaBaseConfig_ppt:'etaBaseConfig:ppt',
     etaBaseConfig_watermark:'etaBaseConfig:watermark',
     etaBaseConfig_watermark_ybChart:'etaBaseConfig:watermark:ybChart',//如果没权限,表单不显示也不校验
-
+    etaBaseConfig_approve:'etaBaseConfig:approve',//研报审批
 }
 
 /*-----------外部链接配置-------- */
@@ -641,11 +641,30 @@ export const outlinkConfigPermission = {
     outlinkListConfig_edit:'outlinkListConfig:edit',//编辑
     outlinkListConfig_del:'outlinkListConfig:del',//删除
 }
+/*----------审批流配置----*/
+export const approveFlowPermission = {
+    reportApprove_save:'reportApprove:save',//保存
+    reportApprove_remove:'reportApprove:remove',//删除
+    reportApprove_edit:'reportApprove:edit',//编辑审批流(按钮)
+    reportApprove_add:'reportApprove:add',//添加审批流
+}
+/*
+ * --------------------------------------------------------------------------审批管理------------------------------------------------
+*/
+export const approvePermission = {
+    reportApprove_approve:'reportApprove:approve',//审批(列表中的按钮)
+    reportApprove_reject:'reportApprove:reject',//驳回(列表中的按钮)
+    reportApprove_agree:'reportApprove:agree',//通过(审批详情-通过按钮)
+    reportApprove_detail:'reportApprove:detail',//详情(列表中的按钮)
+    reportApprove_rejectreason:'reportApprove:rejectreason',//驳回理由(列表中的按钮)
+    reportApprove_return:'reportApprove:return',//返回(审批详情-返回按钮)
+    reportApprove_repeal:'reportApprove:repeal',//撤回(列表中的按钮,审批详情-撤回按钮)
+}
 
 
 //创建了新的ManageBtn记得添加到这里
 const btnMap  = {
-    reportManageBtn,enReportManageBtn,
+    reportManageBtn,enReportManageBtn,smartReportManageBtn,
     classifyBtn,enClassifyBtn,authorManage,
     enChartPermission,cloudDisk,
     pptPermission,enPPTPermission,
@@ -656,7 +675,8 @@ const btnMap  = {
     statisticPermission,stockPlantPermission,
     productPricePermission,sysDepartPermission,
     operateAuthPermission,baseConfigPermission,
-    outlinkConfigPermission
+    outlinkConfigPermission,approveFlowPermission,
+    approvePermission
 }
 
 /**

+ 7 - 2
src/views/Home.vue

@@ -248,7 +248,8 @@
                 style="width: 84px;height: 24; cursor: pointer;" />
                 </div>
               </div>
-
+               <!-- 消息通知 -->
+              <notification-msg ref="notification"/>
               <el-dropdown trigger="click" style="width:130px;">
                 <span class="el-dropdown-link userinfo-inner">
                   <img src="~@/assets/img/home/avatar.png"/>
@@ -316,13 +317,15 @@ import questionnaireDia from "../components/questionnaireDia.vue";
 import EventBus from "@/api/bus.js";
 
 import {recordActiveLoginFun,loginEndCalc} from "@/utils/TimeOnPage.js"
+import NotificationMsg from "../components/notificationMsg.vue";
 
 export default {
   components: {
     PwdDlg,
     questionMsgDia,
     questionnaireDia,
-  },
+    NotificationMsg
+},
   inject: ["reload"],
   filters: {
     formatDate(e) {
@@ -463,6 +466,7 @@ export default {
       //链接系统
       linkSystems: this.$setting.linkSystems,
       bus_code:"",
+
     };
   },
   created() {
@@ -488,6 +492,7 @@ export default {
       this.getMenuList();
     }
     this.getPublicSettings();
+    this.$refs.notification&&this.$refs.notification.getMsgList()
   },
   methods: {
     handleClickSubMenuItem(item,e){

+ 386 - 0
src/views/approve_manage/approveDetail.vue

@@ -0,0 +1,386 @@
+<template>
+    <!-- 审批详情:查看、进行审批操作 -->
+    <div class="approve-detail-wrap" v-if="isETAApprove">
+        <div class="approve-detail">
+            <div class="approve-info">
+                <span>研报名称:{{reportInfo.title||''}}</span>
+                <span>研报分类:{{reportInfo.classify||''}}</span>
+                <span style="min-width: 100px;">发起人:{{reportInfo.approver||''}}</span>
+            </div>
+            <div class="approve-content" 
+                v-loading="isLoading"
+                element-loading-text="研报加载中...">
+                <component v-if="reportInfo.reportId&&!isError"
+                    :is="reportInfo.componentName"
+                    :reportId="reportInfo.reportId"
+                    :isPreview="true"
+                    :isEn="reportInfo.type===2"
+                    @reportStartLoading="isLoading=true"
+                    @reportEndLoading="isLoading=false"
+                    @reportError="isError=true"
+                ></component>
+                <tableNoData v-if="isError" text="无法获取到报告内容,该报告可能已被删除!"></tableNoData>
+            </div>
+        </div>
+        <div class="approve-tool">
+            <div class="tool-btn">
+                <!-- 根据审批的状态决定显示 -->
+                <el-button type="danger" @click="changeApprove('reject')"
+                    v-if="formType==='approve'&&approveInfo.isCurrentApprover&&permissionBtn.isShowBtn('approvePermission','reportApprove_reject')">驳回</el-button>
+                <el-button type="primary" @click="changeApprove('pass')"
+                    v-if="formType==='approve'&&approveInfo.isCurrentApprover&&permissionBtn.isShowBtn('approvePermission','reportApprove_agree')">同意</el-button>
+                <el-button type="primary" @click="changeApprove('return')"
+                    v-if="formType==='myself'&&approveInfo.state!==4&&permissionBtn.isShowBtn('approvePermission','reportApprove_repeal')">撤销</el-button>
+                <el-button type="primary" plain @click="$router.replace(`/approveList?formType=${formType}`)">返回</el-button>
+            </div>
+            <div class="approve-timeline-wrap">
+                <p>审批流程</p>
+                <div class="timeline">
+                    <TimeLine 
+                        :TimeLineData="TimeLineData"
+                    />
+                </div>
+                <div class="approve-status" >
+                    <img :src="require(`@/assets/img/approve_m/${approveInfo.stateText||'pending'}.png`)" alt="">
+                </div>
+            </div>
+        </div>
+        <RejectDialog 
+            :isDetailDialogShow="isDetailDialogShow"
+            :isEdit="true"
+            @close="isDetailDialogShow=false;"
+            @edit="rejectApprove"
+        />
+    </div>
+    <div class="nodata-wrap approve-page-wrap" v-else>
+        <tableNoData :text="pageLoading?'':'系统暂未开通审批流程,请开启审批流程后再进行操作!'"></tableNoData>
+    </div>
+</template>
+
+<script>
+import ReportDetail from '@/views/smartReport/reportDetail.vue';
+import Reportdtl from '@/views/report_manage/reportdtl.vue'
+import TimeLine from './components/timeLine.vue';
+import RejectDialog from './components/rejectDialog.vue';
+import {approveInterence} from '@/api/modules/approve.js';
+import reportApproveConfig from "@/mixins/reportApproveConfig.js"
+
+const ApproveType = ['','依次审批','会签','或签']
+const ApproveState = ['','待审批','已同意','已驳回']
+export default {
+    mixins:[reportApproveConfig],
+    components: { RejectDialog },
+    data() {
+        return {
+            isError:false,
+            isLoading:false,
+            isDetailDialogShow:false,
+            TimeLineData:[],
+            formType:'detail',//进入审批详情的方式:approve(待处理)/detail(已处理)/myself(我发起的)
+            reportInfo:{ //报告相关信息
+                reportId:0,//研报or智能研报的报告id
+                title:'',
+                classify:'',
+                approver:'',
+                componentName:'',
+                type:0,//1中文研报 2英文研报 3智能研报
+            },
+            approveInfo:{//审批相关的信息
+                state:1,//当前审批的状态:1-待审批;2-已同意;3-已驳回;4-已撤回
+                stateText:'pending',//审批状态对应图片文字:待审批(pending),已同意(passed),已驳回(reject),已撤回(return)
+                isCurrentApprover:false,//审批进行中的节点审批人是否是当前用户,控制通过&驳回按钮显示
+            },
+        };
+    },
+    computed:{
+        UserId(){
+            return Number(localStorage.getItem("AdminId"));
+        }
+    },
+    methods: {
+        getApproveDetail(){
+            const {type,approveId} = this.$route.query
+            if(!approveId) return 
+            approveInterence.getApproveDetail({
+                ReportApproveId:Number(approveId)
+            }).then(res=>{
+                if(res.Ret!==200) return
+                //格式化时间线数据 
+                this.formatTimeLineData(res.Data)
+                const {Report={},Approve={}} = res.Data||{}
+                this.reportInfo = {
+                    reportId:Report.ReportId||0,
+                    title:Report.ReportTitle||'',
+                    classify:Report.ReportClassify||'',
+                    approver:Approve.ApplyUserName||'',
+                    componentName:Report.ReportType===3?'ReportDetail':'Reportdtl',
+                    type:Report.ReportType
+                }
+                this.formType = type||'detail'
+                this.approveInfo.state=Approve.State
+                this.approveInfo.stateText=['','pending','passed','reject','return'][Approve.State]
+            })
+        },
+        //转换接口数据
+        formatTimeLineData({Approve={},ApproveFlowNodes=[]}){
+            //发起人节点
+            const startNode = {
+                nodeType:1,
+                nodeText:'发起人:',
+                nodeStatus:'passed',
+                approveList:[{
+                    approverName:Approve.ApplyUserName||'',
+                    approveTime:Approve.CreateTime||''
+                }]
+            }
+            //排序过的审批节点,遍历
+            let currentIndex = 0
+            let Nodes = ApproveFlowNodes.map((i,index)=>{
+                //找到当前节点的index
+                if(i.ReportApproveNodeId===Approve.CurrNodeId){
+                    currentIndex = index
+                }
+                //审批节点只有一个人时不显示是什么审批流
+                const strApproveType = `(${ApproveType[i.ApproveType]})`
+                const node = {
+                    nodeType:2,
+                    nodeText:'审批人:'+i.Users.length+'人'+(i.Users.length>1?strApproveType:''),
+                    nodeStatus:i.ReportApproveNodeId===Approve.CurrNodeId?'process':'future',
+                    approveType:ApproveType[i.ApproveType]
+                }
+                const approveList = i.Users.map(u=>{
+                    const {State='',ApproveTime='',ApproveRemark=''}=u.ApproveRecord||{}
+                    return {
+                        approverName:u.UserName,
+                        approveStatus:ApproveState[State]||'',
+                        approveTime:ApproveTime,
+                        approveReason:ApproveRemark
+                    }
+                })
+                //检测当前节点的User与当前用户是否匹配 且审批需要是待审批状态
+                if(i.ReportApproveNodeId===Approve.CurrNodeId&&Approve.State===1){
+                    //当前节点的User中,有没有当前用户
+                    const hasUser = i.Users.findIndex(u=>u.UserId===this.UserId)
+                    if(hasUser!==-1){
+                        //只有依次审批需要看顺序
+                        if(i.ApproveType===1){
+                            this.approveInfo.isCurrentApprover = i.Users[hasUser].ApproveRecord?true:false
+                        }else{
+                            this.approveInfo.isCurrentApprover = true
+                        }
+                    }else{
+                        this.approveInfo.isCurrentApprover = false
+                    }
+                }
+                node.approveList = approveList
+                return node
+            })
+            //将当前节点之前的置为通过节点,当前节点之后的置为未进行节点
+            Nodes.forEach((n,index)=>{
+                if(index<currentIndex){
+                    n.nodeStatus = 'passed'
+                }
+                if(index>currentIndex){
+                    n.nodeStatus = 'future'
+                }
+            })
+
+            if(!Nodes.length){
+                this.TimeLineData = [startNode,...Nodes]
+                return
+            }
+
+            //如果当前审批是已驳回,移除当前节点后面的节点
+            if(Approve.State===3){
+                Nodes = Nodes.filter((_,index)=>index<=currentIndex)
+                Nodes[currentIndex].nodeStatus = 'reject'
+            }
+
+            //如果当前审批已撤销,移除当前节点后面的节点,在最后加上撤销节点
+            if(Approve.State===4){
+                Nodes = Nodes.filter((_,index)=>index<=currentIndex)
+                //检查最后一个节点是否有人审批
+                let hasApprove = false
+                let stateNum = 0
+                Nodes[currentIndex].approveList.forEach(u=>{
+                    if(u.approveStatus&&u.approveStatus!=='待审批'){
+                        hasApprove = true
+                    }
+                    //依次审批和会签,计算已同意的数量
+                    if(u.approveStatus==='已同意'){
+                        stateNum++
+                    }
+                    if(u.approveStatus==='已驳回'){
+                        Nodes[currentIndex].nodeStatus = 'reject'
+                    }
+                })
+                //若审批撤销,则检查当前节点是否是通过节点
+                if(Nodes[currentIndex].approveType!=='或签'&&stateNum===Nodes[currentIndex].approveList.length){
+                    Nodes[currentIndex].nodeStatus = 'passed'
+                }
+                if(Nodes[currentIndex].approveType==='或签'&&stateNum>0){
+                    Nodes[currentIndex].nodeStatus = 'passed'
+                }
+                //若没有人审批,则把这个节点删除
+                !hasApprove&&(Nodes.pop())
+                //在最后加上撤销节点
+                Nodes.push({
+                    nodeType:3,
+                    nodeText:'发起人:',
+                    nodeStatus:'return',
+                    approveList:[{
+                        approverName:(Approve.ApplyUserName||'')+'(已撤销)',
+                        approveTime:Approve.ModifyTime||''
+                    }],
+                })
+            }
+
+            //如果当前审批已同意,则最后一个节点状态改为已同意
+            if(Approve.State===2){
+                Nodes[currentIndex].nodeStatus = 'passed'
+            }
+
+            //再次遍历Nodes
+            //1.去除已同意的或签节点,没有审批的审批人状态
+            //2.去除已驳回的节点,没有参与审批的审批人的状态
+            Nodes.forEach(n=>{
+                if(n.nodeStatus==='passed'||n.nodeStatus==='reject'){
+                    n.approveList.forEach(a=>{
+                        if(a.approveStatus==='待审批'){
+                            a.approveStatus = ''
+                        }
+                    })
+                }
+            })
+
+            this.TimeLineData = [startNode,...Nodes]
+        },
+        async changeApprove(type){
+            const {approveId} = this.$route.query
+            if(!approveId) return
+            if(type==='reject'){
+                this.isDetailDialogShow = true
+                return 
+            }
+            let res = null
+            if(type==='return'){
+                res = await approveInterence.cancelApprove({
+                    ReportApproveId:Number(approveId)
+                })
+            }
+            if(type==='pass'){
+                res = await approveInterence.passApprove({
+                    ReportApproveId:Number(approveId)
+                })
+            }
+            if(res.Ret!==200) return 
+            this.$message.success(`${type==='return'?'撤销':'通过'}成功`)
+            type!=='reject'&&(this.$router.replace("/approveList"))
+        },
+        rejectApprove(reason){
+            this.isDetailDialogShow = false
+            approveInterence.rejectApprove({
+                ReportApproveId:Number(this.$route.query.approveId),
+                ApproveRemark:reason||''
+            }).then(res=>{
+                if(res.Ret!==200) return 
+                this.$message.success("驳回成功")
+                this.$router.replace("/approveList")
+            })
+        }
+    },
+    mounted(){
+        this.getApproveDetail()
+    },
+    components: { TimeLine, ReportDetail, Reportdtl, RejectDialog }
+};
+</script>
+
+<style lang="scss">
+.approve-detail-wrap{
+    .approve-content{
+        .smart-report-detail{
+            .main-box{
+                width: auto;
+                box-sizing: border-box;
+                margin:0;
+                padding:10px;
+                border:none !important;
+                border-radius: 4px;
+            }
+        }
+        #reportdtl{
+            margin:0 auto;
+            padding:10px;
+            border:none !important;
+            border-radius: 4px;
+        }
+    }
+}
+</style>
+<style scoped lang="scss">
+@import url('./css/pageStyle.scss');
+.approve-detail-wrap{
+    height: calc(100vh - 120px);
+    display: flex;
+    .approve-detail,.approve-tool{
+        height: 100%;
+        box-sizing: border-box;
+    }
+    .approve-tool{
+        width:400px;
+        min-width: 360px;
+        background-color: #fff;
+        display: flex;
+        flex-direction: column;
+        overflow: hidden;
+        .tool-btn{
+            padding:20px;
+            text-align: right;
+        }
+        .approve-timeline-wrap{
+            position: relative;
+            margin-left:20px;
+            flex:1;
+            overflow-y: auto;
+            .timeline{
+                padding:20px;
+                padding-left: 0;
+            }
+            .approve-status{
+                position:absolute;
+                width:200px;
+                height:200px;
+                right:0;
+                bottom:0;
+                overflow: hidden;
+                pointer-events: none;
+                img{
+                    width:100%;
+                    height:100%;
+                }
+            }
+        }
+    }
+    .approve-detail{
+        flex: 1;
+        margin-right:20px;
+        background-color: #fff;
+        display: flex;
+        flex-direction: column;
+        .approve-info{
+            display: flex;
+            gap:60px;
+            padding:15px 20px;
+            border-bottom: 1px solid #C8CDD9;
+        }
+        .approve-content{
+            flex: 1;
+            min-width: 840px;
+            padding:20px;
+            overflow-y: auto;
+            position:relative;
+        }
+    }
+}
+</style>

+ 194 - 0
src/views/approve_manage/approveEdit.vue

@@ -0,0 +1,194 @@
+<template>
+    <!-- 添加编辑审批流 -->
+    <div class="approve-edit-wrap approve-page-wrap" v-if="isETAApprove">
+        <div class="head-box">
+            <el-form :inline="true" :model="approveForm" ref="approve-form" :rules="formRules"
+                label-width="100px" label-position="left">
+                <el-form-item label="审批流名称" prop="name">
+                    <el-input v-model="approveForm.name" :disabled="this.$route.query.flowId" placeholder="请输入审批流名称"></el-input>
+                </el-form-item>
+                <el-form-item label="关联报告" prop="classify">
+                    <el-cascader v-model="approveForm.classify"
+                        placeholder="请选择关联报告" clearable
+                        :disabled="this.$route.query.flowId"
+                        :options="classifyTree"
+                        :props="{value:'ClassifyId',label:'ClassifyName',children:'Children'}"
+                        style="margin-right: auto;margin-left: 15px;"></el-cascader>
+                </el-form-item>
+            </el-form>
+            <div class="form-btn">
+                <el-button type="primary" plain @click="$router.back()">取消</el-button>
+                <el-button v-permission="permissionBtn.approveFlowPermission.reportApprove_save"
+                    type="primary" @click="checkFlow">保存</el-button>
+            </div>
+        </div>
+        <div class="form-item" style="color:#606266;width:100px;">
+            <span style="color:#F56C6C;margin-right: 4px;">*</span>流程配置
+        </div>
+        <!-- 审批流画布 -->
+        <div class="flow-editor-wrap">
+            <FlowEdiotr
+                ref='floweditor'
+                :flowNodes="approveForm.flowNodes"
+            />
+        </div>
+    </div>
+    <div class="approve-page-wrap" v-else>
+        <tableNoData :text="pageLoading?'':'系统暂未开通审批流程,请开启审批流程后再进行操作!'"></tableNoData>
+    </div>
+</template>
+
+<script>
+import FlowEdiotr from './components/flowEdiotr';
+import {approveInterence} from '@/api/modules/approve.js';
+import approveMixins from './mixins/approveMixins';
+import reportApproveConfig from "@/mixins/reportApproveConfig.js"
+const findParentNode = (arr, id)=>{
+      // 遍历取父级code push数组
+      for (let i of arr) {
+        if (i.ClassifyId === id) {
+          return [i.ClassifyId];
+        }
+        if (i.Children) {
+          let node = findParentNode(i.Children, id);
+          if (node) {
+            return node.concat(i.ClassifyId);
+          }
+        }
+      }
+    }
+export default {
+    mixins:[approveMixins,reportApproveConfig],
+    data() {
+        return {
+            approveForm:{
+                name:'',
+                classify:'',
+                /* flowNodes:null */
+            },
+            formRules:{
+                name:[{ required: true, message: '请输入审批流名称名称', trigger: 'blur' },
+                      { max: 20, message: '长度在20个字符内', trigger: 'change' }],
+                classify:[{ required: true, message: '请选择关联报告', trigger: 'blur' },]
+            },
+
+        };
+    },
+    methods: {
+        async checkFlow(){
+            //检查name,region是否为空
+            await this.$refs["approve-form"].validate()
+            //检查审批流内容:每个审批节点是否都选择了审批人
+            const data = this.$refs.floweditor.flowData
+            if(data.length<3){
+                this.$message.warning("请添加审批节点")
+                return
+            }
+            for(let item of data){
+                if(item.nodeType===2&&!item.approvers.length){
+                    this.$message.warning("有节点未选择审批人,请检查")
+                    return
+                }
+            }
+            let Nodes = []
+            //不需要data的第一项和最后一项,其余转换为接口所需格式
+            for(let i=1;i<data.length-1;i++){
+                const Users = data[i].approvers.map((item,index)=>{
+                    return {
+                        UserType:'user',//目前只有审批节点,都是user
+                        UserId:item.ItemId,
+                        UserName:item.ItemName,
+                        Sort:data[i].ApproveType===1?index+1:0
+                    }
+                })
+                Nodes.push({
+                    ApproveType:data[i].ApproveType,
+                    Users
+                })
+            }
+            this.modifyFlow(Nodes)
+        },
+        async modifyFlow(Nodes){
+            const {name,classify} = this.approveForm
+            const params = {
+                FlowName:name,
+                ReportType:classify[0],
+                ClassifyFirstId:classify[classify.length-2]||0,
+                ClassifySecondId:classify[classify.length-1]||0,
+                Nodes
+            }
+            let res
+            const id = this.$route.query.flowId||0
+            if(id){
+                res = await approveInterence.editApproveFlow({
+                    ...params,
+                    ReportApproveFlowId:Number(id)
+                })
+            }else{
+                res = await approveInterence.addNewApproveFlow(params)
+            }
+            if(res.Ret!==200) return
+            this.$message.success(`${id?'编辑':'新增'}成功`)
+            this.$router.push('/approveSetting')
+        },
+        getFlowDetail(){
+            const id = this.$route.query.flowId||0
+            if(id){
+                approveInterence.getApproveFlowDetail({
+                    ReportApproveFlowId:Number(id)
+                }).then(res=>{
+                    if(res.Ret!==200) return 
+                    const {FlowName,ReportType,ClassifySecondId,Nodes} = res.Data||{}
+                    this.approveForm.name = FlowName||''
+                    //递归获取所有父级id
+                    const classify = this.classifyTree.find(i=>i.ClassifyId===ReportType)||{}
+                    const tempArr = findParentNode(classify.Children||[],ClassifySecondId)
+                    tempArr.push(ReportType)
+                    this.approveForm.classify = tempArr.reverse()
+                    this.approveForm.flowNodes = Nodes||[]
+                })
+            }
+        }
+    },
+    async mounted(){
+        this.getClassifyTree()
+    },
+    components: { FlowEdiotr }
+};
+</script>
+<style lang="scss">
+.approve-edit-wrap{
+    .el-form-item__content{
+        flex: 1;
+    }
+}
+</style>
+<style scoped lang="scss">
+@import url('./css/pageStyle.scss');
+.approve-edit-wrap{
+    display: flex;
+    flex-direction: column;
+    height: calc(100vh - 120px);
+    .head-box{
+        display: flex;
+        justify-content: space-between;
+        .el-form{
+            flex:1;
+            .el-input,.el-cascader{
+                min-width: 200px;
+                max-width: 420px;
+                width:100%;
+            }
+            .el-form-item{
+                width:45%;
+                display: inline-flex;
+            }
+
+        }
+    }
+    .flow-editor-wrap{
+        padding-left: 100px;
+        overflow: auto;
+    }
+}
+</style>

+ 311 - 0
src/views/approve_manage/approveList.vue

@@ -0,0 +1,311 @@
+<template>
+    <!-- 审批管理列表页 -->
+    <div class="approve-list-wrap approve-page-wrap" v-if="isETAApprove">
+        <div class="head-tab">
+            <el-tabs v-model="activeTab" @tab-click="handleClick">
+                <el-tab-pane label="待处理" name="pending"></el-tab-pane>
+                <el-tab-pane label="已处理" name="processed"></el-tab-pane>
+                <el-tab-pane label="我发起的" name="originate"></el-tab-pane>
+            </el-tabs>
+        </div>
+        <div class="approve-list">
+            <div class="select-box">
+                <el-cascader v-model="classify"
+                    placeholder="请选择关联报告" clearable
+                    :options="classifyTree"
+                    :props="{value:'ClassifyId',label:'ClassifyName',children:'Children'}"
+                    @change="handleCurrentChange(1)">
+                </el-cascader>
+                <div class="select-time-box">
+                    <el-select v-show="activeTab!=='pending'" v-model="timeType" 
+                        @change="handleCurrentChange(1)"
+                        placeholder="时间类型" style="max-width:120px;" class="custom-select">
+                        <el-option label="提交时间" :value="1" />
+                        <el-option label="处理时间" :value="2" v-if="activeTab==='processed'"/>
+                        <el-option label="审批时间" :value="3" v-if="activeTab==='originate'"/>
+                    </el-select>
+                    <div class="line" v-show="activeTab!=='pending'"></div>
+                    <el-date-picker v-model="timeDate"
+                        @change="handleCurrentChange(1)"
+                        type="daterange"
+                        value-format="yyyy-MM-dd"
+                        range-separator="至"
+                        start-placeholder="开始日期"
+                        end-placeholder="结束日期">
+                    </el-date-picker>
+                </div>
+                
+                <el-select placeholder="请选择处理状态" v-model="ApproveState" clearable v-show="activeTab!=='pending'"
+                    @change="handleCurrentChange(1)">
+                    <template v-if="activeTab==='processed'">
+                        <el-option label="已同意" :value="2" />
+                        <el-option label="已驳回" :value="3" />
+                    </template>
+                    <template v-if="activeTab==='originate'">
+                        <el-option label="待审批" :value="1" />
+                        <el-option label="已通过" :value="2" />
+                        <el-option label="已驳回" :value="3" />
+                        <el-option label="已撤销" :value="4" />
+                    </template>
+                    
+                </el-select>
+
+                <el-input v-model="keyword" prefix-icon="el-icon-search" clearable @input="handleCurrentChange(1)"
+                    placeholder="请输入报告标题" style="width:260px;margin-left: auto;"></el-input>
+            </div>
+            <div class="list-box">
+                <el-table 
+                    ref="reftable"
+                    v-loading="tableLoading"
+                    :data="tableData" 
+                    @sort-change="sortChange" border>
+                    <el-table-column
+                        v-for="item in tableColumns"
+                        :key="item.key"
+                        :label="item.label"
+                        :prop="item.key"
+                        :sortable="item.sortable"
+                        align="center"
+                    >
+                        <template slot-scope="{row}">
+                            <span v-if="item.key==='State'">
+                                {{['','待审批','已通过','已驳回','已撤销'][row.State]}}
+                            </span>
+                            <span v-else-if="item.key==='RecordState'">
+                                {{['','待审批','已同意','已驳回'][row.RecordState]}}
+                            </span>
+                            <span v-else>{{row[item.key]}}</span>
+                        </template>
+                    </el-table-column>
+                    <el-table-column label="操作" align="center">
+                        <template slot-scope="{row}">
+                            <template v-if="activeTab==='pending'">
+                                <el-button type="text" style="padding:0;" @click="toApproveDetail(row,'approve')"
+                                    v-if="permissionBtn.isShowBtn('approvePermission','reportApprove_approve')">审批</el-button>
+                            </template>
+                            <template v-if="activeTab==='processed'">
+                                <el-button type="text" style="padding:0;" @click="toApproveDetail(row,'detail')">详情</el-button>
+                                <el-button type="text" style="padding:0" @click="handleShowDetail(row)" 
+                                    v-if="row.State===3&&permissionBtn.isShowBtn('approvePermission','reportApprove_rejectreason')">驳回理由</el-button>
+                            </template>
+                            <template v-if="activeTab==='originate'">
+                                <el-button type="text" style="padding:0;" @click="toApproveDetail(row,'myself')">详情</el-button>
+                                <el-button type="text" style="padding:0;" @click="cancelApprove(row)" 
+                                    v-if="row.State!==4&&permissionBtn.isShowBtn('approvePermission','reportApprove_repeal')">撤销</el-button>
+                                <el-button type="text" style="padding:0" @click="handleShowDetail(row)" 
+                                    v-if="row.State===3&&permissionBtn.isShowBtn('approvePermission','reportApprove_rejectreason')">驳回理由</el-button>
+                            </template>
+                        </template>
+                        
+                    </el-table-column>
+                </el-table>
+            <div style="text-align:right;margin-top:20px">
+                <el-pagination 
+                        layout="total,prev,pager,next,jumper" 
+                        background 
+                        :current-page="page"
+                        @current-change="handleCurrentChange"
+                        :page-size="pageSize"
+                        :total="total"
+                        style="display: inline-block"
+                    />
+            </div>
+            </div>
+        </div>
+        <RejectDialog 
+            :isDetailDialogShow="isDetailDialogShow"
+            :isEdit="false"
+            :data="currentData"
+            @close="isDetailDialogShow=false;currentData={};"
+        />
+    </div>
+    <div class="approve-page-wrap" v-else>
+        <tableNoData :text="pageLoading?'':'系统暂未开通审批流程,请开启审批流程后再进行操作!'"></tableNoData>
+    </div>
+</template>
+
+<script>
+import RejectDialog from './components/rejectDialog.vue';
+import approveMixins from './mixins/approveMixins';
+import {approveInterence} from '@/api/modules/approve.js';
+import reportApproveConfig from "@/mixins/reportApproveConfig.js"
+import {
+        approve_pending_columns,
+        approve_processed_columns,
+        approve_originate_columns,
+    } from './config/tableConfig'
+const columnsMap = {
+    'pending':approve_pending_columns,
+    'processed':approve_processed_columns,
+    'originate':approve_originate_columns
+}
+const tabMap = {
+    'pending':1,
+    'processed':2,
+    'originate':3
+}
+export default {
+    mixins:[approveMixins,reportApproveConfig],
+    data() {
+        return {
+            activeTab: 'pending',
+            /* 筛选项 */
+            timeType:1,
+            timeDate:'',
+            ApproveState:'',
+            keyword:'',
+            classify:'',
+            /* 排序项 */
+            SortRule:0,
+            SortField:0,
+
+            tableLoading:false,
+            tableData: [],
+            tableColumns: approve_pending_columns,
+            page: 1,
+            pageSize: 10,
+            total: 0,
+
+            currentData: {},
+            isDetailDialogShow: false
+        };
+    },
+    methods: {
+        getTableData(){
+            this.tableLoading = true
+            this.tableData=[]
+            const baseParams = {
+                ListType:tabMap[this.activeTab]||0,
+                PageSize:this.pageSize,
+                CurrentIndex:this.page,
+                Keyword:this.keyword,
+            }
+            const selectParams = {
+                //关联报告
+                ReportType:this.classify[0]||0,
+                ClassifyFirstId:this.classify[this.classify.length-2]||0,
+                ClassifySecondId:this.classify[this.classify.length-1]||0,
+                //时间
+                TimeType:this.timeType,
+                StartTime:this.timeDate?this.timeDate[0]||'':'',
+                EndTime:this.timeDate?this.timeDate[1]||'':'',
+                //排序
+                SortRule:this.SortRule,
+                SortField:this.SortField,
+                //处理状态
+                ApproveState:this.ApproveState,
+            }
+            approveInterence.getApproveList({
+                ...baseParams,
+                ...selectParams
+            }).then(res=>{
+                this.tableLoading=false
+                if(res.Ret!==200) return 
+                const {List=[],Paging={}} = res.Data||{}
+                this.tableData = List||[]
+                this.total = Paging.Totals||0
+            })
+        },
+        handleCurrentChange(page) {
+            this.page = page;
+            this.getTableData()
+        },
+        sortChange({ prop, order }) {
+            this.SortRule = order==='ascending'?1:2
+            this.SortField= prop==='CreateTime'?1
+                            :prop==='HandleTime'?2:3
+            this.handleCurrentChange(1)
+        },
+        handleClick() {
+            this.timeType = 1
+            this.timeDate=''
+            this.SortField=0
+            this.SortField=0
+            this.tableColumns = columnsMap[this.activeTab];
+            this.$refs.reftable&&this.$refs.reftable.clearSort()
+            this.handleCurrentChange(1)
+        },
+        handleShowDetail(data) {
+            this.currentData = data;
+            this.isDetailDialogShow = true;
+        },
+        toApproveDetail(data,type){
+            this.$router.push({
+                path:'/approveDetail',
+                query:{
+                    type,
+                    approveId:data.ReportApproveId
+                }
+            })
+        },
+        cancelApprove(item){
+            approveInterence.cancelApprove({
+                ReportApproveId:Number(item.ReportApproveId)
+            }).then(res=>{
+                if(res.Ret!==200) return 
+                this.$message.success("撤销成功")
+                this.handleCurrentChange(1)
+            })
+        },
+    },
+    mounted(){
+        this.getClassifyTree()
+        const {formType='approve'} = this.$route.query
+        const formTypeMap = {
+            'approve':'pending',
+            'detail':'processed',
+            'myself':'originate'
+        }
+        this.activeTab = formTypeMap[formType]||'pending'
+        this.getTableData()
+    },
+    components: { RejectDialog }
+};
+</script>
+
+<style lang="scss">
+.approve-list-wrap{
+    .custom-select{
+        .el-input__inner{
+            border-color: #0052D9;
+            background-color: #ECF2FE;
+            color:#0052D9;
+        }
+        .el-input__suffix{
+            color:#0052D9;
+            .el-select__caret{
+                color:#0052D9;
+            }
+        }
+        
+    }
+}
+</style>
+<style scoped lang="scss">
+@import url('./css/pageStyle.scss');
+.approve-list-wrap{
+    .head-tab{
+        margin-bottom: 5px;
+    }
+    .approve-list{
+        .select-box{
+            display: flex;
+            justify-content: space-between;
+            gap:10px;
+            .select-time-box{
+                display: flex;
+                align-items: center;
+                max-width: 380px;
+                .line{
+                    width:10px;
+                    height:1px;
+                    background-color: #C8CDD9;
+                }
+            }
+        }
+    }
+    .list-box{
+        margin-top:20px;
+    }
+}
+</style>

+ 162 - 0
src/views/approve_manage/approveSetting.vue

@@ -0,0 +1,162 @@
+<template>
+    <!-- 审批流配置列表 -->
+    <div class="approve-setting-wrap approve-page-wrap" v-if="isETAApprove">
+        <div class="head-box">
+            <el-button v-permission="permissionBtn.approveFlowPermission.reportApprove_add"
+                type="primary" @click="$router.push('/approveEdit')">添加审批流</el-button>
+            <el-cascader v-model="classify"
+                placeholder="请选择关联报告" clearable
+                :options="classifyTree"
+                :props="{value:'ClassifyId',label:'ClassifyName',children:'Children'}"
+                @change="handleSearchChange"
+                style="margin-right: auto;margin-left: 15px;"></el-cascader>
+            <el-input v-model="Keyword" @input="handleCurrentChange(1)"
+                placeholder="请输入审批流名称" prefix-icon="el-icon-search" clearable style="width:260px;"></el-input>
+        </div>
+        <div class="list-box">
+            <el-table :data="tableData" @sort-change="sortChange" border>
+                <el-table-column
+                    v-for="item in tableColumns"
+                    :key="item.key"
+                    :label="item.label"
+                    :prop="item.key"
+                    :sortable="item.sortable"
+                    align="center"
+                ></el-table-column>
+                <el-table-column label="操作" align="center">
+                    <template slot-scope="{row}">
+                        <el-button v-permission="permissionBtn.approveFlowPermission.reportApprove_edit"
+                            type="text" style="padding:0;" @click="handleEditFlow(row)">编辑</el-button>
+                        <el-button v-permission="permissionBtn.approveFlowPermission.reportApprove_remove"
+                            type="text" style="padding:0;color:red;" @click="handleDeleteFlow(row)">删除</el-button>
+                    </template>
+                    
+                </el-table-column>
+            </el-table>
+            <div style="text-align:right;margin-top:20px">
+                <el-pagination 
+                        layout="total,prev,pager,next,jumper" 
+                        background 
+                        :current-page="page"
+                        @current-change="handleCurrentChange"
+                        :page-size="pageSize"
+                        :total="total"
+                        style="display: inline-block"
+                    />
+            </div>
+        </div>
+    </div>
+    <div class="approve-page-wrap" v-else>
+        <tableNoData :text="pageLoading?'':'系统暂未开通审批流程,请开启审批流程后再进行操作!'"></tableNoData>
+    </div>
+</template>
+
+<script>
+import {approveInterence} from '@/api/modules/approve.js'
+import approveMixins from './mixins/approveMixins';
+import reportApproveConfig from "@/mixins/reportApproveConfig.js"
+export default {
+    mixins:[approveMixins,reportApproveConfig],
+    data() {
+        return {
+            /* 列表筛选项 */
+            ClassifyFirstId:0,//研报倒数第二级分类id
+            ClassifySecondId:0,//研报最后一级分类id
+            ReportType:0,//研报类型 1-中文研报;2-英文研报;3-智能研报
+            SortRule:0,//排序规则:1-正序; 2-倒序(默认)
+            Keyword:'',
+            classify:'',
+
+            tableData:[],
+            tableColumns:[{
+                label:'审批流名称',
+                key:'FlowName'
+            },{
+                label:'关联报告',
+                key:'ReportClassify'
+            },{
+                label:'创建时间',
+                key:'CreateTime',
+                sortable:'custom'
+            }],
+            page:1,
+            pageSize:10,
+            total:0,
+        };
+    },
+    methods: {
+        handleCurrentChange(page){
+            this.page = page
+            this.getTableData()
+        },
+        handleSearchChange(){
+            this.ReportType = this.classify[0]||0
+            this.ClassifySecondId = this.classify[this.classify.length-1]||0
+            if(this.classify.length>=3){
+                this.ClassifyFirstId = this.classify[this.classify.length-2]||0
+            }else{
+                this.ClassifyFirstId = 0
+            }
+            this.handleCurrentChange(1)
+        },
+        sortChange({prop,order}){
+            this.SortRule = order==='ascending'?1:2
+            this.handleCurrentChange(1)
+        },
+        getTableData(){
+            approveInterence.getApproveFlowList({
+                PageSize:this.pageSize,
+                CurrentIndex:this.page,
+                ReportType:this.ReportType,
+                ClassifyFirstId:this.ClassifyFirstId,
+                ClassifySecondId:this.ClassifySecondId,
+                Keyword:this.Keyword,
+                SortRule:this.SortRule
+            }).then(res=>{
+                if(res.Ret!==200) return 
+                const {List=[],Paging={}} = res.Data||{}
+                this.tableData = List||[]
+                this.total = Paging.Totals||0
+            })
+        },
+        handleEditFlow(item){
+            this.$router.push({
+                path:'/approveEdit',
+                query:{
+                    flowId:item.ReportApproveFlowId
+                }
+            })
+        },
+        handleDeleteFlow(item){
+            this.$confirm("删除后不可恢复,确认删除吗?","提示",{
+                type:"warning"
+            }).then(()=>{
+                approveInterence.deleteApproveFlow({
+                    ReportApproveFlowId:item.ReportApproveFlowId
+                }).then(res=>{
+                    if(res.Ret!==200) return 
+                    this.$message.success("删除成功")
+                    this.handleCurrentChange(1)
+                })
+            }).catch(()=>{})
+        }
+    },
+    mounted(){
+        this.getClassifyTree()
+        this.getTableData()
+    },
+};
+</script>
+
+<style scoped lang="scss">
+@import url('./css/pageStyle.scss');
+.approve-setting-wrap{
+    .head-box{
+        display: flex;
+        justify-content: space-between;
+    }
+    .list-box{
+        margin-top:30px;
+    }
+}
+</style>

+ 112 - 0
src/views/approve_manage/components/flowEdiotr.vue

@@ -0,0 +1,112 @@
+<template>
+    <!-- 审批流内容 -->
+    <div class="flow-editor">
+        <span class="circle-point"></span>
+        <span class="circle-point end"></span>
+        <component v-for="(node,index) in flowData" :key="index"
+            :is="node.nodeName"
+            :flowNode="{...node,...{index}}"
+            @addNode="addFlowNode"
+            @editNode="editFlowNode"
+            @removeNode="removeNode">
+        </component>
+    </div>
+</template>
+
+<script>
+import StartNode from './flowNode/startNode.vue';
+import AddNode from './flowNode/addNode.vue';
+import ApproveNode from './flowNode/approveNode.vue';
+import EndNode from './flowNode/endNode.vue';
+export default {
+    props:{
+        flowNodes:{ //审批流原数据,只包含审批节点
+            type:Array,
+            default:[]
+        }
+    },
+    data() {
+        return {
+            flowData:[{
+                nodeType: 1,
+                nodeName: 'StartNode',
+            },{
+                nodeType:3,
+                nodeName:'EndNode'
+            }]
+        };
+    },
+    watch:{
+        flowNodes(val){
+            this.initFlowData()
+        }
+    },
+    methods: {
+        initFlowData(){
+            const approveData = this.flowNodes.map(n=>{
+                const approvers = n.Users.map(i=>{
+                    return {
+                        ItemId:i.UserId,
+                        ItemName:i.UserName
+                    }
+                })
+                return {
+                    ...n,
+                    nodeType:2,
+                    nodeName:'ApproveNode',
+                    approvers
+                }
+            })
+            this.flowData.splice(1,0,...approveData)
+        },
+        addFlowNode(node){
+            const {prevNode} = node
+            delete node.prevNode
+            const {index} = prevNode
+            this.flowData.splice(index+1,0,node)
+        },
+        removeNode(node){
+            const {index} = node
+            this.flowData.splice(index,1)
+        },
+        editFlowNode(node){
+            const {index} = node
+            this.flowData.splice(index,1,node)
+        }
+    },
+    mounted(){
+        //this.initFlowData()
+    },
+    components: { StartNode,AddNode,ApproveNode,EndNode }
+};
+</script>
+
+<style scoped lang="scss">
+@import url('../css/nodeStyle.scss');
+.flow-editor{
+    margin-left: 20px;
+    position:relative;
+    .circle-point{
+            position:absolute;
+            top:0;
+            left:-22px;
+            width:6px;
+            height:6px;
+            border-radius: 50%;
+            background-color: #0052D9;
+            &.end{
+                top:auto;
+                bottom:0;
+            }
+        }
+        &::before{
+            content: '';
+            top:0;
+            left:-20px;
+            bottom: 0;
+            width:2px;
+            background-color: #0052D9;
+            position: absolute;
+        }
+}
+</style>

+ 44 - 0
src/views/approve_manage/components/flowNode/addNode.vue

@@ -0,0 +1,44 @@
+<template>
+    <div class="add-node-wrap">
+        <div class="add-btn" @click="handleAddApprove">
+            <span> <i class="el-icon-circle-plus-outline"></i></span>
+            <span>添加审批人</span>
+        </div>
+    </div>
+</template>
+
+<script>
+export default {
+    props:["node"],
+    data() {
+        return {
+            visible:false,
+        };
+    },
+    methods: {
+        handleAddApprove(){
+            this.visible = false
+            const data = {
+                nodeType:2,
+                ApproveType:1,
+                nodeName:'ApproveNode',
+                approvers:[],
+                prevNode:this.node
+            }
+            this.$emit("addNode",data)
+        }
+    },
+};
+</script>
+
+<style scoped lang="scss">
+.add-node-wrap{
+    margin: 20px 0;
+    .add-btn{
+        user-select: none;
+        cursor: pointer;
+        color:#0052D9;
+        display: inline-block;
+    }
+}
+</style>

+ 280 - 0
src/views/approve_manage/components/flowNode/approveNode.vue

@@ -0,0 +1,280 @@
+<template>
+    <div class="approve-node-wrap node-wrap">
+        <div class="node-content">
+            <div class="head">
+                <span class="icon"></span>
+                <span class="name">审核人</span>
+                <span class="icon-btn" @click="removeNode"><i class="el-icon-close"></i></span>
+            </div>
+            <div class="content" @click="showDrawer">
+                <ul class="approver-list" v-if="flowNode.approvers.length">
+                    <li class="list-item" v-for="(item,index) in flowNode.approvers" :key="item.ItemId">
+                        {{item.ItemName}}{{index===flowNode.approvers.length-1?'':'、'}}
+                    </li>
+                </ul>
+                <span v-else style="color:#0052D9;display: flex;align-items: center;">
+                    <img src="~@/assets/img/approve_m/select.png">
+                    请选择审批人
+                </span>
+            </div>
+        </div>
+        <AddNode :node="flowNode" v-on="$listeners"/>
+        <el-drawer
+            direction="rtl"
+            :visible.sync="drawerShow"
+            :withHeader="true"
+            :modal-append-to-body="false"
+            >
+            <div class="approve-drawer-wrap">
+                <div class="header">
+                    <p>审批人设置</p>
+                    <span class="close-icon" @click="drawerShow=false" style="cursor: pointer;"><i class="el-icon-close"></i></span>
+                </div>
+                <div class="drawer-content">
+                    <div class="block">
+                        <p>选择审批人</p>
+                        <div class="choose-box">
+                            <el-radio v-model="block1" :label="1">指定人员</el-radio>
+                            <el-button @click="chooseDialogShow=true" type="primary">
+                                <i class="el-icon-circle-plus-outline" style="margin-right: 5px;"></i>
+                                选择人员
+                            </el-button>
+                        </div>
+                        <draggable 
+                            v-model="choosedList"
+                            animation="300"
+                            tag="ul"
+                            class="approve-list">
+                            <li class="list-item" v-for="item in choosedList" :key="item.ItemId">
+                                <span class="name">{{item.ItemName}}</span>
+                                <span class="icon-btn">
+                                    <i class="el-icon-close" @click.stop="removeChoosedItem(item)"></i>
+                                </span>
+                            </li>
+                        </draggable>
+                    </div>
+                    <div class="line"></div>
+                    <div class="block" style="margin-top:30px;">
+                        <p>多人审批时</p>
+                        <el-radio-group v-model="approveType">
+                            <el-radio :label="1">
+                                依次审批
+                                <el-tooltip effect="dark" placement="top" content="多个审批人依次进行审批;只有当所有审批人同意,该节点才能通过;按选择顺序审批" >
+                                    <span class="hint-text">
+                                        <i class="el-icon-info"></i>
+                                    </span>
+                                </el-tooltip>
+                            </el-radio>
+                            <el-radio :label="2">
+                                会签(须所有审批人同意)
+                                <el-tooltip effect="dark" placement="top" content="所有审批人同意,该节点才能通过;审批无先后顺序" >
+                                    <span class="hint-text">
+                                        <i class="el-icon-info"></i>
+                                    </span>
+                                </el-tooltip>
+                            </el-radio>
+                            <el-radio :label="3">
+                                或签(一名审批人同意或拒绝即可)
+                                <el-tooltip effect="dark" placement="top" content="任意一名审批人同意,该节点即通过;审批无先后顺序" >
+                                    <span class="hint-text">
+                                        <i class="el-icon-info"></i>
+                                    </span>
+                                </el-tooltip>
+                            </el-radio>
+                        </el-radio-group>
+                    </div>
+                </div>
+                <div class="drawer-btn">
+                    <el-button type="primary" plain @click="drawerShow=false">取消</el-button>
+                    <el-button type="primary" @click="editApproveNode">确认</el-button>
+                </div>
+            </div>
+        </el-drawer>
+        <!-- 选择人员弹窗 -->
+        <el-dialog 
+            title="选择人员"
+            width="600px"
+            :visible.sync="chooseDialogShow"
+            :modal-append-to-body="false"
+            :append-to-body="false"
+            @close="chooseDialogShow=false"
+        >
+            <div class="dialog-wrap">
+                <TreeTransfer 
+                    ref="tree-trans"
+                    :defaultList="choosedList"
+                    :chooseDialogShow="chooseDialogShow"
+                />
+            </div>
+            <div class="dialog-btn">
+                <el-button type="primary" plain @click="chooseDialogShow=false">取消</el-button>
+                <el-button type="primary" @click="getChoosedList">确认</el-button>
+            </div>
+        </el-dialog>
+    </div>
+</template>
+
+<script>
+import TreeTransfer from '../treeTransfer';
+import draggable from 'vuedraggable';
+import AddNode from './addNode';
+export default {
+    props:{
+        flowNode:{
+            type:Object,
+            default:{}
+        }
+    },
+    data() {
+        return {
+            drawerShow: false,
+            block1: 1,
+            approveType: 1,
+            chooseDialogShow: false,
+            choosedList:[]
+        };
+    },
+    watch:{
+        drawerShow(val){
+            if(val){
+                this.choosedList = _.cloneDeep(this.flowNode.approvers||[])
+                this.approveType = this.flowNode.ApproveType
+            }
+        }
+    },
+    methods: {
+        removeNode() {
+            this.$emit('removeNode', this.flowNode);
+        },
+        showDrawer() {
+            this.drawerShow = true;
+        },
+        getChoosedList(){
+            if(!this.$refs["tree-trans"].choosedList.length){
+                this.$message.warning("请至少选择一人")
+                return
+            }
+            this.choosedList = _.cloneDeep(this.$refs["tree-trans"].choosedList)||[]
+            this.chooseDialogShow = false
+        },
+        removeChoosedItem(item){
+            const index = this.choosedList.findIndex(i=>i.ItemId===item.ItemId)
+            index!==-1&&this.choosedList.splice(index,1)
+        },
+        editApproveNode(){
+            const node = _.cloneDeep(this.flowNode)
+            node.approvers = _.cloneDeep(this.choosedList)
+            node.ApproveType = this.approveType
+            this.$emit('editNode',node)
+            this.drawerShow = false
+        },
+    },
+    components: { TreeTransfer, draggable, AddNode }
+};
+</script>
+
+<style lang="scss">
+.approve-node-wrap{
+    .el-drawer__body{
+        overflow: hidden;
+    }
+    #el-drawer__title{ //drawer弹出时会自动聚焦第一个元素,设置无内容的title清除聚焦状态
+        height:0px;
+        margin:0px;
+        padding:0px;
+    }
+    .dialog-btn{
+        margin-top:60px;
+        padding-bottom: 40px;
+        text-align: center;
+    }
+}
+</style>
+<style scoped lang="scss">
+.approve-node-wrap{
+    .head{
+        background-color: #0052D9;
+        .icon{
+            background-image: url('~@/assets/img/approve_m/approve.png');
+        }
+        .icon-btn{
+            font-size: 20px;
+        }
+    }
+    .content{
+        .approver-list{
+            color:#0052D9;
+            display: flex;
+            align-items: center;
+            flex-wrap: wrap;
+        }
+    }
+    .approve-drawer-wrap{
+        height: 100%;
+        display: flex;
+        flex-direction: column;
+        overflow: hidden;
+        .header{
+            display: flex;
+            align-items: center;
+            justify-content: space-between;
+            /* font-weight: bold; */
+            font-size: 18px;
+            height:35px;
+            padding:20px;
+            border-bottom: 1px solid #C8CDD9;
+        }
+        .drawer-content{
+            flex:1;
+            overflow-y: auto;
+            box-sizing: border-box;
+            padding:30px;
+            .block{
+                min-height: 340px;
+                .choose-box{
+                    margin-top: 20px;
+                    display: flex;
+                    justify-content: space-between;
+                    align-items: center;
+                }
+            }
+            .line{
+                margin:0 -30px;
+                height: 1px;
+                background-color:#C8CDD9;
+            }
+            .approve-list{
+                margin-top: 10px;
+                display: flex;
+                flex-wrap: wrap;
+                gap:10px;
+                .list-item{
+                    cursor: move;
+                    padding:8px;
+                    border-radius: 4px;
+                    border:1px solid #C8CDD9;
+                    .icon-btn{
+                        cursor: pointer;
+                    }
+                }
+            }
+            .el-radio-group{
+                margin-top: 20px;
+                .el-radio{
+                    display: block;
+                    margin-bottom: 10px;
+                    .hint-text{
+                        color:#C0C4CC;
+                    }
+
+                }
+            }
+        }
+        .drawer-btn{
+            text-align: center;
+            margin:10px;
+        }
+    }
+    
+}
+</style>

+ 26 - 0
src/views/approve_manage/components/flowNode/endNode.vue

@@ -0,0 +1,26 @@
+<template>
+    <div class="end-node-wrap node-wrap">
+        <div class="end-content">流程结束</div>
+    </div>
+</template>
+
+<script>
+export default {
+    data() {
+        return {
+
+        };
+    },
+    methods: {
+
+    },
+};
+</script>
+
+<style scoped lang="scss">
+.end-node-wrap{
+    .end-content{
+        color:#C0C4CC;
+    }
+}
+</style>

+ 43 - 0
src/views/approve_manage/components/flowNode/startNode.vue

@@ -0,0 +1,43 @@
+<template>
+    <div class="start-node-wrap node-wrap">
+        <div class="node-content">
+            <div class="head">
+                <span class="icon"></span>
+                <p class="name">发起人</p>
+            </div>
+            <div class="content">所有人</div>
+        </div>
+        <AddNode :node="flowNode" v-on="$listeners"/>
+    </div>
+</template>
+
+<script>
+import AddNode from './addNode.vue';
+export default {
+    components: { AddNode},
+    props:{
+        flowNode:{
+            type:Object,
+            default:{}
+        }
+    },
+    data() {
+        return {};
+    },
+    methods: {},
+};
+</script>
+
+<style scoped lang="scss">
+.start-node-wrap{
+    .head{
+        background-color: #ECF2FE;
+        .name{
+            color:#0052D9;
+        }
+        .icon{
+            background-image: url('~@/assets/img/approve_m/start.png');
+        }
+    }
+}
+</style>

+ 81 - 0
src/views/approve_manage/components/rejectDialog.vue

@@ -0,0 +1,81 @@
+<template>
+    <el-dialog custom-class="approve-reject-dialog"
+        title="审批驳回"
+        :visible.sync="isDetailDialogShow"
+        :close-on-click-modal="false"
+        :modal-append-to-body="false"
+        @close="$emit('close')"
+        width="692px"
+        v-dialogDrag
+        center
+    >
+        <div class="dialog-content-wrap">
+            <el-input type="textarea" v-model="content" :disabled="!isEdit" :rows="10" :placeholder="isEdit?'请输入驳回理由':'无'"></el-input>
+        </div>
+        <div class="dialog-btn-wrap">
+            
+            <template v-if="isEdit">
+                <el-button @click="$emit('close')">取消</el-button>
+                <el-button type="primary" @click="handleConfirm">确认</el-button>
+            </template>
+            <el-button v-else @click="$emit('close')">知道了</el-button>
+        </div>
+    </el-dialog>
+</template>
+
+<script>
+export default {
+    props:{
+        isDetailDialogShow:{
+            type:Boolean,
+            default:false
+        },
+        isEdit:{
+            type:Boolean,
+            default:true
+        },
+        data:{
+            type:Object,
+            default:()=>{return{}}
+        }
+    },
+    watch:{
+        isDetailDialogShow(val){
+            if(val){
+                this.content = this.data.ApproveRemark||''
+            }
+        }
+    },
+    data() {
+        return {
+            content:''
+        };
+    },
+    methods: {
+        handleConfirm(){
+            /* if(!this.content.length){
+                this.$message.warning("请输入驳回理由")
+                return
+            } */
+            this.$emit('edit',this.content)
+        }
+    },
+};
+</script>
+
+<style lang="scss">
+.approve-reject-dialog{
+    .dialog-content-wrap{
+        .el-textarea{
+            textarea{
+                resize: none !important;
+            }
+        }
+    }
+    .dialog-btn-wrap{
+        text-align: center;
+        margin-top: 20px;
+        padding-bottom: 25px;
+    }
+}
+</style>

+ 60 - 0
src/views/approve_manage/components/timeLine.vue

@@ -0,0 +1,60 @@
+<template>
+    <div class="time-line-wrap">
+        <ul>
+            <li v-for="(node,index) in TimeLineData" :key="index">
+                <TimeLineItem :node="node" :isLast="index===TimeLineData.length-1"/>
+            </li>
+        </ul>
+    </div>
+</template>
+
+<script>
+import TimeLineItem from './timeLineItem.vue';
+export default {
+    components:{TimeLineItem},
+    props:{
+        TimeLineData:{
+            type:Array
+        }
+    },
+    data() {
+        return {
+            //时间线数据格式
+            mockTimeLine:[
+                {
+                    nodeType:1,
+                    nodeText:'发起人:',
+                    approveList:[{
+                        approverName:'张三',
+                        approveTime:'2023-10-10 10:10:10'
+                    }],
+                    nodeStatus:'passed',//passed节点已通过,return节点已撤回,reject节点已驳回,future节点未进行到
+                },{
+                    nodeType:2,
+                    nodeText:'审批人:', //需要拼接成 审批人:2人(会签)
+                    nodeStatus:'process',//节点正在进行中
+                    approveType:'会签',
+                    approveList:[//参与审批的人员
+                        {
+                            approverName:'李四',
+                            approveTime:'2023-10-10 10:15:10',
+                            approveStatus:'已同意'
+                        },{
+                            approverName:'王五',
+                            approveTime:'2023-10-10 10:22:00',
+                            approveStatus:'已驳回',
+                            approveReason:'就是驳回'
+                        }
+                    ]
+                }
+            ]
+        };
+    },
+    methods: {
+
+    },
+};
+</script>
+
+<style scoped lang="scss">
+</style>

+ 120 - 0
src/views/approve_manage/components/timeLineItem.vue

@@ -0,0 +1,120 @@
+<template>
+    <div class="item-wrap">
+        <div class="icon-wrap">
+            <div :class="['icon',node.nodeStatus]">
+                <img :src="require(`@/assets/img/approve_m/${node.nodeStatus}-icon.svg`)" alt="">
+            </div>
+            <div :class="['line',isLast?'last':'',node.nodeStatus]"></div>
+        </div>
+        <div class="info-wrap">
+            <!-- 发起人或审批人 -->
+            <div class="normal-text">
+                <p>{{node.nodeText}}</p>
+            </div>
+            <ul class="approve-list">
+                <li v-for="(item,itemIndex) in node.approveList" :key="itemIndex">
+                    <div class="approve-item-wrap">
+                        <!-- 审批人(审批状态) 审批时间-->
+                        <div class="normal-text">
+                            <p :class="{'passed':item.approveStatus==='已同意'}">{{item.approverName}} <span v-if="item.approveStatus">{{'('+item.approveStatus+')'}}</span> </p>
+                            <span class="time">{{item.approveTime||''}}</span>
+                        </div>
+                        <!-- 驳回理由 -->
+                        <div class="approve-reason" v-if="item.approveReason">
+                            驳回理由:{{item.approveReason}}
+                        </div>
+                    </div>
+                </li>
+            </ul>
+        </div>
+    </div>
+</template>
+
+<script>
+export default {
+    props:{
+        node:{
+            type:Object,
+            default:{}
+        },
+        isLast:{
+            type:Boolean,
+            default:false
+        }
+    },
+    data() {
+        return {
+
+        };
+    },
+    methods: {
+
+    },
+};
+</script>
+
+<style scoped lang="scss">
+.item-wrap{
+    display: flex;
+    width:100%;
+    .icon-wrap{
+        width:25px;
+        /* border:1px solid black; */
+        position:relative;
+        .icon,.line{
+            position:absolute;
+            left:50%;
+            transform: translateX(-50%);
+        }
+        .icon{
+            width:16px;
+            height:16px;
+            border-radius: 50%;
+            background-color: #fff;
+            overflow: hidden;
+            img{
+                width:100%;
+                height:100%;
+            }
+        }
+        .line{
+            top:16px;
+            width:1px;
+            height:calc(100% - 16px);
+            background-color: gray;
+            &.passed{
+                background-color: #0052D9;
+            }
+            &.last{
+                background-color: transparent;
+            }
+        }
+    }
+    .info-wrap{
+        flex:1;
+        margin-left: 15px;
+        margin-bottom: 20px;
+        .approve-list{
+            .approve-item-wrap{
+                .normal-text{
+                    display: flex;
+                    justify-content: space-between;
+                    margin-bottom: 10px;
+                    color:gray;
+                    &.passed{
+                        color:#0052D9;
+                    }
+                }
+                .approve-reason{
+                   /*  margin-left: -40px; */
+                    padding:10px;
+                    /* padding-left: 40px; */
+                    color:#AD352F;
+                    background-color: #FFF0ED;
+                }
+            }
+        }
+        
+    }
+}
+</style>

+ 185 - 0
src/views/approve_manage/components/treeTransfer.vue

@@ -0,0 +1,185 @@
+<template>
+    <!-- 选择审批人组件 -->
+    <div class="tree-transfer">
+        <div class="before-transfer transfer">
+            <div class="search">
+                <el-input placeholder="搜索" suffix-icon="el-icon-search" style="width:100%;"
+                    v-model="searchText" @input="$refs['trans-tree'].filter(searchText)"></el-input>
+            </div>
+            <div class="content">
+                <el-tree 
+                    node-key="ItemId"
+                    ref="trans-tree"
+                    show-checkbox
+                    :data="treeData"
+                    :props="{
+                        label:'ItemName',
+                        children:'Children'
+                    }"
+                    :filter-node-method="filterNode"
+                    @check="SetCheckedNode"
+                ></el-tree>
+            </div>
+        </div>
+        <div class="after-transfer transfer">
+            <div class="head">
+                <span>已选{{choosedList.length}}项</span>
+                <span class="btn-text delete" @click="clearnItem">清空</span>
+            </div>
+            <draggable 
+                v-model="choosedList"
+                animation="300"
+                tag="ul"
+                class="content">
+                <li class="list-item" v-for="item in choosedList" :key="item.ItemId">
+                    <span class="name">{{item.ItemName}}</span>
+                    <span class="icon-btn" style="color:#C0C4CC;">
+                        <i class="el-icon-close" @click.stop="removeItem(item)"></i>
+                    </span>
+                </li>
+            </draggable>
+        </div>
+    </div>
+</template>
+
+<script>
+import { dataAuthInterface } from "@/api/api.js";
+import draggable from 'vuedraggable';
+export default {
+    components:{draggable},
+    props:{
+        defaultList:{
+            type:Array,
+            default:[]
+        },
+        chooseDialogShow:{
+            type:Boolean,
+            default:false
+        }
+    },
+    data() {
+        return {
+            totalNum:0,
+            treeData:[],
+            searchText:'',
+            choosedList:[]
+        };
+    },
+    watch:{
+        chooseDialogShow:{
+            handler(val){
+                if(val){
+                    this.searchText=''
+                    this.getTreeData()
+                }
+            },
+            immediate:true
+        }
+    },
+    methods: {
+        getTreeData(){
+            ///datamanage/manual/sysuser/search?KeyWord= ,要用新接口再换
+            dataAuthInterface.userSearch({
+                KeyWord: ''
+            }).then(res => {
+                if(res.Ret === 200) {
+                    this.treeData = res.Data||[];
+                }
+                this.$nextTick(()=>{
+                    const keys = this.defaultList.map(i=>{
+                        return i.ItemId
+                    })
+                    this.$refs["trans-tree"].setCheckedKeys(keys)
+                    this.choosedList = _.cloneDeep(this.defaultList)
+                })
+            })
+        },
+        filterNode(value,data){
+            if(!value) return true
+            return data.ItemName.indexOf(value)!==-1
+        },
+        SetCheckedNode(data,{checkedNodes}){
+            if(!this.choosedList.length){
+                 //只获取人员
+                this.choosedList = checkedNodes.filter(i=>{
+                    if(i.ItemId<10000&&!i.Children)
+                        return i
+                })
+            }else{
+                //遍历 filterArr choosedList里没有的,push进去
+                const filterArr = checkedNodes.filter(i=>{
+                    if(i.ItemId<10000&&!i.Children)
+                        return i
+                })
+                filterArr.forEach(i=>{
+                    const index = this.choosedList.findIndex(item=>i.ItemId===item.ItemId)
+                    if(index===-1){this.choosedList.push(i)}
+                })
+                //遍历choosedList,filterArr里没有的,删除
+                const tempArr = _.cloneDeep(this.choosedList)
+                tempArr.forEach(i=>{
+                    const checkIndex = filterArr.findIndex(item=>item.ItemId===i.ItemId)
+                    if(checkIndex===-1){
+                        const index = this.choosedList.findIndex(item=>item.ItemId===i.ItemId)
+                        index!==-1&&this.choosedList.splice(index,1)
+                    }
+                })
+            }
+        },
+        removeItem(item){
+            const {ItemId} = item
+            this.$refs["trans-tree"].setChecked(ItemId,false,false)
+            const index = this.choosedList.findIndex(i=>i.ItemId===ItemId)
+            index!==-1&&this.choosedList.splice(index,1)
+        },
+        clearnItem(){
+            this.$refs["trans-tree"].setCheckedKeys([])
+            this.choosedList = []
+        },
+    },
+    mounted(){
+        //this.getTreeData()
+    }
+};
+</script>
+
+<style scoped lang="scss">
+.tree-transfer{
+    display: flex;
+    align-items: center;
+    gap:12px;
+    .transfer{
+        display: flex;
+        flex-direction: column;
+        width:254px;
+        height: 400px;
+        border:1px solid #DCDCDC;
+        border-radius: 6px;
+        padding:8px;
+        .head,.search,.content{
+            padding:10px;
+        }
+        .head{
+            display: flex;
+            justify-content: space-between;
+            .btn-text{
+                cursor: pointer;
+                &.delete{
+                    color:red;
+                }
+            }
+        }
+        .content{
+            flex:1;
+            overflow-y: scroll;
+            margin-bottom: 10px;
+            .list-item{
+                cursor: pointer;
+                padding:6px 0;
+                display: flex;
+                justify-content: space-between;
+            }
+        }
+    }
+}
+</style>

+ 95 - 0
src/views/approve_manage/config/tableConfig.js

@@ -0,0 +1,95 @@
+//审批管理-待处理
+export const approve_pending_columns = [
+    {
+        key:'ReportTitle',
+        label:'报告标题'
+    },{
+        key:'ReportClassify',
+        label:'关联报告'
+    },{
+        key:'ApplyUserName',
+        label:'提交人'
+    },{
+        key:'CreateTime',
+        label:'提交时间',
+        sortable:'custom'
+    },{
+        key:'RecordState',
+        label:'审批状态',
+    }
+]
+export const appreve_pending_status = [
+    {
+        type:1,
+        label:'待审批'
+    }
+]
+//审批管理-已处理
+export const approve_processed_columns=[
+    {
+        key:'ReportTitle',
+        label:'报告标题'
+    },{
+        key:'ReportClassify',
+        label:'关联报告'
+    },{
+        key:'ApplyUserName',
+        label:'提交人'
+    },{
+        key:'CreateTime',
+        label:'提交时间',
+        sortable:'custom'
+    },{
+        key:'HandleTime',
+        label:'处理时间',
+        sortable:'custom'
+    },{
+        key:'RecordState',
+        label:'处理结果',
+    }
+]
+export const approve_processed_status = [
+    {
+        type:1,
+        label:'已同意'
+    },{
+        type:2,
+        label:'已驳回'
+    }
+]
+//审批管理-我发起的
+export const approve_originate_columns=[
+    {
+        key:'ReportTitle',
+        label:'报告标题'
+    },{
+        key:'ReportClassify',
+        label:'关联报告'
+    },{
+        key:'CreateTime',
+        label:'提交时间',
+        sortable:'custom'
+    },{
+        key:'ApproveTime',
+        label:'审批时间',
+        sortable:'custom'
+    },{
+        key:'State',
+        label:'审批状态',
+    }
+]
+export const approve_originate_status=[
+    {
+        type:1,
+        label:'待审批'
+    },{
+        type:2,
+        label:'已通过'
+    },{
+        type:3,
+        label:'已驳回'
+    },{
+        type:4,
+        label:'已撤销'
+    }
+]

+ 39 - 0
src/views/approve_manage/css/nodeStyle.scss

@@ -0,0 +1,39 @@
+.node-wrap{
+    display: flex;
+    flex-direction: column;
+    /* align-items: center; */
+    .node-content{
+        overflow: hidden;
+        cursor: pointer;
+        border-radius: 4px;
+        width:300px;
+        min-height: 100px;
+        background-color: #fff;
+        border:1px solid #0052D9;
+        .head{
+            user-select: none;
+            color:#fff;
+            height:35px;
+            display: flex;
+            align-items: center;
+            padding: 5px;
+            justify-content: space-between;
+            border-bottom: 1px solid #0052D9;
+            .name{
+                margin-left: 5px;
+                margin-right: auto;
+            }
+            .icon{
+                display: inline-block;
+                width:20px;
+                height:20px;
+            }
+        }
+        .content{
+            padding:5px;
+        }
+    }
+    div{
+        box-sizing: border-box;
+    }
+}

+ 6 - 0
src/views/approve_manage/css/pageStyle.scss

@@ -0,0 +1,6 @@
+.approve-page-wrap{
+    min-height: calc(100vh - 120px);
+    background-color: #fff;
+    box-sizing: border-box;
+    padding:30px;
+}

+ 31 - 0
src/views/approve_manage/mixins/approveMixins.js

@@ -0,0 +1,31 @@
+import {approveInterence} from '@/api/modules/approve.js'
+const filterNodes = (arr,hasDisabled)=>{
+    arr.length &&arr.forEach((item) => {
+        hasDisabled&&(item.disabled = item.HasFlow)
+        item.Children.length && filterNodes(item.Children,hasDisabled);
+        if (!item.Children.length) {
+            delete item.Children;
+        }
+    })
+}
+
+export default{
+    data(){
+        return {
+            classifyTree:[],
+        }
+    },
+    methods:{
+        getClassifyTree(){
+            approveInterence.getReportClassifyTree().then(res=>{
+                if(res.Ret!==200) return 
+                this.classifyTree = res.Data||[]
+                const hasDisabled = window.location.pathname.startsWith('/approveEdit')
+                filterNodes(this.classifyTree,hasDisabled)
+                if(this.getFlowDetail){
+                    this.getFlowDetail()
+                }
+            })
+        },
+    }
+}

+ 3 - 4
src/views/dataEntry_manage/databaseList.vue

@@ -88,7 +88,6 @@
 						@node-drag-end="dropMouseLeave"
 						@node-drag-leave="dropMouseLeave"
 						@node-drag-enter="dropMouseOver"
-						@node-drag-over="dropMouseOver"
 					>
 						<span
 							class="custom-tree-node"
@@ -1422,8 +1421,8 @@ export default {
 				}
 			}else{//拖动的是目录
 				// console.log(dropNode.level,draggingNode.level);
-				//目录只能拖动到层级比他大的里面去
-				if(dropNode.level<draggingNode.level||(dropNode.level===draggingNode.level&&type!=='inner')){
+				//目录层级不能改变
+				if((dropNode.level+1==draggingNode.level&&type==='inner'&&!dropNode.data.EdbCode)||(dropNode.level===draggingNode.level&&type!=='inner')){
 					canDrop=true
 				}
 			}
@@ -1509,7 +1508,7 @@ export default {
 			// console.log(e.layerY);
 			
 			// 被拖拽节点对应的 Node、所进入节点对应的 Node、event
-			if((node1.level>node2.level||(node1.data.EdbInfoId>0&&!node2.data.EdbInfoId)) && (e.target.childNodes[0].className.includes('el-tree-node__content') 
+			if(!node2.data.EdbInfoId&&(node1.level>node2.level||(node1.data.EdbInfoId>0&&!node2.data.EdbInfoId)) && (e.target.childNodes[0].className.includes('el-tree-node__content') 
 			|| e.target.className.includes('el-tree-node__content'))) {
 				// console.log(e.target.childNodes[0])
 				e.target.childNodes[0].className.includes('el-tree-node__content') 

+ 3 - 3
src/views/predictEdb_manage/mixins/mixin.js

@@ -182,7 +182,7 @@ export default {
     /* 拖拽覆盖添加背景色 */
     dropMouseOver(node1, node2, e) {
       // 被拖拽节点对应的 Node、所进入节点对应的 Node、event
-			if((node1.level>node2.level||(node1.data.EdbInfoId>0&&!node2.data.EdbInfoId)) && (e.target.childNodes[0].className.includes('el-tree-node__content') 
+			if(!node2.data.EdbInfoId&&(node1.level>node2.level||(node1.data.EdbInfoId>0&&!node2.data.EdbInfoId)) && (e.target.childNodes[0].className.includes('el-tree-node__content') 
 			|| e.target.className.includes('el-tree-node__content'))) {
 				// console.log(e.target.childNodes[0])
 				e.target.childNodes[0].className.includes('el-tree-node__content') 
@@ -236,8 +236,8 @@ export default {
 				}
 			}else{//拖动的是目录
 				// console.log(dropNode.level,draggingNode.level);
-				//目录只能拖动到层级比他大的里面去
-				if(dropNode.level<draggingNode.level||(dropNode.level===draggingNode.level&&type!=='inner')){
+				//目录层级不能改变
+				if((dropNode.level+1==draggingNode.level&&type==='inner'&&!dropNode.data.EdbCode)||(dropNode.level===draggingNode.level&&type!=='inner')){
 					canDrop=true
 				}
 			}

+ 0 - 1
src/views/predictEdb_manage/predictEdb.vue

@@ -69,7 +69,6 @@
 						@node-drag-end="dropMouseLeave"
 						@node-drag-leave="dropMouseLeave"
 						@node-drag-enter="dropMouseOver"
-						@node-drag-over="dropMouseOver"
 					>
 						<span class="custom-tree-node" slot-scope="{ node, data }">
 							<el-input

+ 23 - 7
src/views/report_manage/addreportNew.vue

@@ -17,7 +17,8 @@
 			></froala>
 		</div>
 		<div id="rightitems" v-show="isRightFormShow">
-			<div
+			<!-- 通过接口判断是否走审批流,按钮显示的不一致,干脆判断完成再显示所有按钮-->
+			<div v-if="!pageLoading"
 				style="
 					text-align: right;
 					padding: 0px 0 15px 0;
@@ -50,23 +51,27 @@
 					>存草稿</el-button
 				>
 				<!--不走审批流-->
-				<template v-if="!isApprove">
+				<template v-if="!isApprove||!hasApproveFlow">
 					<el-button v-permission="permissionBtn.reportManageBtn.reportManage_publish"
 						type="primary"
 						size="medium"
+						:disabled="checkLoading"
 						@click.native="clickreportadd('dsfb')"
 						>定时发布</el-button
 					>
-					<el-button
+					<el-button v-permission="permissionBtn.reportManageBtn.reportManage_publish"
 						type="primary"
 						size="medium"
+						:disabled="checkLoading"
 						@click.native="clickreportadd('fb')"
 						:loading="isPublishloading"
 						>发布</el-button
 					>
 				</template>
-				<template v-if="isApprove">
-					<el-button type="primary" size="medium" @click="clickreportadd('fb')">提交</el-button>
+				<template v-if="isApprove&&hasApproveFlow">
+					<el-button v-permission="permissionBtn.reportManageBtn.reportManage_publish"
+						:disabled="checkLoading"
+						type="primary" size="medium" @click="clickreportadd('submit')">提交</el-button>
 				</template>
 			</div>
 			<div
@@ -368,10 +373,11 @@ import VueFroala from 'vue-froala-wysiwyg';
 import urlSlug from 'url-slug';
 import mixinMsg from './mixins/messagePush'
 import reportMixin from './mixins/reportMixin';
+import reportApproveConfig from "@/mixins/reportApproveConfig.js"
 import importMyChart from './components/importMyChart.vue'
 import importSemantics from './components/importSemantics.vue';
 export default {
-	mixins:[mixinMsg,reportMixin],
+	mixins:[mixinMsg,reportMixin,reportApproveConfig],
 	data() {
 		var that = this;
 		return {
@@ -507,6 +513,10 @@ export default {
 						frequency: res.Data.Frequency,
 						content: res.Data.Content,
 					};
+					let classify = this.aeForm.classifynameArr.map(i=>{
+						return JSON.parse(i).v||0
+					})
+					this.checkClassifyNameArr(1,classify)
 				}
 			});
 		},
@@ -518,6 +528,12 @@ export default {
 			});
 		},
 		userclassidreportdetail() {
+			//检查classifynameArr是否有审批流
+			let classify = this.aeForm.classifynameArr.map(i=>{
+				return JSON.parse(i).v||0
+			})
+			this.checkClassifyNameArr(1,classify)
+
 			if (this.aeForm.add_type == 1) {
 				if (this.aeForm.classifynameArr.length == 2) {
 					this.aeForm.title = JSON.parse(this.aeForm.classifynameArr[1]).l;
@@ -612,7 +628,7 @@ export default {
 				window.open(href, '_blank');
 				return false;
 			}
-			if (tp == 'fb') {
+			if (tp == 'fb'||tp == 'submit') {
 				this.isPublishloading = true;
 			}
 			const isPost = this.permissionBtn.checkPermissionBtn(this.permissionBtn.reportManageBtn.reportManage_sendMsg)&&(!this.isApprove)

+ 23 - 7
src/views/report_manage/editreportNew.vue

@@ -17,7 +17,8 @@
 			></froala>
 		</div>
 		<div id="rightitems" v-show="isRightFormShow">
-			<div
+			<!-- 通过接口判断是否走审批流,按钮显示的不一致,干脆判断完成再显示所有按钮-->
+			<div v-if="!pageLoading"
 				style="
 					text-align: right;
 					padding: 0px 0 15px 0;
@@ -50,23 +51,27 @@
 					>存草稿</el-button
 				>
 				<!--不走审批流-->
-				<template v-if="!isApprove">
+				<template v-if="!isApprove||!hasApproveFlow">
 					<el-button v-permission="permissionBtn.reportManageBtn.reportManage_publish"
 						type="primary"
 						size="medium"
+						:disabled="checkLoading"
 						@click.native="clickreportadd('dsfb')"
 						>定时发布</el-button
 					>
-					<el-button
+					<el-button v-permission="permissionBtn.reportManageBtn.reportManage_publish"
 						type="primary"
 						size="medium"
+						:disabled="checkLoading"
 						@click.native="clickreportadd('fb')"
 						:loading="isPublishloading"
 						>发布</el-button
 					>
 				</template>
-				<template v-if="isApprove">
-					<el-button type="primary" size="medium" @click="clickreportadd('fb')">提交</el-button>
+				<template v-if="isApprove&&hasApproveFlow">
+					<el-button v-permission="permissionBtn.reportManageBtn.reportManage_publish"
+						:disabled="checkLoading"
+						type="primary" size="medium" @click="clickreportadd('submit')">提交</el-button>
 				</template>
 			</div>
 			<div
@@ -364,10 +369,11 @@ import urlSlug from 'url-slug';
 import http from '@/api/http.js';
 import mixinMsg from './mixins/messagePush'
 import reportMixin from './mixins/reportMixin';
+import reportApproveConfig from "@/mixins/reportApproveConfig.js"
 import importMyChart from './components/importMyChart.vue'
 import importSemantics from './components/importSemantics.vue';
 export default {
-	mixins:[mixinMsg,reportMixin],
+	mixins:[mixinMsg,reportMixin,reportApproveConfig],
 	data() {
 		var that = this;
 		return {
@@ -486,6 +492,12 @@ export default {
 			// }
 		},
 		userclassidreportdetail() {
+			//检查classifynameArr是否有审批流
+			let classify = this.aeForm.classifynameArr.map(i=>{
+				return JSON.parse(i).v||0
+			})
+			this.checkClassifyNameArr(1,classify)
+
 			if (this.aeForm.add_type == 1) {
 				if (this.aeForm.classifynameArr.length == 2) {
 					this.aeForm.title = JSON.parse(this.aeForm.classifynameArr[1]).l;
@@ -587,6 +599,8 @@ export default {
 					if(data.PrePublishTime){
 						this.taskTime=data.PrePublishTime
 					}
+					let classify = [data.ClassifyIdFirst,data.ClassifyIdSecond]
+					this.checkClassifyNameArr(1,classify)
 				}
 			});
 		},
@@ -639,9 +653,11 @@ export default {
 				window.open(href, '_blank');
 				return false;
 			}
+			if(tp=='fb'||tp=='submit'){
+				this.isPublishloading = true;
+			}
 			const isPost = this.permissionBtn.checkPermissionBtn(this.permissionBtn.reportManageBtn.reportManage_sendMsg)&&(!this.isApprove)
 			if (tp == 'fb') {
-				this.isPublishloading = true;
 				// 判断是否要推送客群
 				let hasTel=0
 				if(this.aeForm.classifynameArr.length == 2){

+ 31 - 11
src/views/report_manage/mixins/messagePush.js

@@ -1,23 +1,14 @@
 import { reportadd, reportedit, messagePushPost,dataBaseInterface,reportMessageSend } from "@/api/api.js";
+import {approveInterence} from '@/api/modules/approve.js';
 import * as sheetInterface from '@/api/modules/sheetApi.js';
 import { getUrlParams } from '@/utils/common'
 export default {
   data() {
     return {
       isMessagePost: false,
-      //isApprove:false,//是否走审批流
-      isRightFormShow:true
+      isRightFormShow:true,
     };
   },
-  computed:{
-    //是否开启审批流,若开启,发布相关按钮,筛选项改变
-    isApprove(){
-        const type = this.$setting.dynamicOutLinks.ApprovalFlow ||
-                     this.$store.state.dynamicOutLinks.ApprovalFlow ||
-                     JSON.parse(localStorage.getItem('dynamicOutLinks')).ApprovalFlow||''
-        return ['1','3'].includes(type)
-    }
-  },
   methods: {
     reporteditMsg(params2, tp) {
       reportedit(params2).then(async (res) => {
@@ -46,6 +37,8 @@ export default {
           } else if(tp=='dsfb'){
             this.showDSFB=true
             // this.$router.push({path:'/reportlist'});
+          }else if(tp=='submit'){
+            this.handleSubmitReport(res.Data.ReportId)
           }
         }
       });
@@ -78,6 +71,8 @@ export default {
           } else if(tp=='dsfb'){
             this.showDSFB=true
             // this.$router.push({path:'/reportlist'});
+          }else if(tp=='submit'){
+            this.handleSubmitReport(res.Data.ReportId)
           }
           //已经添加过报告
           this.isAddEnter = true;
@@ -151,5 +146,30 @@ export default {
           }
       }
     },1000),
+    //展示提交审批弹窗
+    handleSubmitReport(id){
+        this.submitId = id
+        this.$confirm("是否确认提交该报告进入审批流程?","提示",{
+            confirmButtonText:'确定',
+            cancelButtonText:'取消',
+            type:'warning',
+        }).then(()=>{
+            this.submitReport("submit")
+        })
+        
+    },
+    //提交审批
+    submitReport(type){
+        /* if(type==='submit'){ */
+            approveInterence.reportCnSubmit({
+                ReportId:Number(this.submitId)
+            }).then(res=>{
+                if(res.Ret!==200) return
+                this.$message.success("提交成功")
+                this.isPublishloading = false;
+                this.$router.push({ path: '/reportlist' });
+            })
+        /* } */
+    }
   },
 };

+ 50 - 15
src/views/report_manage/reportEn/reportEditor.vue

@@ -31,7 +31,7 @@
     </div>
 		
 		<div id="rightitems" v-show="isRightFormShow">
-			<div
+			<div v-if="!pageLoading"
 				style="
 					text-align: right;
 					padding: 0px 0 15px 0;
@@ -63,19 +63,28 @@
 					@click.native="clickreportadd('cg')"
 					>存草稿</el-button
 				>
-				<el-button v-permission="permissionBtn.enReportManageBtn.enReport_publish"
-					type="primary"
-					size="medium"
-					@click.native="clickreportadd('dsfb')"
-					>定时发布</el-button
-				>
-				<el-button
-					type="primary"
-					size="medium"
-					@click.native="clickreportadd('fb')"
-					:loading="isPublishloading"
-					>发布</el-button
-				>
+				<template v-if="!isApprove||!hasApproveFlow">
+					<el-button v-permission="permissionBtn.enReportManageBtn.enReport_publish"
+						type="primary"
+						size="medium"
+						:disabled="checkLoading"
+						@click.native="clickreportadd('dsfb')"
+						>定时发布</el-button
+					>
+					<el-button v-permission="permissionBtn.enReportManageBtn.enReport_publish"
+						type="primary"
+						size="medium"
+						:disabled="checkLoading"
+						@click.native="clickreportadd('fb')"
+						:loading="isPublishloading"
+						>发布</el-button
+					>
+				</template>
+				<template v-if="isApprove&&hasApproveFlow">
+					<el-button v-permission="permissionBtn.enReportManageBtn.enReport_publish"
+						:disabled="checkLoading"
+						type="primary" size="medium" @click="clickreportadd('submit')">提交</el-button>
+				</template>
 			</div>
 			<div
 				style="margin: 0px 0 0 20px;padding: 10px 20px;box-sizing: border-box;background: #fff;border: 1px solid #3464e0;"
@@ -371,14 +380,16 @@ import {
 } from 'api/api.js';
 import {authorEn} from '@/api/modules/reportAuthorApi.js';
 import * as reportEnInterface from '@/api/modules/reportEnApi';
+import {approveInterence} from '@/api/modules/approve.js';
 import http from '@/api/http.js';
 import mixinMsg from '../mixins/messagePush'
 import reportMixin from '../mixins/reportMixin';
+import reportApproveConfig from "@/mixins/reportApproveConfig.js"
 import importMyChart from '../components/importMyChart.vue'
 import setEnNameDia from '@/views/dataEntry_manage/components/setEnNameDia.vue'
 import importSemantics from '../components/importSemantics.vue';
 export default {
-	mixins:[mixinMsg,reportMixin],
+	mixins:[mixinMsg,reportMixin,reportApproveConfig],
 	data() {
 		return {
 			//批量导入图表
@@ -574,6 +585,11 @@ export default {
 		},
 
 		userclassidreportdetail() {
+			//检查classifynameArr是否有审批流
+			let classify = this.aeForm.classifynameArr.map(i=>{
+				return JSON.parse(i).v||0
+			})
+			this.checkClassifyNameArr(2,classify)
 			// console.log(this.aeForm.classifynameArr,'this.aeForm.classifynameArr');
 			if (this.aeForm.add_type == 1) {
 				if (this.aeForm.classifynameArr.length == 3) {
@@ -672,6 +688,8 @@ export default {
 					if(data.PrePublishTime){
 						this.taskTime=data.PrePublishTime
 					}
+					let classify = [data.ClassifyIdRoot,data.ClassifyIdFirst,data.ClassifyIdSecond]
+					this.checkClassifyNameArr(2,classify)
 				}
 			});
 		},
@@ -754,6 +772,8 @@ export default {
 				}else if(tp==='dsfb'){
 					//定时发布
 					this.showDSFB=true
+				}else if(tp==='submit'){
+					this.submitReport()
 				}
 			// if (tp == 'yl') { //预览
 			// 	sessionStorage.setItem('reportdtl', JSON.stringify(params));
@@ -767,6 +787,21 @@ export default {
 			// 	this.reporteditMsg(params,tp)
 			// }
 		},
+		submitReport(){
+			this.$confirm("是否确认提交该报告进入审批流程?","提示",{
+				confirmButtonText:'确定',
+				cancelButtonText:'取消',
+				type:'warning',
+			}).then(()=>{
+				approveInterence.reportEnSubmit({
+					ReportId:Number(this.report_id)
+				}).then(res=>{
+					if(res.Ret!==200) return
+					this.$message.success("提交成功")
+					this.$router.push({ path: '/reportEnList' });
+				})
+			})
+		},
 
 		publishreport(id) {
 			//发布报告

+ 126 - 94
src/views/report_manage/reportEn/reportlist.vue

@@ -39,6 +39,7 @@
                             style="width:100%;"
                         >
                             <el-option label="发布时间" value="publish_time"></el-option>
+                            <el-option label="审批时间" value="approve_time"></el-option>
                             <el-option label="更新时间" value="modify_time"></el-option>
                         </el-select>
                     </div>
@@ -75,8 +76,12 @@
                             clearable
                             style="width:100%;"
                         >
+                            <el-option label="未发布" :value="1" v-if="!isOtherApprove"></el-option>
                             <el-option label="已发布" :value="2"></el-option>
-                            <el-option label="未发布" :value="1"></el-option>
+                            <el-option label="待提交" :value="3" v-if="isApprove"></el-option>
+                            <el-option label="待审批" :value="4" v-if="isApprove"></el-option>
+                            <el-option label="已驳回" :value="5"></el-option>
+                            <el-option label="已通过" :value="6"></el-option>
                         </el-select>
                     </div>
                     <div class="select-item">
@@ -100,17 +105,6 @@
                 </div>
             </el-popover>
           </el-form-item>
-          <!-- <el-form-item label="">
-            <el-select
-              v-model="searchform.timeType"
-              placeholder="选择时间类型"
-              size="medium"
-              style="width:110px"
-            >
-              <el-option label="发布时间" value="publish_time"></el-option>
-              <el-option label="更新时间" value="modify_time"></el-option>
-            </el-select>
-          </el-form-item> -->
           <el-form-item label="">
             <el-date-picker
               v-model="searchform.dateValue"
@@ -124,56 +118,6 @@
               style="width: 280px"
             ></el-date-picker>
           </el-form-item>
-          <!-- <el-form-item label="">
-            <el-select
-              v-model="searchform.frequency"
-              placeholder="更新频度筛选"
-              size="medium"
-              clearable
-              style="width: 140px"
-            >
-              <el-option v-for="item in frequencyArr" :key="item" :label="item" :value="item"></el-option>
-            </el-select>
-          </el-form-item> -->
-          <!-- <el-form-item label="">
-            <el-cascader
-              :options="optionsArr"
-              :props="{
-                value:'Id',
-                label:'ClassifyName',
-                children:'Child'
-              }"
-              v-model="searchform.classifynameArr"
-              clearable
-              placeholder="类型筛选"
-              size="medium"
-            ></el-cascader>
-          </el-form-item> -->
-          <!-- <el-form-item label="">
-            <el-select
-              v-model.number="searchform.publishState"
-              placeholder="发布筛选"
-              size="medium"
-              clearable
-              style="width: 140px"
-            >
-              <el-option label="已发布" :value="2"></el-option>
-              <el-option label="未发布" :value="1"></el-option>
-            </el-select>
-          </el-form-item> -->
-          <!-- <el-form-item label="">
-            <el-select
-              v-permission="permissionBtn.enReportManageBtn.enReport_sendEmail"
-              v-model.number="searchform.EmailState"
-              placeholder="群发状态筛选"
-              size="medium"
-              clearable
-              style="width: 140px"
-            >
-              <el-option label="未群发邮件" :value="1"></el-option>
-              <el-option label="已群发邮件" :value="2"></el-option>
-            </el-select>
-          </el-form-item> -->
           <el-form-item style="margin-left:auto;">
             <el-input
               placeholder="标题 / 创建人"
@@ -213,6 +157,9 @@
                 <i class="el-icon-warning"/>
               </el-tooltip>
             </span>
+            <span v-else-if="item.key==='PublishTime'">
+                发布/审批时间
+            </span>
             <span v-else>{{ item.label }}</span>
           </template>	
 					<template slot-scope="{row}">
@@ -225,7 +172,12 @@
                 <!-- <span v-if="row.ClassifyNameSecond">/ {{row.ClassifyNameSecond}}</span> -->
               </span>
               <span v-else-if="item.key==='State'" :style="row.State===2 && 'color:#46C371;'">
-                {{row.State===2 ? '已发布' : '未发布'}}
+                <span v-if="row.State == '1'">未发布</span>
+                <span v-if="row.State == '2'">已发布</span>
+                <span v-if="row.State == '3'">待提交</span>
+                <span v-if="row.State == '4'">待审批</span>
+                <span v-if="row.State == '5'">已驳回</span>
+                <span v-if="row.State == '6'">已通过</span>
               </span>
               <span v-else-if="item.key==='Stage'">第{{row.Stage}}期</span>
               <span v-else-if="item.key==='Pv'" style="cursor:pointer; color:#4099ef;" >
@@ -234,40 +186,86 @@
                 <span v-if="row.Pv" style="color:#333">{{row.Pv}}</span>
               </span>
               <span v-else-if="item.key==='PublishTime'">
-                <span>{{row.PrePublishTime?row.PrePublishTime:row.PublishTime}}</span>
-                <svg v-if="row.PrePublishTime&&row.State===1" width="17" height="16" viewBox="0 0 17 16" fill="none" xmlns="http://www.w3.org/2000/svg">
-                  <path d="M15.2002 8C15.2002 4.13401 12.0662 1 8.20019 1C4.3342 1 1.20019 4.13401 1.2002 8C1.2002 11.866 4.3342 15 8.2002 15C12.0662 15 15.2002 11.866 15.2002 8ZM5.2002 10L5.2002 9L8.17491 9L11.2002 4.5L11.9073 5.20711L8.58912 10L5.2002 10Z" fill="#0052D9"/>
-                </svg>
+                <template v-if="[1,2].includes(row.State)">
+                    <span>{{row.PrePublishTime?row.PrePublishTime:row.PublishTime}}</span>
+                    <svg v-if="row.PrePublishTime&&row.State===1" width="17" height="16" viewBox="0 0 17 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+                        <path d="M15.2002 8C15.2002 4.13401 12.0662 1 8.20019 1C4.3342 1 1.20019 4.13401 1.2002 8C1.2002 11.866 4.3342 15 8.2002 15C12.0662 15 15.2002 11.866 15.2002 8ZM5.2002 10L5.2002 9L8.17491 9L11.2002 4.5L11.9073 5.20711L8.58912 10L5.2002 10Z" fill="#0052D9"/>
+                    </svg>
+                </template>
+                <template v-else>
+                    <span>{{row.ApproveTime}}</span>
+                </template>
+                
+                
               </span>
 
               <span v-else-if="item.key==='handle'">
-                <template v-if="row.State===1">
-                    <span class="editsty" v-permission="permissionBtn.enReportManageBtn.enReport_publish"
-                        @click="reportHandle(row,'publish')" v-if="row.CanEdit">发布</span>
-                    <span v-permission="permissionBtn.enReportManageBtn.enReport_reportEdit"
-                        class="editsty" @click="reportHandle(row,'edit')" v-if="row.CanEdit">编辑</span>
-                  <!-- <span class="editsty" @click="reportHandle(row,'editing')" v-else>{{row.Editor||''}}编辑中...</span> -->
-                  <span v-permission="permissionBtn.enReportManageBtn.enReport_reportEdit"
-                    class="editsty" @click="reportHandle(row,'edit')" v-else>{{row.Editor||''}}编辑中...</span>
-                  <span v-permission="permissionBtn.enReportManageBtn.enReport_reportDel"
-                    class="deletesty" @click="reportHandle(row,'del')" v-if="row.CanEdit">删除</span>
-                </template>
-                <template v-else>
-                    <span v-if="permissionBtn.checkPermissionBtn(permissionBtn.enReportManageBtn.enReport_cancelPublish)"
-                        @click="reportHandle(row,'cancelPublish')" class="deletesty">取消发布</span>
-                    <span v-if="row.EmailState===0&&row.EmailAuth&&permissionBtn.checkPermissionBtn(permissionBtn.enReportManageBtn.enReport_sendEmail)"
-                        class="editsty copylink" @click="reportHandle(row,'sendEmail')">群发邮件</span>
+                    <!-- 操作:未发布——发布、编辑、删除
+                    已发布——取消发布、群发邮件/群发日志
+                    待提交——提交、编辑、删除
+                    待审批——撤销
+                    已通过——撤销、群发邮件/群发日志
+                    已驳回——撤销 -->
+                    <template v-if="[1,3].includes(row.State)">
+                        <span class="editsty" @click="reportHandle(row,'publish')" v-if="row.CanEdit&&row.State===1
+                                &&permissionBtn.isShowBtn('enReportManageBtn','enReport_publish')">发布</span>
+                        <span class="editsty" @click="handleSubmitReport(row)" v-if="row.CanEdit&&row.State===3
+                                &&permissionBtn.isShowBtn('enReportManageBtn','enReport_publish')">提交</span>
+                        <span v-permission="permissionBtn.enReportManageBtn.enReport_reportEdit" class="editsty"
+                            @click="reportHandle(row,'edit')" v-if="row.CanEdit">编辑</span>
+                        <span v-permission="permissionBtn.enReportManageBtn.enReport_reportEdit" class="editsty"
+                            @click="reportHandle(row,'edit')" v-else>{{row.Editor||''}}编辑中...</span>
+                        <span v-permission="permissionBtn.enReportManageBtn.enReport_reportDel" class="deletesty"
+                            @click="reportHandle(row,'del')" v-if="row.CanEdit">删除</span>
+                    </template>
+                    <template v-if="[2,6].includes(row.State)">
+                        <span
+                            v-if="permissionBtn.isShowBtn('enReportManageBtn','enReport_cancelPublish')&&row.State===2"
+                            @click="reportHandle(row,'cancelPublish')" class="deletesty">撤销</span><!-- 取消发布 -->
+                        <span
+                            v-if="permissionBtn.isShowBtn('enReportManageBtn','enReport_cancelPublish')&&row.State===6"
+                            @click="cancelApprove(row)" class="deletesty">撤销</span>
+                        <span
+                            v-if="row.EmailState===0&&row.EmailAuth&&permissionBtn.checkPermissionBtn(permissionBtn.enReportManageBtn.enReport_sendEmail)"
+                            class="editsty copylink" @click="reportHandle(row,'sendEmail')">群发邮件</span>
+
+                        <span class="editsty copylink"
+                            v-if="row.EmailState===1&&row.EmailAuth&&permissionBtn.checkPermissionBtn(permissionBtn.enReportManageBtn.enReport_sendEmail)"
+                            @click="reportHandle(row,'view-log')" style="position: relative;">
+                            群发日志
+                            <span class="warn-tag" v-if="row.EmailHasFail"></span>
+                        </span>
+                    </template>
+                    <template v-if="[4,5].includes(row.State)">
+                        <span v-if="permissionBtn.isShowBtn('enReportManageBtn','enReport_cancelPublish')"
+                            @click="cancelApprove(row)" class="deletesty">撤销</span>
+                    </template>
+
+                  <!-- <template v-if="row.State===1">
+                      <span class="editsty" v-permission="permissionBtn.enReportManageBtn.enReport_publish"
+                          @click="reportHandle(row,'publish')" v-if="row.CanEdit">发布</span>
+                      <span v-permission="permissionBtn.enReportManageBtn.enReport_reportEdit" class="editsty"
+                          @click="reportHandle(row,'edit')" v-if="row.CanEdit">编辑</span>
+                      <span v-permission="permissionBtn.enReportManageBtn.enReport_reportEdit" class="editsty"
+                          @click="reportHandle(row,'edit')" v-else>{{row.Editor||''}}编辑中...</span>
+                      <span v-permission="permissionBtn.enReportManageBtn.enReport_reportDel" class="deletesty"
+                          @click="reportHandle(row,'del')" v-if="row.CanEdit">删除</span>
+                  </template>
+                  <template v-else>
+                      <span
+                          v-if="permissionBtn.checkPermissionBtn(permissionBtn.enReportManageBtn.enReport_cancelPublish)"
+                          @click="reportHandle(row,'cancelPublish')" class="deletesty">取消发布</span>
+                      <span
+                          v-if="row.EmailState===0&&row.EmailAuth&&permissionBtn.checkPermissionBtn(permissionBtn.enReportManageBtn.enReport_sendEmail)"
+                          class="editsty copylink" @click="reportHandle(row,'sendEmail')">群发邮件</span>
 
-                  <span
-                    class="editsty copylink" 
-                    v-if="row.EmailState===1&&row.EmailAuth&&permissionBtn.checkPermissionBtn(permissionBtn.enReportManageBtn.enReport_sendEmail)" 
-                    @click="reportHandle(row,'view-log')"
-                    style="position: relative;"
-                  >
-                    群发日志 
-                    <span class="warn-tag" v-if="row.EmailHasFail"></span>
-                  </span>
-								</template>
+                      <span class="editsty copylink"
+                          v-if="row.EmailState===1&&row.EmailAuth&&permissionBtn.checkPermissionBtn(permissionBtn.enReportManageBtn.enReport_sendEmail)"
+                          @click="reportHandle(row,'view-log')" style="position: relative;">
+                          群发日志
+                          <span class="warn-tag" v-if="row.EmailHasFail"></span>
+                      </span>
+                  </template> -->
               </span>
 
 							<span v-else>{{ row[item.key] || '' }}</span>
@@ -456,9 +454,12 @@
 <script>
 import * as reportEnInterface from '@/api/modules/reportEnApi';
 import {strategyReportInterence,reportVarietyENInterence,customInterence} from '@/api/api.js'
+import {approveInterence} from '@/api/modules/approve.js';
+import reportApproveConfig from "@/mixins/reportApproveConfig.js"
 import mPage from '@/components/mPage.vue';
 import strategyReportEdit from '../components/strategyReportEdit.vue'
 export default {
+  mixins:[reportApproveConfig],
   watch: {
     searchform: {
       handler() {
@@ -533,7 +534,7 @@ export default {
             minwidthsty: 100
         },
         {
-            label: '发布状态',
+            label: '状态',
             key: 'State',
         },
         {
@@ -675,6 +676,37 @@ export default {
 
       handleMap[key](row);
     },
+    /* 提交报告 */
+    handleSubmitReport(row){
+        this.$confirm("是否确认提交该报告进入审批流程?","提示",{
+            confirmButtonText:'确定',
+            cancelButtonText:'取消',
+            type:'warning',
+        }).then(()=>{
+            approveInterence.reportEnSubmit({
+                ReportId:Number(row.Id)
+            }).then(res=>{
+                if(res.Ret!==200) return 
+                this.$message.success("提交成功")
+                this.getTableData()
+            })
+        })
+    },
+    //撤销提交报告
+    cancelApprove(item){
+        this.$confirm("确定要撤销审批吗?","提示",{
+            confirmButtonText:'确定',
+            cancelButtonText:'取消'
+        }).then(()=>{
+            approveInterence.reportEnCancel({
+                ReportId:Number(item.Id)
+            }).then(res=>{
+                if(res.Ret!==200) return 
+                this.$message.success("撤销成功")
+                this.getTableData()
+            })
+        })
+    },
 
     /* 发布报告 */
     publishReport(item) {

+ 24 - 9
src/views/report_manage/reportdtl.vue

@@ -7,7 +7,7 @@
 		</div>
 		
 		<!-- 英文版摘要+overview -->
-		<div id="abstract-en" v-if="$route.query.fromPage=='en'">
+		<div id="abstract-en" v-if="$route.query.fromPage=='en'||isEn">
 			<div 
 				class="abstract" 
 				:style="{borderBottom:reportInfo.Overview?'1px solid #C1C1C1':'none',paddingBottom:reportInfo.Overview?'20px':'0'}"
@@ -31,7 +31,7 @@
 			</div>
 		</div>
 		<div id="abstract" v-else>
-		  <div>{{$route.query.fromPage=='en'?'Abstract':'摘要'}}:{{reportInfo.Abstract}}</div>
+		  <div>{{($route.query.fromPage=='en'||isEn)?'Abstract':'摘要'}}:{{reportInfo.Abstract}}</div>
 		</div>
 		<div id="resetsty" style="padding:30px; box-sizing:border-box; overflow:hidden;">
 			<block v-if="reportInfo.ChapterType=='day'||reportInfo.ChapterType=='week'">
@@ -95,6 +95,16 @@
 				return str
 			}
 		},
+		props:{
+			reportId:{ //审批详情-预览报告
+				type:Number,
+				default:0
+			},
+			isEn:{
+				type:Boolean,
+				default:false
+			}
+		},
 		data() {
 			return {
 				id:parseInt(this.$route.query.id),
@@ -110,7 +120,7 @@
 			vueQr
 		},
 		mounted() {
-			if(this.$route.query.id) {
+			if(this.$route.query.id||this.reportId) {
 				this.getreportdetail();
 			}else {
 				let reportdtl=sessionStorage.getItem('reportdtl') || false;
@@ -136,15 +146,20 @@
 			},
 			async getreportdetail(){
 				let res
-				if(this.$route.query.fromPage == 'en'){
-					res=await reportEnInterface.reportDetail({ReportId:parseInt(this.id)})
+				let reportId = this.id||this.reportId
+				this.$emit("reportStartLoading")
+				if((this.$route.query.fromPage == 'en'||this.isEn)){
+					res=await reportEnInterface.reportDetail({ReportId:parseInt(reportId)})
 				}else if(this.$route.query.fromPage == 'strategyReport'){
-					res=await strategyReportInterence.getReportDetail({Id:parseInt(this.id)})
+					res=await strategyReportInterence.getReportDetail({Id:parseInt(reportId)})
 				}else{
-					res=await reportdetail({ReportId:parseInt(this.id)})
+					res=await reportdetail({ReportId:parseInt(reportId)})
+				}
+				this.$emit("reportEndLoading")
+				if( res.Ret!==200 ){
+					this.$emit("reportError")
+					return 
 				}
-
-				if( res.Ret!==200 )return
 
 				this.reportInfo=res.Data;
 				this.isshow=true;

+ 129 - 131
src/views/report_manage/reportlist.vue

@@ -49,7 +49,8 @@
                             style="width:100%;"
                             @change="search"
                         >
-                            <el-option :label="isApprove?'审批时间':'发布时间'" value="publish_time"></el-option>
+                            <el-option label="发布时间" value="publish_time"></el-option>
+                            <el-option label="审批时间" value="approve_time"></el-option>
                             <el-option label="更新时间" value="modify_time"></el-option>
                         </el-select>
                     </div>
@@ -82,20 +83,7 @@
                             style="width:100%;"
                         ></el-cascader>
                     </div>
-                    <div class="select-item" v-if="!isApprove">
-                        <el-select 
-                            v-model.number="searchform.publishState"
-                            placeholder="发布筛选"
-                            size="medium"
-                            clearable
-                            style="width:100%;"
-                            @change="search"
-                        >
-                            <el-option label="已发布" :value="2"></el-option>
-                            <el-option label="未发布" :value="1"></el-option>
-                        </el-select>
-                    </div>
-                    <div class="select-item" v-if="isApprove">
+                    <div class="select-item">
                         <el-select
                             v-model.number="searchform.publishState"
                             placeholder="状态筛选"
@@ -104,10 +92,12 @@
                             style="width:100%;"
                             @change="search"
                         >
-                            <el-option label="待提交" :value="1"></el-option>
-                            <el-option label="待审批" :value="2"></el-option>
-                            <el-option label="已审批" :value="4"></el-option>
-                            <el-option label="已驳回" :value="3"></el-option>
+                            <el-option label="未发布" :value="1" v-if="!isOtherApprove"></el-option>
+                            <el-option label="已发布" :value="2"></el-option>
+                            <el-option label="待提交" :value="3" v-if="isApprove"></el-option>
+                            <el-option label="待审批" :value="4" v-if="isApprove"></el-option>
+                            <el-option label="已驳回" :value="5"></el-option>
+                            <el-option label="已通过" :value="6"></el-option>
                         </el-select>
                     </div>
                     <div class="select-item">
@@ -227,24 +217,18 @@
             align="center"
             min-width="100"
           ></el-table-column>
-          <el-table-column label="发布状态" align="center" v-if="!isApprove">
-            <template slot-scope="scope">
-              <span v-if="scope.row.State == '2'" style="color: #46c371"
-                >已发布</span
-              >
-              <span v-if="scope.row.State == '1'">未发布</span>
-            </template>
-          </el-table-column>
           <el-table-column label="状态" align="center" v-if="isApprove">
             <template slot-scope="scope">
-                <span v-if="scope.row.State == '1'">待提交</span>
-                <span v-if="scope.row.State == '2'">待审批</span>
-                <span v-if="scope.row.State == '4'">已审批</span>
-                <span v-if="scope.row.State == '3'">已驳回</span>
+                <span v-if="scope.row.State == '1'">未发布</span>
+                <span v-if="scope.row.State == '2'">已发布</span>
+                <span v-if="scope.row.State == '3'">待提交</span>
+                <span v-if="scope.row.State == '4'">待审批</span>
+                <span v-if="scope.row.State == '5'">已驳回</span>
+                <span v-if="scope.row.State == '6'">已通过</span>
             </template>
           </el-table-column>
 
-          <el-table-column
+          <!-- <el-table-column
             v-if="!isApprove"
             prop="PublishTime"
             label="发布时间"
@@ -261,14 +245,27 @@
           </el-table-column>
           <el-table-column
             v-if="isApprove"
-            prop="PublishTime"
+            prop="ApproveTime"
             label="审批时间"
             min-width="124"
             align="center"
             :formatter="formatterColumn"
           >
             <template slot-scope="scope">
-                <span>{{scope.row.PrePublishTime?scope.row.PrePublishTime:scope.row.PublishTime|formatTime}}</span>
+                <span>{{scope.row.ApproveTime|formatTime}}</span>
+            </template>
+          </el-table-column> -->
+          <el-table-column prop="PublishTime" label="发布/审批时间" min-width="124" align="center">
+            <template slot-scope="scope">
+                <template v-if="[1,2].includes(scope.row.State)">
+                    <span>{{scope.row.PrePublishTime?scope.row.PrePublishTime:scope.row.PublishTime|formatTime}}</span>
+                    <svg style="position: relative;top:2px" v-if="scope.row.PrePublishTime&&scope.row.State == '1'" width="17" height="16" viewBox="0 0 17 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+                        <path d="M15.2002 8C15.2002 4.13401 12.0662 1 8.20019 1C4.3342 1 1.20019 4.13401 1.2002 8C1.2002 11.866 4.3342 15 8.2002 15C12.0662 15 15.2002 11.866 15.2002 8ZM5.2002 10L5.2002 9L8.17491 9L11.2002 4.5L11.9073 5.20711L8.58912 10L5.2002 10Z" fill="#0052D9"/>
+                    </svg>
+                </template>
+                <template v-else>
+                    <span>{{scope.row.ApproveTime|formatTime}}</span>
+                </template>
             </template>
           </el-table-column>
 
@@ -314,96 +311,62 @@
           <el-table-column label="操作" align="center" min-width="130" fixed="right">
             <template slot-scope="scope">
               <div class="opt-btns">
-                <!--不走审批流的按钮-->
-                <template v-if="!isApprove">
-                    <template v-if="scope.row.State == 1">
-                        <span v-permission="permissionBtn.reportManageBtn.reportManage_publish" class="editsty"
-                            @click="publishreport(scope.row)" v-if="scope.row.CanEdit">发布</span>
-                        <span v-permission="permissionBtn.reportManageBtn.reportManage_reportEdit" class="editsty"
-                            @click="editreport(scope.row, 'edit')" v-if="scope.row.CanEdit">编辑</span>
-                        <span v-permission="permissionBtn.reportManageBtn.reportManage_reportEdit" class="editsty"
-                            @click="editreport(scope.row, 'editing')" v-else>{{ scope.row.Editor || "" }}编辑中...</span>
-                        <span v-permission="permissionBtn.reportManageBtn.reportManage_reportDel" class="deletesty"
-                            @click="deleteitem(scope.row)" v-if="scope.row.CanEdit">删除</span>
-                    </template>
-                    <template v-if="scope.row.State == 2">
-                        <span
-                            v-if="permissionBtn.checkPermissionBtn(permissionBtn.reportManageBtn.reportManage_cancelPublish)"
-                            @click="canclepublish(scope.row)" style="color: red; cursor: pointer">取消发布</span>
-                        <span
-                            v-if="scope.row.MsgIsSend == 0 && permissionBtn.checkPermissionBtn(permissionBtn.reportManageBtn.reportManage_sendMsg)"
-                            style="color: #4099ef; cursor: pointer" @click="messageSend(scope.row)">推送消息</span>
-                        <span
-                            v-else-if="scope.row.MsgIsSend != 0&&permissionBtn.checkPermissionBtn(permissionBtn.reportManageBtn.reportManage_sendMsg)"
-                            style="color: red">已推送消息</span>
-                    </template>
-                    <span style="color: #46c371; cursor: pointer"
-                        v-if="!['晨报', '周报'].includes(scope.row.ClassifyNameFirst)&&permissionBtn.checkPermissionBtn(permissionBtn.reportManageBtn.reportManage_audioUpload)"
-                        @click="openupload(scope.row.Id)">音频上传</span>
-                    <a v-permission="permissionBtn.reportManageBtn.reportManage_audioDownload"
-                        :href="hostapi + '?ReportId=' + parseInt(scope.row.Id)" v-if="
-                        scope.row.VideoUrl &&
-                        !['晨报', '周报'].includes(scope.row.ClassifyNameFirst)
-                    " :download="scope.row.VideoName" style="cursor: pointer; color: #4099ef">音频下载</a>
-                    <span v-permission="permissionBtn.reportManageBtn.reportManage_audioDownload"
-                        style="cursor: pointer; color: #4099ef" v-if="
-                        ['晨报', '周报'].includes(scope.row.ClassifyNameFirst) &&
-                        scope.row.ChapterVideoList.length > 0
-                    " @click="handleShowDownloadAudio(scope.row)">音频下载</span>
+                <!-- 操作:未发布——发布、编辑、删除
+                    已发布——取消发布、推送消息/已推送消息
+                    待提交——提交、编辑、删除
+                    待审批——撤销
+                    已通过——撤销、推送消息/已推送消息
+                    已驳回——撤销 
+                -->
+                <!-- 未发布,待提交 -->
+                <template v-if="[1,3].includes(scope.row.State)">
+                    <span class="editsty" @click="publishreport(scope.row)"
+                        v-if="scope.row.CanEdit&&scope.row.State===1
+                            &&permissionBtn.isShowBtn('reportManageBtn','reportManage_publish')"
+                    >发布</span>
+                    <span class="editsty" @click="handleSubmitReport(scope.row)"
+                        v-if="scope.row.CanEdit&&scope.row.State===3
+                            &&permissionBtn.isShowBtn('reportManageBtn','reportManage_publish')"
+                    >提交</span>
+                    <span v-permission="permissionBtn.reportManageBtn.reportManage_reportEdit" class="editsty"
+                        @click="editreport(scope.row, 'edit')" v-if="scope.row.CanEdit">编辑</span>
+                    <span v-permission="permissionBtn.reportManageBtn.reportManage_reportEdit" class="editsty"
+                        @click="editreport(scope.row, 'editing')" v-else>{{ scope.row.Editor || "" }}编辑中...</span>
+                    <span v-permission="permissionBtn.reportManageBtn.reportManage_reportDel" class="deletesty"
+                        @click="deleteitem(scope.row)" v-if="scope.row.CanEdit">删除</span>
                 </template>
-                <!--走审批流的按钮,权限与原先按钮对应-->
-                <template v-if="isApprove">
-                    <!--待提交-->
-                    <template v-if="scope.row.State===1">
-                        <span v-permission="permissionBtn.reportManageBtn.reportManage_publish"
-                            @click="publishreport(scope.row)"
-                            class="editsty">提交</span>
-                        <span v-permission="permissionBtn.reportManageBtn.reportManage_reportEdit" class="editsty"
-                            @click="editreport(scope.row, 'edit')" v-if="scope.row.CanEdit">编辑</span>
-                        <span v-permission="permissionBtn.reportManageBtn.reportManage_reportEdit" class="editsty"
-                            @click="editreport(scope.row, 'editing')" v-else>{{ scope.row.Editor || "" }}编辑中...</span>
-                        <span v-permission="permissionBtn.reportManageBtn.reportManage_reportDel" class="deletesty"
-                            @click="deleteitem(scope.row)" v-if="scope.row.CanEdit">删除</span>
-                    </template>
-                    <!--已提交(待审批,已审批)-->
-                    <template v-if="[2,4].includes(scope.row.State)">
-                        <span
-                            v-if="permissionBtn.checkPermissionBtn(permissionBtn.reportManageBtn.reportManage_cancelPublish)"
-                            @click="canclepublish(scope.row)"
-                            class="editsty">撤销</span>
-                        <template v-if="scope.row.State!==2">
-                            <span
-                                v-if="scope.row.MsgIsSend == 0 && permissionBtn.checkPermissionBtn(permissionBtn.reportManageBtn.reportManage_sendMsg)"
-                                style="color: #4099ef; cursor: pointer" @click="messageSend(scope.row)">推送消息</span>
-                            <span
-                                v-else-if="scope.row.MsgIsSend != 0&&permissionBtn.checkPermissionBtn(permissionBtn.reportManageBtn.reportManage_sendMsg)"
-                                style="color: red">已推送消息</span>
-                        </template>
-                    </template>
-
-                    <!--已驳回则只显示撤销按钮-->
-                    <template v-if="scope.row.State===3">
-                        <span v-permission="permissionBtn.reportManageBtn.reportManage_publish"
-                            @click="canclepublish(scope.row)"
-                            class="editsty">撤销</span>
-                    </template>
-                    <!--音频上传/下载 按原先逻辑-->
-                    <template v-if="scope.row.State!==3">
-                        <span style="color: #46c371; cursor: pointer"
-                            v-if="!['晨报', '周报'].includes(scope.row.ClassifyNameFirst)&&permissionBtn.checkPermissionBtn(permissionBtn.reportManageBtn.reportManage_audioUpload)"
-                            @click="openupload(scope.row.Id)">音频上传</span>
-                        <a v-permission="permissionBtn.reportManageBtn.reportManage_audioDownload"
-                            :href="hostapi + '?ReportId=' + parseInt(scope.row.Id)" v-if="
-                            scope.row.VideoUrl &&
-                            !['晨报', '周报'].includes(scope.row.ClassifyNameFirst)
-                        " :download="scope.row.VideoName" style="cursor: pointer; color: #4099ef">音频下载</a>
-                        <span v-permission="permissionBtn.reportManageBtn.reportManage_audioDownload"
-                            style="cursor: pointer; color: #4099ef" v-if="
-                            ['晨报', '周报'].includes(scope.row.ClassifyNameFirst) &&
-                            scope.row.ChapterVideoList.length > 0
-                        " @click="handleShowDownloadAudio(scope.row)">音频下载</span>
-                    </template>
+                <!-- 已发布,已通过 -->
+                <template v-if="[2,6].includes(scope.row.State)">
+                    <span v-if="scope.row.State===2&&permissionBtn.checkPermissionBtn(permissionBtn.reportManageBtn.reportManage_cancelPublish)"
+                        @click="canclepublish(scope.row)" style="color: red; cursor: pointer">撤销</span><!-- 取消发布 -->
+                    <span v-if="scope.row.State===6&&permissionBtn.checkPermissionBtn(permissionBtn.reportManageBtn.reportManage_cancelPublish)"
+                        @click="cancelReport(scope.row)" style="color: red; cursor: pointer">撤销</span>
+                    <span
+                        v-if="scope.row.MsgIsSend == 0 && permissionBtn.checkPermissionBtn(permissionBtn.reportManageBtn.reportManage_sendMsg)"
+                        style="color: #4099ef; cursor: pointer" @click="messageSend(scope.row)">推送消息</span>
+                    <span
+                        v-else-if="scope.row.MsgIsSend != 0&&permissionBtn.checkPermissionBtn(permissionBtn.reportManageBtn.reportManage_sendMsg)"
+                        style="color: red">已推送消息</span>
+                </template>
+                <!-- 待审批,已驳回 -->
+                <template v-if="[4,5].includes(scope.row.State)">
+                    <span v-if="permissionBtn.checkPermissionBtn(permissionBtn.reportManageBtn.reportManage_cancelPublish)"
+                        @click="cancelReport(scope.row)" style="color: red; cursor: pointer">撤销</span>
                 </template>
+                <!-- 音频上传和下载,跟State无关 -->
+                <span style="color: #46c371; cursor: pointer"
+                    v-if="!['晨报', '周报'].includes(scope.row.ClassifyNameFirst)&&permissionBtn.checkPermissionBtn(permissionBtn.reportManageBtn.reportManage_audioUpload)"
+                    @click="openupload(scope.row.Id)">音频上传</span>
+                <a v-permission="permissionBtn.reportManageBtn.reportManage_audioDownload"
+                    :href="hostapi + '?ReportId=' + parseInt(scope.row.Id)" v-if="
+                    scope.row.VideoUrl &&
+                    !['晨报', '周报'].includes(scope.row.ClassifyNameFirst)
+                " :download="scope.row.VideoName" style="cursor: pointer; color: #4099ef">音频下载</a>
+                <span v-permission="permissionBtn.reportManageBtn.reportManage_audioDownload"
+                    style="cursor: pointer; color: #4099ef" v-if="
+                    ['晨报', '周报'].includes(scope.row.ClassifyNameFirst) &&
+                    scope.row.ChapterVideoList.length > 0
+                " @click="handleShowDownloadAudio(scope.row)">音频下载</span>
               </div>
             </template>
           </el-table-column>
@@ -638,7 +601,10 @@ import {
   reportMessageSend,
   weekReportValidAudio,
 } from "api/api.js";
+import {approveInterence} from '@/api/modules/approve.js';
+import reportApproveConfig from "@/mixins/reportApproveConfig.js"
 export default {
+  mixins:[reportApproveConfig],
   computed: {
     exportUrlDl() {
       let url = this.exportUrl;
@@ -672,13 +638,6 @@ export default {
     hasUV(){
       return this.permissionBtn.checkPermissionBtn(this.permissionBtn.reportManageBtn.reportManage_reportList_uv)
     },
-    //是否开启审批流,若开启,发布相关按钮,筛选项改变
-    isApprove(){
-        const type = this.$setting.dynamicOutLinks.ApprovalFlow ||
-                     this.$store.state.dynamicOutLinks.ApprovalFlow ||
-                     JSON.parse(localStorage.getItem('dynamicOutLinks')).ApprovalFlow||''
-        return ['1','3'].includes(type)
-    }
   },
   data() {
     return {
@@ -725,9 +684,9 @@ export default {
       showPublish: false,
       isDSFB:false,//是否为定时发布
       tableKey:0,
-      selectNum:1
+      selectNum:1,
 
-      //isApprove:false,//是否开启审批流,若开启,发布相关按钮,筛选项改变
+      submitId:0,//当前选择的报告id
     };
   },
   mounted() {
@@ -1065,6 +1024,45 @@ export default {
       this.batches = [];
       this.showPublish = false;
     },
+    //提交报告
+    handleSubmitReport(item){
+        this.submitId = item.Id
+        this.$confirm("是否确认提交该报告进入审批流程?","提示",{
+            confirmButtonText:'确定',
+            cancelButtonText:'取消',
+            type:'warning',
+        }).then(()=>{
+            this.submitReport("submit")
+        })
+        
+    },
+    submitReport(type){
+        //both:提交&推送
+        /* if(type==='submit'){ */
+            approveInterence.reportCnSubmit({
+                ReportId:Number(this.submitId)
+            }).then(res=>{
+                if(res.Ret!==200) return
+                this.$message.success("提交成功")
+                this.getlist()
+            })
+        /* } */
+    },
+    //撤销提交报告
+    cancelReport(item){
+        this.$confirm("确定要撤销审批吗?","提示",{
+            confirmButtonText:'确定',
+            cancelButtonText:'取消'
+        }).then(()=>{
+            approveInterence.reportCnCancel({
+                ReportId:Number(item.Id)
+            }).then(res=>{
+                if(res.Ret!==200) return 
+                this.$message.success("撤销成功")
+                this.getlist()
+            })
+        })
+    },
 
     selectchange(val) {
       //多选操作

+ 41 - 16
src/views/smartReport/editReport.vue

@@ -20,18 +20,21 @@
                     <img src="~@/assets/img/smartReport/icon01.png" alt="">
                     <span>存草稿</span>
                 </li>
-                <template v-if="!isApprove">
-                    <li class="action-item" @click="handlePublishOpt('dsfb')">
+                <template v-if="!isApprove||!hasApproveFlow">
+                    <li class="action-item" :class="{'disabled':checkLoading}"
+                        @click="handlePublishOpt('dsfb')">
                         <img src="~@/assets/img/smartReport/icon01.png" alt="">
                         <span>定时发布</span>
                     </li>
-                    <li class="action-item" @click="handlePublishOpt('fb')">
+                    <li class="action-item" :class="{'disabled':checkLoading}"
+                        @click="handlePublishOpt('fb')">
                         <img src="~@/assets/img/smartReport/icon01.png" alt="">
                         <span>发布</span>
                     </li>
                 </template>
-                <template v-if="isApprove">
-                    <li class="action-item" @click="handlePublishOpt('fb')">
+                <template v-if="isApprove&&hasApproveFlow">
+                    <li class="action-item" :class="{'disabled':checkLoading}"
+                        @click="handlePublishOpt('submit')">
                         <img src="~@/assets/img/smartReport/icon01.png" alt="">
                         <span>提交</span>
                     </li>
@@ -240,14 +243,17 @@ import ETASheet from './components/ETASheet.vue'
 import { getPublicSettingsApi } from '@/api/modules/oldApi';
 import { dataBaseInterface } from "@/api/api.js";
 import {apiSmartReport}  from '@/api/modules/smartReport'
+import {approveInterence} from '@/api/modules/approve.js';
 import BaseInfo from './components/BaseInfo.vue'
 import StatisticAnalysis from './components/StatisticAnalysis.vue'
 import ETAPriceChart from './components/ETAPriceChart.vue'
 import ETASandBox from './components/ETASandBox.vue'
 import SemanticAnalysis from './components/SemanticAnalysis.vue'
 import { getUrlParams } from '@/utils/common'
+import reportApproveConfig from "@/mixins/reportApproveConfig.js"
 import ImgSource from './components/ImgSource.vue'
 export default {
+    mixins:[reportApproveConfig],
     name:"smartReportEdit",
     components: {
         draggable,
@@ -290,15 +296,6 @@ export default {
             deep:true
         }
     },
-    computed:{
-        //是否开启审批流,若开启,发布相关按钮,筛选项改变
-        isApprove(){
-            const type = this.$setting.dynamicOutLinks.ApprovalFlow ||
-                        this.$store.state.dynamicOutLinks.ApprovalFlow ||
-                        JSON.parse(localStorage.getItem('dynamicOutLinks')).ApprovalFlow||''
-            return ['2','3'].includes(type)
-        }
-    },
     data() {
         return {
             reportInfo:null,
@@ -804,6 +801,10 @@ export default {
                 CanvasColor:this.bgColor
             }
             console.log(params);
+            //检查classifynameArr是否有审批流
+            let classify = [e.ClassifyIdFirst,e.ClassifyIdSecond]
+            this.checkClassifyNameArr(3,classify)
+
             apiSmartReport.reportEdit({...params}).then(res=>{
                 if(res.Ret===200){
                     this.$message.success('保存成功')
@@ -837,6 +838,8 @@ export default {
                     this.$nextTick(()=>{
                         this.contentChange=false
                     })
+                    let classify = [res.Data.ClassifyIdFirst,res.Data.ClassifyIdSecond]
+                    this.checkClassifyNameArr(3,classify)
                 }
             })
         },
@@ -924,10 +927,11 @@ export default {
                 return
             }
             // 发布
-            if(this.isApprove){
-                this.reportPublish({sendMsg:false})
+            if(type==='submit'){
+                this.submitReport()
                 return
             }
+            //截止至ETA1.3.8 智能研报无推送模板消息,所有的reportInfo.MsgIsSend都为1
             if(this.reportInfo.MsgIsSend==1){//该报告已经推送过模板消息
                 this.reportPublish({sendMsg:false})
             }else{
@@ -960,6 +964,22 @@ export default {
                 )
             }
         },
+        //提交报告
+        submitReport(){
+            this.$confirm("是否确认提交该报告进入审批流程?","提示",{
+                confirmButtonText:'确定',
+                cancelButtonText:'取消',
+                type:'warning',
+            }).then(()=>{
+                approveInterence.reportSmartSubmit({
+                    ReportId:Number(this.$route.query.id)
+                }).then(res=>{
+                    if(res.Ret!==200) return 
+                    this.$message.success("提交成功")
+                    this.$router.replace({ path: '/smartReportList' });
+                })
+            })
+        },
 
         // 定时发布报告
         async handleSetReportPrepublish(){
@@ -1180,6 +1200,11 @@ div{
                 &:last-child{
                     border-right: none;
                 }
+                &.disabled{
+                    pointer-events: none;
+                    cursor: not-allowed;
+                    color:#999;
+                }
             }
         }
     }

+ 12 - 2
src/views/smartReport/reportDetail.vue

@@ -10,7 +10,7 @@
             </div> -->
             <div class="html-wrap" v-html="content"></div>
         </div>
-        <div class="right-opt-box" v-if="$route.query.type!=='preview'">
+        <div class="right-opt-box" v-if="$route.query.type!=='preview'&&!reportId">
             <div 
                 class="item copy" 
                 v-if="linkUrl" 
@@ -73,6 +73,12 @@ export default {
             return ['2','3'].includes(type)
         }
     },
+    props:{
+        reportId:{//审批详情-预览报告
+            type:Number,
+            default:0
+        }
+    },
     data() {
         return {
             reportInfo:null,
@@ -87,11 +93,13 @@ export default {
     methods: {
         // 获取报告详情
         getReportDetail(){
-            const id=this.$route.query.id||0
+            const id=this.$route.query.id||this.reportId||0
             if(!id) return
+            this.$emit("reportStartLoading")
             apiSmartReport.reportDetail({
                 SmartReportId:Number(id)
             }).then(res=>{
+                this.$emit("reportEndLoading")
                 if(res.Ret===200){
                     this.reportInfo=res.Data
                     if(this.$route.query.type==='preview'){
@@ -99,6 +107,8 @@ export default {
                     }else{
                         this.content=res.Data.Content
                     }
+                }else{
+                    this.$emit("reportError")
                 }
             })
         },

+ 116 - 166
src/views/smartReport/reportList.vue

@@ -29,7 +29,8 @@
                                     style="width:100%"
                                     @change="search"
                                     >
-                                    <el-option :label="isApprove?'审批时间':'发布时间'" value="publish_time"></el-option>
+                                    <el-option label="发布时间" value="publish_time"></el-option>
+                                    <el-option label="审批时间" value="approve_time"></el-option>
                                     <el-option label="更新时间" value="modify_time"></el-option>
                                 </el-select>
                             </div>
@@ -62,20 +63,7 @@
                                     style="width:100%;"
                                 />
                             </div>
-                            <div class="select-item" v-if="!isApprove">
-                                <el-select
-                                    v-model.number="searchform.publishState"
-                                    placeholder="发布筛选"
-                                    size="medium"
-                                    clearable
-                                    style="width:100%;"
-                                    @change="search"
-                                >
-                                    <el-option label="已发布" :value="2"></el-option>
-                                    <el-option label="未发布" :value="1"></el-option>
-                                </el-select>
-                            </div>
-                            <div class="select-item" v-if="isApprove">
+                            <div class="select-item">
                                 <el-select
                                     v-model.number="searchform.publishState"
                                     placeholder="状态筛选"
@@ -84,10 +72,12 @@
                                     style="width:100%;"
                                     @change="search"
                                 >
-                                    <el-option label="待提交" :value="1"></el-option>
-                                    <el-option label="待审批" :value="2"></el-option>
-                                    <el-option label="已审批" :value="4"></el-option>
-                                    <el-option label="已驳回" :value="3"></el-option>
+                                    <el-option label="未发布" :value="1" v-if="!isOtherApprove"></el-option>
+                                    <el-option label="已发布" :value="2"></el-option>
+                                    <el-option label="待提交" :value="3" v-if="isApprove"></el-option>
+                                    <el-option label="待审批" :value="4" v-if="isApprove"></el-option>
+                                    <el-option label="已驳回" :value="5"></el-option>
+                                    <el-option label="已通过" :value="6"></el-option>
                                 </el-select>
                             </div>
                         </div>
@@ -112,20 +102,6 @@
                         style="width: 280px"
                     />
                 </el-form-item>
-                <!-- <el-form-item label="">
-                    <el-select
-                        v-permission="permissionBtn.smartReportManageBtn.reportManage_reportList_sendTime"
-                        @change="search"
-                        v-model.number="searchform.msgIsSend"
-                        placeholder="推送消息状态"
-                        size="medium"
-                        clearable
-                        style="width: 140px"
-                    >
-                        <el-option label="未推送消息" :value="1"></el-option>
-                        <el-option label="已推送消息" :value="2"></el-option>
-                    </el-select>
-                </el-form-item> -->
                 <el-form-item style="flex:1;text-align:right;">
                     <el-input
                         @input="search"
@@ -207,23 +183,17 @@
                     align="center"
                     min-width="100"
                 ></el-table-column>
-                <el-table-column label="发布状态" align="center" v-if="!isApprove">
-                    <template slot-scope="scope">
-                    <span v-if="scope.row.State == '2'" style="color: #46c371"
-                        >已发布</span
-                    >
-                    <span v-if="scope.row.State == '1'">未发布</span>
-                    </template>
-                </el-table-column>
-                <el-table-column label="状态" align="center" v-if="isApprove">
+                <el-table-column label="状态" align="center">
                     <template slot-scope="scope">
-                        <span v-if="scope.row.State == '1'">待提交</span>
-                        <span v-if="scope.row.State == '2'">待审批</span>
-                        <span v-if="scope.row.State == '4'">已审批</span>
-                        <span v-if="scope.row.State == '3'">已驳回</span>
+                        <span v-if="scope.row.State == '1'">未发布</span>
+                        <span v-if="scope.row.State == '2'">已发布</span>
+                        <span v-if="scope.row.State == '3'">待提交</span>
+                        <span v-if="scope.row.State == '4'">待审批</span>
+                        <span v-if="scope.row.State == '5'">已驳回</span>
+                        <span v-if="scope.row.State == '6'">已通过</span>
                     </template>
                 </el-table-column>
-                <el-table-column v-if="!isApprove"
+                <!-- <el-table-column v-if="!isApprove"
                     prop="PublishTime"
                     label="发布时间"
                     min-width="124"
@@ -239,26 +209,29 @@
                 </el-table-column>
                 <el-table-column
                     v-if="isApprove"
-                    prop="PublishTime"
+                    prop="ApproveTime"
                     label="审批时间"
                     min-width="124"
                     align="center"
                     :formatter="formatterColumn"
                 >
                     <template slot-scope="scope">
-                        <span>{{scope.row.PrePublishTime?scope.row.PrePublishTime:scope.row.PublishTime|formatTime}}</span>
+                        <span>{{scope.row.ApproveTime|formatTime}}</span>
                     </template>
-                </el-table-column>
-                <!-- <el-table-column v-if="permissionBtn.checkPermissionBtn(permissionBtn.smartReportManageBtn.reportManage_reportList_sendTime)"
-                    prop="MsgSendTime"
-                    label="报告推送时间"
-                    min-width="124"
-                    align="center"
-                >
-                    <template slot-scope="scope">{{
-                    scope.row.MsgSendTime | formatTime
-                    }}</template>
                 </el-table-column> -->
+                <el-table-column prop="PublishTime" label="发布/审批时间" min-width="124" align="center">
+                <template slot-scope="scope">
+                    <template v-if="[1,2].includes(scope.row.State)">
+                        <span>{{scope.row.PrePublishTime?scope.row.PrePublishTime:scope.row.PublishTime|formatTime}}</span>
+                        <svg style="position: relative;top:2px" v-if="scope.row.PrePublishTime&&scope.row.State == '1'" width="17" height="16" viewBox="0 0 17 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+                            <path d="M15.2002 8C15.2002 4.13401 12.0662 1 8.20019 1C4.3342 1 1.20019 4.13401 1.2002 8C1.2002 11.866 4.3342 15 8.2002 15C12.0662 15 15.2002 11.866 15.2002 8ZM5.2002 10L5.2002 9L8.17491 9L11.2002 4.5L11.9073 5.20711L8.58912 10L5.2002 10Z" fill="#0052D9"/>
+                        </svg>
+                    </template>
+                    <template v-else>
+                        <span>{{scope.row.ApproveTime|formatTime}}</span>
+                    </template>
+                </template>
+            </el-table-column>
                 <el-table-column
                     prop="ContentModifyTime"
                     label="更新时间"
@@ -285,109 +258,59 @@
                 <el-table-column label="操作" align="center" min-width="130" fixed="right">
                     <template slot-scope="scope">
                     <div class="opt-btns">
-                        <!-- 不走审批流的按钮 -->
-                        <template v-if="!isApprove">
-                            <template v-if="scope.row.State == 1">
-                                <span v-permission="permissionBtn.smartReportManageBtn.reportManage_publish"
-                                    class="editsty" @click="handlePublishReportOpt(scope.row)"
-                                    v-if="scope.row.CanEdit">发布</span>
-                                <span v-permission="permissionBtn.smartReportManageBtn.reportManage_reportEdit"
-                                    class="editsty" @click="editreport(scope.row, 'edit')"
-                                    v-if="scope.row.CanEdit">编辑</span>
-                                <span v-permission="permissionBtn.smartReportManageBtn.reportManage_reportEdit"
-                                    class="editsty" @click="editreport(scope.row, 'editing')"
-                                    v-else>{{ scope.row.Editor || "" }}编辑中...</span>
-                                <span v-permission="permissionBtn.smartReportManageBtn.reportManage_reportDel"
-                                    class="deletesty" @click="handleDelReport(scope.row)"
-                                    v-if="scope.row.CanEdit">删除</span>
-                            </template>
-                            <template v-if="scope.row.State == 2">
-                                <span
-                                    v-if="permissionBtn.checkPermissionBtn(permissionBtn.smartReportManageBtn.reportManage_cancelPublish)"
-                                    @click="handleReportPublishCancel(scope.row)"
-                                    style="color: red; cursor: pointer"
-                                >取消发布</span>
-                                <span
-                                    v-if="scope.row.DetailImgUrl"
-                                    v-permission="permissionBtn.smartReportManageBtn.reportManage_exportImg"
-                                    @click="handleDownReportImg(scope.row.DetailImgUrl,scope.row.Title)"
-                                    style="cursor: pointer; color: #4099ef;display:inline-block"
-                                >图片下载</span>
-                                <!-- <span
-                            v-if="scope.row.MsgIsSend == 0 && permissionBtn.checkPermissionBtn(permissionBtn.smartReportManageBtn.reportManage_sendMsg)"
-                            style="color: #4099ef; cursor: pointer"
-                            @click="handleSendMsg(scope.row)"
-                            >推送消息</span
-                        >
-                        <span v-else-if="scope.row.MsgIsSend != 0&&permissionBtn.checkPermissionBtn(permissionBtn.smartReportManageBtn.reportManage_sendMsg)"
-                            style="color: red">已推送消息</span> -->
-                            </template>
-                            <span style="color: #46c371; cursor: pointer;display:inline-block"
-                                v-if="permissionBtn.checkPermissionBtn(permissionBtn.smartReportManageBtn.reportManage_audioUpload)"
-                                @click="openupload(scope.row.SmartReportId)">音频上传</span>
-                            <span style="cursor: pointer; color: #4099ef;display:inline-block"
-                                v-permission="permissionBtn.smartReportManageBtn.reportManage_audioDownload"
-                                v-if="scope.row.VideoUrl" @click="handleDownloadVoice(scope.row)">
-                                音频下载
-                            </span>
-                            <!-- <a
-                                v-permission="permissionBtn.smartReportManageBtn.reportManage_audioDownload"
-                                :href="scope.row.VideoUrl"
-                                v-if="scope.row.VideoUrl"
-                                :download="scope.row.VideoName"
-                                style="cursor: pointer; color: #4099ef"
-                                >音频下载</a
-                                > -->
+                        <!-- 操作:
+                            已发布——取消发布、下载图片
+                            未发布——发布、编辑、删除
+                            待提交——提交、编辑、删除
+                            待审批——撤销
+                            已通过——撤销、下载图片、
+                            已驳回——撤销 -->
+                        <!-- 未发布,待提交 -->
+                        <template v-if="[1,3].includes(scope.row.State)">
+                            <span v-permission="permissionBtn.smartReportManageBtn.reportManage_publish"
+                                class="editsty" @click="handlePublishReportOpt(scope.row)"
+                                v-if="scope.row.CanEdit&&scope.row.State===1">发布</span>
+                            <span v-permission="permissionBtn.smartReportManageBtn.reportManage_publish"
+                                class="editsty" @click="handleSubmitReport(scope.row)"
+                                v-if="scope.row.CanEdit&&scope.row.State===3">提交</span>
+                            <span v-permission="permissionBtn.smartReportManageBtn.reportManage_reportEdit"
+                                class="editsty" @click="editreport(scope.row, 'edit')"
+                                v-if="scope.row.CanEdit">编辑</span>
+                            <span v-permission="permissionBtn.smartReportManageBtn.reportManage_reportEdit"
+                                class="editsty" @click="editreport(scope.row, 'editing')"
+                                v-else>{{ scope.row.Editor || "" }}编辑中...</span>
+                            <span v-permission="permissionBtn.smartReportManageBtn.reportManage_reportDel"
+                                class="deletesty" @click="handleDelReport(scope.row)"
+                                v-if="scope.row.CanEdit">删除</span>
                         </template>
-                        <!-- 走审批流的按钮 -->
-                        <template v-if="isApprove">
-                            <!-- 待提交 -->
-                            <template v-if="scope.row.State == 1">
-                                <span v-permission="permissionBtn.smartReportManageBtn.reportManage_publish"
-                                    class="editsty" @click="handlePublishReportOpt(scope.row)"
-                                    v-if="scope.row.CanEdit">提交</span>
-                                <span v-permission="permissionBtn.smartReportManageBtn.reportManage_reportEdit"
-                                    class="editsty" @click="editreport(scope.row, 'edit')"
-                                    v-if="scope.row.CanEdit">编辑</span>
-                                <span v-permission="permissionBtn.smartReportManageBtn.reportManage_reportEdit"
-                                    class="editsty" @click="editreport(scope.row, 'editing')"
-                                    v-else>{{ scope.row.Editor || "" }}编辑中...</span>
-                                <span v-permission="permissionBtn.smartReportManageBtn.reportManage_reportDel"
-                                    class="deletesty" @click="handleDelReport(scope.row)"
-                                    v-if="scope.row.CanEdit">删除</span>
-                            </template>
-                            <!--已提交(待审批,已审批)-->
-                            <template v-if="[2,4].includes(scope.row.State)">
-                                <span
-                                    v-if="permissionBtn.checkPermissionBtn(permissionBtn.smartReportManageBtn.reportManage_cancelPublish)"
-                                    @click="handleReportPublishCancel(scope.row)"
-                                    style="color: red; cursor: pointer">撤销
-                                </span>
-                                <span
-                                    v-if="scope.row.DetailImgUrl&&scope.row.State===4"
-                                    v-permission="permissionBtn.smartReportManageBtn.reportManage_reportView_exportImg"
-                                    @click="handleDownReportImg(scope.row.DetailImgUrl,scope.row.Title)"
-                                    style="cursor: pointer; color: #4099ef;display:inline-block"
-                                >图片下载</span>
-                            </template>
-                             <!--已驳回则只显示撤销按钮-->
-                            <template v-if="scope.row.State===3">
-                                <span v-permission="permissionBtn.smartReportManageBtn.reportManage_publish"
+                        <!-- 已发布,已通过 -->
+                        <template v-if="[2,6].includes(scope.row.State)">
+                            <span v-if="permissionBtn.isShowBtn('smartReportManageBtn','reportManage_cancelPublish')&&scope.row.State===2"
                                 @click="handleReportPublishCancel(scope.row)"
-                                    class="editsty">撤销</span>
-                            </template>
-                            <!--音频上传/下载 按原先逻辑-->
-                            <template v-if="scope.row.State!==3">
-                                <span style="color: #46c371; cursor: pointer;display:inline-block"
-                                    v-if="permissionBtn.checkPermissionBtn(permissionBtn.smartReportManageBtn.reportManage_audioUpload)"
-                                    @click="openupload(scope.row.SmartReportId)">音频上传</span>
-                                <span style="cursor: pointer; color: #4099ef;display:inline-block"
-                                    v-permission="permissionBtn.smartReportManageBtn.reportManage_audioDownload"
-                                    v-if="scope.row.VideoUrl" @click="handleDownloadVoice(scope.row)">
-                                    音频下载
-                                </span>
-                            </template>
+                                style="color: red; cursor: pointer">撤销</span><!-- 取消发布 -->
+                            <span v-if="permissionBtn.isShowBtn('smartReportManageBtn','reportManage_cancelPublish')&&scope.row.State===6"
+                                @click="cancelReport(scope.row)"
+                                style="color: red; cursor: pointer">撤销</span>
+                            <span v-if="scope.row.DetailImgUrl"
+                                v-permission="permissionBtn.smartReportManageBtn.reportManage_reportView_exportImg"
+                                @click="handleDownReportImg(scope.row.DetailImgUrl,scope.row.Title)"
+                                style="cursor: pointer; color: #4099ef;display:inline-block">图片下载</span>
                         </template>
+                        <!-- 待审批,已驳回 -->
+                        <template v-if="[4,5].includes(scope.row.State)">
+                            <span v-if="permissionBtn.isShowBtn('smartReportManageBtn','reportManage_cancelPublish')"
+                                @click="cancelReport(scope.row)"
+                                style="color: red; cursor: pointer">撤销</span>
+                        </template>
+                        <!-- 音频上传、下载,与状态无关 -->
+                        <span style="color: #46c371; cursor: pointer;display:inline-block"
+                            v-if="permissionBtn.checkPermissionBtn(permissionBtn.smartReportManageBtn.reportManage_audioUpload)"
+                            @click="openupload(scope.row.SmartReportId)">音频上传</span>
+                        <span style="cursor: pointer; color: #4099ef;display:inline-block"
+                            v-permission="permissionBtn.smartReportManageBtn.reportManage_audioDownload"
+                            v-if="scope.row.VideoUrl" @click="handleDownloadVoice(scope.row)">
+                            音频下载
+                        </span>
                     </div>
                     </template>
                 </el-table-column>
@@ -522,8 +445,11 @@
 <script>
 import { voiceupload } from "api/api.js";
 import {apiSmartReport}  from '@/api/modules/smartReport'
+import {approveInterence} from '@/api/modules/approve.js';
+import reportApproveConfig from "@/mixins/reportApproveConfig.js"
 import BaseInfo from './components/BaseInfo.vue'
 export default {
+    mixins:[reportApproveConfig],
     components:{BaseInfo},
     computed:{
         Role() {
@@ -534,13 +460,6 @@ export default {
         hasUV(){
             return this.permissionBtn.checkPermissionBtn(this.permissionBtn.smartReportManageBtn.reportManage_reportList_uv)
         },
-        //是否开启审批流,若开启,发布相关按钮,筛选项改变
-        isApprove(){
-            const type = this.$setting.dynamicOutLinks.ApprovalFlow ||
-                        this.$store.state.dynamicOutLinks.ApprovalFlow ||
-                        JSON.parse(localStorage.getItem('dynamicOutLinks')).ApprovalFlow||''
-            return ['2','3'].includes(type)
-        }
     },
     data() {
         return {
@@ -685,6 +604,37 @@ export default {
             this.isDSFB=false
             this.showPublish=false
         },
+        //提交报告
+        handleSubmitReport(item){
+            this.$confirm("是否确认提交该报告进入审批流程?","提示",{
+                confirmButtonText:'确定',
+                cancelButtonText:'取消',
+                type:'warning',
+            }).then(()=>{
+                approveInterence.reportSmartSubmit({
+                    ReportId:Number(item.SmartReportId)
+                }).then(res=>{
+                    if(res.Ret!==200) return 
+                    this.$message.success("提交成功")
+                    this.getReportList()
+                })
+            })
+        },
+        cancelReport(item){
+            this.$confirm("确定要撤销审批吗?","提示",{
+                confirmButtonText:'确定',
+                cancelButtonText:'取消',
+                type:'warning',
+            }).then(()=>{
+                approveInterence.reportSmartCancel({
+                    ReportId:Number(item.SmartReportId)
+                }).then(res=>{
+                    if(res.Ret!==200) return 
+                    this.$message.success("撤销成功")
+                    this.getReportList()
+                })
+            })
+        },
 
         //编辑报告
         async editreport(item, type){

+ 36 - 1
src/views/system_manage/etaBaseConfig.vue

@@ -142,6 +142,28 @@
                             </el-form-item>
                         </template>
                     </div>
+                    <!-- 研报审批 -->
+                    <div v-if="isShowApprove">
+                        <div style="width:100%;margin-bottom: 20px;">
+                            <span style="color:#606266;">研报审批</span> 
+                            <el-switch v-model="approve"></el-switch>
+                        </div>
+                        <div class="side" v-if="approve">
+                            <el-form-item label="" prop="ReportApproveType">
+                                <el-radio-group v-model="formData.ReportApproveType">
+                                    <el-radio label="eta">ETA内部审批</el-radio>
+                                    <el-radio label="other">
+                                        <span>第三方审批</span>
+                                        <el-tooltip effect="dark" placement="top" content="中文研报(智能研报/研报列表)通过API接口对接第三方审批系统" >
+                                            <span class="hint-text">
+                                                <i class="el-icon-warning-outline"></i>
+                                            </span>
+                                        </el-tooltip>
+                                    </el-radio>
+                                </el-radio-group>
+                            </el-form-item>
+                        </div>
+                    </div>
                 </div>
                 <div class="side">
                     <el-form-item label="中文研报分享抬头" prop="H5ShareName">
@@ -314,6 +336,7 @@ export default {
             /* base config */
             checkList:[],//水印应用
             Iflytek:false,//是否启用科大讯飞服务
+            approve:false,//是否开启研报审批
             formData: {
                 Disclaimer: '',//免责声明
                 CompanyName:'',//公司名称
@@ -347,6 +370,9 @@ export default {
 
                 WatermarkReport:false,//研报分享水印
 
+                IsReportApprove:false,//是否开启研报审批
+                ReportApproveType:'eta',//研报审批选项
+
             },//表单预设值
             rules: {
                 Disclaimer:[{ required: true, message: '请输入免责声明', trigger: 'blur' }],
@@ -445,6 +471,12 @@ export default {
                     this.permissionBtn.baseConfigPermission.etaBaseConfig_xunfei
                 )
         },
+        //是否显示研报审批相关表单项
+        isShowApprove(){
+            return this.permissionBtn.checkPermissionBtn(
+                this.permissionBtn.baseConfigPermission.etaBaseConfig_approve
+            )
+        },
         //是否显示中文PPT相关的表单项
         isShowPPT(){
             return this.permissionBtn.checkPermissionBtn(
@@ -530,11 +562,13 @@ export default {
             });
             //获取WatermarkChart的值,赋值checkList
             //获取UseXf的值,赋值Iflytek
+            //获取IsReportApprove的值,赋值approve
             etaBaseConfigInterence.getBaseConfig().then(res=>{
                 if(res.Ret!==200) return 
-                const {WatermarkChart='',UseXf='',CnPptCoverImgs='',EnPptCoverImgs=''} = res.Data
+                const {WatermarkChart='',UseXf='',IsReportApprove='',CnPptCoverImgs='',EnPptCoverImgs=''} = res.Data
                 this.checkList = WatermarkChart==='true'?['研报图表']:[]
                 this.Iflytek = UseXf==='true'?true:false
+                this.approve = IsReportApprove==='true'?true:false
                 if(res.Data){
                     // this.$set(this,'formData',res.Data)
                     this.formData = {...this.formData,...res.Data}
@@ -583,6 +617,7 @@ export default {
                     this.formData.LoginEmailTemplateContent = this.formData.LoginEmailTemplateContent.replace(/<p data-f-id=\"pbf\".*?<\/p>/g, "");
                     this.formData.WatermarkChart = ''+(this.checkList.includes('研报图表')?true:false)
                     this.formData.UseXf = ''+(this.Iflytek?true:false)
+                    this.formData.IsReportApprove = ''+(this.approve?true:false)
                     const CnPptCoverImgs = this.formData.CnPptCoverImgs.join(',')
                     const EnPptCoverImgs = this.formData.EnPptCoverImgs.join(',')
                     //通过验证后,提交数据前