mirror of
https://gitee.com/myxzgzs/boyue-ui-admin-vue3
synced 2025-08-10 01:12:44 +08:00
Merge branch 'feature/bpm' of https://github.com/yudaocode/yudao-ui-admin-vue3 into feature/bpm
This commit is contained in:
commit
6b1c0e7369
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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 ------------------------------------------------------ */
|
||||||
|
@ -152,6 +152,9 @@ watch(
|
|||||||
handleKeyUpdate(props.model.key)
|
handleKeyUpdate(props.model.key)
|
||||||
handleNameUpdate(props.model.name)
|
handleNameUpdate(props.model.name)
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
immediate: true
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -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()
|
||||||
|
@ -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
|
||||||
|
@ -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,
|
||||||
|
@ -262,6 +262,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' })
|
||||||
|
|
||||||
@ -498,6 +499,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) => {
|
||||||
@ -507,6 +509,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('复制流程')
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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 @zws:需要初始化,不然首次创建后,无法发布!相当于说,key、name 要去赋值下
|
// TODO @zws:需要初始化,不然首次创建后,无法发布!相当于说,key、name 要去赋值下
|
||||||
const initModeler = async (item) => {
|
const initModeler = async (item) => {
|
||||||
|
//先初始化模型数据
|
||||||
|
model.value = modelData.value
|
||||||
modeler.value = item
|
modeler.value = item
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 {
|
||||||
// 新增场景
|
// 新增场景
|
||||||
|
Loading…
x
Reference in New Issue
Block a user