index.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  1. <template>
  2. <div :class="ui" class="hc-tasks-user">
  3. <div class="tasks-user-box">
  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">点击这里选择任务人</div>
  10. </div>
  11. </div>
  12. <!-- 选择任务人 -->
  13. <el-dialog v-model="showModal" title="选择任务人" width="62rem" class="hc-modal-border hc-modal-nop" draggable destroy-on-close append-to-body>
  14. <div class="hc-tasks-user-modal-content-box">
  15. <div class="tree-box">
  16. <el-scrollbar>
  17. <ElTree class="hc-tree-node-box" :props="ElTreeProps" :data="ElTreeData" node-key="roleId" highlight-current accordion :default-expanded-keys="[0]" @node-click="ElTreeNodeClick" />
  18. </el-scrollbar>
  19. </div>
  20. <div class="user-box">
  21. <div class="y-user-list-box">
  22. <div class="title-box">
  23. <div class="title">可选择</div>
  24. </div>
  25. <div class="user-list">
  26. <el-scrollbar>
  27. <el-checkbox-group v-model="checkboxUserList">
  28. <template v-for="item in signUserList" :key="item.certificateUserId">
  29. <div class="user-item checkbox-li">
  30. <el-checkbox :label="`${item.certificateUserName}-${item.certificateUserId}`">
  31. <div class="item-user-name">{{ item.certificateUserName }}</div>
  32. </el-checkbox>
  33. </div>
  34. </template>
  35. </el-checkbox-group>
  36. </el-scrollbar>
  37. </div>
  38. </div>
  39. <div class="s-user-list-box">
  40. <div class="title-box">
  41. <div class="title">已选择({{ checkboxUserList.length }})</div>
  42. <el-button plain size="small" @click="sequenceModal = true">调整顺序</el-button>
  43. </div>
  44. <div class="user-list">
  45. <el-scrollbar>
  46. <template v-for="(item, index) in checkboxUserList" :key="index">
  47. <el-tag closable @close="delCheckboxUser(index)">{{ setCheckboxUserName(item) }}</el-tag>
  48. </template>
  49. </el-scrollbar>
  50. </div>
  51. </div>
  52. </div>
  53. </div>
  54. <template #footer>
  55. <div class="dialog-footer">
  56. <el-button hc-btn style="border: 1px solid var(--el-button-border-color);" @click="showModal = false">
  57. <HcIcon name="close" />
  58. <span>取消</span>
  59. </el-button>
  60. <el-button hc-btn type="primary" :loading="sureSignUserLoading" @click="sureSignUserClick">
  61. <HcIcon name="check" />
  62. <span>确定</span>
  63. </el-button>
  64. </div>
  65. </template>
  66. </el-dialog>
  67. <!-- 调整顺序 -->
  68. <el-dialog v-model="sequenceModal" title="调整顺序" width="38rem" class="hc-modal-border" draggable destroy-on-close append-to-body>
  69. <el-alert title="可拖动排序,也可在后面点击图标,切换排序" type="warning" :closable="false" />
  70. <div class="sort-node-body-box list-group header">
  71. <div class="list-group-item">
  72. <div class="index-box">序号</div>
  73. <div class="title-box">任务人</div>
  74. <div class="icon-box">排序</div>
  75. </div>
  76. </div>
  77. <Draggable class="sort-node-body-box list-group" ghost-class="ghost" :list="checkboxUserList" item-key="id" @start="sortNodeDrag = true" @end="sortNodeDrag = false">
  78. <template #item="{ element, index }">
  79. <div class="list-group-item">
  80. <div class="index-box">{{ index + 1 }}</div>
  81. <div class="title-box">{{ setCheckboxUserName(element) }}</div>
  82. <div class="icon-box">
  83. <span class="icon" @click="downSortClick(index)">
  84. <HcIcon name="arrow-down" ui="text-lg" />
  85. </span>
  86. <span class="icon" @click="upSortClick(index)">
  87. <HcIcon name="arrow-up" ui="text-lg" />
  88. </span>
  89. </div>
  90. </div>
  91. </template>
  92. </Draggable>
  93. <template #footer>
  94. <div class="dialog-footer">
  95. <el-button size="large" @click="sequenceModal = false">取消</el-button>
  96. <el-button type="primary" hc-btn @click="sequenceModal = false">确认</el-button>
  97. </div>
  98. </template>
  99. </el-dialog>
  100. </div>
  101. </template>
  102. <script setup>
  103. import { onMounted, ref, watch } from 'vue'
  104. import tasksFlowApi from '~api/tasks/flow'
  105. import { deepClone, getArrValue } from 'js-fast-way'
  106. import Draggable from 'vuedraggable'
  107. //参数
  108. const props = defineProps({
  109. ui: {
  110. type: String,
  111. default: '',
  112. },
  113. //选中的用户数组
  114. users: {
  115. type: String,
  116. default: '',
  117. },
  118. projectId: {
  119. type: [String, Number],
  120. default: '',
  121. },
  122. contractId: {
  123. type: [String, Number],
  124. default: '',
  125. },
  126. })
  127. //事件
  128. const emit = defineEmits(['change'])
  129. //变量
  130. const showModal = ref(false)
  131. const sequenceModal = ref(false)
  132. const checkboxUserList = ref([])
  133. const UserDataList = ref([])
  134. const projectId = ref(props.projectId)
  135. const contractId = ref(props.contractId)
  136. //树数据
  137. const ElTreeProps = { children: 'childRoleList', label: 'roleName' }
  138. const ElTreeData = ref([{
  139. roleName: '全部人员',
  140. roleId: 0,
  141. childRoleList: [],
  142. signPfxFileList: [],
  143. }])
  144. //监听
  145. watch(() => [
  146. props.users,
  147. props.projectId,
  148. props.contractId,
  149. ], ([users, pid, cid]) => {
  150. projectId.value = pid
  151. contractId.value = cid
  152. setUserDataList(users)
  153. })
  154. //渲染完成
  155. onMounted(() => {
  156. setUserDataList(props.users)
  157. queryAllRoleList()
  158. })
  159. //处理用户数据
  160. const setUserDataList = (users) => {
  161. if (users) {
  162. const usersArr = users.split(',')
  163. UserDataList.value = usersArr
  164. checkboxUserList.value = usersArr
  165. } else {
  166. UserDataList.value = []
  167. checkboxUserList.value = []
  168. }
  169. }
  170. //展开弹窗
  171. const showModalClick = () => {
  172. showModal.value = true
  173. }
  174. //获取系统所有角色划分
  175. const signUserList = ref([])
  176. const queryAllRoleList = async () => {
  177. const { error, code, data } = await tasksFlowApi.queryAllRoleList({
  178. contractId: contractId.value,
  179. })
  180. //处理数据
  181. if (!error && code === 200) {
  182. let signList = [], dataArr = getArrValue(data)
  183. ElTreeData.value[0].childRoleList = dataArr
  184. if (dataArr.length > 0) {
  185. dataArr.forEach(item => {
  186. signList = signList.concat(item.signPfxFileList)
  187. })
  188. }
  189. ElTreeData.value[0].signPfxFileList = signList
  190. signUserList.value = signList
  191. } else {
  192. signUserList.value = []
  193. ElTreeData.value[0].childRoleList = []
  194. ElTreeData.value[0].signPfxFileList = []
  195. }
  196. }
  197. //树被点击
  198. const ElTreeNodeClick = (data) => {
  199. signUserList.value = getArrValue(data?.signPfxFileList)
  200. }
  201. //处理已选择的用户问题
  202. const setCheckboxUserName = (item) => {
  203. if (item) {
  204. const itemArr = item.split('-')
  205. if (itemArr.length > 0 && itemArr[0]) {
  206. return itemArr[0]
  207. } else {
  208. return ''
  209. }
  210. } else {
  211. return ''
  212. }
  213. }
  214. //删除已选择的用户
  215. const delCheckboxUser = (index) => {
  216. checkboxUserList.value.splice(index, 1)
  217. }
  218. //排序
  219. const sortNodeDrag = ref(false)
  220. //向下
  221. const downSortClick = (index) => {
  222. const indexs = index + 1
  223. const data = checkboxUserList.value
  224. if (indexs !== data.length) {
  225. const tmp = data.splice(indexs, 1)
  226. checkboxUserList.value.splice(index, 0, tmp[0])
  227. } else {
  228. window?.$message?.warning('已经处于置底,无法下移')
  229. }
  230. }
  231. //向上
  232. const upSortClick = (index) => {
  233. const data = checkboxUserList.value || []
  234. if (index !== 0) {
  235. const tmp = data.splice(index - 1, 1)
  236. checkboxUserList.value.splice(index, 0, tmp[0])
  237. } else {
  238. window?.$message?.warning('已经处于置顶,无法上移')
  239. }
  240. }
  241. //确认选择
  242. const sureSignUserLoading = ref(false)
  243. const sureSignUserClick = () => {
  244. let newUser = [], newUserId = [], users = ''
  245. const dataList = deepClone(checkboxUserList.value)
  246. UserDataList.value = dataList
  247. if (dataList.length > 0) {
  248. sureSignUserLoading.value = true
  249. //封装数据
  250. dataList.forEach(item => {
  251. const itemArr = item.split('-')
  252. if (itemArr.length > 0 && itemArr[0]) {
  253. users = users ? `${users},${item}` : item
  254. newUser.push({
  255. userId: itemArr[1],
  256. userName: itemArr[0],
  257. })
  258. newUserId.push(itemArr[1])
  259. }
  260. })
  261. showModal.value = false
  262. sureSignUserLoading.value = false
  263. emit('change', newUser, newUserId, users)
  264. } else {
  265. window.$message?.warning('请先选择任务人员,或点击取消')
  266. }
  267. }
  268. </script>
  269. <style lang="scss" scoped>
  270. @import './style.scss';
  271. </style>
  272. <style lang="scss">
  273. .hc-tasks-user .tasks-user-box .tag-user-list {
  274. .el-tag {
  275. --el-icon-size: 14px;
  276. padding: 0 10px;
  277. height: 26px;
  278. margin: 4px 0;
  279. }
  280. }
  281. .hc-tasks-user-modal-content-box {
  282. .checkbox-li .el-checkbox {
  283. width: 100%;
  284. .el-checkbox__input {
  285. position: absolute;
  286. right: 0;
  287. .el-checkbox__inner {
  288. width: 18px;
  289. height: 18px;
  290. &:after {
  291. height: 9px;
  292. left: 6px;
  293. top: 2px;
  294. }
  295. }
  296. }
  297. .el-checkbox__label {
  298. flex: 1;
  299. padding-left: 0;
  300. padding-right: 20px;
  301. }
  302. }
  303. .user-list {
  304. .el-tag {
  305. margin-right: 10px;
  306. margin-top: 12px;
  307. }
  308. }
  309. }
  310. </style>