|
@@ -0,0 +1,312 @@
|
|
|
+<template>
|
|
|
+ <div class="create-approval">
|
|
|
+ <div class="create-approval-header flex flex_align-center">
|
|
|
+ <div v-if="false" class="create-approval-header-back">
|
|
|
+ <el-icon :size="18">
|
|
|
+ <ArrowLeft />
|
|
|
+ </el-icon>
|
|
|
+ </div>
|
|
|
+ <div class="create-approval-header-left-zh">
|
|
|
+ <div class="create-approval-header-name">{{ processName }}</div>
|
|
|
+ <div v-if="false" class="create-approval-header-time">最近保存:6 分钟前</div>
|
|
|
+ </div>
|
|
|
+ <div class="create-approval-header-tab-list">
|
|
|
+ <div
|
|
|
+ v-for="(item, idx) in componentsArr"
|
|
|
+ :key="idx"
|
|
|
+ class="create-approval-header-tab-item"
|
|
|
+ :class="[item.value === activeTab ? 'active' : '']"
|
|
|
+ @click="activeComponent(idx)"
|
|
|
+ >
|
|
|
+ <span class="create-approval-header-tab-counter">{{ idx + 1 }}</span>
|
|
|
+ <span>{{ item.label }}</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="create-approval-header-right">
|
|
|
+ <el-button type="primary" @click="submitHandler">发布</el-button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="create-approval-main">
|
|
|
+ <component :is="item.component" v-for="(item, idx) in componentsArr" v-show="item.value === activeTab" ref="compRefs" :key="idx" />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script setup name="flow_create">
|
|
|
+import { computed, nextTick, ref } from 'vue'
|
|
|
+import { storeToRefs } from 'pinia'
|
|
|
+import useFlowStore from '@/store/modules/flow'
|
|
|
+import BasicInfoTab from './components/BasicInfo.vue'
|
|
|
+import FlowDesignTab from './components/FlowDesign.vue'
|
|
|
+import { useRoute, useRouter } from 'vue-router'
|
|
|
+import process from '@/api/flow/process'
|
|
|
+import useStore from '@/store'
|
|
|
+import { ElMessage } from 'element-plus'
|
|
|
+const { tagsView } = useStore()
|
|
|
+const router = useRouter()
|
|
|
+const route = useRoute()
|
|
|
+const flowStore = useFlowStore()
|
|
|
+const { categoryId, processId, processIcon, processKey, processName, remark, modelContent, processForm, processSetting } = storeToRefs(flowStore)
|
|
|
+
|
|
|
+const compRefs = ref() // 实例化子组件
|
|
|
+const cache_components = ref({})
|
|
|
+const componentsArr = [
|
|
|
+ {
|
|
|
+ component: BasicInfoTab,
|
|
|
+ label: '基础信息',
|
|
|
+ value: '基础信息'
|
|
|
+ // ref: 'basicInfoRef'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ component: FlowDesignTab,
|
|
|
+ label: '流程设计',
|
|
|
+ value: '流程设计'
|
|
|
+ // ref: 'flowDesignRef'
|
|
|
+ }
|
|
|
+]
|
|
|
+const activeTab = ref('基础信息')
|
|
|
+const removeCurTab = () => {
|
|
|
+ cache_components.value = {}
|
|
|
+ const _view = tagsView.visitedViews.find(v => v.path === '/flow_create/child')
|
|
|
+ if (_view)
|
|
|
+ tagsView.delView(_view).then(res => {
|
|
|
+ const latestView = res.visitedViews.slice(-1)[0]
|
|
|
+ if (latestView && latestView.fullPath) {
|
|
|
+ router.push(latestView.fullPath)
|
|
|
+ } else {
|
|
|
+ router.push('/')
|
|
|
+ }
|
|
|
+ flowStore.$reset()
|
|
|
+ })
|
|
|
+}
|
|
|
+const submitHandler = async () => {
|
|
|
+ // 基础信息
|
|
|
+ // 表单设计
|
|
|
+ // 流程设计
|
|
|
+ // 扩展设置
|
|
|
+ let leavePageFlag = await validateTabs()
|
|
|
+ // let _id = queryObj.value.id
|
|
|
+ // if (_id) {
|
|
|
+ //
|
|
|
+ // } else {
|
|
|
+ // leavePageFlag = await validateTabs()
|
|
|
+ // }
|
|
|
+ if (!leavePageFlag) return
|
|
|
+ const params = {
|
|
|
+ categoryId: categoryId.value,
|
|
|
+ processIcon: processIcon.value,
|
|
|
+ processKey: processKey.value,
|
|
|
+ processName: processName.value,
|
|
|
+ remark: remark.value,
|
|
|
+ processId: processId.value,
|
|
|
+ processForm: processForm.value,
|
|
|
+ modelContent: JSON.stringify({
|
|
|
+ key: processKey.value,
|
|
|
+ name: processName.value,
|
|
|
+ nodeConfig: JSON.parse(modelContent.value || '{}')
|
|
|
+ }),
|
|
|
+ processSetting: processSetting.value
|
|
|
+ }
|
|
|
+ const res = await process.progressCreateApi(params)
|
|
|
+ ElMessage.success('操作成功')
|
|
|
+ // 创建完成 删除 当前tab页
|
|
|
+ removeCurTab()
|
|
|
+}
|
|
|
+
|
|
|
+// 切换选项卡之前,做相应的保存操作
|
|
|
+const validateTabs = async () => {
|
|
|
+ const _refs = compRefs.value
|
|
|
+ // await nextTick()
|
|
|
+ for (let i = 0; i < _refs.length; i++) {
|
|
|
+ let bool = true
|
|
|
+ /*// 若没开启过的 tab 需要尝试 进行更新数据
|
|
|
+ if (!cache_components.value[i]) {
|
|
|
+ cache_components.value[i]?.updateCompInfo()
|
|
|
+ }*/
|
|
|
+ const _validate =
|
|
|
+ _refs[i]?.validate ||
|
|
|
+ function () {
|
|
|
+ return Promise.resolve()
|
|
|
+ }
|
|
|
+ await _validate().catch(e => {
|
|
|
+ activeTab.value = componentsArr[i].label
|
|
|
+ if (activeTab.value === '表单设计') {
|
|
|
+ ElMessage.error('请为流程设计表单内容')
|
|
|
+ }
|
|
|
+ bool = false
|
|
|
+ })
|
|
|
+ if (!bool) return false
|
|
|
+ }
|
|
|
+ return true
|
|
|
+}
|
|
|
+
|
|
|
+const activeComponent = index => {
|
|
|
+ const cur = componentsArr[index]
|
|
|
+ if (activeTab.value !== cur.value) {
|
|
|
+ if (activeTab.value === '表单设计') {
|
|
|
+ compRefs.value[1]?.exportJsonEv()
|
|
|
+ }
|
|
|
+ // 当前缓存
|
|
|
+ if (!cache_components.value[index]) {
|
|
|
+ // 更新数据
|
|
|
+ const updateCompInfo = compRefs.value[index]?.updateCompInfo
|
|
|
+ // console.error('刷新数据')
|
|
|
+ // console.error(updateCompInfo, 'updateCompInfo')
|
|
|
+ if (updateCompInfo) {
|
|
|
+ updateCompInfo()
|
|
|
+ }
|
|
|
+ }
|
|
|
+ activeTab.value = cur.value
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+const queryObj = computed(() => route.query)
|
|
|
+
|
|
|
+const getCurrentProcessDetailEv = () => {
|
|
|
+ let _id = queryObj.value.id
|
|
|
+ if (_id) {
|
|
|
+ cache_components.value = {}
|
|
|
+ process.processDetailApi(_id).then(res => {
|
|
|
+ processId.value = res.processId
|
|
|
+ categoryId.value = res.categoryId
|
|
|
+ processIcon.value = res.processIcon
|
|
|
+ processKey.value = res.processKey
|
|
|
+ processName.value = res.processName
|
|
|
+ remark.value = res.remark
|
|
|
+ let nodeConfig = JSON.parse(res.modelContent).nodeConfig
|
|
|
+ modelContent.value = JSON.stringify(nodeConfig)
|
|
|
+ processForm.value = res.processForm
|
|
|
+ flowStore.setProcessForm(processForm)
|
|
|
+ flowStore.setProcessSetting(res.processSetting)
|
|
|
+ // 默认执行一次保存
|
|
|
+ const _refs = compRefs.value
|
|
|
+ for (let i = 0; i < _refs.length; i++) {
|
|
|
+ const updateCompInfo = compRefs.value[i]?.updateCompInfo
|
|
|
+ if (updateCompInfo) {
|
|
|
+ updateCompInfo()
|
|
|
+ }
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+getCurrentProcessDetailEv()
|
|
|
+</script>
|
|
|
+
|
|
|
+<style scoped lang="scss">
|
|
|
+.create-approval {
|
|
|
+ height: 100%;
|
|
|
+ min-width: 1200px;
|
|
|
+ min-height: 600px;
|
|
|
+ overflow: auto;
|
|
|
+
|
|
|
+ &-header {
|
|
|
+ justify-content: flex-start;
|
|
|
+ height: 64px;
|
|
|
+ //z-index: 12;
|
|
|
+ position: relative;
|
|
|
+ box-shadow: 0 1px 6px 0 rgba(0, 0, 0, 0.06);
|
|
|
+ padding-left: 16px;
|
|
|
+ padding-right: 20px;
|
|
|
+
|
|
|
+ &-back {
|
|
|
+ display: flex;
|
|
|
+ justify-content: flex-start;
|
|
|
+ align-items: center;
|
|
|
+ height: 100%;
|
|
|
+ margin-right: 15px;
|
|
|
+ }
|
|
|
+
|
|
|
+ &-left-zh {
|
|
|
+ width: calc(50% - 316.5px);
|
|
|
+ min-width: 248px;
|
|
|
+ }
|
|
|
+
|
|
|
+ &-name {
|
|
|
+ font-weight: 500;
|
|
|
+ font-size: 16px;
|
|
|
+ white-space: nowrap;
|
|
|
+ cursor: pointer;
|
|
|
+ width: -webkit-fit-content;
|
|
|
+ width: -moz-fit-content;
|
|
|
+ width: fit-content;
|
|
|
+ max-width: 100%;
|
|
|
+ height: 24px;
|
|
|
+ overflow: hidden;
|
|
|
+ text-overflow: ellipsis;
|
|
|
+ }
|
|
|
+
|
|
|
+ &-time {
|
|
|
+ width: 100%;
|
|
|
+ height: 20px;
|
|
|
+ line-height: 20px;
|
|
|
+ font-size: 12px;
|
|
|
+ color: #8f959e;
|
|
|
+ overflow: hidden;
|
|
|
+ white-space: nowrap;
|
|
|
+ text-overflow: ellipsis;
|
|
|
+ }
|
|
|
+
|
|
|
+ &-tab-list {
|
|
|
+ margin-left: 10px;
|
|
|
+ flex-shrink: 0;
|
|
|
+ display: flex;
|
|
|
+ justify-content: center;
|
|
|
+ }
|
|
|
+
|
|
|
+ &-tab-item {
|
|
|
+ font-family: PingFang SC, Microsoft YaHei;
|
|
|
+ font-size: 18px;
|
|
|
+ line-height: 28px;
|
|
|
+ color: #646a73;
|
|
|
+ margin-right: 42px;
|
|
|
+ padding: 18px 0;
|
|
|
+ border-bottom: 2px solid transparent;
|
|
|
+ cursor: pointer;
|
|
|
+
|
|
|
+ &.active {
|
|
|
+ // var(--el-color-primary);
|
|
|
+ border-bottom-color: var(--el-color-primary);
|
|
|
+ color: var(--el-color-primary);
|
|
|
+ font-weight: 500;
|
|
|
+
|
|
|
+ .create-approval-header-tab-counter {
|
|
|
+ border-color: var(--el-color-primary);
|
|
|
+ background-color: var(--el-color-primary);
|
|
|
+ color: var(--el-color-white);
|
|
|
+ font-weight: 400;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ &-tab-counter {
|
|
|
+ display: inline-block;
|
|
|
+ margin-right: 6px;
|
|
|
+ width: 24px;
|
|
|
+ height: 24px;
|
|
|
+ border-radius: 50%;
|
|
|
+ border: 1px solid #646a73;
|
|
|
+ font-size: 16px;
|
|
|
+ line-height: 22px;
|
|
|
+ text-align: center;
|
|
|
+ }
|
|
|
+
|
|
|
+ &-right {
|
|
|
+ flex: 1 1;
|
|
|
+ flex-shrink: 0;
|
|
|
+ display: flex;
|
|
|
+ justify-content: flex-end;
|
|
|
+ align-items: center;
|
|
|
+ position: relative;
|
|
|
+ height: 100%;
|
|
|
+ width: -webkit-fit-content;
|
|
|
+ width: -moz-fit-content;
|
|
|
+ width: fit-content;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ &-main {
|
|
|
+ height: calc(100% - 64px);
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|