workbench.vue 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841
  1. <template>
  2. <div class="app-container">
  3. <el-tabs v-model="activeTab" class="tabs" :before-leave="handleChange" @tab-click="changeTab">
  4. <el-tab-pane v-for="item in tabList" :key="item.key" :name="item.key">
  5. <span slot="label"><i :class="item.icon" /> {{ item.label }}</span>
  6. <div v-if="activeTab === item.key" class="tab-container">
  7. <div class="table-container">
  8. <ibps-crud
  9. :ref="item.key"
  10. :data="dataList"
  11. :toolbars="item.key === 'save' ? listConfig.darftTool : listConfig.toolbars"
  12. :search-form="listConfig.searchForm[item.key]"
  13. :pk-key="pkKey"
  14. :columns="listConfig.columns[item.key]"
  15. :pagination="pagination"
  16. :loading="loading"
  17. :index-row="false"
  18. :selection-row="item.key === 'save'"
  19. @row-click="handleRowClick"
  20. @action-event="handleAction"
  21. @sort-change="handleSortChange"
  22. @pagination-change="handlePaginationChange"
  23. >
  24. <template slot="name" slot-scope="scope">{{ scope.row.subject | getWorkInfo('name') }}</template>
  25. <template slot="desc" slot-scope="scope">{{ scope.row.subject | getWorkInfo('desc') }}</template>
  26. <!-- 待办字段处理 -->
  27. <template slot="waitStatus" slot-scope="scope">{{ '待' + scope.row.name }}</template>
  28. <template slot="stateLabel" slot-scope="scope">
  29. <span>{{ scope.column.label }}</span>
  30. <el-tooltip effect="dark" placement="top">
  31. <div slot="content">
  32. 普通事务:接收三天之内为待办理,三天之后为已超时
  33. <br>
  34. 计划事务:月底前七天内为即将超时,超过接收当月月底为已超时,其余为待办理
  35. </div>
  36. <i class="el-icon-info" />
  37. </el-tooltip>
  38. </template>
  39. <template slot="state" slot-scope="scope">
  40. <el-tag :type="scope.row.state ? stateOption[scope.row.state].type : ''">{{ scope.row.state ? stateOption[scope.row.state].label : '待办理' }}</el-tag>
  41. </template>
  42. <template slot="submitBy" slot-scope="scope">
  43. <span>{{ scope.column.label }}</span>
  44. <el-tooltip effect="dark" placement="top">
  45. <div slot="content">
  46. 该事务对应流程的发起人
  47. </div>
  48. <i class="el-icon-info" />
  49. </el-tooltip>
  50. </template>
  51. <template slot="forwardBy" slot-scope="scope">
  52. <span>上节点</span><br>
  53. <span>提交人</span>
  54. <el-tooltip effect="dark" placement="top">
  55. <div slot="content">
  56. 该事务对应流程上一节点的提交人
  57. </div>
  58. <i class="el-icon-info" />
  59. </el-tooltip>
  60. </template>
  61. <!-- 已办、办结字段处理 -->
  62. <template slot="overStatus" slot-scope="scope">{{ getStatus(scope.row.status) }}</template>
  63. <template slot="overDept" slot-scope="scope">{{ getParenthesesStr(scope.row.subject)[1] }}</template>
  64. <template slot="creator" slot-scope="scope">{{ scope.row.createBy | getUserName(userList) }}</template>
  65. <template slot="updateBy" slot-scope="scope">{{ getName(scope.row) }}</template>
  66. </ibps-crud>
  67. </div>
  68. </div>
  69. </el-tab-pane>
  70. </el-tabs>
  71. <bpmn-formrender
  72. :visible="dialogFormVisible"
  73. :task-id="activeTab === 'wait' ? taskId : null"
  74. :wai-jian="activeTab === 'wait' ? waiJian : null"
  75. :instance-id="['over', 'finish'].includes(activeTab) ? instanceId : null"
  76. :def-id="activeTab === 'save' ? defId : null"
  77. :pro-inst-id="activeTab === 'save' ? proInstId : null"
  78. :title="['wait', 'save'].includes(activeTab) ? FlowName : null"
  79. @callback="updateList"
  80. @close="visible => (dialogFormVisible = visible)"
  81. />
  82. <news-detail
  83. :id="newsId"
  84. title="公告明细"
  85. :visible="newsDialogVisible"
  86. readonly
  87. @close="visible => newsDialogVisible = visible"
  88. />
  89. </div>
  90. </template>
  91. <script>
  92. import { pending, handledTask } from '@/api/platform/office/bpmReceived'
  93. import { myDraft, removeDraft } from '@/api/platform/office/bpmInitiated'
  94. import { queryPageList as newsList } from '@/api/platform/system/news'
  95. import { queryOrgManager } from '@/api/platform/org/employee'
  96. import { save } from '@/api/platform/message/innerMessage'
  97. import BpmnFormrender from '@/business/platform/bpmn/form/dialog'
  98. import ActionUtils from '@/utils/action'
  99. import { typeOptions } from '@/views/platform/system/news/constants'
  100. import NewsDetail from '@/views/platform/system/news/detail'
  101. const tabList = [
  102. {
  103. label: '待办事宜',
  104. key: 'wait',
  105. icon: 'el-icon-edit'
  106. },
  107. {
  108. label: '已办事宜',
  109. key: 'over',
  110. icon: 'el-icon-document-remove'
  111. },
  112. {
  113. label: '办结事宜',
  114. key: 'finish',
  115. icon: 'el-icon-paperclip'
  116. },
  117. {
  118. label: '暂存事宜',
  119. key: 'save',
  120. icon: 'el-icon-receiving'
  121. },
  122. {
  123. label: '通知公告',
  124. key: 'news',
  125. icon: 'el-icon-message'
  126. }
  127. ]
  128. const taskState = {
  129. running: '已发起',
  130. end: '已结束',
  131. manualend: '人工结束'
  132. }
  133. const paramsType = {
  134. wait: 'temp.',
  135. over: '',
  136. finish: 'inst.',
  137. save: '',
  138. news: ''
  139. }
  140. const stateOption = {
  141. wait: {
  142. label: '待办理',
  143. type: ''
  144. },
  145. soon: {
  146. label: '即将超时',
  147. type: 'warning'
  148. },
  149. overtime: {
  150. label: '已超时',
  151. type: 'danger'
  152. }
  153. }
  154. const operate = {
  155. wait: pending,
  156. over: handledTask,
  157. finish: handledTask,
  158. save: myDraft,
  159. news: newsList
  160. }
  161. export default {
  162. name: 'calendar',
  163. components: { BpmnFormrender, NewsDetail },
  164. filters: {
  165. getWorkInfo (v, type) {
  166. const hasDesc = v.includes('#')
  167. const res = {
  168. name: {
  169. '0': v.includes('{') ? v.split('{')[0] : v.includes('(') ? v.split('(')[0] : v,
  170. '1': v.split('#')[0]
  171. },
  172. // 无#返回空,有#返回(左边的字符串,
  173. desc: {
  174. '0': '',
  175. '1': v.split('#')[1]
  176. }
  177. }
  178. if (!hasDesc) {
  179. return res[type]['0']
  180. }
  181. return res[type]['1']
  182. },
  183. getUserName (v, list) {
  184. const user = list.find(i => i.userId === v)
  185. return user ? user.userName : ''
  186. }
  187. },
  188. props: {
  189. plan: {
  190. type: Array,
  191. default: () => []
  192. }
  193. },
  194. data () {
  195. return {
  196. tabList,
  197. stateOption,
  198. pkKey: 'id',
  199. taskId: '', // 编辑dialog需要使用
  200. waiJian: '', // 编辑dialog需要使用
  201. instanceId: '',
  202. defId: '',
  203. proInstId: '',
  204. newsId: '',
  205. loading: false,
  206. dialogFormVisible: false,
  207. newsDialogVisible: false,
  208. orgName: '',
  209. roleName: '',
  210. FlowName: '',
  211. posName: '',
  212. timer: null,
  213. userList: [],
  214. orgInfo: {},
  215. activeTab: tabList[0].key,
  216. height: document.body.clientHeight,
  217. selection: [],
  218. defaultPagination: { page: 1, limit: 15 },
  219. sorts: { CREATE_TIME_: 'DESC' },
  220. dataList: [],
  221. pagination: {},
  222. searchParams: {
  223. typeId: '',
  224. subject: '',
  225. createTime: ''
  226. },
  227. listConfig: {
  228. searchForm: {
  229. wait: {
  230. forms: [
  231. { prop: 'Q^subject_^SL', name: 'Q^temp.subject_^SL', label: '事务名称', fieldType: 'input' },
  232. { prop: ['Q^temp.create_time_^DL', 'Q^temp.create_time_^DG'], label: '提交时间', fieldType: 'daterange' }
  233. ]
  234. },
  235. over: {
  236. forms: [
  237. { prop: 'Q^subject_^SL', label: '事务名称', fieldType: 'input' },
  238. { prop: ['Q^create_time_^DL', 'Q^create_time_^DG'], label: '创建时间', fieldType: 'daterange' }
  239. ]
  240. },
  241. finish: {
  242. forms: [
  243. { prop: 'Q^subject_^SL', name: 'Q^inst.subject_^SL', label: '事务名称', fieldType: 'input' },
  244. { prop: ['Q^create_time_^DL', 'Q^create_time_^DG'], name: ['Q^inst.create_time_^DL', 'Q^inst.create_time_^DG'], label: '结束时间', fieldType: 'daterange' }
  245. ]
  246. },
  247. save: {
  248. forms: [
  249. { prop: 'Q^subject_^SL', label: '事务名称', fieldType: 'input' },
  250. { prop: ['Q^create_time_^DL', 'Q^create_time_^DG'], label: '提交时间', fieldType: 'daterange' }
  251. ]
  252. },
  253. news: {
  254. forms: [
  255. { prop: 'Q^title_^SL', label: '标题', fieldType: 'input' },
  256. { prop: 'Q^user_name_^SL', label: '发布人', fieldType: 'input' },
  257. { prop: ['Q^public_date_^DL', 'Q^public_date_^DG'], label: '发布时间', fieldType: 'daterange' }
  258. ]
  259. }
  260. },
  261. toolbars: [
  262. {
  263. key: 'search'
  264. }
  265. ],
  266. darftTool: [
  267. {
  268. key: 'search'
  269. },
  270. {
  271. key: 'remove'
  272. }
  273. ],
  274. // 表格字段配置
  275. columns: {
  276. wait: [
  277. { prop: 'scope', label: '事务名称', slotName: 'name', width: 250 },
  278. { prop: 'scope', label: '事务说明', slotName: 'desc', minWidth: 250 },
  279. { prop: 'scope', label: '事务状态', slotName: 'waitStatus', width: 120 },
  280. { prop: 'scope', label: '办理进度', headerName: 'stateLabel', slotName: 'state', width: 120 },
  281. { prop: 'startDept', label: '发起部门', width: 120 },
  282. { prop: 'submitBy', label: '发起人', headerName: 'submitBy', width: 100 },
  283. { prop: 'forwardBy', label: `上节点提交人`, headerName: 'forwardBy', width: 100 },
  284. { prop: 'createTime', label: '上节点提交时间', width: 150 }
  285. ],
  286. over: [
  287. { prop: 'scope', label: '事务名称', slotName: 'name', width: 250 },
  288. { prop: 'scope', label: '事务说明', slotName: 'desc', minWidth: 250 },
  289. { prop: 'scope', label: '事务状态', slotName: 'overStatus', width: 120 },
  290. { prop: 'scope', label: '发起部门', slotName: 'overDept', width: 120 },
  291. { prop: 'scope', label: '发起人', headerName: 'submitBy', slotName: 'creator', width: 100 },
  292. { prop: 'scope', label: `提交人`, slotName: 'updateBy', width: 100 },
  293. { prop: 'createTime', label: '创建时间', width: 150 }
  294. ],
  295. finish: [
  296. { prop: 'scope', label: '事务名称', slotName: 'name', width: 250 },
  297. { prop: 'scope', label: '事务说明', slotName: 'desc', minWidth: 250 },
  298. { prop: 'scope', label: '事务状态', slotName: 'overStatus', width: 120 },
  299. { prop: 'scope', label: '发起部门', slotName: 'overDept', width: 120 },
  300. { prop: 'scope', label: '发起人', headerName: 'submitBy', slotName: 'creator', width: 100 },
  301. { prop: 'scope', label: `提交人`, slotName: 'updateBy', width: 100 },
  302. { prop: 'createTime', label: '结束时间', width: 150 }
  303. ],
  304. save: [
  305. { prop: 'scope', label: '事务名称', slotName: 'name', width: 250 },
  306. { prop: 'scope', label: '事务说明', slotName: 'desc', minWidth: 250 },
  307. { prop: 'createTime', label: '暂存时间', width: 150 }
  308. ],
  309. news: [
  310. { prop: 'title', label: '标题', minWidth: 250 },
  311. { prop: 'userName', label: '发布人', width: 120 },
  312. { prop: 'publicDate', label: '发布时间', dateFormat: 'yyyy-MM-dd', width: 120 },
  313. { prop: 'loseDate', label: '失效时间', dateFormat: 'yyyy-MM-dd', width: 120 },
  314. { prop: 'status', label: '发布状态', tags: typeOptions, width: 100 }
  315. ]
  316. }
  317. }
  318. }
  319. },
  320. mounted: function () {
  321. this.getData(this.activeTab)
  322. this.getUserList()
  323. this.getOrgInfo()
  324. if (this.timer) {
  325. clearInterval(this.timer)
  326. }
  327. // 轮询刷新公告数据和任务数据
  328. this.timer = setInterval(() => {
  329. // this.getMessage()
  330. this.getData(this.activeTab)
  331. }, 30 * 1000)
  332. },
  333. beforeDestroy () {
  334. clearInterval(this.timer)
  335. },
  336. // 路由离开时
  337. beforeRouteLeave (to, from, next) {
  338. clearInterval(this.timer)
  339. },
  340. methods: {
  341. // 获取系统用户信息
  342. getUserList () {
  343. const { userList } = this.$store.getters
  344. // store中有则无需请求
  345. if (userList && userList.length) {
  346. this.userList = userList
  347. return
  348. }
  349. const sql = `select id_ as userId, name_ as userName, mobile_ as phone from ibps_party_employee where status_ = 'actived'`
  350. this.$common.request('sql', sql).then(res => {
  351. this.userList = res.variables && res.variables.data
  352. })
  353. },
  354. // 获取用户部门信息
  355. getOrgInfo () {
  356. const { org = {}} = this.$store.getters
  357. if (!org || !org.id) {
  358. return
  359. }
  360. const params = {
  361. parameters: [{ key: 'Q^MANAGER_ORG_ID_^S', value: org.id }]
  362. }
  363. queryOrgManager(params).then(res => {
  364. this.orgInfo = {}
  365. const data = res.data.dataResult
  366. if (data && data.length) {
  367. const { id, name, mobile, account, gender, groupID } = data[0]
  368. this.orgInfo = { id, name, mobile, account, gender, groupID, orgName: org.name }
  369. }
  370. })
  371. },
  372. getName ({ createBy, updateBy }) {
  373. const id = updateBy || createBy
  374. const { name = '' } = this.$store.getters
  375. if (this.activeTab === 'finish') {
  376. const t = this.userList.find(i => i.userId === id)
  377. return t ? t.userName : ''
  378. }
  379. return name
  380. },
  381. getStatus (val) {
  382. const s = taskState[val]
  383. return s || '暂停'
  384. },
  385. tableRowClassName ({ row, rowIndex }) {
  386. if (rowIndex % 2 === 1) return 'warning-row'
  387. return 'success-row'
  388. },
  389. // 获取表格数据
  390. getData (type) {
  391. this.loading = true
  392. const pageParams = this.pagination.page ? this.pagination : this.defaultPagination
  393. operate[this.activeTab](this.getFormatParams(null, pageParams)).then(response => {
  394. const { dataResult, pageResult } = response.data
  395. if (dataResult && dataResult.length) {
  396. // 待办事宜对任务发起人做额外处理
  397. if (type === 'wait') {
  398. const instList = []
  399. dataResult.forEach(item => {
  400. instList.push(item.bpmnInstId)
  401. })
  402. const sql = `select b.bpmn_inst_id_, b.create_by_, a.name_ from ibps_bpm_inst b left join ibps_party_employee a on a.id_ = b.create_by_ where b.bpmn_inst_id_ in (${instList.join(',')}) order by find_in_set(b.bpmn_inst_id_,'${instList.join(',')}')`
  403. const currentTime = Date.now()
  404. this.$common.request('sql', sql).then(res => {
  405. const data = res.variables && res.variables.data
  406. data.forEach((item, index) => {
  407. dataResult[index].submitBy = item.name_
  408. dataResult[index].workName = dataResult[index].subject.includes('#') ? dataResult[index].subject.split('#')[0] : dataResult[index].subject.split('(')[0]
  409. dataResult[index].workType = this.plan.includes(dataResult[index].procDefKey) ? 'plan' : 'normal'
  410. dataResult[index].state = this.judgeExpire(dataResult[index].createTime, currentTime, dataResult[index].workType, '1')
  411. })
  412. this.dataList = dataResult.sort((a, b) => b.createTime.localeCompare(a.createTime))
  413. this.pagination = pageResult
  414. })
  415. // this.urgeToManager()
  416. } else {
  417. this.dataList = dataResult
  418. this.pagination = pageResult
  419. }
  420. }
  421. this.loading = false
  422. }).catch(() => {
  423. this.loading = false
  424. })
  425. },
  426. // 延迟更新列表数据
  427. updateList () {
  428. setTimeout(() => {
  429. this.getData(this.activeTab)
  430. }, 1000)
  431. },
  432. // 查询
  433. search () {
  434. this.dataList = []
  435. this.pagination = {}
  436. this.getData(this.activeTab)
  437. },
  438. handleChange (activeName, oldActiveName) {
  439. // this.$refs[oldActiveName][0].handleReset()
  440. },
  441. // 切换tab
  442. changeTab () {
  443. // 数据、筛选条件初始化
  444. this.dataList = []
  445. this.selection = []
  446. this.pagination = {}
  447. this.getData(this.activeTab)
  448. },
  449. handleSortChange (sort) {
  450. console.log(sort)
  451. ActionUtils.setSorts(this.sorts, sort)
  452. this.getData(this.activeTab)
  453. },
  454. handlePaginationChange (page) {
  455. ActionUtils.setPagination(this.pagination, page)
  456. this.getData(this.activeTab)
  457. },
  458. getFormatParams (v, page) {
  459. const params = this.$refs[this.activeTab] && this.$refs[this.activeTab].length ? this.$refs[this.activeTab][0].getSearcFormData() : {}
  460. if (this.activeTab === 'finish') {
  461. params.end = '1'
  462. }
  463. if (this.activeTab === 'news') {
  464. // 公告限制显示当前医院且状态为已发布的数据,过滤草稿及失效公告
  465. params['Q^type_^SL'] = this.$store.getters.level ? this.$store.getters.level.first : ''
  466. params['Q^status_^SL'] = 'publish'
  467. }
  468. const s = this.activeTab === 'news' ? { 'PUBLIC_DATE_': 'DESC' } : this.sorts
  469. return ActionUtils.formatParams(params, page, s)
  470. },
  471. // 处理表格点击事件
  472. handleRowClick (data) {
  473. if (this.activeTab === 'news') {
  474. this.newsId = data.id
  475. this.newsDialogVisible = true
  476. return
  477. }
  478. this.taskId = data.id || ''
  479. this.waiJian = data.waiJian || ''
  480. this.instanceId = data.id || ''
  481. this.defId = data.procDefId || ''
  482. this.proInstId = data.id || ''
  483. this.FlowName = data.name
  484. this.dialogFormVisible = true
  485. },
  486. handleAction (command, position, selection, data) {
  487. switch (command) {
  488. case 'search':// 查询
  489. ActionUtils.setFirstPagination(this.pagination)
  490. this.search()
  491. break
  492. case 'remove':// 删除
  493. ActionUtils.removeRecord(selection).then((ids) => {
  494. console.log(ids)
  495. this.handleRemove(ids)
  496. }).catch(() => { })
  497. break
  498. default:
  499. break
  500. }
  501. },
  502. // 删除暂存数据
  503. handleRemove (ids) {
  504. removeDraft({ ids }).then(() => {
  505. ActionUtils.removeSuccessMessage()
  506. this.selection = []
  507. this.search()
  508. })
  509. },
  510. // 数组去重
  511. unique (arr) {
  512. const res = new Map()
  513. return arr.filter(arr => !res.has(arr.id) && res.set(arr.id, 1))
  514. },
  515. // 文字替换
  516. getParenthesesStr (text) {
  517. let result = ''
  518. if (!text) return result
  519. const regex1 = /\{(.+?)\}/g
  520. const regex2 = /\((.+?)\)/g
  521. const options1 = text.match(regex1)
  522. const options2 = text.match(regex2)
  523. const options = options1 && options1.length ? options1 : options2
  524. if (options) {
  525. const option = options[0]
  526. if (option) {
  527. result = option.substring(1, option.length - 1)
  528. }
  529. if (options[1]) {
  530. const yersOption = options[1]
  531. if (yersOption) {
  532. result = result + '/' + yersOption.substring(1, yersOption.length - 1)
  533. }
  534. }
  535. }
  536. return result.split('/')
  537. },
  538. /**
  539. * 主管提醒
  540. * 数据处理,将所有待办数据根据是否过期处理为两个数组
  541. * 过期判断依据:普通事务-创建时间到当前时间超过三天即为过期;计划事务【事务名称中含计划】-创建当月月末前七天
  542. * 逻辑说明:过期数组中不存于在主管提醒表中的数据插入主管提醒表,并发送内部通知,主管提醒表删除不存在于未过期数组中的数据
  543. */
  544. urgeToManager () {
  545. const { userId } = this.$store.getters
  546. const params = {
  547. parameters: [],
  548. sorts: []
  549. }
  550. const sql = `select id_, shi_wu_id_ as taskId from t_gqswb where position('${userId}' in chu_li_ren_id_) FOR UPDATE`
  551. // Promise.all([pending(params), this.$common.request('sql', sql)]).then(([res1, res2]) => {
  552. // let workData = res1.data && res1.data.dataResult
  553. // let noticeData = res2.variables && res2.variables.data
  554. // if (!workData || !workData.length) {
  555. // return
  556. // }
  557. // this.dealData(workData, noticeData)
  558. // })
  559. pending(params).then(res1 => {
  560. const workData = res1.data && res1.data.dataResult
  561. this.$common.request('sql', sql).then(res2 => {
  562. const noticeData = res2.variables && res2.variables.data
  563. if (!workData || !workData.length) {
  564. return
  565. }
  566. this.dealData(workData, noticeData)
  567. })
  568. })
  569. },
  570. // 处理数据
  571. dealData (workList, noticeList) {
  572. const result = {
  573. expire: [],
  574. unexpire: [],
  575. all: []
  576. }
  577. const currentTime = Date.now()
  578. // 筛选已过期数据
  579. workList.forEach(item => {
  580. // 截取流程名
  581. item.workName = item.subject.includes('#') ? item.subject.split('#')[0] : item.subject.split('(')[0]
  582. item.workType = this.plan.includes(item.procDefKey) ? 'plan' : 'normal'
  583. const isExpire = this.judgeExpire(item.createTime, currentTime, item.workType)
  584. if (isExpire) {
  585. result.expire.push(item)
  586. } else {
  587. result.unexpire.push(item)
  588. }
  589. result.all.push(item)
  590. })
  591. // console.log('处理后数据:', result)
  592. // 有过期数据才执行过期数据处理
  593. if (result.expire.length) {
  594. this.dealExpile(result.expire, noticeList)
  595. }
  596. // 主管提醒表中有数据才执行数据删除
  597. if (noticeList && noticeList.length) {
  598. this.dealUnexpile(result.all, noticeList)
  599. }
  600. },
  601. // 判断是否过期、获取办理状态
  602. judgeExpire (time, current, type, isState) {
  603. const D = new Date(time)
  604. const a = new Date(time).getTime()
  605. const b = new Date(current).getTime()
  606. // 创建时间当月最后一天的时间戳
  607. const c = new Date(D.getFullYear(), D.getMonth() + 1, 0).getTime() + 86400000
  608. // 返回办理状态
  609. if (isState) {
  610. let state = ''
  611. if (type === 'plan') {
  612. state = b >= c ? 'overtime' : b + (86400000 * 7) > c ? 'soon' : 'wait'
  613. } else {
  614. state = a + (86400000 * 3) < b ? 'overtime' : 'wait'
  615. }
  616. return state
  617. }
  618. // 返回是否过期
  619. if (type === 'plan') {
  620. return b + (86400000 * 7) > c
  621. } else {
  622. return a + (86400000 * 3) < b
  623. }
  624. },
  625. // 处理已过期数据
  626. dealExpile (data, noticeList) {
  627. // console.log('已过期流程数据:', data)
  628. // console.log('过期事务表数据:', noticeList)
  629. const { userId } = this.$store.getters
  630. const addList = []
  631. const sendList = []
  632. const msgContent = {
  633. plan: '距离过期还剩七天,请及时处理!',
  634. normal: '至今三天未处理,已超时,请及时处理!'
  635. }
  636. const msgTitle = {
  637. plan: '计划事务即将到期提醒',
  638. normal: '事务超时提醒'
  639. }
  640. const nowTime = new Date(new Date().getTime() + 28800000).toJSON().slice(0, 16).replace('T', ' ')
  641. data.forEach(item => {
  642. const isExist = !!noticeList.find(i => i.taskId === item.taskId)
  643. // 筛选出不存在于主管提醒表的过期数据
  644. if (!isExist) {
  645. // 无部门信息的用户不往过期事务表加数据
  646. // if (this.orgInfo.groupID) {
  647. const obj = {
  648. // 事务ID
  649. shi_wu_id_: item.taskId,
  650. // 完整名称
  651. wan_zheng_ming_ch: item.subject,
  652. // 事务说明
  653. shi_wu_shuo_ming_: item.subject.includes('#') ? item.subject.split('#')[1] : '',
  654. // 事务名称
  655. shi_wu_ming_cheng: item.workName,
  656. // 事务状态
  657. shi_wu_zhuang_tai: `待${item.name}`,
  658. // 事务类型
  659. shi_wu_lei_xing_: item.workType,
  660. chu_li_ren_ming_: item.ownerName,
  661. chu_li_ren_id_: this.getInfoByName(item.ownerName, 'id'),
  662. chu_li_ren_dian_h: this.getInfoByName(item.ownerName, 'phone'),
  663. bu_men_: this.orgInfo.orgName,
  664. bu_men_id_: this.orgInfo.groupID,
  665. // 主管ID与当前用户id相等时将主管ID设置为主任【】的ID,主管电话设为空
  666. zhu_guan_id_: this.orgInfo.id === userId ? '990927120278487040' : this.orgInfo.id,
  667. zhu_guan_dian_hua: this.orgInfo.id === userId ? '' : this.orgInfo.mobile,
  668. bian_zhi_shi_jian: item.createTime,
  669. ti_xing_ci_shu_: 1,
  670. duan_xin_ci_shu_: 0,
  671. ti_xing_shi_jian_: nowTime
  672. }
  673. addList.push(obj)
  674. // }
  675. const msg = {
  676. subject: msgTitle[item.workType],
  677. content: `<p>事务【${item.workName}】${msgContent[item.workType]}<p>`,
  678. receiverId: userId,
  679. canreply: '0',
  680. taskId: item.taskId
  681. }
  682. sendList.push(msg)
  683. }
  684. })
  685. const addParams = {
  686. tableName: 't_gqswb',
  687. paramWhere: addList
  688. }
  689. // console.log('新增过期事务表数据:', addList, '发送消息数据', sendList)
  690. if (addList.length) {
  691. this.$common.request('add', addParams)
  692. }
  693. if (sendList.length) {
  694. this.sendMsg(sendList)
  695. }
  696. },
  697. // 删除已办的提醒表数据
  698. dealUnexpile (data, noticeList) {
  699. // 清除存在于主管提醒表中【处理人含我】,但是不存在于待办中的数据
  700. const deleteList = []
  701. noticeList.forEach(item => {
  702. const isExist = !!data.find(i => i.taskId === item.taskId)
  703. if (!isExist) {
  704. deleteList.push(item.id_)
  705. }
  706. })
  707. // console.log('过期事务表中需删除的数据:', deleteList)
  708. if (!deleteList.length) {
  709. return
  710. }
  711. const params = {
  712. tableName: 't_gqswb',
  713. paramWhere: {
  714. id_: deleteList.join(',')
  715. }
  716. }
  717. this.$common.request('delete', params).then(() => {}).catch(err => {
  718. console.log(err)
  719. })
  720. },
  721. // 发送站内消息
  722. sendMsg (data) {
  723. data.forEach(item => {
  724. save(item).then(() => {}).catch(err => {
  725. console.log(err)
  726. })
  727. })
  728. },
  729. // 通过名字获取id/电话
  730. getInfoByName (names, type) {
  731. const res = {
  732. id: [],
  733. phone: []
  734. }
  735. const temp = names.split(',')
  736. temp.forEach(item => {
  737. const t = this.userList.find(i => i.userName === item)
  738. if (t) {
  739. res.id.push(t.userId)
  740. res.phone.push(t.phone)
  741. }
  742. })
  743. return res[type].filter(i => i).join(',')
  744. }
  745. }
  746. }
  747. </script>
  748. <style lang="scss" scoped>
  749. ::v-deep .el-table__row {
  750. cursor: pointer;
  751. }
  752. ::v-deep .el-tabs__header {
  753. margin-bottom: 0;
  754. }
  755. .el-completing {
  756. background: #409eff !important;
  757. }
  758. .el-col {
  759. min-height: 1px;
  760. }
  761. .firstcol {
  762. padding-right: 10px;
  763. }
  764. .el-nothing {
  765. font-size: 13px;
  766. }
  767. .calendar-day {
  768. text-align: center;
  769. color: #202535;
  770. line-height: 30px;
  771. font-size: 12px;
  772. }
  773. .is-selected {
  774. color: #f8a535;
  775. font-size: 10px;
  776. margin-top: 5px;
  777. }
  778. #calendar .el-button-group > .el-button:not(:first-child):not(:last-child):after {
  779. content: '当月';
  780. }
  781. #calendar .item {
  782. position: relative;
  783. margin: 0;
  784. padding: 0;
  785. height: auto;
  786. border-radius: 4px;
  787. -webkit-box-sizing: border-box;
  788. box-sizing: border-box;
  789. overflow: hidden;
  790. color: #f8a535;
  791. }
  792. .ibps-list-split .ibps-list-item {
  793. border-bottom: 1px solid #dcdfe6;
  794. padding: 6px 0;
  795. }
  796. .jbd-font-style {
  797. font-weight: bold;
  798. }
  799. .home-text-border {
  800. color: #999999;
  801. box-shadow: 0 0 0 0 rgba(0, 0, 0, 0.1), 0 0 0 0 rgba(0, 0, 0, 0.1), 0 0 0 0 rgba(0, 0, 0, 0.1), 0 1px 0px 0 rgba(0, 0, 0, 0.1);
  802. min-height: 20px;
  803. font-size: 14px;
  804. margin-left: 60px;
  805. margin-bottom: 5px;
  806. }
  807. .jbd-home-card {
  808. overflow: auto;
  809. }
  810. .jbd-home-task {
  811. width: 100%;
  812. padding: 10px;
  813. cursor: pointer;
  814. font-size: 12px;
  815. margin-bottom: 35px;
  816. }
  817. .jbd-home-card::-webkit-scrollbar {
  818. display: none;
  819. }
  820. .jbd-control-cont {
  821. text-align: center;
  822. position: absolute;
  823. z-index: 10;
  824. right: 0px;
  825. top: 50%;
  826. }
  827. .tab-container {
  828. height: calc(100vh - 160px);
  829. min-height: 600px;
  830. >div {
  831. display: inline-block;
  832. }
  833. .table-container {
  834. width: 100%;
  835. vertical-align: top;
  836. }
  837. }
  838. </style>