BasicInfo.vue 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362
  1. <script setup name="BasicInfo">
  2. import useFlowStore from '@/store/modules/flow'
  3. import { ref, nextTick, onMounted, computed, watch } from 'vue'
  4. import UseSelect from '@/components/scWorkflow/select'
  5. import group from '@/api/flow/group'
  6. import { useRoute } from 'vue-router'
  7. import { flowIconPrefix } from '@/utils/index'
  8. const route = useRoute()
  9. const flowInfo = useFlowStore()
  10. const visiblePopover = ref(false)
  11. const selectVisible = ref(false)
  12. const useSelectRef = ref(null)
  13. const nodeRoleList = ref([])
  14. const nodeRoleManageList = ref([])
  15. const currentNode = ref('nodeRoleList')
  16. const formRef = ref()
  17. const options = ref([])
  18. const rules = {
  19. processIcon: [
  20. {
  21. required: true,
  22. message: '请选择图标'
  23. }
  24. ],
  25. processKey: [
  26. {
  27. required: true,
  28. message: '请输入唯一标识'
  29. }
  30. ],
  31. processName: [
  32. {
  33. required: true,
  34. message: '请输入名称'
  35. }
  36. ],
  37. categoryId: [
  38. {
  39. required: true,
  40. message: '请选择分组'
  41. }
  42. ]
  43. }
  44. const imgsArr = ref([
  45. 'approval',
  46. 'bank-card',
  47. 'bell',
  48. 'box',
  49. 'calendar',
  50. 'car',
  51. 'cash',
  52. 'checklist',
  53. 'clock',
  54. 'coin',
  55. 'contract',
  56. 'dimission',
  57. 'exchange',
  58. 'lightning',
  59. 'location',
  60. 'male',
  61. 'manager',
  62. 'offboarding',
  63. 'onboarding',
  64. 'plane',
  65. 'presentation',
  66. 'propotion',
  67. 'regular',
  68. 'relation',
  69. 'ticket',
  70. 'toolbox',
  71. 'transfer',
  72. 'wallet'
  73. ])
  74. const validate = () => {
  75. return new Promise((resolve, reject) => {
  76. formRef.value.validate((valid, errObj) => {
  77. if (valid) {
  78. console.error('valid 成功')
  79. // cb?.(form.value)
  80. resolve(form.value)
  81. // return form.value
  82. return
  83. }
  84. return reject(['基本信息', errObj])
  85. })
  86. })
  87. }
  88. const openApprovePerson = () => {
  89. selectVisible.value = !selectVisible.value
  90. }
  91. const selectHandle = (type, data, name) => {
  92. currentNode.value = name
  93. openApprovePerson()
  94. nextTick(() => {
  95. useSelectRef.value.open(type, data)
  96. })
  97. }
  98. const selectContentEv = item => {
  99. if (currentNode.value === 'nodeRoleList') {
  100. nodeRoleList.value = item
  101. const flag = !item.length
  102. flowInfo.value.useScope = flag ? 0 : 1
  103. let processActorList = []
  104. for (let i in item) {
  105. processActorList.push({
  106. actorId: item[i].id,
  107. actorName: item[i].name,
  108. actorType: 0
  109. })
  110. }
  111. flowInfo.value.processActorList = processActorList
  112. } else {
  113. let processPermissionList = []
  114. for (let i in item) {
  115. processPermissionList.push({
  116. userId: item[i].id,
  117. userName: item[i].name,
  118. operateApproval: 0,
  119. operateOwner: 0,
  120. operateData: 0
  121. })
  122. }
  123. nodeRoleManageList.value = item
  124. flowInfo.processPermissionList = processPermissionList
  125. }
  126. }
  127. const delRole = (index, itemName) => {
  128. if (itemName === 'nodeRoleList') {
  129. nodeRoleList.value.splice(index, 1)
  130. } else {
  131. nodeRoleManageList.value.splice(index, 1)
  132. }
  133. }
  134. const getGroupList = async () => {
  135. const data = await group.flowGroupListAllApi({})
  136. options.value = data || []
  137. }
  138. const initBaseicInfEv = item => {
  139. const { processForm, modelContent, ...rest } = item
  140. flowInfo.value = rest
  141. flowStore.setProcessForm(processForm)
  142. flowStore.setModelContent(modelContent)
  143. flowProcessId.value = queryObj.value.id // 赋值流程id
  144. if (item.processPermissionList && item.processPermissionList.length) {
  145. nodeRoleManageList.value = item.processPermissionList.map(item => {
  146. return {
  147. id: item.userId,
  148. name: item.userName,
  149. operateApproval: 0,
  150. operateOwner: 0,
  151. operateData: 0
  152. }
  153. })
  154. }
  155. }
  156. // icon图标点击保存
  157. const chooseIconEv = item => {
  158. value.processIcon = item
  159. visiblePopover.value = !visiblePopover.value
  160. }
  161. // 当前是否是编辑
  162. const queryObj = computed(() => route.query)
  163. // 流程名称变化
  164. // watch(
  165. // () => flowInfo.value.processName,
  166. // newVal => {
  167. // flowName.value = newVal
  168. // }
  169. // )
  170. // ----- 缓存相关 end ------
  171. onMounted(() => {
  172. getGroupList()
  173. // flowStore.$reset() // 重置缓存
  174. })
  175. defineExpose({
  176. formRef,
  177. validate
  178. })
  179. </script>
  180. <template>
  181. <div class="base-info">
  182. <div class="base-info-panel" style="position: relative">
  183. <el-form ref="formRef" :rules="rules" label-position="top">
  184. <el-form-item label="图标" prop="flowInfo.processIcon">
  185. <el-space>
  186. <LeIcon class="icon-shower" :icon-class="`${flowIconPrefix}${flowInfo.processIcon}`" />
  187. </el-space>
  188. <el-popover placement="right-end" :width="450" trigger="focus" class="base-popover" :visible="visiblePopover">
  189. <div class="icon-selector__dialog__content">
  190. <div class="icon-selector-list">
  191. <div v-for="item in imgsArr" :key="item" class="icon-selector-item" @click="chooseIconEv(item)">
  192. <LeIcon class="icon" :icon-class="`${flowIconPrefix}${item}`" />
  193. </div>
  194. </div>
  195. </div>
  196. <template #reference>
  197. <el-link :underline="false" @click="visiblePopover = !visiblePopover">修改</el-link>
  198. </template>
  199. </el-popover>
  200. </el-form-item>
  201. <el-form-item label="唯一标识 key" prop="flowInfo.processKey">
  202. <el-input v-model="flowInfo.processKey" clearable></el-input>
  203. </el-form-item>
  204. <el-form-item label="名称" prop="flowInfo.processName">
  205. <el-input v-model="flowInfo.processName" clearable></el-input>
  206. </el-form-item>
  207. <el-form-item label="说明" prop="flowInfo.remark">
  208. <el-input v-model="flowInfo.remark" type="textarea" clearable></el-input>
  209. </el-form-item>
  210. <el-form-item label="分组" prop="flowInfo.categoryId">
  211. <el-select v-model="flowInfo.categoryId">
  212. <el-option v-for="item in options" :key="item.id" :label="item.name" :value="item.id" />
  213. </el-select>
  214. </el-form-item>
  215. <el-form-item v-if="false" label="谁可以发起该流程(不选择,默认全员)" prop="谁可以发起该流程">
  216. <div class="add-btn" @click="selectHandle(1, nodeRoleList, 'nodeRoleList')">
  217. <el-icon :size="18"><Plus /></el-icon>
  218. </div>
  219. <div class="tags-list" style="margin-top: 15px; width: 100%">
  220. <el-tag
  221. v-for="(role, index) in nodeRoleList"
  222. :key="role.id"
  223. type="info"
  224. closable
  225. style="margin-right: 8px"
  226. @close="delRole(index, 'nodeRoleList')"
  227. >{{ role.name }}</el-tag
  228. >
  229. </div>
  230. </el-form-item>
  231. <el-form-item label="管理员" prop="管理员">
  232. <div class="add-btn" @click="selectHandle(1, nodeRoleManageList, 'nodeRoleManageList')">
  233. <el-icon :size="18"><Plus /></el-icon>
  234. </div>
  235. <div class="tags-list" style="margin-top: 15px; width: 100%">
  236. <el-tag
  237. v-for="(role, index) in nodeRoleManageList"
  238. :key="role.id"
  239. type="info"
  240. closable
  241. style="margin-right: 8px"
  242. @close="delRole(index, 'nodeRoleManageList')"
  243. >{{ role.name }}</el-tag
  244. >
  245. </div>
  246. </el-form-item>
  247. </el-form>
  248. </div>
  249. <use-select v-if="selectVisible" ref="useSelectRef" @closed="selectVisible = false" @content-ev="selectContentEv"></use-select>
  250. </div>
  251. </template>
  252. <style scoped lang="scss">
  253. .basic-info-wrap {
  254. //background: var(--el-color-danger);
  255. }
  256. .flow-name {
  257. padding-right: 4px;
  258. color: var(--el-color-danger);
  259. }
  260. .base-info {
  261. margin: 0 auto;
  262. padding: 24px 0;
  263. height: 100%;
  264. text-align: center;
  265. overflow-y: auto;
  266. background-color: #eff0f1;
  267. position: relative;
  268. &-panel {
  269. display: inline-block;
  270. width: 1128px;
  271. padding: 24px 288px;
  272. background-color: #fff;
  273. text-align: left;
  274. }
  275. }
  276. .icon-selector__dialog__content {
  277. height: 384px;
  278. overflow-x: visible;
  279. overflow-y: scroll;
  280. scrollbar-width: none;
  281. -ms-overflow-style: none;
  282. .icon-selector-list {
  283. display: grid;
  284. grid-template-columns: repeat(5, 64px);
  285. grid-template-rows: repeat(auto, 64px);
  286. grid-gap: 16px;
  287. justify-content: flex-start;
  288. align-items: flex-start;
  289. flex-wrap: wrap;
  290. .icon-selector-item {
  291. width: 64px;
  292. height: 64px;
  293. padding: 8px;
  294. border: 1px solid #d0d3d6;
  295. box-sizing: border-box;
  296. border-radius: 6px;
  297. cursor: pointer;
  298. &:hover {
  299. border-color: #3370ff;
  300. }
  301. .icon {
  302. border-radius: 4px;
  303. font-size: 46px;
  304. }
  305. /*img {
  306. width: 100%;
  307. height: 100%;
  308. border-radius: 4px;
  309. overflow: hidden;
  310. }*/
  311. }
  312. }
  313. }
  314. .icon-shower {
  315. width: 48px;
  316. font-size: 48px;
  317. //height: 48px;
  318. border-radius: 50%;
  319. overflow: hidden;
  320. /*img {
  321. width: 100%;
  322. height: 100%;
  323. object-fit: cover;
  324. }*/
  325. }
  326. .add-btn {
  327. width: 48px;
  328. height: 48px;
  329. font-family: PingFang SC, Microsoft YaHei;
  330. font-size: 14px;
  331. line-height: 20px;
  332. background-color: #eff0f1;
  333. border-radius: 50%;
  334. cursor: pointer;
  335. display: flex;
  336. justify-content: center;
  337. align-items: center;
  338. }
  339. </style>