Merge pull request #123 from zws-code/feature/bpm_fix_250116

Feature/bpm fix 250116
This commit is contained in:
芋道源码 2025-01-17 19:38:03 +08:00 committed by GitHub
commit cde758d324
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 110 additions and 61 deletions

View File

@ -51,6 +51,7 @@ import { SimpleFlowNode, NodeType, NODE_DEFAULT_TEXT } from './consts'
import { useWatchNode } from './node' import { useWatchNode } from './node'
import { ZoomOut, ZoomIn, ScaleToOriginal } from '@element-plus/icons-vue' import { ZoomOut, ZoomIn, ScaleToOriginal } from '@element-plus/icons-vue'
import { isString } from '@/utils/is' import { isString } from '@/utils/is'
import download from "@/utils/download";
defineOptions({ defineOptions({
name: 'SimpleProcessModel' name: 'SimpleProcessModel'
@ -174,18 +175,7 @@ defineExpose({
/** 导出 JSON */ /** 导出 JSON */
// TODO @zws download json // TODO @zws download json
const exportJson = () => { const exportJson = () => {
const blob = new Blob([JSON.stringify(processNodeTree.value)]) download.json(new Blob([JSON.stringify(processNodeTree.value)]), 'model.json')
const tempLink = document.createElement('a') // a
const href = window.URL.createObjectURL(blob) //
// filename
const fileName = `model.json`
tempLink.href = href
tempLink.target = '_blank'
tempLink.download = fileName
document.body.appendChild(tempLink)
tempLink.click() //
document.body.removeChild(tempLink) //
window.URL.revokeObjectURL(href) // blob
} }
/** 导入 JSON */ /** 导入 JSON */
@ -200,6 +190,7 @@ const importLocalFile = () => {
reader.onload = function () { reader.onload = function () {
if (isString(this.result)) { if (isString(this.result)) {
processNodeTree.value = JSON.parse(this.result) processNodeTree.value = JSON.parse(this.result)
emits('save', processNodeTree.value)
} }
} }
} }

View File

@ -547,6 +547,7 @@ const importLocalFile = () => {
reader.onload = function () { reader.onload = function () {
let xmlStr = this.result let xmlStr = this.result
createNewDiagram(xmlStr) createNewDiagram(xmlStr)
emit('save', xmlStr)
} }
} }
/* ------------------------------------------------ refs methods ------------------------------------------------------ */ /* ------------------------------------------------ refs methods ------------------------------------------------------ */

View File

@ -152,6 +152,9 @@ watch(
handleKeyUpdate(props.model.key) handleKeyUpdate(props.model.key)
handleNameUpdate(props.model.name) handleNameUpdate(props.model.name)
} }
},
{
immediate: true
} }
) )

View File

@ -12,6 +12,11 @@ import { useDesign } from '@/hooks/web/useDesign'
import { useTemplateRefsList } from '@vueuse/core' import { useTemplateRefsList } from '@vueuse/core'
import { ElScrollbar } from 'element-plus' import { ElScrollbar } from 'element-plus'
import { useScrollTo } from '@/hooks/event/useScrollTo' import { useScrollTo } from '@/hooks/event/useScrollTo'
import { useTagsView } from '@/hooks/web/useTagsView'
import { cloneDeep } from 'lodash-es'
defineOptions({ name: 'TagsView' })
const { getPrefixCls } = useDesign() const { getPrefixCls } = useDesign()
@ -19,7 +24,9 @@ const prefixCls = getPrefixCls('tags-view')
const { t } = useI18n() const { t } = useI18n()
const { currentRoute, push, replace } = useRouter() const { currentRoute, push } = useRouter()
const { closeAll, closeLeft, closeRight, closeOther, closeCurrent, refreshPage } = useTagsView()
const permissionStore = usePermissionStore() const permissionStore = usePermissionStore()
@ -31,6 +38,10 @@ const visitedViews = computed(() => tagsViewStore.getVisitedViews)
const affixTagArr = ref<RouteLocationNormalizedLoaded[]>([]) const affixTagArr = ref<RouteLocationNormalizedLoaded[]>([])
const selectedTag = computed(() => tagsViewStore.getSelectedTag)
const setSelectTag = tagsViewStore.setSelectedTag
const appStore = useAppStore() const appStore = useAppStore()
const tagsViewImmerse = computed(() => appStore.getTagsViewImmerse) const tagsViewImmerse = computed(() => appStore.getTagsViewImmerse)
@ -45,66 +56,30 @@ const initTags = () => {
for (const tag of unref(affixTagArr)) { for (const tag of unref(affixTagArr)) {
// Must have tag name // Must have tag name
if (tag.name) { if (tag.name) {
tagsViewStore.addVisitedView(tag) tagsViewStore.addVisitedView(cloneDeep(tag))
} }
} }
} }
const selectedTag = ref<RouteLocationNormalizedLoaded>()
// tag // tag
const addTags = () => { const addTags = () => {
const { name } = unref(currentRoute) const { name } = unref(currentRoute)
if (name) { if (name) {
selectedTag.value = unref(currentRoute) setSelectTag(unref(currentRoute))
tagsViewStore.addView(unref(currentRoute)) tagsViewStore.addView(unref(currentRoute))
} }
return false
} }
// tag // tag
const closeSelectedTag = (view: RouteLocationNormalizedLoaded) => { const closeSelectedTag = (view: RouteLocationNormalizedLoaded) => {
if (view?.meta?.affix) return closeCurrent(view, () => {
tagsViewStore.delView(view)
if (isActive(view)) { if (isActive(view)) {
toLastView() toLastView()
} }
}
//
const closeAllTags = () => {
tagsViewStore.delAllViews()
toLastView()
}
//
const closeOthersTags = () => {
tagsViewStore.delOthersViews(unref(selectedTag) as RouteLocationNormalizedLoaded)
}
//
const refreshSelectedTag = async (view?: RouteLocationNormalizedLoaded) => {
if (!view) return
tagsViewStore.delCachedView()
const { path, query } = view
await nextTick()
replace({
path: '/redirect' + path,
query: query
}) })
} }
// //
const closeLeftTags = () => {
tagsViewStore.delLeftViews(unref(selectedTag) as RouteLocationNormalizedLoaded)
}
//
const closeRightTags = () => {
tagsViewStore.delRightViews(unref(selectedTag) as RouteLocationNormalizedLoaded)
}
//
const toLastView = () => { const toLastView = () => {
const visitedViews = tagsViewStore.getVisitedViews const visitedViews = tagsViewStore.getVisitedViews
const latestView = visitedViews.slice(-1)[0] const latestView = visitedViews.slice(-1)[0]
@ -118,11 +93,38 @@ const toLastView = () => {
addTags() addTags()
return return
} }
// TODO: You can set another route // You can set another route
push('/') push(permissionStore.getAddRouters[0].path)
} }
} }
//
const closeAllTags = () => {
closeAll(() => {
toLastView()
})
}
//
const closeOthersTags = () => {
closeOther()
}
//
const refreshSelectedTag = async (view?: RouteLocationNormalizedLoaded) => {
refreshPage(view)
}
//
const closeLeftTags = () => {
closeLeft()
}
//
const closeRightTags = () => {
closeRight()
}
// tag // tag
const moveToCurrentTag = async () => { const moveToCurrentTag = async () => {
await nextTick() await nextTick()
@ -209,13 +211,14 @@ const isActive = (route: RouteLocationNormalizedLoaded): boolean => {
// //
const itemRefs = useTemplateRefsList<ComponentRef<typeof ContextMenu & ContextMenuExpose>>() const itemRefs = useTemplateRefsList<ComponentRef<typeof ContextMenu & ContextMenuExpose>>()
// //
const visibleChange = (visible: boolean, tagItem: RouteLocationNormalizedLoaded) => { const visibleChange = (visible: boolean, tagItem: RouteLocationNormalizedLoaded) => {
if (visible) { if (visible) {
for (const v of unref(itemRefs)) { for (const v of unref(itemRefs)) {
const elDropdownMenuRef = v.elDropdownMenuRef const elDropdownMenuRef = v.elDropdownMenuRef
if (tagItem.fullPath !== v.tagItem.fullPath) { if (tagItem.fullPath !== v.tagItem.fullPath) {
elDropdownMenuRef?.handleClose() elDropdownMenuRef?.handleClose()
setSelectTag(tagItem)
} }
} }
} }
@ -243,6 +246,16 @@ const move = (to: number) => {
start() start()
} }
const canShowIcon = (item: RouteLocationNormalizedLoaded) => {
if (
(item?.matched?.[1]?.meta?.icon && unref(tagsViewIcon)) ||
(item?.meta?.affix && unref(tagsViewIcon) && item?.meta?.icon)
) {
return true
}
return false
}
onBeforeMount(() => { onBeforeMount(() => {
initTags() initTags()
addTags() addTags()

View File

@ -4,16 +4,19 @@ import { getRawRoute } from '@/utils/routerHelper'
import { defineStore } from 'pinia' import { defineStore } from 'pinia'
import { store } from '../index' import { store } from '../index'
import { findIndex } from '@/utils' import { findIndex } from '@/utils'
import { useUserStoreWithOut } from './user'
export interface TagsViewState { export interface TagsViewState {
visitedViews: RouteLocationNormalizedLoaded[] visitedViews: RouteLocationNormalizedLoaded[]
cachedViews: Set<string> cachedViews: Set<string>
selectedTag?: RouteLocationNormalizedLoaded
} }
export const useTagsViewStore = defineStore('tagsView', { export const useTagsViewStore = defineStore('tagsView', {
state: (): TagsViewState => ({ state: (): TagsViewState => ({
visitedViews: [], visitedViews: [],
cachedViews: new Set() cachedViews: new Set(),
selectedTag: undefined
}), }),
getters: { getters: {
getVisitedViews(): RouteLocationNormalizedLoaded[] { getVisitedViews(): RouteLocationNormalizedLoaded[] {
@ -21,6 +24,9 @@ export const useTagsViewStore = defineStore('tagsView', {
}, },
getCachedViews(): string[] { getCachedViews(): string[] {
return Array.from(this.cachedViews) return Array.from(this.cachedViews)
},
getSelectedTag(): RouteLocationNormalizedLoaded | undefined {
return this.selectedTag
} }
}, },
actions: { actions: {
@ -98,8 +104,12 @@ export const useTagsViewStore = defineStore('tagsView', {
}, },
// 删除所有tag // 删除所有tag
delAllVisitedViews() { delAllVisitedViews() {
const userStore = useUserStoreWithOut()
// const affixTags = this.visitedViews.filter((tag) => tag.meta.affix) // const affixTags = this.visitedViews.filter((tag) => tag.meta.affix)
this.visitedViews = [] this.visitedViews = userStore.getUser
? this.visitedViews.filter((tag) => tag?.meta?.affix)
: []
}, },
// 删除其他 // 删除其他
delOthersViews(view: RouteLocationNormalizedLoaded) { delOthersViews(view: RouteLocationNormalizedLoaded) {
@ -145,6 +155,18 @@ export const useTagsViewStore = defineStore('tagsView', {
break break
} }
} }
},
// 设置当前选中的tag
setSelectedTag(tag: RouteLocationNormalizedLoaded) {
this.selectedTag = tag
},
setTitle(title: string, path?: string) {
for (const v of this.visitedViews) {
if (v.path === (path ?? this.selectedTag?.path)) {
v.meta.title = title
break
}
}
} }
}, },
persist: false persist: false

View File

@ -33,6 +33,10 @@ const download = {
markdown: (data: Blob, fileName: string) => { markdown: (data: Blob, fileName: string) => {
download0(data, fileName, 'text/markdown') download0(data, fileName, 'text/markdown')
}, },
// 下载 Json 方法
json: (data: Blob, fileName: string) => {
download0(data, fileName, 'application/json')
},
// 下载图片(允许跨域) // 下载图片(允许跨域)
image: ({ image: ({
url, url,

View File

@ -254,6 +254,7 @@ import { checkPermi } from '@/utils/permission'
import { useUserStoreWithOut } from '@/store/modules/user' import { useUserStoreWithOut } from '@/store/modules/user'
import { useAppStore } from '@/store/modules/app' import { useAppStore } from '@/store/modules/app'
import { cloneDeep } from 'lodash-es' import { cloneDeep } from 'lodash-es'
import {useTagsView} from "@/hooks/web/useTagsView";
defineOptions({ name: 'BpmModel' }) defineOptions({ name: 'BpmModel' })
@ -474,6 +475,7 @@ const handleDeleteCategory = async () => {
} catch {} } catch {}
} }
const tagsView = useTagsView();
/** 添加流程模型弹窗 */ /** 添加流程模型弹窗 */
const modelFormRef = ref() const modelFormRef = ref()
const openModelForm = (type: string, id?: number) => { const openModelForm = (type: string, id?: number) => {
@ -483,6 +485,10 @@ const openModelForm = (type: string, id?: number) => {
push({ push({
name: 'BpmModelUpdate', name: 'BpmModelUpdate',
params: { id, type } params: { id, type }
}).then((_) => {
if (type === 'copy') {
tagsView.setTitle('复制流程')
}
}) })
} }
} }

View File

@ -12,6 +12,8 @@
:additionalModel="controlForm.additionalModel" :additionalModel="controlForm.additionalModel"
:model="model" :model="model"
@save="save" @save="save"
:process-id="modelKey"
:process-name="modelName"
/> />
<!-- 流程属性器负责编辑每个流程节点的属性 --> <!-- 流程属性器负责编辑每个流程节点的属性 -->
<MyProcessPenal <MyProcessPenal
@ -53,6 +55,8 @@ provide('formType', formType)
// //
const xmlString = inject('processData') as Ref const xmlString = inject('processData') as Ref
//
const modelData = inject('modelData') as Ref
const modeler = shallowRef() // BPMN Modeler const modeler = shallowRef() // BPMN Modeler
const processDesigner = ref() const processDesigner = ref()
@ -69,6 +73,8 @@ const model = ref<ModelApi.ModelVO>() // 流程模型的信息
/** 初始化 modeler */ /** 初始化 modeler */
// TODO @zwskeyname // TODO @zwskeyname
const initModeler = async (item) => { const initModeler = async (item) => {
//
model.value = modelData.value
modeler.value = item modeler.value = item
} }

View File

@ -145,6 +145,7 @@ const formData: any = ref({
const processData = ref<any>() const processData = ref<any>()
provide('processData', processData) provide('processData', processData)
provide('modelData', formData)
// //
const formList = ref([]) const formList = ref([])
@ -160,6 +161,8 @@ const initData = async () => {
// //
if (route.params.type === 'copy') { if (route.params.type === 'copy') {
delete formData.value.id delete formData.value.id
formData.value.name += '副本'
formData.value.key += '_copy'
} }
} else { } else {
// //