hc-data.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489
  1. <template>
  2. <div class="hc-layout-box">
  3. <HcTabsSimple :no-drop-shadow="showTaskReviewModal" :cur="sbTableKey" :datas="sbTableData" @tabClick="sbTableClick">
  4. <template #tab-key1>
  5. <TableCard
  6. v-if="sbTableKey === 'key1'" :contract-id="contractId"
  7. :contract-list="contractList"
  8. :project-id="projectId" :table-key="sbTableKey"
  9. @batchApproval="batchApprovalTaskClick" @rowTaskName="rowTaskName"
  10. @signRules="setSignRulesClick"
  11. />
  12. </template>
  13. <template #tab-key2>
  14. <TableCard
  15. v-if="sbTableKey === 'key2'" :contract-id="contractId"
  16. :contract-list="contractList"
  17. :project-id="projectId" :table-key="sbTableKey"
  18. @batchApproval="batchApprovalTaskClick" @rowTaskName="rowTaskName"
  19. @signRules="setSignRulesClick"
  20. />
  21. </template>
  22. <template #tab-key3>
  23. <TableCard
  24. v-if="sbTableKey === 'key3'" :contract-id="contractId"
  25. :contract-list="contractList"
  26. :project-id="projectId" :table-key="sbTableKey"
  27. @batchApproval="batchApprovalTaskClick" @rowTaskName="rowTaskName"
  28. @signRules="setSignRulesClick"
  29. />
  30. </template>
  31. </HcTabsSimple>
  32. <!-- 任务审核 -->
  33. <el-dialog
  34. v-model="showTaskReviewModal" class="hc-modal-border hc-modal-table" destroy-on-close draggable
  35. width="80vw"
  36. >
  37. <template #header="{ titleId, titleClass }">
  38. <div class="hc-card-header flex items-center">
  39. <div :id="titleId" :class="titleClass">
  40. 任务审核 【已开启电签】
  41. </div>
  42. <div v-if="taskReviewType === '1'" class="ml-6 font-bold text-main">
  43. 任务名称:{{ taskReviewInfo.taskName }}
  44. </div>
  45. </div>
  46. </template>
  47. <div class="hc-card-body-flex">
  48. <div v-if="batchPdfUrl" class="flex-iframe">
  49. <!-- <HcPdf :src="batchPdfUrl" @change="changeSealStrategy" /> -->
  50. <HcPdf v-if="pdfItem.pdfUrl" :sign="logoName" :src="pdfItem.pdfUrl" :dom="pdfItem.hcSignImageArr" :is-batch="isBatch" @change="pdfChange" />
  51. </div>
  52. <div v-else class="flex-iframe hc-no-table-form">
  53. <div class="table-form-no">
  54. <img :src="notableform" alt="">
  55. <div class="desc">
  56. 暂无 PDF 数据
  57. </div>
  58. </div>
  59. </div>
  60. <div :class="sbTableKey === 'key1' ? '' : 'vh'" class="flex-table">
  61. <div v-if="taskReviewType === '1'" class="data-table taskReviewData">
  62. <HcTable :column="taskReviewColumns" :datas="taskReviewData" @row-click="rowTaskReviewClick" />
  63. </div>
  64. <div v-if="taskReviewType === '2'" class="data-table checkedRowsRef">
  65. <el-button :loading="isBatchLoaing" hc-btn type="primary" @click="clickBatch">
  66. 批量电签
  67. </el-button>
  68. <HcTable :column="checkedRowsColumns" :datas="checkedRowsRef" @row-click="rowTaskReviewClick" />
  69. </div>
  70. <div v-if="sbTableKey === 'key1'" class="radio-group-box">
  71. <span class="label">审批操作:</span>
  72. <el-radio-group v-model="taskReviewForm.flag">
  73. <el-radio label="OK">
  74. 同意
  75. </el-radio>
  76. <el-radio label="NO">
  77. 废除任务
  78. </el-radio>
  79. </el-radio-group>
  80. </div>
  81. <div v-if="sbTableKey === 'key1'" class="textarea-box">
  82. <el-input
  83. v-model="taskReviewForm.comment" :autosize="{ minRows: 3, maxRows: 5 }"
  84. placeholder="请输入审核意见"
  85. type="textarea"
  86. />
  87. </div>
  88. </div>
  89. </div>
  90. <template v-if="sbTableKey === 'key1'" #footer>
  91. <div class="dialog-footer">
  92. <el-button size="large" @click="showTaskReviewModal = false">
  93. 取消
  94. </el-button>
  95. <el-button :loading="SMSAuthLoading" hc-btn type="primary" @click="ConfirmApprovalClick">
  96. 确认审批
  97. </el-button>
  98. </div>
  99. </template>
  100. </el-dialog>
  101. <!-- 设置重签规则 -->
  102. <el-dialog
  103. v-model="showSetSignRulesModal" class="hc-modal-border" destroy-on-close draggable
  104. title="设置重签规则"
  105. width="38rem"
  106. >
  107. <div class="text-orange mb-10">
  108. <span
  109. class="mr-4"
  110. >提示:设置默认时长,在任务被废除需要重签的时候,规定的重签上报时间提示时间段内,系统提示用户重签信息,但是超过处理时间,系统可默认自动授权重签</span>
  111. <el-checkbox v-model="setPactVal" label="Option 1" size="large">
  112. <span class="text-main">《授权系统自动电签协议》</span>
  113. </el-checkbox>
  114. </div>
  115. <div class="obj-item-cell">
  116. <div class="label">
  117. 默认处理时间(时)
  118. </div>
  119. <HcCounter v-model="formReport.date" @update:modelValue="dateUpdateValue" />
  120. </div>
  121. <div class="obj-item-cell">
  122. <div class="label">
  123. 开启系统自动电签
  124. </div>
  125. <el-switch v-model="formReport.active" />
  126. </div>
  127. <template #footer>
  128. <div class="dialog-footer">
  129. <el-button size="large" @click="showSetSignRulesModal = false">
  130. 取消
  131. </el-button>
  132. <el-button hc-btn type="primary">
  133. 保存
  134. </el-button>
  135. </div>
  136. </template>
  137. </el-dialog>
  138. <!-- 短信认证 -->
  139. <HcSmsAuth :loading="SMSAuthLoading" :show="SMSAuthShow" @cancel="SMSAuthCancel" @confirm="SMSAuthConfirm" />
  140. </div>
  141. </template>
  142. <script setup>
  143. import { nextTick, onMounted, ref } from 'vue'
  144. import { useAppStore } from '~src/store'
  145. import { useRoute, useRouter } from 'vue-router'
  146. import TableCard from './components/TableCard.vue'
  147. import notableform from '~src/assets/view/notableform.svg'
  148. import { getContractInfo } from '~api/other'
  149. import tasksFlowApi from '~api/tasks/flow'
  150. import { arrToKey, getArrValue, getUUID, isString } from 'js-fast-way'
  151. import tasksApi from '~api/tasks/data'
  152. import dayjs from 'dayjs'
  153. import HcPdf from './components/hc-pdf1.vue'
  154. import userApi from '~api/userInfo/index'
  155. //初始变量
  156. const router = useRouter()
  157. const useRoutes = useRoute()
  158. const useAppState = useAppStore()
  159. //路由参数
  160. const routerQuery = useRoutes?.query
  161. const activeName = routerQuery?.active || 'key1'
  162. //全局变量
  163. const projectId = ref(useAppState.getProjectId)
  164. const contractId = ref(useAppState.getContractId)
  165. const projectInfo = ref(useAppState.getProjectInfo)
  166. const sealStrategy = ref([])//签章数据列表
  167. //渲染完成
  168. onMounted(() => {
  169. checkSmsCode()
  170. getContractInfoList()
  171. })
  172. //pdf
  173. //合同段信息
  174. const contractList = ref([])
  175. const getContractInfoList = async ()=>{
  176. const { error, code, data } = await getContractInfo({
  177. pid: projectId.value,
  178. })
  179. if (!error && code === 200) {
  180. contractList.value = getArrValue(data)
  181. } else {
  182. contractList.value = []
  183. }
  184. }
  185. //类型处理
  186. const sbTableKey = ref(activeName)
  187. const sbTableData = ref([
  188. { icon: 'time', label: '待办任务', key: 'key1' },
  189. { icon: 'calendar-check', label: '已办任务', key: 'key2' },
  190. { icon: 'user-shared', label: '我发起的', key: 'key3' },
  191. ])
  192. const sbTableClick = (key) => {
  193. sbTableKey.value = key
  194. router.push({
  195. path: useRoutes.path,
  196. query: { active: key },
  197. })
  198. }
  199. //审批页详情
  200. const showTaskReviewModal = ref(false)
  201. const taskReviewType = ref('1')
  202. const taskReviewInfo = ref({})
  203. const taskReviewData = ref([])
  204. const batchPdfUrl = ref('')
  205. const taskReviewForm = ref({ flag: 'OK', comment: '' })
  206. const taskReviewColumns = ref([
  207. { key: 'fileName', name: '文件名称' },
  208. ])
  209. const pdfItem = ref({})
  210. const pdfIndex = ref(-1)
  211. const logoName = ref('')
  212. //const clickBatch
  213. const isBatchLoaing = ref(false)
  214. const isBatch = ref(false)//是否批量电签
  215. const clickBatch = async ()=>{
  216. await queryCurrentUserData()
  217. isBatch.value = true
  218. }
  219. //获取用户信息
  220. const queryCurrentUserData = async () => {
  221. const { error, code, data } = await userApi.queryCurrentUserData()
  222. if (!error && code === 200) {
  223. logoName.value = data?.signatureUrl || ''
  224. } else {
  225. logoName.value = ''
  226. }
  227. }
  228. const pdfDataClick = (item, index) => {
  229. pdfItem.value = {}
  230. pdfIndex.value = index
  231. nextTick(() => {
  232. pdfItem.value = item
  233. })
  234. }
  235. //签章数据改变
  236. const pdfChange = (data) => {
  237. // pdfData.value[pdfIndex.value].hcSignImageArr = data
  238. checkedRowsRef.value.forEach((ele)=>{
  239. if (ele.id === pdfIndex.value) {
  240. ele.hcSignImageArr = data
  241. }
  242. })
  243. console.log('签章数据', data)
  244. }
  245. //任务审核
  246. const rowTaskName = async (row) => {
  247. if (row.id) {
  248. taskReviewInfo.value = row
  249. const { error, code, data } = await tasksApi.queryTaskInfo({
  250. taskIds:row.id,
  251. })
  252. if (!error && code === 200) {
  253. const approvalFileList = getArrValue(data)
  254. taskReviewData.value = approvalFileList
  255. if (approvalFileList.length > 0) {
  256. batchPdfUrl.value = approvalFileList[0].pdfUrl
  257. }
  258. taskReviewType.value = '1'
  259. showTaskReviewModal.value = true
  260. } else {
  261. taskReviewData.value = []
  262. batchPdfUrl.value = ''
  263. }
  264. } else {
  265. taskReviewInfo.value = {}
  266. taskReviewData.value = []
  267. batchPdfUrl.value = ''
  268. window?.$message?.warning('此数据异常')
  269. }
  270. }
  271. //批量审批
  272. const checkedRowsColumns = ref([
  273. { key: 'taskName', name: '任务名称' },
  274. ])
  275. const checkedRowsRef = ref([])
  276. const taskId = ref([])
  277. const batchApprovalTaskClick = (rows) => {
  278. taskReviewType.value = '2'
  279. showTaskReviewModal.value = true
  280. checkedRowsRef.value = rows
  281. let taskids = []
  282. rows.forEach((item) => {
  283. taskids.push(item.id)
  284. })
  285. taskids = taskids.join()
  286. queryTaskInfo(rows[0], taskids)
  287. }
  288. //行被点击
  289. const rowTaskReviewClick = async ({ row }) => {
  290. const type = taskReviewType.value
  291. if (type === '1') {
  292. batchPdfUrl.value = row.pdfUrl
  293. } else if (row['hc_batchPdfUrl']) {
  294. batchPdfUrl.value = row['hc_batchPdfUrl']
  295. } else {
  296. queryTaskInfo(row)
  297. }
  298. pdfDataClick(row, row.id)
  299. }
  300. //默认点击
  301. //获取PDF数据
  302. const queryTaskInfo = async (row, taskids) => {
  303. taskId.value = taskids && taskids.length > 0 ? taskids : row['id']
  304. const { error, code, data } = await tasksApi.queryTaskInfo({
  305. taskIds: taskids && taskids.length > 0 ? taskids : row['id'],
  306. })
  307. //处理数据
  308. if (!error && code === 200) {
  309. const alldata = getArrValue(data)
  310. let approvalFileList = alldata
  311. if (approvalFileList.length > 0) {
  312. batchPdfUrl.value = approvalFileList[0].pdfUrl
  313. row['pdfUrl'] = approvalFileList[0].pdfUrl
  314. } else {
  315. batchPdfUrl.value = ''
  316. row['pdfUrl'] = ''
  317. window?.$message?.warning('PDF获取异常')
  318. }
  319. } else {
  320. batchPdfUrl.value = ''
  321. row['pdfUrl'] = ''
  322. window?.$message?.warning(data.msg || 'PDF异常')
  323. }
  324. }
  325. //确认审批
  326. const ConfirmApprovalClick = async () => {
  327. const formData = taskReviewForm.value
  328. if (formData.flag === 'NO' && !formData.comment) {
  329. window?.$message?.warning('请先输入审核意见')
  330. } else {
  331. formData.taskId = taskId.value
  332. let objarr = []
  333. checkedRowsRef.value.forEach((ele)=>{
  334. objarr.push({
  335. taskId:ele.id,
  336. comment:formData.comment,
  337. flag:formData.flag,
  338. sealStrategy:ele.hcSignImageArr,
  339. })
  340. })
  341. console.log(objarr, 'objarr')
  342. SMSAuthLoading.value = true
  343. const { error, code, msg, data } = await tasksApi.batchApproval({ taskArchiveDtoList:objarr }, false)
  344. //判断数据
  345. SMSAuthLoading.value = false
  346. if (!error && code === 200 && data === true) {
  347. const ShowAuth = isCheckSmsCodeTime()
  348. SMSAuthShow.value = ShowAuth
  349. //免短信验证
  350. if (!ShowAuth) {
  351. SMSAuthConfirm()
  352. }
  353. } else {
  354. window.$message?.warning(msg)
  355. }
  356. }
  357. }
  358. //短信验证有效期
  359. const smsCodeTime = ref('')
  360. const checkSmsCode = async () => {
  361. const { error, code, data } = await tasksApi.checkSmsCode()
  362. //处理数据
  363. if (!error && code === 200) {
  364. smsCodeTime.value = isString(data) ? data : ''
  365. } else {
  366. smsCodeTime.value = ''
  367. }
  368. }
  369. //验证短信有效期
  370. const isCheckSmsCodeTime = () => {
  371. const smsTime = smsCodeTime.value
  372. if (!smsTime) {
  373. return true
  374. } else {
  375. const toDayTime = dayjs(new Date()).format('YYYY-MM-DD HH:mm:ss')
  376. return dayjs(smsTime).isBefore(toDayTime)
  377. }
  378. }
  379. //短信验证
  380. const SMSAuthLoading = ref(false)
  381. const SMSAuthShow = ref(false)
  382. const SMSAuthConfirm = () => {
  383. const type = taskReviewType.value
  384. if (type === '1') {
  385. saveCompleteApprovalTask()
  386. } else {
  387. batchCompleteApprovalTask()
  388. }
  389. checkSmsCode()
  390. }
  391. const SMSAuthCancel = () => {
  392. SMSAuthShow.value = false
  393. }
  394. //单个审批
  395. const saveCompleteApprovalTask = async () => {
  396. const DataInfo = taskReviewInfo.value
  397. SMSAuthLoading.value = true
  398. const { error, code } = await tasksApi.saveCompleteApprovalTask({
  399. ...taskReviewForm.value,
  400. taskId: DataInfo['taskId'] || '',
  401. parallelProcessInstanceId: DataInfo['parallelProcessInstanceId'] || '',
  402. formDataId: DataInfo['formDataId'] || '',
  403. approvalType: DataInfo['approvalType'],
  404. }, false)
  405. //处理数据
  406. SMSAuthLoading.value = false
  407. if (!error && code === 200) {
  408. SMSAuthShow.value = false
  409. showTaskReviewModal.value = false
  410. window?.$message?.success('审批成功')
  411. setTimeout(() => {
  412. window?.location?.reload() //刷新页面
  413. }, 3000)
  414. } else {
  415. window?.$message?.warning('审批异常')
  416. }
  417. }
  418. //批量审批
  419. const batchCompleteApprovalTask = async () => {
  420. const rows = checkedRowsRef.value
  421. SMSAuthLoading.value = true
  422. let taskIds = arrToKey(rows, 'taskId', ',')
  423. let approvalType = arrToKey(rows, 'approvalType', ',')
  424. let formDataId = arrToKey(rows, 'formDataId', ',')
  425. let parallelProcessInstanceIds = arrToKey(rows, 'parallelProcessInstanceId', ',')
  426. const { error, code } = await tasksApi.batchCompleteApprovalTask({
  427. ...taskReviewForm.value,
  428. taskIds,
  429. approvalType,
  430. formDataId,
  431. parallelProcessInstanceIds,
  432. }, false)
  433. //处理数据
  434. SMSAuthLoading.value = false
  435. if (!error && code === 200) {
  436. SMSAuthShow.value = false
  437. showTaskReviewModal.value = false
  438. window?.$message?.success('审批成功')
  439. setTimeout(() => {
  440. window?.location?.reload() //刷新页面
  441. }, 3000)
  442. } else {
  443. window?.$message?.warning('审批出错')
  444. }
  445. }
  446. //设置重签规则
  447. const showSetSignRulesModal = ref(false)
  448. const setPactVal = ref(true)
  449. const formReport = ref({ date: 1, active: true })
  450. const setSignRulesClick = () => {
  451. showSetSignRulesModal.value = true
  452. }
  453. const dateUpdateValue = (val) => {
  454. formReport.value.date = val
  455. }
  456. </script>
  457. <style lang="scss" scoped>
  458. @import '../../styles/tasks/hc-data.scss';
  459. </style>