mirror of
https://gitee.com/cai_xiao_feng/lowflow-design.git
synced 2025-12-08 00:58:23 +08:00
完善只读模式
This commit is contained in:
parent
b48706c2c4
commit
be7f45ff0a
4
src/typings/components.d.ts
vendored
4
src/typings/components.d.ts
vendored
@ -10,6 +10,7 @@ declare module 'vue' {
|
|||||||
AdvancedFilter: typeof import('./../components/AdvancedFilter/index.vue')['default']
|
AdvancedFilter: typeof import('./../components/AdvancedFilter/index.vue')['default']
|
||||||
ElAvatar: typeof import('element-plus/es')['ElAvatar']
|
ElAvatar: typeof import('element-plus/es')['ElAvatar']
|
||||||
ElButton: typeof import('element-plus/es')['ElButton']
|
ElButton: typeof import('element-plus/es')['ElButton']
|
||||||
|
ElButtonGroup: typeof import('element-plus/es')['ElButtonGroup']
|
||||||
ElCard: typeof import('element-plus/es')['ElCard']
|
ElCard: typeof import('element-plus/es')['ElCard']
|
||||||
ElCheckbox: typeof import('element-plus/es')['ElCheckbox']
|
ElCheckbox: typeof import('element-plus/es')['ElCheckbox']
|
||||||
ElCol: typeof import('element-plus/es')['ElCol']
|
ElCol: typeof import('element-plus/es')['ElCol']
|
||||||
@ -17,6 +18,9 @@ declare module 'vue' {
|
|||||||
ElDatePicker: typeof import('element-plus/es')['ElDatePicker']
|
ElDatePicker: typeof import('element-plus/es')['ElDatePicker']
|
||||||
ElDialog: typeof import('element-plus/es')['ElDialog']
|
ElDialog: typeof import('element-plus/es')['ElDialog']
|
||||||
ElDrawer: typeof import('element-plus/es')['ElDrawer']
|
ElDrawer: typeof import('element-plus/es')['ElDrawer']
|
||||||
|
ElDropdown: typeof import('element-plus/es')['ElDropdown']
|
||||||
|
ElDropdownItem: typeof import('element-plus/es')['ElDropdownItem']
|
||||||
|
ElDropdownMenu: typeof import('element-plus/es')['ElDropdownMenu']
|
||||||
ElForm: typeof import('element-plus/es')['ElForm']
|
ElForm: typeof import('element-plus/es')['ElForm']
|
||||||
ElFormItem: typeof import('element-plus/es')['ElFormItem']
|
ElFormItem: typeof import('element-plus/es')['ElFormItem']
|
||||||
ElIcon: typeof import('element-plus/es')['ElIcon']
|
ElIcon: typeof import('element-plus/es')['ElIcon']
|
||||||
|
|||||||
@ -12,7 +12,6 @@ import type {
|
|||||||
} from './nodes/type'
|
} from './nodes/type'
|
||||||
import type { FilterRules } from '@/components/AdvancedFilter/type'
|
import type { FilterRules } from '@/components/AdvancedFilter/type'
|
||||||
import type { Field } from '@/components/Render/type'
|
import type { Field } from '@/components/Render/type'
|
||||||
import { downloadXml } from '@/api/modules/model'
|
|
||||||
|
|
||||||
const props = withDefaults(
|
const props = withDefaults(
|
||||||
defineProps<{
|
defineProps<{
|
||||||
@ -27,7 +26,6 @@ const props = withDefaults(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
const isDark = ref(false)
|
|
||||||
const flatFields = computed(() => {
|
const flatFields = computed(() => {
|
||||||
const all: Field[] = []
|
const all: Field[] = []
|
||||||
const loop = (children: Field[]) => {
|
const loop = (children: Field[]) => {
|
||||||
@ -45,6 +43,7 @@ const flatFields = computed(() => {
|
|||||||
})
|
})
|
||||||
const getScale = computed(() => zoom.value / 100)
|
const getScale = computed(() => zoom.value / 100)
|
||||||
const zoom = ref(props.defaultZoom)
|
const zoom = ref(props.defaultZoom)
|
||||||
|
const readOnly = computed(() => props.readOnly)
|
||||||
const activeData = ref<FlowNode>({
|
const activeData = ref<FlowNode>({
|
||||||
id: '',
|
id: '',
|
||||||
name: '',
|
name: '',
|
||||||
@ -53,17 +52,10 @@ const activeData = ref<FlowNode>({
|
|||||||
const penalVisible = ref(false)
|
const penalVisible = ref(false)
|
||||||
const nodesError = ref<Recordable<ErrorInfo[]>>({})
|
const nodesError = ref<Recordable<ErrorInfo[]>>({})
|
||||||
provide('flowDesign', {
|
provide('flowDesign', {
|
||||||
readOnly: props.readOnly || false,
|
readOnly: readOnly,
|
||||||
fields: flatFields,
|
fields: flatFields,
|
||||||
nodesError: nodesError
|
nodesError: nodesError
|
||||||
})
|
})
|
||||||
const handleToggleDark = () => {
|
|
||||||
if (isDark.value) {
|
|
||||||
document.documentElement.classList.add('dark')
|
|
||||||
} else {
|
|
||||||
document.documentElement.classList.remove('dark')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const openPenal = (node: FlowNode) => {
|
const openPenal = (node: FlowNode) => {
|
||||||
activeData.value = node
|
activeData.value = node
|
||||||
penalVisible.value = true
|
penalVisible.value = true
|
||||||
@ -284,23 +276,6 @@ const validate = () => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
const converterBpmn = () => {
|
|
||||||
const processModel = {
|
|
||||||
code: 'test',
|
|
||||||
name: '测试',
|
|
||||||
icon: {
|
|
||||||
name: 'el:HomeFilled',
|
|
||||||
color: '#409EFF'
|
|
||||||
},
|
|
||||||
process: props.process,
|
|
||||||
enable: true,
|
|
||||||
version: 1,
|
|
||||||
sort: 0,
|
|
||||||
groupId: '',
|
|
||||||
remark: ''
|
|
||||||
}
|
|
||||||
downloadXml(processModel)
|
|
||||||
}
|
|
||||||
defineExpose({
|
defineExpose({
|
||||||
validate
|
validate
|
||||||
})
|
})
|
||||||
@ -309,13 +284,7 @@ defineExpose({
|
|||||||
<template>
|
<template>
|
||||||
<div class="designer-container">
|
<div class="designer-container">
|
||||||
<div class="tool">
|
<div class="tool">
|
||||||
<el-switch
|
<slot></slot>
|
||||||
inline-prompt
|
|
||||||
active-icon="Sunny"
|
|
||||||
inactive-icon="Moon"
|
|
||||||
@change="handleToggleDark"
|
|
||||||
v-model="isDark"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<!--放大/缩小-->
|
<!--放大/缩小-->
|
||||||
<div class="zoom">
|
<div class="zoom">
|
||||||
@ -326,7 +295,6 @@ defineExpose({
|
|||||||
<el-tooltip content="缩小" placement="bottom-start">
|
<el-tooltip content="缩小" placement="bottom-start">
|
||||||
<el-button icon="minus" @click="zoom -= 10" circle :disabled="zoom <= 50"></el-button>
|
<el-button icon="minus" @click="zoom -= 10" circle :disabled="zoom <= 50"></el-button>
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
<el-button @click="converterBpmn" type="primary" icon="Download">转bpmn</el-button>
|
|
||||||
</div>
|
</div>
|
||||||
<!--流程树-->
|
<!--流程树-->
|
||||||
<div class="node-container">
|
<div class="node-container">
|
||||||
@ -361,8 +329,10 @@ defineExpose({
|
|||||||
.tool {
|
.tool {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
z-index: 999;
|
z-index: 999;
|
||||||
top: 10px;
|
top: 5px;
|
||||||
left: 20px;
|
left: 5px;
|
||||||
|
display: flex;
|
||||||
|
gap: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.node-container {
|
.node-container {
|
||||||
|
|||||||
@ -1,10 +1,11 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { PopoverInstance } from 'element-plus'
|
import type { PopoverInstance } from 'element-plus'
|
||||||
import type { NodeType } from './type'
|
import type { NodeType } from './type'
|
||||||
|
import type { Ref } from 'vue'
|
||||||
|
|
||||||
const { readOnly } = inject<{
|
const { readOnly } = inject<{
|
||||||
readOnly?: boolean
|
readOnly?: Ref<boolean>
|
||||||
}>('flowDesign', { readOnly: false })
|
}>('flowDesign', { readOnly: ref(false) })
|
||||||
const popoverRef = ref<PopoverInstance>()
|
const popoverRef = ref<PopoverInstance>()
|
||||||
const $emits = defineEmits<{
|
const $emits = defineEmits<{
|
||||||
(e: 'addNode', type: NodeType): void
|
(e: 'addNode', type: NodeType): void
|
||||||
@ -100,6 +101,7 @@ const addTimerNode = () => {
|
|||||||
&.Share {
|
&.Share {
|
||||||
background-color: #45cf9b;
|
background-color: #45cf9b;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.Timer {
|
&.Timer {
|
||||||
background-color: #e872b7;
|
background-color: #e872b7;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,6 +2,7 @@
|
|||||||
import TreeNode from './TreeNode.vue'
|
import TreeNode from './TreeNode.vue'
|
||||||
import type { BranchNode, FlowNode, NodeType } from './type'
|
import type { BranchNode, FlowNode, NodeType } from './type'
|
||||||
import Add from './Add.vue'
|
import Add from './Add.vue'
|
||||||
|
import type { Ref } from 'vue'
|
||||||
|
|
||||||
const $emits = defineEmits<{
|
const $emits = defineEmits<{
|
||||||
(e: 'addNode', type: NodeType, node: FlowNode): void
|
(e: 'addNode', type: NodeType, node: FlowNode): void
|
||||||
@ -10,8 +11,8 @@ const props = defineProps<{
|
|||||||
node: BranchNode
|
node: BranchNode
|
||||||
}>()
|
}>()
|
||||||
const { readOnly } = inject<{
|
const { readOnly } = inject<{
|
||||||
readOnly?: boolean
|
readOnly?: Ref<boolean>
|
||||||
}>('flowDesign', { readOnly: false })
|
}>('flowDesign', { readOnly: ref(false) })
|
||||||
const addNode = (type: NodeType, node?: FlowNode) => {
|
const addNode = (type: NodeType, node?: FlowNode) => {
|
||||||
$emits('addNode', type, node || props.node)
|
$emits('addNode', type, node || props.node)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,9 +5,9 @@ import Add from './Add.vue'
|
|||||||
import type { Ref } from 'vue'
|
import type { Ref } from 'vue'
|
||||||
|
|
||||||
const _inject = inject<{
|
const _inject = inject<{
|
||||||
readOnly?: boolean
|
readOnly?: Ref<boolean>
|
||||||
nodesError: Ref<Recordable<ErrorInfo[]>>
|
nodesError: Ref<Recordable<ErrorInfo[]>>
|
||||||
}>('flowDesign', { readOnly: false, nodesError: ref({}) })
|
}>('flowDesign', { readOnly: ref(false), nodesError: ref({}) })
|
||||||
const $emits = defineEmits<{
|
const $emits = defineEmits<{
|
||||||
(e: 'addNode', type: NodeType, node: FlowNode): void
|
(e: 'addNode', type: NodeType, node: FlowNode): void
|
||||||
(e: 'delNode', node: FlowNode): void
|
(e: 'delNode', node: FlowNode): void
|
||||||
@ -27,7 +27,7 @@ const $props = withDefaults(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
const errorInfo = computed<ErrorInfo[] | undefined>(() => _inject.nodesError.value[$props.node.id])
|
const errorInfo = computed<ErrorInfo[] | undefined>(() => _inject.nodesError.value[$props.node.id])
|
||||||
const _readOnly = computed(() => _inject.readOnly || $props.readOnly)
|
const _readOnly = computed(() => _inject.readOnly?.value || $props.readOnly)
|
||||||
const showInput = ref(false)
|
const showInput = ref(false)
|
||||||
const inputRef = ref<InputInstance>()
|
const inputRef = ref<InputInstance>()
|
||||||
const onShowInput = () => {
|
const onShowInput = () => {
|
||||||
@ -56,7 +56,10 @@ const delNode = () => {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="node-box">
|
<div class="node-box">
|
||||||
<el-card @click="activeNode" :class="['node', { 'error-node': errorInfo?.length }]">
|
<el-card
|
||||||
|
@click="activeNode"
|
||||||
|
:class="['node', { 'error-node': errorInfo?.length && !_readOnly }]"
|
||||||
|
>
|
||||||
<!--头部-->
|
<!--头部-->
|
||||||
<template #header>
|
<template #header>
|
||||||
<div class="head">
|
<div class="head">
|
||||||
@ -108,7 +111,7 @@ const delNode = () => {
|
|||||||
{{ err.message }}
|
{{ err.message }}
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<el-icon class="warn-icon" :size="20" v-show="errorInfo?.length">
|
<el-icon class="warn-icon" :size="20" v-show="errorInfo?.length && !_readOnly">
|
||||||
<WarnTriangleFilled @click.stop />
|
<WarnTriangleFilled @click.stop />
|
||||||
</el-icon>
|
</el-icon>
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
@ -198,6 +201,7 @@ const delNode = () => {
|
|||||||
background-color: var(--el-card-bg-color);
|
background-color: var(--el-card-bg-color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
:deep(.el-card__body) {
|
:deep(.el-card__body) {
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,6 +2,7 @@
|
|||||||
import FlowDesign from '@/views/flowDesign/index.vue'
|
import FlowDesign from '@/views/flowDesign/index.vue'
|
||||||
import type { Field } from '@/components/Render/type'
|
import type { Field } from '@/components/Render/type'
|
||||||
import type { EndNode, FlowNode, StartNode } from '@/views/flowDesign/nodes/type'
|
import type { EndNode, FlowNode, StartNode } from '@/views/flowDesign/nodes/type'
|
||||||
|
import { downloadXml } from '@/api/modules/model'
|
||||||
|
|
||||||
// 流程节点
|
// 流程节点
|
||||||
const process = ref<FlowNode>({
|
const process = ref<FlowNode>({
|
||||||
@ -27,7 +28,7 @@ const fields = ref<Field[]>([
|
|||||||
name: 'UserSelector',
|
name: 'UserSelector',
|
||||||
value: null,
|
value: null,
|
||||||
readonly: false,
|
readonly: false,
|
||||||
required: false,
|
required: true,
|
||||||
hidden: false,
|
hidden: false,
|
||||||
props: {
|
props: {
|
||||||
multiple: false,
|
multiple: false,
|
||||||
@ -45,7 +46,7 @@ const fields = ref<Field[]>([
|
|||||||
name: 'ElInputNumber',
|
name: 'ElInputNumber',
|
||||||
value: null,
|
value: null,
|
||||||
readonly: false,
|
readonly: false,
|
||||||
required: false,
|
required: true,
|
||||||
hidden: false,
|
hidden: false,
|
||||||
props: {
|
props: {
|
||||||
disabled: false,
|
disabled: false,
|
||||||
@ -66,7 +67,7 @@ const fields = ref<Field[]>([
|
|||||||
name: 'ElSelect',
|
name: 'ElSelect',
|
||||||
value: null,
|
value: null,
|
||||||
readonly: false,
|
readonly: false,
|
||||||
required: false,
|
required: true,
|
||||||
hidden: false,
|
hidden: false,
|
||||||
props: {
|
props: {
|
||||||
disabled: false,
|
disabled: false,
|
||||||
@ -110,7 +111,7 @@ const fields = ref<Field[]>([
|
|||||||
name: 'ElInput',
|
name: 'ElInput',
|
||||||
value: null,
|
value: null,
|
||||||
readonly: false,
|
readonly: false,
|
||||||
required: false,
|
required: true,
|
||||||
hidden: false,
|
hidden: false,
|
||||||
props: {
|
props: {
|
||||||
type: 'textarea',
|
type: 'textarea',
|
||||||
@ -126,10 +127,78 @@ const fields = ref<Field[]>([
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
|
// 是否只读
|
||||||
|
const readOnly = ref(false)
|
||||||
|
// 是否暗黑模式
|
||||||
|
const isDark = ref(false)
|
||||||
|
const converterBpmn = () => {
|
||||||
|
const processModel = {
|
||||||
|
code: 'test',
|
||||||
|
name: '测试',
|
||||||
|
icon: {
|
||||||
|
name: 'el:HomeFilled',
|
||||||
|
color: '#409EFF'
|
||||||
|
},
|
||||||
|
process: process.value,
|
||||||
|
enable: true,
|
||||||
|
version: 1,
|
||||||
|
sort: 0,
|
||||||
|
groupId: '',
|
||||||
|
remark: ''
|
||||||
|
}
|
||||||
|
downloadXml(processModel)
|
||||||
|
}
|
||||||
|
const handleToggleDark = () => {
|
||||||
|
if (isDark.value) {
|
||||||
|
document.documentElement.classList.add('dark')
|
||||||
|
} else {
|
||||||
|
document.documentElement.classList.remove('dark')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const gitee = () => {
|
||||||
|
window.open('https://gitee.com/cai_xiao_feng/lowflow-design')
|
||||||
|
}
|
||||||
|
const github = () => {
|
||||||
|
window.open('https://github.com/tsai996/lowflow-design')
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<FlowDesign :process="process" :fields="fields" />
|
<FlowDesign :process="process" :fields="fields" :readOnly="readOnly">
|
||||||
|
<el-switch
|
||||||
|
inline-prompt
|
||||||
|
active-text="正常模式"
|
||||||
|
inactive-text="暗黑模式"
|
||||||
|
@change="handleToggleDark"
|
||||||
|
v-model="isDark"
|
||||||
|
/>
|
||||||
|
<el-switch
|
||||||
|
v-model="readOnly"
|
||||||
|
active-text="只读模式"
|
||||||
|
inactive-text="编辑模式"
|
||||||
|
inline-prompt
|
||||||
|
:active-value="true"
|
||||||
|
:inactive-value="false"
|
||||||
|
/>
|
||||||
|
<el-button-group>
|
||||||
|
<el-button @click="converterBpmn" type="primary" icon="Download"> 转bpmn </el-button>
|
||||||
|
<!--开源地址-->
|
||||||
|
<el-dropdown>
|
||||||
|
<el-button type="primary">
|
||||||
|
开源地址
|
||||||
|
<el-icon class="el-icon--right">
|
||||||
|
<arrow-down />
|
||||||
|
</el-icon>
|
||||||
|
</el-button>
|
||||||
|
<template #dropdown>
|
||||||
|
<el-dropdown-menu>
|
||||||
|
<el-dropdown-item @click.stop="gitee">Gitee</el-dropdown-item>
|
||||||
|
<el-dropdown-item @click.stop="github">Github</el-dropdown-item>
|
||||||
|
</el-dropdown-menu>
|
||||||
|
</template>
|
||||||
|
</el-dropdown>
|
||||||
|
</el-button-group>
|
||||||
|
</FlowDesign>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped lang="scss"></style>
|
<style scoped lang="scss"></style>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user