index.vue 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516
  1. <template>
  2. <div :class="ui" class="hc-tasks-user">
  3. <div class="tasks-user-box" :class="disabled ? 'no-check' : ''">
  4. <div class="tag-user-list" @click="showModalClick">
  5. <template v-for="(item, index) in UserDataList" :key="index">
  6. <el-tag>{{ setCheckboxUserName(item) }}</el-tag>
  7. <HcIcon v-if="(UserDataList.length - 1) > index" name="arrow-right" ui="arrow-icon-tag" />
  8. </template>
  9. <div v-if="UserDataList.length <= 0" class="tasks-placeholder">
  10. <span v-if="!isChangePopele"> 点击这里选择任务人</span>
  11. <span v-else> 点击这里选择整改人</span>
  12. </div>
  13. </div>
  14. </div>
  15. <!-- 选择任务人 -->
  16. <hc-new-dialog v-model="showModal" title="选择任务人" widths="62rem">
  17. <div class="hc-tasks-user-modal-content-box">
  18. <div class="tree-box">
  19. <el-scrollbar>
  20. <ElTree
  21. v-if="isShowTree"
  22. :data="ElTreeData" :default-expanded-keys="[0]" :props="ElTreeProps" accordion
  23. class="hc-tree-node-box" highlight-current node-key="roleId"
  24. @node-click="ElTreeNodeClick"
  25. />
  26. </el-scrollbar>
  27. </div>
  28. <div class="user-box">
  29. <div class="y-user-list-box">
  30. <div class="title-box">
  31. <div class="title">
  32. 可选择
  33. </div>
  34. </div>
  35. <div class="user-list">
  36. <el-scrollbar>
  37. <el-checkbox-group v-model="checkboxUserList">
  38. <template v-for="item in signUserList">
  39. <div class="user-item checkbox-li">
  40. <el-checkbox
  41. :label="`${item.certificateUserName}-${item.certificateUserId}`"
  42. >
  43. <div class="item-user-name">
  44. {{ item.certificateUserName }}
  45. </div>
  46. </el-checkbox>
  47. </div>
  48. </template>
  49. </el-checkbox-group>
  50. </el-scrollbar>
  51. </div>
  52. </div>
  53. <div class="s-user-list-box">
  54. <div class="title-box">
  55. <div class="title">
  56. 已选择({{ checkboxUserList.length }})
  57. </div>
  58. <el-button plain size="small" @click="sequenceModal = true">
  59. 调整顺序
  60. </el-button>
  61. </div>
  62. <div class="user-list">
  63. <el-scrollbar>
  64. <template v-for="(item, index) in checkboxUserList" :key="index">
  65. <el-tag closable @close="delCheckboxUser(index)">
  66. {{ setCheckboxUserName(item) }}
  67. </el-tag>
  68. </template>
  69. </el-scrollbar>
  70. </div>
  71. </div>
  72. </div>
  73. </div>
  74. <template #footer>
  75. <div class="dialog-footer">
  76. <el-button size="large" @click="showModal = false">
  77. <HcIcon name="close" />
  78. <span>取消</span>
  79. </el-button>
  80. <el-button :loading="sureSignUserLoading" hc-btn type="primary" @click="sureSignUserClick">
  81. <HcIcon name="check" />
  82. <span>确定</span>
  83. </el-button>
  84. </div>
  85. </template>
  86. </hc-new-dialog>
  87. <!-- 调整顺序 -->
  88. <hc-new-dialog v-model="sequenceModal" title="调整顺序" widths="38rem">
  89. <el-alert :closable="false" title="可拖动排序,也可在后面点击图标,切换排序" type="warning" />
  90. <div class="sort-node-body-box list-group header">
  91. <div class="list-group-item">
  92. <div class="index-box">
  93. 序号
  94. </div>
  95. <div class="title-box">
  96. 任务人
  97. </div>
  98. <div class="icon-box">
  99. 排序
  100. </div>
  101. </div>
  102. </div>
  103. <Draggable
  104. :list="checkboxUserList" class="sort-node-body-box list-group" ghost-class="ghost" item-key="id"
  105. @end="sortNodeDrag = false" @start="sortNodeDrag = true"
  106. >
  107. <template #item="{ element, index }">
  108. <div class="list-group-item">
  109. <div class="index-box">
  110. {{ index + 1 }}
  111. </div>
  112. <div class="title-box">
  113. {{ setCheckboxUserName(element) }}
  114. </div>
  115. <div class="icon-box">
  116. <span class="icon" @click="downSortClick(index)">
  117. <HcIcon name="arrow-down" ui="text-lg" />
  118. </span>
  119. <span class="icon" @click="upSortClick(index)">
  120. <HcIcon name="arrow-up" ui="text-lg" />
  121. </span>
  122. </div>
  123. </div>
  124. </template>
  125. </Draggable>
  126. <template #footer>
  127. <div class="dialog-footer">
  128. <el-button size="large" @click="sequenceModal = false">
  129. 取消
  130. </el-button>
  131. <el-button hc-btn type="primary" @click="sequenceModal = false">
  132. 确认
  133. </el-button>
  134. </div>
  135. </template>
  136. </hc-new-dialog>
  137. </div>
  138. </template>
  139. <script setup>
  140. import { onMounted, ref, watch } from 'vue'
  141. import tasksFlowApi from '~api/tasks/flow'
  142. import { deepClone, getArrValue } from 'js-fast-way'
  143. import { checkCustomFlowUserIsEVisaPermissions, checkCustomFlowUserIsEVisaPermissions3, checkCustomFlowUserIsEVisaPermissionsquery } from '~api/other'
  144. import Draggable from 'vuedraggable'
  145. //参数
  146. const props = defineProps({
  147. ui: {
  148. type: String,
  149. default: '',
  150. },
  151. //选中的用户数组
  152. users: {
  153. type: String,
  154. default: '',
  155. },
  156. projectId: {
  157. type: [String, Number],
  158. default: '',
  159. },
  160. contractId: {
  161. type: [String, Number],
  162. default: '',
  163. },
  164. type: { //first,log,wbs
  165. type: [String, Number],
  166. default: '',
  167. },
  168. typeData: {
  169. type: [String, Number, Array, Object],
  170. default: '',
  171. },
  172. classifyType: {
  173. type: [String, Number],
  174. default: '',
  175. },
  176. tableOwner: {
  177. type: [String, Number],
  178. default: '',
  179. },
  180. nodeId: {
  181. type: [String, Number],
  182. default: '', //选中节点nodeid
  183. },
  184. infoIds:{
  185. type: [String, Number],
  186. default: '', //上报任务ID
  187. },
  188. disabled:{
  189. type:Boolean,
  190. default:false,
  191. },
  192. isChangePopele:{
  193. type:Boolean,
  194. default:false, //显示整改人还是任务人
  195. },
  196. })
  197. //事件
  198. const emit = defineEmits(['change'])
  199. //变量
  200. const showModal = ref(false)
  201. const sequenceModal = ref(false)
  202. const checkboxUserList = ref([])
  203. const UserDataList = ref([])
  204. const projectId = ref(props.projectId)
  205. const contractId = ref(props.contractId)
  206. const isTypes = ref(props.type)
  207. const typeDatas = ref(props.typeData)
  208. const classifyType = ref(props.classifyType)
  209. const tableOwner = ref(props.tableOwner)
  210. const nodeId = ref(props.nodeId)
  211. const infoIds = ref(props.infoIds)
  212. const disabled = ref(props.disabled)
  213. const isChangePopele = ref(props.isChangePopele)
  214. //树数据
  215. const ElTreeProps = { children: 'childRoleList', label: 'roleName' }
  216. const ElTreeData = ref([{
  217. roleName: '全部人员',
  218. roleId: 0,
  219. childRoleList: [],
  220. signPfxFileList: [],
  221. }])
  222. const isShowTree = ref(true)
  223. //监听
  224. watch(() => [
  225. props.users,
  226. props.projectId,
  227. props.contractId,
  228. props.type,
  229. props.typeData,
  230. props.classifyType,
  231. props.tableOwner,
  232. props.nodeId,
  233. props.infoIds,
  234. props.disabled,
  235. props.isChangePopele,
  236. ], ([users, pid, cid, type, data, cla, tab, noid, infoid, disa, isChan]) => {
  237. projectId.value = pid
  238. contractId.value = cid
  239. isTypes.value = type
  240. typeDatas.value = data
  241. setUserDataList(users)
  242. classifyType.value = cla
  243. tableOwner.value = tab
  244. nodeId.value = noid
  245. infoIds.value = infoid
  246. disabled.value = disa
  247. isChangePopele.value = isChan
  248. })
  249. //渲染完成
  250. onMounted(() => {
  251. setUserDataList(props.users)
  252. queryAllRoleList()
  253. })
  254. //处理用户数据
  255. const setUserDataList = (users) => {
  256. if (users) {
  257. const usersArr = users.split(',')
  258. UserDataList.value = usersArr
  259. checkboxUserList.value = usersArr
  260. } else {
  261. UserDataList.value = []
  262. checkboxUserList.value = []
  263. }
  264. }
  265. //展开弹窗
  266. const showModalClick = () => {
  267. if (!disabled.value) {
  268. showModal.value = true
  269. } else {
  270. showModal.value = false
  271. }
  272. }
  273. //获取系统所有角色划分
  274. const signUserList = ref([])
  275. const queryAllRoleList = async () => {
  276. isShowTree.value = false
  277. const { error, code, data } = await tasksFlowApi.queryAllRoleList({
  278. contractId: contractId.value,
  279. })
  280. isShowTree.value = true
  281. //处理数据
  282. if (!error && code === 200) {
  283. let signList = [], dataArr = getArrValue(data)
  284. ElTreeData.value[0].childRoleList = dataArr
  285. if (dataArr.length > 0) {
  286. dataArr.forEach(item => {
  287. signList = signList.concat(item.signPfxFileList)
  288. })
  289. }
  290. ElTreeData.value[0].signPfxFileList = signList
  291. signUserList.value = signList
  292. } else {
  293. signUserList.value = []
  294. ElTreeData.value[0].childRoleList = []
  295. ElTreeData.value[0].signPfxFileList = []
  296. }
  297. }
  298. //树被点击
  299. const ElTreeNodeClick = (data) => {
  300. signUserList.value = getArrValue(data?.signPfxFileList)
  301. }
  302. //处理已选择的用户问题
  303. const setCheckboxUserName = (item) => {
  304. if (item) {
  305. const itemArr = item.split('-')
  306. if (itemArr.length > 0 && itemArr[0]) {
  307. return itemArr[0]
  308. } else {
  309. return ''
  310. }
  311. } else {
  312. return ''
  313. }
  314. }
  315. //删除已选择的用户
  316. const delCheckboxUser = (index) => {
  317. checkboxUserList.value.splice(index, 1)
  318. }
  319. //排序
  320. const sortNodeDrag = ref(false)
  321. //向下
  322. const downSortClick = (index) => {
  323. const indexs = index + 1
  324. const data = checkboxUserList.value
  325. if (indexs !== data.length) {
  326. const tmp = data.splice(indexs, 1)
  327. checkboxUserList.value.splice(index, 0, tmp[0])
  328. } else {
  329. window?.$message?.warning('已经处于置底,无法下移')
  330. }
  331. }
  332. //向上
  333. const upSortClick = (index) => {
  334. const data = checkboxUserList.value || []
  335. if (index !== 0) {
  336. const tmp = data.splice(index - 1, 1)
  337. checkboxUserList.value.splice(index, 0, tmp[0])
  338. } else {
  339. window?.$message?.warning('已经处于置顶,无法上移')
  340. }
  341. }
  342. //确认选择
  343. const sureSignUserLoading = ref(false)
  344. const sureSignUserClick = () => {
  345. let type = isTypes.value, flowJson = {}, newUser = [], newUserId = [], users = ''
  346. const dataList = deepClone(checkboxUserList.value)
  347. UserDataList.value = dataList
  348. if (dataList.length > 0) {
  349. sureSignUserLoading.value = true
  350. //判断类型
  351. if (type === 'first') {
  352. flowJson['firstId'] = typeDatas.value
  353. } else if (type === 'log') {
  354. // flowJson['theLogPrimaryKeyId'] = typeDatas.value
  355. flowJson['theLogPrimaryKeyId'] = nodeId.value
  356. } else if (type === 'wbs') {
  357. flowJson['privatePKeyId'] = typeDatas.value
  358. } else if (type === 'query') {
  359. flowJson['privatePKeyId'] = typeDatas.value
  360. }
  361. //封装数据
  362. dataList.forEach(item => {
  363. const itemArr = item.split('-')
  364. if (itemArr.length > 0 && itemArr[0]) {
  365. users = users ? `${users},${item}` : item
  366. newUser.push({
  367. userId: itemArr[1],
  368. userName: itemArr[0],
  369. })
  370. newUserId.push(itemArr[1])
  371. }
  372. })
  373. //效验人员
  374. if (type === 'wbs') {
  375. getCheckCustomFlowUserIsEVisaPermissions(flowJson, newUser, newUserId, users)
  376. } else if (type === 'first' || type === 'log' ) {
  377. getCheckCustomFlowUserIsEVisaPermissions3(flowJson, newUser, newUserId, users)
  378. } else if (type === 'query') {
  379. getCheckCustomFlowUserIsEVisaPermissionsquery(flowJson, newUser, newUserId, users)
  380. } else {
  381. showModal.value = false
  382. sureSignUserLoading.value = false
  383. emit('change', newUser, newUserId, users)
  384. }
  385. } else {
  386. window.$message?.warning('请先选择任务人员,或点击取消')
  387. }
  388. }
  389. //检查所选的流程环节处理人是否具有审批权限(三大填报页、日志列表的批量上报、首件列表的批量上报)
  390. const getCheckCustomFlowUserIsEVisaPermissions = async (flowJson, newUser, newUserId, users) => {
  391. const { error, code, data } = await checkCustomFlowUserIsEVisaPermissions({
  392. projectId: projectId.value,
  393. contractId: contractId.value,
  394. customFlowUserList: newUserId,
  395. ...flowJson,
  396. classifyType:classifyType.value,
  397. tableOwner:tableOwner.value,
  398. nodeId:nodeId.value,
  399. })
  400. //处理数据
  401. sureSignUserLoading.value = false
  402. if (!error && code === 200 && data === true) {
  403. showModal.value = false
  404. emit('change', newUser, newUserId, users)
  405. } else {
  406. emit('change', [], [], '')
  407. }
  408. }
  409. //资料查询页面
  410. const getCheckCustomFlowUserIsEVisaPermissionsquery = async (flowJson, newUser, newUserId, users) => {
  411. const { error, code, data } = await checkCustomFlowUserIsEVisaPermissionsquery({
  412. projectId: projectId.value,
  413. contractId: contractId.value,
  414. customFlowUserList: newUserId,
  415. ...flowJson,
  416. nodeId:nodeId.value,
  417. classifyType:classifyType.value,
  418. tableOwner:tableOwner.value,
  419. infoIds:infoIds.value,
  420. })
  421. //处理数据
  422. sureSignUserLoading.value = false
  423. if (!error && code === 200 && data === true) {
  424. showModal.value = false
  425. emit('change', newUser, newUserId, users)
  426. } else {
  427. emit('change', [], [], '')
  428. }
  429. }
  430. //日志和首件页面
  431. const getCheckCustomFlowUserIsEVisaPermissions3 = async (flowJson, newUser, newUserId, users) => {
  432. const { error, code, data } = await checkCustomFlowUserIsEVisaPermissions3({
  433. projectId: projectId.value,
  434. contractId: contractId.value,
  435. customFlowUserList: newUserId,
  436. ...flowJson,
  437. // nodeId:nodeId.value,
  438. classifyType:classifyType.value,
  439. tableOwner:tableOwner.value,
  440. infoIds:infoIds.value,
  441. })
  442. //处理数据
  443. sureSignUserLoading.value = false
  444. if (!error && code === 200 && data === true) {
  445. showModal.value = false
  446. emit('change', newUser, newUserId, users)
  447. } else {
  448. emit('change', [], [], '')
  449. }
  450. }
  451. </script>
  452. <style lang="scss" scoped>
  453. @import './style.scss';
  454. </style>
  455. <style lang="scss">
  456. .no-check{
  457. cursor: not-allowed !important;
  458. }
  459. .hc-tasks-user .tasks-user-box .tag-user-list {
  460. .el-tag {
  461. --el-icon-size: 14px;
  462. padding: 0 10px;
  463. height: 26px;
  464. margin: 4px 0;
  465. }
  466. }
  467. .hc-tasks-user-modal-content-box {
  468. .checkbox-li .el-checkbox {
  469. width: 100%;
  470. .el-checkbox__input {
  471. position: absolute;
  472. right: 0;
  473. .el-checkbox__inner {
  474. width: 18px;
  475. height: 18px;
  476. &:after {
  477. height: 9px;
  478. left: 6px;
  479. top: 2px;
  480. }
  481. }
  482. }
  483. .el-checkbox__label {
  484. flex: 1;
  485. padding-left: 0;
  486. padding-right: 20px;
  487. }
  488. }
  489. .user-list {
  490. .el-tag {
  491. margin-right: 10px;
  492. margin-top: 12px;
  493. }
  494. }
  495. }
  496. </style>