优化审批流

This commit is contained in:
xh
2025-12-06 01:55:24 +08:00
parent 387bc074bc
commit 894eb74e24
9 changed files with 49 additions and 265 deletions

View File

@@ -6,9 +6,9 @@
"scripts": {
"dev": "vite",
"dev:prod": "vite --mode prod",
"prod": "vite build",
"build": "vite build",
"preview": "vite preview --port 4173",
"build": "node ./scripts/build.mjs",
"build:all": "node ./scripts/build.mjs",
"type-check": "vue-tsc --noEmit --checkJs true --skipLibCheck",
"lint": "eslint src --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts src --fix --ignore-path .gitignore",
"preinstall": "npx only-allow pnpm",
@@ -19,17 +19,17 @@
"@form-create/designer": "^3.3.1",
"@form-create/element-ui": "^3.2.33",
"@highlightjs/vue-plugin": "^2.1.0",
"@logicflow/core": "^2.1.2",
"@logicflow/extension": "^2.1.3",
"@logicflow/core": "^2.2.0",
"@logicflow/extension": "^2.2.0",
"@vueuse/core": "^13.5.0",
"@wangeditor/editor": "^5.1.23",
"@wangeditor/editor-for-vue": "^5.1.12",
"axios": "^1.11.0",
"axios": "^1.13.2",
"crypto-js": "^4.2.0",
"css-color-function": "^1.3.3",
"dayjs": "^1.11.18",
"dayjs": "^1.11.19",
"echarts": "^5.6.0",
"element-plus": "^2.11.1",
"element-plus": "^2.12.0",
"highlight.js": "^11.11.1",
"lodash-es": "^4.17.21",
"nprogress": "^0.2.0",
@@ -37,8 +37,7 @@
"query-string": "^9.2.2",
"rolldown-vite": "^7.2.7",
"spark-md5": "^3.0.2",
"vform3-builds": "^3.0.10",
"vue": "^3.5.21",
"vue": "^3.5.25",
"vue-clipboard3": "^2.0.0",
"vue-echarts": "^7.0.3",
"vue-router": "^4.5.1",
@@ -52,12 +51,12 @@
"@types/lodash-es": "^4.17.12",
"@types/node": "^22.14.1",
"@types/nprogress": "^0.2.3",
"@vitejs/plugin-vue": "^6.0.0",
"@vitejs/plugin-vue-jsx": "^5.1.1",
"@vitejs/plugin-vue": "^6.0.2",
"@vitejs/plugin-vue-jsx": "^5.1.2",
"@vue/eslint-config-prettier": "^9.0.0",
"@vue/eslint-config-typescript": "^13.0.0",
"@vue/tsconfig": "^0.8.1",
"autoprefixer": "^10.4.21",
"autoprefixer": "^10.4.22",
"eslint": "^8.57.0",
"eslint-plugin-vue": "^9.27.0",
"execa": "^9.5.2",

View File

@@ -35,7 +35,7 @@
</header>
</template>
<div class="page__content" v-if="mockData">
<div class="page__content" v-if="dialogVisible">
<BasicSetting
ref="basicSetting"
:conf="mockData.basicSetting"
@@ -60,12 +60,12 @@
</template>
<script setup lang="ts">
import { ref, useTemplateRef, watch } from 'vue'
import { ref, useTemplateRef, watch, defineAsyncComponent } from 'vue'
// import XForm from './XForm/index.vue'
// import XForm2 from './XForm2/index.vue'
const XForm2 = () => import('./XForm2/index.vue')
const XForm2 = defineAsyncComponent(() => import('./XForm2/index.vue'))
// import FlowEdit from './flowEdit/index.vue'
const FlowEdit = () => import('./flowEdit/index.vue')
const FlowEdit = defineAsyncComponent(() => import('./flowEdit/index.vue'))
import BasicSetting from './BasicSetting/index.vue'
import feedback from '@/utils/feedback'

View File

@@ -17,18 +17,26 @@ function setData(json: any[]) {
// 使用 setRule和 setOptions方法回显数据。
}
function getFieldWidgets() {
// const fieldList = designerRef.value.getFieldWidgets()
// console.log('getFieldWidgets', fieldList)
// return fieldList
const description = designerRef.value.getDescription()
console.log('description', description)
const fieldList: { id: string; name: string }[] = []
description.forEach((item) => {
fieldList.push({
id: item.field,
name: item.title
function deepChild(item: any) {
if (item.children) {
item.children.forEach((child: any) => {
deepChild(child)
})
} else {
fieldList.push({
id: item.field,
name: item.title
})
}
}
description &&
description.forEach((item) => {
deepChild(item)
})
})
console.log('getFieldWidgets', fieldList)
return fieldList
}

View File

@@ -22,7 +22,7 @@
</template>
<script setup lang="ts">
import { ref, onMounted, useTemplateRef } from 'vue'
import { ref, onMounted, onBeforeUnmount, useTemplateRef } from 'vue'
import { LogicFlow } from '@logicflow/core'
import { SelectionSelect, Menu, BpmnElement, MiniMap } from '@logicflow/extension'
@@ -56,7 +56,14 @@ const PropertyPanelRef = useTemplateRef<InstanceType<typeof PropertyPanel>>('Pro
onMounted(() => {
initLogicFlow(props.conf)
})
// Lifecycle hook to clean up LogicFlow when the component is unmounted
onBeforeUnmount(() => {
if (lf.value) {
console.log('卸载LogicFlow')
lf.value.destroy()
lf.value = null
}
})
// Function to initialize LogicFlow
function initLogicFlow(data) {
const logicFlowInstance = new LogicFlow({

View File

@@ -1,116 +0,0 @@
<template>
<el-dialog
v-model="dialogVisible"
:fullscreen="false"
:close-on-click-modal="false"
:close-on-press-escape="false"
:destroy-on-close="true"
:title="applyDetail.flowName"
>
<v-form-render
:form-json="formJson"
:form-data="formData"
:option-data="optionData"
ref="vFormRef"
>
</v-form-render>
<el-table size="large" :data="historyList" v-if="historyList.length">
<el-table-column label="审批人" prop="approverNickname" />
<el-table-column label="节点" prop="nodeLabel" />
<el-table-column label="状态" prop="passStatus" />
<el-table-column label="备注" prop="passRemark" />
</el-table>
<!-- {{ historyList }} -->
<template #footer>
<el-button @click="dialogVisible = false">关闭</el-button>
<el-button
v-if="applyDetail.status == 1 || applyDetail.status == 4"
type="primary"
@click="onSubmit"
>
确定
</el-button>
</template>
</el-dialog>
</template>
<script setup>
import { ref, reactive } from 'vue'
import 'vform3-builds/dist/designer.style.css' //引入VForm3样式
import { flow_history_list_all } from '@/api/flow/flow_history'
const formJson = ref({})
const formData = ref({})
const optionData = reactive({})
const vFormRef = ref(null)
const dialogVisible = ref(false)
const applyDetail = ref({
id: null,
status: null,
flowName: ''
})
const historyList = ref([])
const props = defineProps({
save: {
type: Function,
default: () => {}
}
})
function open(row, form_json, form_data) {
applyDetail.value = row
getHistoryList(row.id)
formData.value = form_data
formJson.value = form_json
console.log('open')
dialogVisible.value = true
}
async function getHistoryList(applyId) {
try {
historyList.value = await flow_history_list_all({
applyId: applyId
})
} catch (error) {
historyList.value = []
}
}
function closeFn() {
dialogVisible.value = false
applyDetail.value = {
id: null,
status: null,
flowName: ''
}
formData.value = {}
formJson.value = {}
historyList.value = []
}
function onSubmit() {
vFormRef.value.getFormData().then((formData) => {
console.log('formData', formData)
props
.save(applyDetail.value?.id, formData)
.then(() => {
closeFn()
})
.catch(() => {})
})
}
defineExpose({
open
})
</script>
<style lang="scss">
// body {
// margin: 0; /* 如果页面出现垂直滚动条则加入此行CSS以消除之 */
// }
.el-range-editor.el-input__wrapper {
box-sizing: border-box;
}
</style>

View File

@@ -1,114 +0,0 @@
<template>
<el-dialog
v-model="dialogVisible"
:fullscreen="false"
:close-on-click-modal="false"
:close-on-press-escape="false"
:destroy-on-close="true"
draggable
:title="applyDetail.flowName"
>
<v-form-render
:form-json="formJson"
:form-data="formData"
:option-data="optionData"
ref="vFormRef"
>
</v-form-render>
<template #footer>
<el-button @click="dialogVisible = false">关闭</el-button>
<el-button v-if="historyDetail.passStatus == 1" type="warning" @click="onBack">
驳回
</el-button>
<el-button v-if="historyDetail.passStatus == 1" type="primary" @click="onSubmit">
确定
</el-button>
</template>
</el-dialog>
</template>
<script setup>
import { ref, reactive } from 'vue'
import 'vform3-builds/dist/designer.style.css' //引入VForm3样式
// import { flow_apply_detail } from '@/api/flow/flow_apply'
const formJson = ref({})
const formData = ref({})
const optionData = reactive({})
const vFormRef = ref(null)
const dialogVisible = ref(false)
const applyDetail = ref({
flowName: ''
})
const historyDetail = ref({
id: null,
passStatus: null
})
const props = defineProps({
save: {
type: Function,
default: () => {}
}
})
const emit = defineEmits(['back'])
function open(row, history, form_json, form_data) {
applyDetail.value = row
historyDetail.value = history
formData.value = form_data
formJson.value = form_json
console.log('open')
dialogVisible.value = true
}
function disableWidgets(widgetNames) {
vFormRef.value.disableWidgets(widgetNames)
}
function hideWidgets(widgetNames) {
vFormRef.value.hideWidgets(widgetNames)
}
function closeFn() {
dialogVisible.value = false
applyDetail.value = { flowName: '' }
formData.value = {}
formJson.value = {}
historyDetail.value = {
id: null,
passStatus: null
}
}
function onBack() {
emit('back', historyDetail.value)
}
function onSubmit() {
vFormRef.value.getFormData().then((formData) => {
console.log('formData', formData)
props
.save(historyDetail.value?.id, formData)
.then(() => {
closeFn()
})
.catch(() => {})
})
}
defineExpose({
open,
disableWidgets,
hideWidgets,
closeFn
})
</script>
<style lang="scss">
// body {
// margin: 0; /* 如果页面出现垂直滚动条则加入此行CSS以消除之 */
// }
.el-range-editor.el-input__wrapper {
box-sizing: border-box;
}
</style>

View File

@@ -106,12 +106,12 @@ const { dictData } = useDictData<{
// const handleOpen = async (row) => {
// ApproveRef.value?.open(toRaw(row))
// }
const OpenViewForm = async (row: any) => {
const applyDetail = await flow_apply_detail({ id: row.applyId })
const OpenViewForm = async (history_row: type_flow_history) => {
const applyDetail = await flow_apply_detail({ id: history_row.applyId })
let form_data = {}
try {
form_data = JSON.parse(row.formValue)
form_data = JSON.parse(history_row.formValue)
} catch (error) {
// 解析失败
}
@@ -124,7 +124,7 @@ const OpenViewForm = async (row: any) => {
console.log(applyDetail, form_data, form_json)
viewFormRef.value?.open(applyDetail, row, form_json, form_data)
viewFormRef.value?.open(applyDetail, history_row, form_json, form_data)
}
const SaveViewForm = (historyId, form_data) => {
return new Promise((resolve, reject) => {

View File

@@ -91,7 +91,7 @@
</div>
</template>
<script lang="ts" setup>
import { ref, shallowRef, reactive } from 'vue'
import { ref, shallowRef, reactive, defineAsyncComponent } from 'vue'
import {
flow_template_delete,
flow_template_lists,
@@ -102,7 +102,7 @@ import { useDictData } from '@/hooks/useDictOptions'
import { usePaging } from '@/hooks/usePaging'
import feedback from '@/utils/feedback'
import EditPopup from './edit.vue'
const Approver = () => import('@/components/flow/Approver.vue')
const Approver = defineAsyncComponent(() => import('@/components/flow/Approver.vue'))
defineOptions({
name: 'flow_template'

View File

@@ -45,9 +45,9 @@ func swaggerJson(api *gin.RouterGroup) {
}
// @Summary ws通用接口
// @schemes ws
// @schemes ws
// @Tags 公共接口
// @Success 101 {string} string "协议切换成功"
// @Success 101 {string} string "ws连接成功"
// @Router /api/ws [get]
func wsHandler(api *gin.RouterGroup) {
api.GET("/ws", middleware.LoginAuth(), controller.WsHandler)