index.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  1. <template>
  2. <z-paging class="hc-task-page" ref="pageRef" v-model="taskList" @query="getTaskList">
  3. <template #top>
  4. <view class="hc-paging-top-bar">
  5. <view class="task-nav-bar">
  6. <view class="segmented-bar">
  7. <template v-for="item in taskTypeData">
  8. <view class="task-tab-item"
  9. :class="item.key === taskType?'task-cur':''"
  10. @click="taskTypeChange(item)"
  11. >{{item.name}}</view>
  12. </template>
  13. </view>
  14. <view class="more-bar" v-if="taskType === 1 && taskList.length > 0" @click="moreBarClick">
  15. <text class="i-ri-more-2-fill icon"/>
  16. </view>
  17. </view>
  18. <view class="controls-bar-box">
  19. <view class="controls-bar">
  20. <view class="left">
  21. <text class="i-ri-filter-fill icon" :class="isControlsFilter?'cur':''" @click="dateFilterClick"/>
  22. <text class="i-ri-filter-off-fill icon" @click="dateFilterClear"/>
  23. </view>
  24. <view class="right">
  25. <text class="i-ri-sort-desc icon" :class="searchForm.ordType === 1?'cur':''" @click="changeOrdType(1)"/>
  26. <text class="i-ri-sort-asc icon" :class="searchForm.ordType === 2?'cur':''" @click="changeOrdType(2)"/>
  27. </view>
  28. </view>
  29. <view class="controls-filter" v-show="isControlsFilter">
  30. <view class="search-form-date">
  31. <picker class="search-date-input" mode="date" :value="searchForm.startTime" @change="startDateChange">
  32. <view class="content">
  33. <view class="text">{{searchForm.startTime??'点此选择开始日期'}}</view>
  34. <text class="i-ri-close-circle-line icon" v-if="searchForm.startTime" @click.stop="startDateClear"/>
  35. </view>
  36. </picker>
  37. </view>
  38. <view class="search-form-date">
  39. <picker class="search-date-input" mode="date" :value="searchForm.endTime" @change="endDateChange">
  40. <view class="content">
  41. <view class="text">{{searchForm.endTime??'点此选择结束日期'}}</view>
  42. <text class="i-ri-close-circle-line icon" v-if="searchForm.endTime" @click.stop="endDateClear"/>
  43. </view>
  44. </picker>
  45. </view>
  46. <button class="search-form-btn" type="primary" size="mini" @click="searchClick">查询</button>
  47. </view>
  48. </view>
  49. </view>
  50. </template>
  51. <!--任务列表-->
  52. <uni-card v-for="item in taskList" padding="0" :class="item.check?'is-check':''" @click="taskItemClick(item)">
  53. <view class="py-3 text-30 text-black">{{item.taskName}}</view>
  54. <view slot="actions" class="card-actions no-border">
  55. <view class="card-actions-item">
  56. <view class="item-icon-check" v-if="showCheck">
  57. <uni-icons type="checkbox-filled" size="26" color="#ee5b20" v-if="item.check"/>
  58. <uni-icons type="checkbox" size="26" color="#9a9a9a" v-else/>
  59. </view>
  60. <text>{{item.startTime}}提交的申请</text>
  61. </view>
  62. <view class="card-actions-item">
  63. <uni-icons type="calendar" size="18" color="#EE5B20"/>
  64. <text class="card-actions-item-text" style="color: #EE5B20;">审批</text>
  65. </view>
  66. </view>
  67. </uni-card>
  68. </z-paging>
  69. </template>
  70. <script setup>
  71. import {ref, watch} from "vue";
  72. import mainApi from '~api/tasks/data';
  73. import {errorToast, successToast} from "@/utils/tools";
  74. import {arrToKey, getArrValue, getObjValue} from "js-fast-way";
  75. import {useAppStore} from "@/store";
  76. //初始变量
  77. const store = useAppStore()
  78. const projectId = ref(store.projectId);
  79. const contractId = ref(store.contractId);
  80. const pageRef = ref(null)
  81. //顶部类型切换
  82. const taskType = ref(2)
  83. const taskTypeData = [
  84. {key: 1, name: '我的审批'},
  85. {key: 2, name: '我发起的'},
  86. {key: 3, name: '已办结的'}
  87. ]
  88. const taskTypeChange = ({key}) => {
  89. taskType.value = key
  90. searchClick()
  91. }
  92. //批量操作
  93. const showCheck = ref(false)
  94. const moreBarClick = () => {
  95. showCheck.value = !showCheck.value
  96. }
  97. //日期选择器弹出框
  98. const isControlsFilter = ref(false)
  99. //监听顶部高度变化
  100. watch(isControlsFilter, (res) => {
  101. pageRef.value?.updatePageScrollTopHeight()
  102. })
  103. //监听底部高度变化
  104. watch(showCheck, (res) => {
  105. pageRef.value?.updatePageScrollBottomHeight()
  106. })
  107. const dateFilterClick = () => {
  108. isControlsFilter.value = !isControlsFilter.value
  109. }
  110. const dateFilterClear = () => {
  111. isControlsFilter.value = false
  112. searchForm.value.startTime = null
  113. searchForm.value.endTime = null
  114. searchClick()
  115. }
  116. //开启日期选择完毕
  117. const startDateChange = (e) => {
  118. const val = e.detail.value, endTime = searchForm.value.endTime
  119. if (endTime && val && val > endTime) {
  120. errorToast('开始日期不能大于结束日期', 2000)
  121. return false
  122. } else {
  123. searchForm.value.startTime = val
  124. }
  125. }
  126. const startDateClear = () => {
  127. searchForm.value.startTime = null
  128. }
  129. //结束日期选择完毕
  130. const endDateChange = (e) => {
  131. const val = e.detail.value, startTime = searchForm.value.startTime
  132. if (startTime && val && val < startTime) {
  133. errorToast('结束日期不能小于开始日期', 2000)
  134. return false
  135. } else {
  136. searchForm.value.endTime = val
  137. }
  138. }
  139. const endDateClear = () => {
  140. searchForm.value.endTime = null
  141. }
  142. //条件搜索
  143. const searchClick = () => {
  144. pageRef.value?.reload()
  145. }
  146. //排序切换
  147. const changeOrdType = (type) => {
  148. searchForm.value.ordType = type
  149. searchClick()
  150. }
  151. //搜索表单
  152. const searchForm = ref({
  153. startTime: null, endTime: null, ordType: 1
  154. })
  155. //获取任务列表数据
  156. const taskList = ref([])
  157. const getTaskList = async (pageNo, pageSize) => {
  158. let task_type = taskType.value, res = {};
  159. uni.showLoading({title: '获取数据中...', mask: true});
  160. if (task_type === 1) {
  161. const { data } = await mainApi.queryUserToDoTaskList({
  162. projectId: projectId.value,
  163. contractId: contractId.value,
  164. ...searchForm.value,
  165. current: pageNo,
  166. size: pageSize,
  167. })
  168. res = getObjValue(data)
  169. } else if (task_type === 2) {
  170. const { data } = await mainApi.queryUserStartFlow({
  171. projectId: projectId.value,
  172. contractId: contractId.value,
  173. ...searchForm.value,
  174. current: pageNo,
  175. size: pageSize,
  176. })
  177. res = getObjValue(data)
  178. } else if (task_type === 3) {
  179. const { data } = await mainApi.queryUserDoneTaskList({
  180. projectId: projectId.value,
  181. contractId: contractId.value,
  182. ...searchForm.value,
  183. current: pageNo,
  184. size: pageSize,
  185. })
  186. res = getObjValue(data)
  187. }
  188. uni.hideLoading();
  189. pageRef.value?.complete(getArrValue(res?.records));
  190. if (isAllCheck.value) {
  191. isAllCheck.value = itemCheckIndex.value === taskList.value.length
  192. }
  193. }
  194. //任务被点击
  195. const itemCheckIndex = ref(0)
  196. const taskItemClick = (item) => {
  197. if (showCheck.value) {
  198. const check = !item.check, list = taskList.value
  199. if (check) {
  200. itemCheckIndex.value++
  201. } else {
  202. itemCheckIndex.value--
  203. }
  204. item.check = check
  205. isAllCheck.value = list.length === itemCheckIndex.value
  206. } else {
  207. toTaskDetail([item])
  208. }
  209. }
  210. //全选
  211. const isAllCheck = ref(false)
  212. const allCheckClick = () => {
  213. uni.showLoading({title: '处理中...', mask: true});
  214. const list = taskList.value, isCheck = !isAllCheck.value
  215. for (let i = 0; i < list.length; i++) {
  216. list[i].check = isCheck;
  217. }
  218. itemCheckIndex.value = isCheck ? list.length : 0
  219. isAllCheck.value = isCheck
  220. uni.hideLoading();
  221. }
  222. //取消操作
  223. const cancelCheckClick = () => {
  224. const list = taskList.value
  225. for (let i = 0; i < list.length; i++) {
  226. list[i].check = false;
  227. }
  228. itemCheckIndex.value = 0
  229. showCheck.value = false
  230. }
  231. //批量审批
  232. const batchApproval = () => {
  233. let rows = taskList.value.filter((item) => {
  234. return item.check
  235. })
  236. if (rows.length <= 0) {
  237. errorToast('请选择需要审批的任务')
  238. return false
  239. }
  240. //路由跳转
  241. toTaskDetail(rows)
  242. }
  243. //跳转任务详情
  244. const toTaskDetail = (rows) => {
  245. uni.navigateTo({
  246. url: '/pages/task/detail',
  247. events: {
  248. finish: () => {
  249. searchClick();
  250. }
  251. },
  252. success: (res) => {
  253. res.eventChannel.emit('data', {
  254. rows: rows,
  255. //是否可以审批
  256. isTask: taskType.value === 1
  257. })
  258. }
  259. });
  260. }
  261. //批量废除
  262. const popupRef = ref(null)
  263. const argument = ref('')
  264. const cancelTaskList = ref([])
  265. const cancelTaskClick = () => {
  266. cancelTaskList.value = []
  267. let rows = taskList.value.filter((item) => {
  268. return item.check
  269. })
  270. if (rows.length <= 0) {
  271. errorToast('请选择需要废除的任务')
  272. return false
  273. }
  274. cancelTaskList.value = rows
  275. argument.value = ''
  276. popupRef.value?.open()
  277. }
  278. //确认废除
  279. const confirmRepeal = () => {
  280. if (!argument.value) {
  281. errorToast('请先填写废除理由')
  282. return false
  283. }
  284. batchCompleteApprovalTaskApi(cancelTaskList.value)
  285. }
  286. //批量废除接口
  287. const batchCompleteApprovalTaskApi = async (rows) => {
  288. uni.showLoading({title: '批量废除中...', mask: true});
  289. let taskIds = arrToKey(rows, 'taskId', ',')
  290. let approvalType = arrToKey(rows, 'approvalType', ',')
  291. let formDataId = arrToKey(rows, 'formDataId', ',')
  292. let parallelProcessInstanceIds = arrToKey(rows, 'parallelProcessInstanceId', ',')
  293. const {error, code, msg} = await mainApi.batchCompleteApprovalTask({
  294. flag: 'NO',
  295. comment: argument.value,
  296. taskIds: taskIds,
  297. approvalType: approvalType,
  298. formDataId: formDataId,
  299. parallelProcessInstanceIds: parallelProcessInstanceIds,
  300. })
  301. uni.hideLoading();
  302. if (!error && code === 200) {
  303. successToast('废除成功')
  304. cancelClick()
  305. searchClick()
  306. } else {
  307. errorToast(`废除失败:${msg}`)
  308. }
  309. }
  310. //取消废除
  311. const cancelClick = () => {
  312. popupRef.value?.close()
  313. argument.value = ''
  314. }
  315. </script>
  316. <style lang="scss" scoped>
  317. page {
  318. background: #EFEFF4;
  319. height: 100%;
  320. }
  321. </style>
  322. <style lang="scss">
  323. @import "@/style/task/index.scss";
  324. </style>