BasicInfo.vue 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. <script setup name="BasicInfo">
  2. import useFlowStore from '@/store/modules/flow'
  3. import { ref, nextTick, onMounted } 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, ImageArr } 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 currentNode = ref('nodeRoleList')
  15. const formRef = ref()
  16. const options = ref([])
  17. const imgArr = ref(ImageArr)
  18. // 表单规则
  19. const rules = {
  20. processKey: [
  21. {
  22. required: true,
  23. // message: '请输入唯一标识',
  24. validator(rule, value, callback) {
  25. if (!value) callback('请输入唯一标识')
  26. if (!/^[a-zA-Z0-9]+$/g.test(value)) callback('仅支持字母和数字')
  27. callback()
  28. },
  29. trigger: 'blur'
  30. }
  31. ],
  32. processName: [
  33. {
  34. required: true,
  35. message: '请输入名称',
  36. trigger: 'blur'
  37. }
  38. ],
  39. categoryId: [
  40. {
  41. required: true,
  42. message: '请选择分组',
  43. trigger: 'change'
  44. }
  45. ]
  46. }
  47. // 基础信息表单提交校验
  48. const validate = () => {
  49. return new Promise((resolve, reject) => {
  50. formRef.value.validate((valid, errObj) => {
  51. // console.error(valid, 'valid errObj', errObj)
  52. if (valid) {
  53. // cb?.(form.value)
  54. resolve()
  55. // return form.value
  56. return
  57. }
  58. return reject(errObj)
  59. })
  60. })
  61. }
  62. // 弹窗显示隐藏
  63. const openApprovePerson = () => {
  64. selectVisible.value = !selectVisible.value
  65. }
  66. // 点击选择管理员
  67. const selectHandle = (type, data, name) => {
  68. currentNode.value = name
  69. openApprovePerson()
  70. nextTick(() => {
  71. useSelectRef.value.open(type, data)
  72. })
  73. }
  74. // 选中后进行回显
  75. const selectContentEv = item => {
  76. if (currentNode.value === 'nodeRoleList') {
  77. nodeRoleList.value = item
  78. const flag = !item.length
  79. flowInfo.useScope = flag ? 0 : 1
  80. let processActorList = []
  81. for (let i in item) {
  82. processActorList.push({
  83. actorId: item[i].id,
  84. actorName: item[i].name,
  85. actorType: 0
  86. })
  87. }
  88. flowInfo.processActorList = processActorList
  89. } else {
  90. let processPermissionList = []
  91. for (let i in item) {
  92. processPermissionList.push({
  93. userId: item[i].id,
  94. userName: item[i].name,
  95. operateApproval: 0,
  96. operateOwner: 0,
  97. operateData: 0,
  98. id: item[i].id,
  99. name: item[i].name
  100. })
  101. }
  102. flowInfo.processPermissionList = processPermissionList
  103. }
  104. }
  105. const delRole = (index, itemName) => {
  106. if (itemName === 'nodeRoleList') {
  107. nodeRoleList.value.splice(index, 1)
  108. } else {
  109. flowInfo.processPermissionList.splice(index, 1)
  110. }
  111. }
  112. const getGroupList = async () => {
  113. const data = await group.flowGroupListAllApi({})
  114. options.value = data || []
  115. }
  116. // icon图标点击保存
  117. const chooseIconEv = item => {
  118. flowInfo.processIcon = item
  119. visiblePopover.value = !visiblePopover.value
  120. }
  121. onMounted(() => {
  122. getGroupList()
  123. })
  124. defineExpose({
  125. formRef,
  126. validate
  127. })
  128. </script>
  129. <template>
  130. <div class="base-info">
  131. <div class="base-info-panel" style="position: relative">
  132. <el-form ref="formRef" :model="flowInfo" :rules="rules" label-position="top">
  133. <el-form-item label="图标" prop="flowInfo.processIcon">
  134. <el-space>
  135. <LeIcon class="icon-shower" :icon-class="`${flowIconPrefix}${flowInfo.processIcon}`" />
  136. </el-space>
  137. <el-popover placement="right-end" :width="450" trigger="focus" class="base-popover" :visible="visiblePopover">
  138. <div class="icon-selector__dialog__content">
  139. <div class="icon-selector-list">
  140. <div v-for="item in imgArr" :key="item" class="icon-selector-item" @click="chooseIconEv(item)">
  141. <LeIcon class="icon" :icon-class="`${flowIconPrefix}${item}`" />
  142. </div>
  143. </div>
  144. </div>
  145. <template #reference>
  146. <el-link :underline="false" @click="visiblePopover = !visiblePopover">修改</el-link>
  147. </template>
  148. </el-popover>
  149. </el-form-item>
  150. <el-form-item label="唯一标识 key" prop="processKey">
  151. <el-input v-model="flowInfo.processKey" clearable maxlength="100"></el-input>
  152. </el-form-item>
  153. <el-form-item label="名称" prop="processName">
  154. <el-input v-model="flowInfo.processName" clearable maxlength="15"></el-input>
  155. </el-form-item>
  156. <el-form-item label="说明" prop="remark">
  157. <el-input v-model="flowInfo.remark" type="textarea" clearable></el-input>
  158. </el-form-item>
  159. <el-form-item label="分组" prop="categoryId">
  160. <el-select v-model="flowInfo.categoryId">
  161. <el-option v-for="item in options" :key="item.id" :label="item.name" :value="item.id" />
  162. </el-select>
  163. </el-form-item>
  164. <el-form-item v-if="false" label="谁可以发起该流程(不选择,默认全员)" prop="谁可以发起该流程">
  165. <div class="add-btn" @click="selectHandle(1, nodeRoleList, 'nodeRoleList')">
  166. <el-icon :size="18"><Plus /></el-icon>
  167. </div>
  168. <div class="tags-list" style="margin-top: 15px; width: 100%">
  169. <el-tag
  170. v-for="(role, index) in nodeRoleList"
  171. :key="role.id"
  172. type="info"
  173. closable
  174. style="margin-right: 8px"
  175. @close="delRole(index, 'nodeRoleList')"
  176. >{{ role.name }}</el-tag
  177. >
  178. </div>
  179. </el-form-item>
  180. <el-form-item label="管理员" prop="管理员">
  181. <div class="add-btn" @click="selectHandle(1, flowInfo.processPermissionList, 'nodeRoleManageList')">
  182. <el-icon :size="18"><Plus /></el-icon>
  183. </div>
  184. <div class="tags-list" style="margin-top: 15px; width: 100%">
  185. <el-tag
  186. v-for="(user, index) in flowInfo.processPermissionList"
  187. :key="user.userId"
  188. type="info"
  189. closable
  190. style="margin-right: 8px"
  191. @close="delRole(index, 'nodeRoleManageList')"
  192. >{{ user.userName }}
  193. </el-tag>
  194. </div>
  195. </el-form-item>
  196. </el-form>
  197. </div>
  198. <use-select v-if="selectVisible" ref="useSelectRef" @closed="selectVisible = false" @update:selected="selectContentEv"></use-select>
  199. </div>
  200. </template>
  201. <style scoped lang="scss">
  202. .basic-info-wrap {
  203. //background: var(--el-color-danger);
  204. }
  205. .flow-name {
  206. padding-right: 4px;
  207. color: var(--el-color-danger);
  208. }
  209. .base-info {
  210. margin: 0 auto;
  211. padding: 24px 0;
  212. height: 100%;
  213. text-align: center;
  214. overflow-y: auto;
  215. background-color: var(--el-color-info-light-9);
  216. position: relative;
  217. &-panel {
  218. display: inline-block;
  219. width: 1128px;
  220. padding: 24px 288px;
  221. background-color: var(--el-bg-color);
  222. text-align: left;
  223. }
  224. }
  225. .icon-selector__dialog__content {
  226. height: 384px;
  227. overflow-x: visible;
  228. overflow-y: scroll;
  229. scrollbar-width: none;
  230. -ms-overflow-style: none;
  231. .icon-selector-list {
  232. display: grid;
  233. grid-template-columns: repeat(5, 64px);
  234. grid-template-rows: repeat(auto, 64px);
  235. grid-gap: 16px;
  236. justify-content: flex-start;
  237. align-items: flex-start;
  238. flex-wrap: wrap;
  239. .icon-selector-item {
  240. width: 64px;
  241. height: 64px;
  242. padding: 8px;
  243. border: 1px solid #d0d3d6;
  244. box-sizing: border-box;
  245. border-radius: 6px;
  246. cursor: pointer;
  247. &:hover {
  248. border-color: #3370ff;
  249. }
  250. .icon {
  251. border-radius: 4px;
  252. font-size: 46px;
  253. }
  254. /*img {
  255. width: 100%;
  256. height: 100%;
  257. border-radius: 4px;
  258. overflow: hidden;
  259. }*/
  260. }
  261. }
  262. }
  263. .icon-shower {
  264. width: 48px;
  265. font-size: 48px;
  266. //height: 48px;
  267. border-radius: 50%;
  268. overflow: hidden;
  269. /*img {
  270. width: 100%;
  271. height: 100%;
  272. object-fit: cover;
  273. }*/
  274. }
  275. .add-btn {
  276. width: 48px;
  277. height: 48px;
  278. font-family: PingFang SC, Microsoft YaHei;
  279. font-size: 14px;
  280. line-height: 20px;
  281. background-color: var(--el-fill-color);
  282. border-radius: 50%;
  283. cursor: pointer;
  284. display: flex;
  285. justify-content: center;
  286. align-items: center;
  287. }
  288. </style>