index.vue 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. <template>
  2. <div class="create-approval">
  3. <div class="create-approval-header flex flex_align-center">
  4. <div v-if="false" class="create-approval-header-back">
  5. <el-icon :size="18">
  6. <ArrowLeft />
  7. </el-icon>
  8. </div>
  9. <div class="create-approval-header-left-zh">
  10. <div class="create-approval-header-name">{{ processName }}</div>
  11. <div v-if="false" class="create-approval-header-time">最近保存:6 分钟前</div>
  12. </div>
  13. <div class="create-approval-header-tab-list">
  14. <div
  15. v-for="(item, idx) in componentsArr"
  16. :key="idx"
  17. class="create-approval-header-tab-item"
  18. :class="[item.label === activeName ? 'active' : '']"
  19. @click="activeComponent(item)"
  20. >
  21. <span class="create-approval-header-tab-counter">{{ idx + 1 }}</span>
  22. <span>{{ item.label }}</span>
  23. </div>
  24. </div>
  25. <div class="create-approval-header-right">
  26. <el-button type="primary" @click="submitHandler">发布</el-button>
  27. </div>
  28. </div>
  29. <div class="create-approval-main">
  30. <component :is="currentComponent" ref="dyncComponent" />
  31. </div>
  32. </div>
  33. </template>
  34. <script setup name="flow_create">
  35. import { computed, ref } from 'vue'
  36. import { storeToRefs } from 'pinia'
  37. import useFlowStore from '@/store/modules/flow'
  38. import BasicInfoTab from './components/BasicInfo.vue'
  39. import ExtendSetTab from './components/ExtendSet.vue'
  40. import FlowDesignTab from './components/FlowDesign.vue'
  41. import FormDesignTab from './components/FormDesign.vue'
  42. import { useRoute, useRouter } from 'vue-router'
  43. import process from '@/api/flow/process'
  44. import useStore from '@/store'
  45. import { ElMessage } from 'element-plus'
  46. const { tagsView } = useStore()
  47. const router = useRouter()
  48. const route = useRoute()
  49. const flowStore = useFlowStore()
  50. const { categoryId, processId, processIcon, processKey, processName, remark, modelContent, processForm, processSetting } = storeToRefs(flowStore)
  51. const dyncComponent = ref() // 实例化子组件
  52. const componentsArr = [
  53. {
  54. component: BasicInfoTab,
  55. label: '基础信息',
  56. name: '基础信息'
  57. // ref: 'basicInfoRef'
  58. },
  59. {
  60. component: FormDesignTab,
  61. label: '表单设计',
  62. name: '表单设计'
  63. // ref: 'formDesignRef'
  64. },
  65. {
  66. component: FlowDesignTab,
  67. label: '流程设计',
  68. name: '流程设计'
  69. // ref: 'flowDesignRef'
  70. },
  71. {
  72. component: ExtendSetTab,
  73. label: '扩展设置',
  74. name: '扩展设置'
  75. // ref: 'extendSetRef'
  76. }
  77. ]
  78. const activeName = ref('基础信息')
  79. const removeCurTab = () => {
  80. const _view = tagsView.visitedViews.find(v => v.path === '/flow_create/index')
  81. if (_view)
  82. tagsView.delView(_view).then(res => {
  83. const latestView = res.visitedViews.slice(-1)[0]
  84. if (latestView && latestView.fullPath) {
  85. router.push(latestView.fullPath)
  86. } else {
  87. router.push('/')
  88. }
  89. })
  90. }
  91. const submitHandler = async () => {
  92. // 基础信息
  93. // 表单设计
  94. // 流程设计
  95. // 扩展设置
  96. const leavePageFlag = changeTab()
  97. if (leavePageFlag) return // 说明表单设计的值有重复的
  98. const params = {
  99. categoryId: categoryId.value,
  100. processIcon: processIcon.value,
  101. processKey: processKey.value,
  102. processName: processName.value,
  103. remark: remark.value,
  104. processId: processId.value,
  105. processForm: processForm.value,
  106. modelContent: JSON.stringify({
  107. key: processKey.value,
  108. name: processName.value,
  109. nodeConfig: JSON.parse(modelContent.value)
  110. }),
  111. processSetting: processSetting.value
  112. }
  113. const res = await process.progressCreateApi(params)
  114. console.log('---r-e-s----', res)
  115. // 创建完成 删除 当前tab页
  116. removeCurTab()
  117. }
  118. // 切换选项卡之前,做相应的保存操作
  119. const changeTab = () => {
  120. let leavePageFlag = false
  121. if (activeName.value === '表单设计') {
  122. // 这里针对表单设计单独处理,如果不符合条件,则不允许切换
  123. dyncComponent.value.exportJsonEv()
  124. leavePageFlag = dyncComponent.value.validateOnlyEv() // FormDesign.vue中的方法
  125. if (leavePageFlag) {
  126. return ElMessage.error(`表单设计中字段ID不能重复,请确认唯一值`)
  127. }
  128. } else if (activeName.value === '流程设计') {
  129. dyncComponent.value.saveDesign()
  130. }
  131. return leavePageFlag
  132. }
  133. const activeComponent = item => {
  134. const leavePageFlag = changeTab()
  135. if (!leavePageFlag) {
  136. activeName.value = item.label
  137. }
  138. }
  139. const currentComponent = computed(() => {
  140. return componentsArr.find(item => item.label === activeName.value)?.component
  141. })
  142. const queryObj = computed(() => route.query)
  143. const getCurrentProcessDetailEv = () => {
  144. let _id = queryObj.value.id
  145. if (_id) {
  146. process.processDetailApi(_id).then(res => {
  147. processId.value = res.processId
  148. categoryId.value = res.categoryId
  149. processIcon.value = res.processIcon
  150. processKey.value = res.processKey
  151. processName.value = res.processName
  152. remark.value = res.remark
  153. let nodeConfig = JSON.parse(res.modelContent).nodeConfig
  154. modelContent.value = JSON.stringify(nodeConfig)
  155. processForm.value = res.processForm
  156. flowStore.setProcessForm(processForm)
  157. })
  158. }
  159. }
  160. getCurrentProcessDetailEv()
  161. </script>
  162. <style scoped lang="scss">
  163. .create-approval {
  164. height: 100%;
  165. min-width: 1200px;
  166. min-height: 600px;
  167. overflow: auto;
  168. &-header {
  169. justify-content: flex-start;
  170. height: 64px;
  171. z-index: 12;
  172. position: relative;
  173. box-shadow: 0 1px 6px 0 rgba(0, 0, 0, 0.06);
  174. padding-left: 16px;
  175. padding-right: 20px;
  176. &-back {
  177. display: flex;
  178. justify-content: flex-start;
  179. align-items: center;
  180. height: 100%;
  181. margin-right: 15px;
  182. }
  183. &-left-zh {
  184. width: calc(50% - 316.5px);
  185. min-width: 248px;
  186. }
  187. &-name {
  188. font-weight: 500;
  189. font-size: 16px;
  190. white-space: nowrap;
  191. cursor: pointer;
  192. width: -webkit-fit-content;
  193. width: -moz-fit-content;
  194. width: fit-content;
  195. max-width: 100%;
  196. height: 24px;
  197. overflow: hidden;
  198. text-overflow: ellipsis;
  199. }
  200. &-time {
  201. width: 100%;
  202. height: 20px;
  203. line-height: 20px;
  204. font-size: 12px;
  205. color: #8f959e;
  206. overflow: hidden;
  207. white-space: nowrap;
  208. text-overflow: ellipsis;
  209. }
  210. &-tab-list {
  211. margin-left: 10px;
  212. flex-shrink: 0;
  213. display: flex;
  214. justify-content: center;
  215. }
  216. &-tab-item {
  217. font-family: PingFang SC, Microsoft YaHei;
  218. font-size: 18px;
  219. line-height: 28px;
  220. color: #646a73;
  221. margin-right: 42px;
  222. padding: 18px 0;
  223. border-bottom: 2px solid transparent;
  224. cursor: pointer;
  225. &.active {
  226. // var(--el-color-primary);
  227. border-bottom-color: var(--el-color-primary);
  228. color: var(--el-color-primary);
  229. font-weight: 500;
  230. .create-approval-header-tab-counter {
  231. border-color: var(--el-color-primary);
  232. background-color: var(--el-color-primary);
  233. color: var(--el-color-white);
  234. font-weight: 400;
  235. }
  236. }
  237. }
  238. &-tab-counter {
  239. display: inline-block;
  240. margin-right: 6px;
  241. width: 24px;
  242. height: 24px;
  243. border-radius: 50%;
  244. border: 1px solid #646a73;
  245. font-size: 16px;
  246. line-height: 22px;
  247. text-align: center;
  248. }
  249. &-right {
  250. flex: 1 1;
  251. flex-shrink: 0;
  252. display: flex;
  253. justify-content: flex-end;
  254. align-items: center;
  255. position: relative;
  256. height: 100%;
  257. width: -webkit-fit-content;
  258. width: -moz-fit-content;
  259. width: fit-content;
  260. }
  261. }
  262. &-main {
  263. height: calc(100% - 64px);
  264. }
  265. }
  266. </style>