workbench.vue 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855
  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">{{ getWorkInfo(scope.row.subject, 'name') }}</template>
  25. <template slot="desc" slot-scope="scope">{{ getWorkInfo(scope.row.subject, '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">{{ getAttr(scope.row.subject, 'deptName') }}</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. <template slot="time" slot-scope="scope">{{ scope.row.endTime || scope.row.updateTime || scope.row.createTime }}</template>
  67. </ibps-crud>
  68. </div>
  69. </div>
  70. </el-tab-pane>
  71. </el-tabs>
  72. <bpmn-formrender
  73. :visible="dialogFormVisible"
  74. :task-id="activeTab === 'wait' ? taskId : null"
  75. :wai-jian="activeTab === 'wait' ? waiJian : null"
  76. :instance-id="['over', 'finish'].includes(activeTab) ? instanceId : null"
  77. :def-id="activeTab === 'save' ? defId : null"
  78. :pro-inst-id="activeTab === 'save' ? proInstId : null"
  79. :title="['wait', 'save'].includes(activeTab) ? FlowName : null"
  80. @callback="search"
  81. @close="visible => (dialogFormVisible = visible)"
  82. />
  83. <news-detail
  84. :id="newsId"
  85. :title="newsTitle"
  86. :visible="newsDialogVisible"
  87. readonly
  88. @close="visible => newsDialogVisible = visible"
  89. />
  90. </div>
  91. </template>
  92. <script>
  93. import { pending, handledTask } from '@/api/platform/office/bpmReceived'
  94. import { myDraft, removeDraft } from '@/api/platform/office/bpmInitiated'
  95. import { queryPageList as newsList } from '@/api/platform/system/news'
  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 NewsDetail from '@/views/platform/system/news/detail'
  100. import { tabList, taskState, stateOption, listSearchForm, listColumns } from './workbench'
  101. const operate = {
  102. wait: pending,
  103. over: handledTask,
  104. finish: handledTask,
  105. save: myDraft,
  106. news: newsList,
  107. guide: ''
  108. }
  109. export default {
  110. name: 'calendar',
  111. components: { BpmnFormrender, NewsDetail },
  112. filters: {
  113. getUserName (v, list) {
  114. const user = list.find(i => i.userId === v)
  115. return user ? user.userName : ''
  116. }
  117. },
  118. props: {
  119. plan: {
  120. type: Array,
  121. default: () => []
  122. }
  123. },
  124. data () {
  125. const { first = '', second = '' } = this.$store.getters.level || {}
  126. const level = second || first
  127. const { userList = [], deptList = [], role = [], menus = [], isSuper } = this.$store.getters || {}
  128. const allRolesMap = new Map()
  129. userList.forEach(user => {
  130. user.roleId.split(',').forEach((roleId, index) => {
  131. if (!allRolesMap.has(roleId)) {
  132. allRolesMap.set(roleId, user.roles.split(',')[index])
  133. }
  134. })
  135. })
  136. const allRoles = Array.from(allRolesMap, ([key, value]) => ({ key, value: key, label: value }))
  137. const isManager = role.some(i => i.alias === 'xtgljs') || isSuper
  138. const roleOption = isManager ? allRoles : role.map(i => ({ key: i.id, value: i.id, label: i.name }))
  139. const sysOption = menus.map(i => ({ key: i.alias, value: i.title, label: i.title })).filter(i => !['xtgl', 'xnyz'].includes(i.key))
  140. listSearchForm.guide.forms[0].value = isManager ? 'all' : 'aboutMe'
  141. listSearchForm.guide.forms[1].options = sysOption
  142. listSearchForm.guide.forms[3].options = roleOption
  143. const getGuide = ({ parameters, requestPage, sorts }) => {
  144. // 获取查询角色信息
  145. let roleParams = ''
  146. let aboutMeParams = ''
  147. const range = {
  148. aboutMe: [],
  149. sponsor: [],
  150. review: [],
  151. approve: []
  152. }
  153. const sortField = {
  154. TABLE_NO_: 'biao_dan_bian_hao'
  155. }
  156. let sortParams = 'sn_ + 0 asc'
  157. if (sorts && sorts.length) {
  158. sortParams = sorts.map(i => `${sortField[i.field]} ${i.order}`).join(',')
  159. }
  160. role.forEach(i => {
  161. range.aboutMe.push(`bian_zhi_jiao_se_ like '%${i.id}%' or shen_he_jiao_se_ like '%${i.id}%' or shen_pi_jiao_se_ like '%${i.id}%'`)
  162. range.sponsor.push(`bian_zhi_jiao_se_ like '%${i.id}%'`)
  163. range.review.push(`shen_he_jiao_se_ like '%${i.id}%'`)
  164. range.approve.push(`shen_pi_jiao_se_ like '%${i.id}%'`)
  165. })
  166. parameters.forEach(item => {
  167. if (item.key === 'range' && item.value !== 'all') {
  168. aboutMeParams = ` and (${range[item.value].join(' or ')})`
  169. }
  170. if (item.key === 'role') {
  171. roleParams = ` and (bian_zhi_jiao_se_ like '%${item.value}%')`
  172. }
  173. })
  174. // 获取查询字段
  175. let params = parameters.filter(i => i.key !== 'role' && i.key !== 'range').reduce((acc, curr) => {
  176. return `${acc} and ${curr.key} like '%${curr.value}%'`
  177. }, '')
  178. params = params + aboutMeParams + roleParams
  179. // and di_dian_ = '${level}'
  180. const sql = `select sn_ as sn, suo_shu_xi_tong_ as sysName, gong_neng_mo_kuai as module, biao_dan_ming_che as tableName, biao_dan_bian_hao as tableNo, tian_xie_shi_ji_ as timing, shi_wu_lei_xing_ as taskType, cheng_xu_wen_jian as fileName, bian_zhi_ren_ as creator, shen_he_ren_ as reviewer, shen_pi_ren_ as approver, ye_mian_lu_jing_ as path, zi_yuan_lu_jing_ as res from t_bdbhpzb where sn_ + 0 > 0 ${params} order by ${sortParams}`
  181. const { pageNo = 1, limit = 15 } = requestPage || {}
  182. return new Promise((resolve, reject) => {
  183. this.$common.request('sql', sql).then(res => {
  184. const { data = [] } = res.variables || {}
  185. const page = {
  186. limit,
  187. page: pageNo,
  188. totalCount: data.length,
  189. totalPages: Math.ceil(data.length / limit)
  190. }
  191. const result = {
  192. data: {
  193. dataResult: data.slice((pageNo - 1) * limit, pageNo * limit),
  194. pageResult: page
  195. }
  196. }
  197. resolve(result)
  198. }).catch(error => {
  199. reject(error)
  200. })
  201. })
  202. }
  203. operate.guide = getGuide
  204. return {
  205. level,
  206. tabList,
  207. stateOption,
  208. userList,
  209. deptList,
  210. menus,
  211. pkKey: 'id',
  212. taskId: '', // 编辑dialog需要使用
  213. waiJian: '', // 编辑dialog需要使用
  214. instanceId: '',
  215. defId: '',
  216. proInstId: '',
  217. newsId: '',
  218. loading: false,
  219. dialogFormVisible: false,
  220. newsDialogVisible: false,
  221. newsTitle: '公告明细',
  222. orgName: '',
  223. roleName: '',
  224. FlowName: '',
  225. posName: '',
  226. timer: null,
  227. orgInfo: {},
  228. activeTab: tabList[0].key,
  229. height: document.body.clientHeight,
  230. selection: [],
  231. defaultPagination: { page: 1, limit: 15 },
  232. sorts: { },
  233. dataList: [],
  234. pagination: {},
  235. searchParams: {
  236. typeId: '',
  237. subject: '',
  238. createTime: ''
  239. },
  240. listConfig: {
  241. searchForm: listSearchForm,
  242. toolbars: [
  243. {
  244. key: 'search'
  245. }
  246. ],
  247. darftTool: [
  248. {
  249. key: 'search'
  250. },
  251. {
  252. key: 'remove'
  253. }
  254. ],
  255. // 表格字段配置
  256. columns: listColumns
  257. }
  258. }
  259. },
  260. mounted () {
  261. this.getData(this.activeTab)
  262. if (this.timer) {
  263. clearInterval(this.timer)
  264. }
  265. // 轮询刷新公告数据和任务数据
  266. this.timer = setInterval(() => {
  267. // this.getMessage()
  268. // 仅待办事宜自动更新数据
  269. if (this.activeTab === 'wait') {
  270. this.getData(this.activeTab)
  271. }
  272. }, 30 * 1000)
  273. },
  274. beforeDestroy () {
  275. clearInterval(this.timer)
  276. },
  277. // 路由离开时
  278. beforeRouteLeave (to, from, next) {
  279. clearInterval(this.timer)
  280. },
  281. methods: {
  282. getWorkInfo (v, type) {
  283. if (!v.includes('#')) {
  284. return ''
  285. }
  286. const res = {
  287. name: v.split('#')[0],
  288. // 无#返回空,有#返回(左边的字符串,
  289. desc: v.split('#')[1] ? v.split('#')[1] : ''
  290. }
  291. return res[type]
  292. },
  293. getName ({ createBy, updateBy }) {
  294. const id = updateBy || createBy
  295. const { name = '' } = this.$store.getters || {}
  296. if (this.activeTab === 'finish') {
  297. const t = this.userList.find(i => i.userId === id)
  298. return t ? t.userName : ''
  299. }
  300. return name
  301. },
  302. getStatus (val) {
  303. const s = taskState[val]
  304. return s || '暂停'
  305. },
  306. getAttr (val, arg) {
  307. const arr = val.split('#')
  308. if (!arr[2]) {
  309. return ''
  310. }
  311. const result = JSON.parse(`{${arr[2]}}`)
  312. if (!result.dept) {
  313. return ''
  314. }
  315. const depts = result.dept.split(',')
  316. const deptNames = []
  317. depts.forEach(item => {
  318. const t = this.deptList.find(i => i.positionId === item)
  319. deptNames.push(t ? t.positionName : result.dept)
  320. })
  321. result.deptName = deptNames.join(',')
  322. return result[arg]
  323. },
  324. getDept (v, arg = 'positionName') {
  325. if (!v) {
  326. return ''
  327. }
  328. const t = this.deptList.find(i => i.positionId === v)
  329. return t ? t[arg] : ''
  330. },
  331. tableRowClassName ({ row, rowIndex }) {
  332. if (rowIndex % 2 === 1) return 'warning-row'
  333. return 'success-row'
  334. },
  335. // 获取表格数据
  336. getData (type) {
  337. this.loading = true
  338. const pageParams = this.pagination && this.pagination.page ? this.pagination : this.defaultPagination
  339. operate[this.activeTab](this.getFormatParams(null, pageParams)).then(response => {
  340. const { dataResult, pageResult } = response.data
  341. // 待办事宜对任务发起人做额外处理
  342. if (type === 'wait') {
  343. const instList = []
  344. dataResult.forEach(item => {
  345. instList.push(item.bpmnInstId)
  346. })
  347. 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.length ? instList.join(',') : `''`}) order by find_in_set(b.bpmn_inst_id_,'${instList.join(',')}')`
  348. const currentTime = Date.now()
  349. this.$common.request('sql', sql).then(res => {
  350. const data = res.variables && res.variables.data
  351. data.forEach((item, index) => {
  352. dataResult[index].submitBy = item.name_
  353. dataResult[index].workName = this.getWorkInfo(dataResult[index].subject, 'name')
  354. dataResult[index].workDesc = this.getWorkInfo(dataResult[index].subject, 'desc')
  355. dataResult[index].workType = this.plan.includes(dataResult[index].procDefKey) ? 'plan' : 'normal'
  356. const limit = this.getAttr(dataResult[index].subject, 'loseDate') || this.getAttr(dataResult[index].subject, 'timeLimit') || 3
  357. dataResult[index].state = this.judgeExpire(dataResult[index].createTime, currentTime, dataResult[index].workType, limit)
  358. })
  359. this.dataList = dataResult.sort((a, b) => b.createTime.localeCompare(a.createTime))
  360. this.pagination = pageResult
  361. })
  362. this.urgeToManager()
  363. } else {
  364. this.dataList = dataResult
  365. this.pagination = pageResult || {}
  366. }
  367. this.loading = false
  368. }).catch(() => {
  369. // 请求出错清除轮询
  370. if (type === 'wait') {
  371. clearInterval(this.timer)
  372. }
  373. this.loading = false
  374. })
  375. },
  376. // 延迟更新列表数据
  377. updateList () {
  378. setTimeout(() => {
  379. this.getData(this.activeTab)
  380. }, 750)
  381. },
  382. // 查询
  383. search () {
  384. this.dataList = []
  385. this.pagination = {}
  386. this.getData(this.activeTab)
  387. },
  388. handleChange (activeName, oldActiveName) {
  389. // this.$refs[oldActiveName][0].handleReset()
  390. },
  391. // 切换tab
  392. changeTab () {
  393. // 数据、筛选条件初始化
  394. this.dataList = []
  395. this.selection = []
  396. this.pagination = { }
  397. this.$nextTick(() => {
  398. this.getData(this.activeTab)
  399. })
  400. },
  401. handleSortChange (sort) {
  402. console.log(sort)
  403. ActionUtils.setSorts(this.sorts, sort)
  404. this.getData(this.activeTab)
  405. },
  406. handlePaginationChange (page) {
  407. ActionUtils.setPagination(this.pagination, page)
  408. this.getData(this.activeTab)
  409. },
  410. getFormatParams (v, page) {
  411. const params = this.$refs[this.activeTab] && this.$refs[this.activeTab].length ? this.$refs[this.activeTab][0].getSearcFormData() : {}
  412. if (this.activeTab === 'finish') {
  413. params.end = '1'
  414. }
  415. if (this.activeTab === 'news') {
  416. // 公告限制显示当前医院且状态为已发布的数据,过滤草稿及失效公告
  417. params['Q^type_^SL'] = this.level
  418. params['Q^status_^SL'] = 'publish'
  419. }
  420. let pageParams
  421. if (this.activeTab === 'guide') {
  422. pageParams = { ...page, limit: 100 }
  423. } else {
  424. pageParams = page
  425. }
  426. // const s = this.activeTab === 'news' ? this.sorts { 'PUBLIC_DATE_': 'DESC' } : this.sorts
  427. return ActionUtils.formatParams(params, pageParams, this.sorts)
  428. },
  429. // 处理表格点击事件
  430. handleRowClick (data) {
  431. if (this.activeTab === 'guide') {
  432. const { res = '' } = data
  433. if (!res) {
  434. this.$message.warning('未配置资源菜单!')
  435. return
  436. }
  437. const path = '/' + this.findPagePath(res)
  438. this.$router.push(path)
  439. return
  440. }
  441. if (this.activeTab === 'news') {
  442. this.newsId = data.id
  443. this.newsDialogVisible = true
  444. this.newsTitle = data.title
  445. return
  446. }
  447. this.taskId = data.id || ''
  448. this.waiJian = data.waiJian || ''
  449. this.instanceId = data.id || ''
  450. this.defId = data.procDefId || ''
  451. this.proInstId = data.id || ''
  452. this.FlowName = data.name
  453. this.dialogFormVisible = true
  454. },
  455. handleAction (command, position, selection, data) {
  456. switch (command) {
  457. case 'search':// 查询
  458. ActionUtils.setFirstPagination(this.pagination || {})
  459. this.search()
  460. break
  461. case 'remove':// 删除
  462. if (!data || !data.length) {
  463. this.$message.warning('请选择数据!')
  464. return
  465. }
  466. if (data.length > 20) {
  467. this.$message.warning('单次最多只能删除二十条!')
  468. return
  469. }
  470. this.handleRemove(data, selection)
  471. break
  472. default:
  473. break
  474. }
  475. },
  476. // 删除暂存数据
  477. handleRemove (datas, selection) {
  478. this.$confirm('将删除选中暂存记录与对应数据表数据,删除之后无法恢复, 是否确定?', '提示', {
  479. confirmButtonText: '确定',
  480. cancelButtonText: '取消',
  481. type: 'warning',
  482. showClose: false,
  483. closeOnClickModal: false
  484. }).then(() => {
  485. const defKeyArr = []
  486. const delList = {}
  487. const idList = []
  488. datas.forEach(item => {
  489. const { id, bizKey, procDefKey } = item
  490. idList.push(id)
  491. if (!delList[procDefKey]) {
  492. delList[procDefKey] = []
  493. defKeyArr.push(procDefKey)
  494. }
  495. delList[procDefKey].push(bizKey)
  496. })
  497. console.log(idList, delList, defKeyArr)
  498. const sql = `select bo_code_, def_key_ from ibps_bpm_def where find_in_set(def_key_, '${defKeyArr.join(',')}')`
  499. // const sql = `select a.bo_code_, b.key_ from ibps_form_bo a, ibps_form_def b where a.form_id_ = b.id_ and find_in_set(b.key_, '${formKeyArr.join(',')}')`
  500. this.$common.request('sql', sql).then(res => {
  501. const { data = [] } = res.variables || {}
  502. if (!data.length) {
  503. return
  504. }
  505. const codes = {}
  506. data.forEach(item => {
  507. const { bo_code_, def_key_ } = item
  508. codes[def_key_] = bo_code_
  509. })
  510. // 删除选中记录
  511. removeDraft({ ids: idList.join(',') }).then(() => {
  512. ActionUtils.removeSuccessMessage()
  513. this.selection = []
  514. // 循环删除对应数据表数据
  515. defKeyArr.forEach(k => {
  516. const deleteParams = {
  517. tableName: `t_${codes[k]}`,
  518. paramWhere: { id_: delList[k].join(',') }
  519. }
  520. this.$common.request('delete', deleteParams, 'post', true)
  521. })
  522. this.$message.success('删除成功!')
  523. this.search()
  524. })
  525. }).catch(() => {
  526. this.$message.error('获取数据表key值出错,请联系开发人员!')
  527. })
  528. })
  529. },
  530. // 数组去重
  531. unique (arr) {
  532. const res = new Map()
  533. return arr.filter(arr => !res.has(arr.id) && res.set(arr.id, 1))
  534. },
  535. /**
  536. * 主管提醒
  537. * 数据处理,将所有待办数据根据是否过期处理为两个数组
  538. * 过期判断依据:普通事务-创建时间到当前时间超过三天即为过期;计划事务【事务名称中含计划】-创建当月月末前七天
  539. * 逻辑说明:过期数组中不存于在主管提醒表中的数据插入主管提醒表,并发送内部通知,主管提醒表删除不存在于未过期数组中的数据
  540. */
  541. urgeToManager () {
  542. const { userId } = this.$store.getters
  543. const params = {
  544. parameters: [],
  545. sorts: []
  546. }
  547. const sql = `select id_, shi_wu_id_ as taskId from t_gqswb where position('${userId}' in chu_li_ren_id_)`
  548. // Promise.all([pending(params), this.$common.request('sql', sql)]).then(([res1, res2]) => {
  549. // let workData = res1.data && res1.data.dataResult
  550. // let noticeData = res2.variables && res2.variables.data
  551. // if (!workData || !workData.length) {
  552. // return
  553. // }
  554. // this.dealData(workData, noticeData)
  555. // })
  556. pending(params).then(res1 => {
  557. const workData = res1.data && res1.data.dataResult
  558. this.$common.request('sql', sql).then(res2 => {
  559. const noticeData = res2.variables && res2.variables.data
  560. if (!workData || !workData.length) {
  561. return
  562. }
  563. this.dealData(workData, noticeData)
  564. })
  565. })
  566. },
  567. // 处理数据
  568. dealData (workList, noticeList) {
  569. const result = {
  570. expire: [],
  571. unexpire: [],
  572. all: []
  573. }
  574. const currentTime = Date.now()
  575. // 筛选已过期数据
  576. workList.forEach(item => {
  577. // 截取流程名
  578. item.workName = this.getWorkInfo(item.subject, 'name')
  579. item.workDesc = this.getWorkInfo(item.subject, 'desc')
  580. item.workType = this.plan.includes(item.procDefKey) ? 'plan' : 'normal'
  581. item.deptId = this.getAttr(item.subject, 'dept')
  582. item.state = this.judgeExpire(item.createTime, currentTime, item.workType, limit)
  583. const limit = this.getAttr(item.subject, 'loseDate') || this.getAttr(item.subject, 'timeLimit')
  584. if (['overtime', 'soon'].includes(item.state)) {
  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. * 判断是否过期、获取办理状态
  603. * @param {string} time 比较时间
  604. * @param {number} current 当前时间戳
  605. * @param {string} type 事务类型
  606. * @param {string} limit 限时,值分为两种类型,传值为字符串格式的时间时,判定逻辑为当前时间小于该时间,传值为字符串类型数字时,判定逻辑为创建limit天后,大于当前时间
  607. * @param {string} isState 调用类型
  608. */
  609. judgeExpire (time, current, type, limit) {
  610. const D = new Date(time)
  611. const a = new Date(time).getTime()
  612. const b = new Date(current).getTime()
  613. const l = limit || 3
  614. // 创建时间当月最后一天的时间戳
  615. const c = new Date(D.getFullYear(), D.getMonth() + 1, 0).getTime() + 86400000
  616. const isDate = l.toString().includes('-')
  617. // 返回办理状态
  618. let state = ''
  619. if (type === 'plan') {
  620. const M = isDate ? new Date(l).getTime() : c
  621. state = b >= M ? 'overtime' : b + (86400000 * 7) > M ? 'soon' : 'wait'
  622. } else {
  623. if (isDate) {
  624. const L = new Date(l).getTime()
  625. state = b >= L ? 'overtime' : 'wait'
  626. } else {
  627. state = a + (86400000 * parseInt(l)) < b ? 'overtime' : 'wait'
  628. }
  629. }
  630. return state
  631. },
  632. // 处理已过期数据
  633. dealExpile (data, noticeList) {
  634. // console.log('已过期流程数据:', data)
  635. // console.log('过期事务表数据:', noticeList)
  636. const { userId } = this.$store.getters
  637. const addList = []
  638. const sendList = []
  639. const msgContent = {
  640. soon: '即将超时,请及时处理!',
  641. overtime: '已超时,请及时处理!'
  642. }
  643. const msgTitle = {
  644. soon: '计划事务即将到期提醒',
  645. overtime: '事务超时提醒'
  646. }
  647. const nowTime = new Date(new Date().getTime() + 28800000).toJSON().slice(0, 16).replace('T', ' ')
  648. data.forEach(item => {
  649. const isExist = !!noticeList.find(i => i.taskId === item.taskId)
  650. // 筛选出不存在于主管提醒表的过期数据
  651. if (!isExist) {
  652. const obj = {
  653. // 事务ID
  654. shi_wu_id_: item.taskId,
  655. // 完整名称
  656. wan_zheng_ming_ch: item.subject,
  657. // 事务说明
  658. shi_wu_shuo_ming_: item.workDesc,
  659. // 事务名称
  660. shi_wu_ming_cheng: item.workName,
  661. // 事务状态
  662. shi_wu_zhuang_tai: `待${item.name}`,
  663. // 事务类型
  664. shi_wu_lei_xing_: item.workType,
  665. chu_li_ren_ming_: item.ownerName,
  666. chu_li_ren_id_: this.getInfoByName(item.ownerName, 'id'),
  667. chu_li_ren_dian_h: this.getInfoByName(item.ownerName, 'phone'),
  668. bu_men_: this.getDept(item.deptId),
  669. bu_men_id_: item.deptId,
  670. zhu_guan_id_: this.getDept(item.deptId, 'managerId'),
  671. zhu_guan_dian_hua: this.getInfoByName(this.getDept(item.deptId, 'manager'), 'phone'),
  672. bian_zhi_shi_jian: item.createTime,
  673. ti_xing_ci_shu_: 1,
  674. duan_xin_ci_shu_: 0,
  675. ti_xing_shi_jian_: nowTime,
  676. guo_qi_zhuang_tai: item.state
  677. }
  678. addList.push(obj)
  679. const msg = {
  680. subject: msgTitle[item.state],
  681. content: `${item.workName}【${item.workDesc}】${msgContent[item.state]}`,
  682. receiverId: userId,
  683. canreply: '0',
  684. taskId: item.taskId
  685. }
  686. sendList.push(msg)
  687. }
  688. })
  689. const addParams = {
  690. tableName: 't_gqswb',
  691. paramWhere: addList
  692. }
  693. // console.log('新增过期事务表数据:', addList, '发送消息数据', sendList)
  694. if (addList.length) {
  695. this.$common.request('add', addParams)
  696. }
  697. if (sendList.length) {
  698. this.sendMsg(sendList)
  699. }
  700. },
  701. // 删除已办的提醒表数据
  702. dealUnexpile (data, noticeList) {
  703. // 清除存在于主管提醒表中【处理人含我】,但是不存在于待办中的数据
  704. const deleteList = []
  705. noticeList.forEach(item => {
  706. const isExist = !!data.find(i => i.taskId === item.taskId)
  707. if (!isExist) {
  708. deleteList.push(item.id_)
  709. }
  710. })
  711. // console.log('过期事务表中需删除的数据:', deleteList)
  712. if (!deleteList.length) {
  713. return
  714. }
  715. const params = {
  716. tableName: 't_gqswb',
  717. paramWhere: {
  718. id_: deleteList.join(',')
  719. }
  720. }
  721. this.$common.request('delete', params, 'post', true).then(() => {}).catch(err => {
  722. console.log(err)
  723. })
  724. },
  725. // 发送站内消息
  726. sendMsg (data) {
  727. data.forEach(item => {
  728. save(item).then(() => {}).catch(err => {
  729. console.log(err)
  730. })
  731. })
  732. },
  733. // 通过名字获取id/电话
  734. getInfoByName (names, type) {
  735. const res = {
  736. id: [],
  737. phone: []
  738. }
  739. const temp = names.split(',')
  740. temp.forEach(item => {
  741. const t = this.userList.find(i => i.userName === item)
  742. if (t) {
  743. res.id.push(t.userId)
  744. res.phone.push(t.phone)
  745. }
  746. })
  747. return res[type].filter(i => i).join(',')
  748. },
  749. findPagePath (res) {
  750. const resList = res.split('.')
  751. const findAlias = (nodes, path) => {
  752. const [currentId, ...rest] = path
  753. const node = nodes.find(n => n.id === currentId)
  754. return node && rest.length ? [node.alias, ...findAlias(node.children, rest)] : node && [node.alias]
  755. }
  756. this.$store.dispatch('ibps/menu/activeHeaderSet', { activeHeader: resList[0], vm: this })
  757. return findAlias(this.menus, resList).join('/')
  758. }
  759. }
  760. }
  761. </script>
  762. <style lang="scss" scoped>
  763. ::v-deep .el-table__row {
  764. cursor: pointer;
  765. }
  766. ::v-deep .el-tabs__header {
  767. margin-bottom: 0;
  768. }
  769. .el-completing {
  770. background: #409eff !important;
  771. }
  772. .el-col {
  773. min-height: 1px;
  774. }
  775. .firstcol {
  776. padding-right: 10px;
  777. }
  778. .el-nothing {
  779. font-size: 13px;
  780. }
  781. .calendar-day {
  782. text-align: center;
  783. color: #202535;
  784. line-height: 30px;
  785. font-size: 12px;
  786. }
  787. .is-selected {
  788. color: #f8a535;
  789. font-size: 10px;
  790. margin-top: 5px;
  791. }
  792. #calendar .el-button-group > .el-button:not(:first-child):not(:last-child):after {
  793. content: '当月';
  794. }
  795. #calendar .item {
  796. position: relative;
  797. margin: 0;
  798. padding: 0;
  799. height: auto;
  800. border-radius: 4px;
  801. -webkit-box-sizing: border-box;
  802. box-sizing: border-box;
  803. overflow: hidden;
  804. color: #f8a535;
  805. }
  806. .ibps-list-split .ibps-list-item {
  807. border-bottom: 1px solid #dcdfe6;
  808. padding: 6px 0;
  809. }
  810. .jbd-font-style {
  811. font-weight: bold;
  812. }
  813. .home-text-border {
  814. color: #999999;
  815. 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);
  816. min-height: 20px;
  817. font-size: 14px;
  818. margin-left: 60px;
  819. margin-bottom: 5px;
  820. }
  821. .jbd-home-card {
  822. overflow: auto;
  823. }
  824. .jbd-home-task {
  825. width: 100%;
  826. padding: 10px;
  827. cursor: pointer;
  828. font-size: 12px;
  829. margin-bottom: 35px;
  830. }
  831. .jbd-home-card::-webkit-scrollbar {
  832. display: none;
  833. }
  834. .jbd-control-cont {
  835. text-align: center;
  836. position: absolute;
  837. z-index: 10;
  838. right: 0px;
  839. top: 50%;
  840. }
  841. .tab-container {
  842. height: calc(100vh - 160px);
  843. min-height: 600px;
  844. >div {
  845. display: inline-block;
  846. }
  847. .table-container {
  848. width: 100%;
  849. vertical-align: top;
  850. }
  851. }
  852. </style>