BasicInfo.vue 8.4 KB

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