提交 96778066 authored 作者: kxjia's avatar kxjia

问题工作流

上级 4c79503d
...@@ -162,6 +162,12 @@ export function assign(data) { ...@@ -162,6 +162,12 @@ export function assign(data) {
data: data data: data
}) })
} }
export function todoListAll() {
return defHttp.get({
url: '/flowable/task/todoListAll'
})
}
......
...@@ -139,15 +139,16 @@ ...@@ -139,15 +139,16 @@
}, },
}) })
} else { } else {
// await rejectTask({ await rejectTask({
// instanceId: myTaskFlow.procInsId || '', instanceId: myTaskFlow.procInsId || '',
// deployId: myTaskFlow.deployId || '', deployId: myTaskFlow.deployId || '',
// taskId: myTaskFlow.taskId, taskId: myTaskFlow.taskId,
// comment: formDataTmp.comment, comment: formDataTmp.comment,
// values: { values: {
// rejectNode: props.beforeFlowNode, rejectNode: props.beforeFlowNode,
// }, },
// }) })
alert(3333)
emit('approval-fail', props.dataId) emit('approval-fail', props.dataId)
} }
} }
......
<template> <template>
<div> <div>
<div style="margin-bottom: 16px; display: flex; justify-content: flex-end;">
<a-upload
:before-upload="handleBeforeUpload"
:show-upload-list="false"
accept=".xml"
>
<a-button type="primary">
<UploadOutlined />
上传XML文件
</a-button>
</a-upload>
</div>
<bpmn-model <bpmn-model
:xml="xml" :xml="xml"
:is-view="false" :is-view="false"
...@@ -31,6 +43,8 @@ ...@@ -31,6 +43,8 @@
import { ref, onMounted, computed } from 'vue' import { ref, onMounted, computed } from 'vue'
import { readXml, saveXml } from "/@/components/Process/api/definition" import { readXml, saveXml } from "/@/components/Process/api/definition"
import BpmnModel from '/@/components/Process/index.vue' import BpmnModel from '/@/components/Process/index.vue'
import { message, Modal } from 'ant-design-vue'
import { UploadOutlined } from '@ant-design/icons-vue'
import * as vkbeautify from 'vkbeautify' import * as vkbeautify from 'vkbeautify'
import hljs from 'highlight.js' import hljs from 'highlight.js'
...@@ -38,7 +52,6 @@ import { useRouter, useRoute } from 'vue-router' ...@@ -38,7 +52,6 @@ import { useRouter, useRoute } from 'vue-router'
import "highlight.js/styles/atom-one-dark.css" import "highlight.js/styles/atom-one-dark.css"
const router = useRouter() const router = useRouter()
const route = useRoute() const route = useRoute()
...@@ -62,6 +75,7 @@ const xml = ref<string>('') ...@@ -62,6 +75,7 @@ const xml = ref<string>('')
const xmlOpen = ref<boolean>(false) const xmlOpen = ref<boolean>(false)
const xmlTitle = ref<string>('') const xmlTitle = ref<string>('')
const xmlData = ref<string>('') const xmlData = ref<string>('')
const originalXml = ref<string>('') // 保存原始XML,用于判断是否需要提示保存
// 计算属性,用于高亮显示的XML // 计算属性,用于高亮显示的XML
const highlightedXml = computed(() => { const highlightedXml = computed(() => {
...@@ -73,11 +87,75 @@ const highlightedXml = computed(() => { ...@@ -73,11 +87,75 @@ const highlightedXml = computed(() => {
const getXmlData = async (deployId: string) => { const getXmlData = async (deployId: string) => {
try { try {
xml.value = await readXml(deployId) xml.value = await readXml(deployId)
originalXml.value = xml.value // 保存原始内容
} catch (error) { } catch (error) {
console.error('Failed:', error) console.error('Failed:', error)
} }
} }
// 上传前的处理
const handleBeforeUpload = (file: File) => {
// 检查文件类型
if (file.type !== 'text/xml' && !file.name.endsWith('.xml')) {
message.error('请上传 XML 格式的文件!')
return false
}
// 检查文件大小(限制为 10MB)
const isLt10M = file.size / 1024 / 1024 < 10
if (!isLt10M) {
message.error('文件大小不能超过 10MB!')
return false
}
// 读取文件内容
const reader = new FileReader()
reader.onload = (e) => {
const content = e.target?.result as string
// 检查当前是否有未保存的修改
if (xml.value && xml.value !== originalXml.value) {
Modal.confirm({
title: '提示',
content: '当前有未保存的修改,上传新文件将丢失这些修改,确定要继续吗?',
onOk: () => {
updateXmlContent(content)
},
})
} else {
updateXmlContent(content)
}
}
reader.onerror = () => {
message.error('文件读取失败!')
}
reader.readAsText(file, 'UTF-8')
return false // 阻止自动上传
}
// 更新XML内容
const updateXmlContent = (content: string) => {
try {
// 验证XML格式
const parser = new DOMParser()
const xmlDoc = parser.parseFromString(content, 'text/xml')
const parserError = xmlDoc.querySelector('parsererror')
if (parserError) {
message.error('XML 格式不正确,请检查文件内容!')
return
}
xml.value = content
originalXml.value = content
message.success('XML 文件上传成功!')
} catch (error) {
console.error('XML解析错误:', error)
message.error('XML 格式不正确,请检查文件内容!')
}
}
// 保存XML // 保存XML
const save = async (data: ProcessData) => { const save = async (data: ProcessData) => {
const params: SaveParams = { const params: SaveParams = {
...@@ -88,9 +166,13 @@ const save = async (data: ProcessData) => { ...@@ -88,9 +166,13 @@ const save = async (data: ProcessData) => {
try { try {
const res = await saveXml(params) const res = await saveXml(params)
// 更新原始XML引用
originalXml.value = data.xml
message.success('保存成功!')
await handleSuccess() await handleSuccess()
} catch (error) { } catch (error) {
console.error('Failed to save XML:', error) console.error('Failed to save XML:', error)
message.error('保存失败:' + (error as Error).message)
} }
} }
...@@ -103,7 +185,6 @@ const showXML = (xmlContent: string) => { ...@@ -103,7 +185,6 @@ const showXML = (xmlContent: string) => {
xmlTitle.value = 'XML查看' xmlTitle.value = 'XML查看'
xmlOpen.value = true xmlOpen.value = true
// 修改2: 使用正确的大小写和调用方式
try { try {
// 第一种方式: 使用 default 导出(如果库是这种方式) // 第一种方式: 使用 default 导出(如果库是这种方式)
if (vkbeautify && typeof vkbeautify === 'object' && vkbeautify.xml) { if (vkbeautify && typeof vkbeautify === 'object' && vkbeautify.xml) {
...@@ -164,7 +245,6 @@ onMounted(() => { ...@@ -164,7 +245,6 @@ onMounted(() => {
pre { pre {
margin: 0; margin: 0;
padding: 16px; padding: 16px;
// background-color: #282c34;
border-radius: 4px; border-radius: 4px;
code { code {
......
...@@ -36,7 +36,7 @@ ...@@ -36,7 +36,7 @@
<StProblemCheckArchiveModal @register="registerModal" @success="handleSuccess"></StProblemCheckArchiveModal> <StProblemCheckArchiveModal @register="registerModal" @success="handleSuccess"></StProblemCheckArchiveModal>
<!-- 审批记录 --> <!-- 审批记录 -->
<BpmPictureModal @register="registerBpmModal" /> <BpmPictureModal @register="registerBpmModal" />
<FlowHistoryDrawer @register="refFlowHistoryDrawer"/>
</div> </div>
</template> </template>
...@@ -48,20 +48,16 @@ ...@@ -48,20 +48,16 @@
import StProblemCheckArchiveModal from './components/StProblemCheckArchiveModal.vue' import StProblemCheckArchiveModal from './components/StProblemCheckArchiveModal.vue'
import {columns, searchFormSchema, superQuerySchema} from './StProblemCheckArchive.data'; import {columns, searchFormSchema, superQuerySchema} from './StProblemCheckArchive.data';
import {list, deleteOne, batchDelete, getImportUrl,getExportUrl} from './StProblemCheckArchive.api'; import {list, deleteOne, batchDelete, getImportUrl,getExportUrl} from './StProblemCheckArchive.api';
import FlowHistoryDrawer from '../../common/FlowHistoryDrawer.vue'
import { useDrawer } from '/@/components/Drawer';
import { getDateByPicker } from '/@/utils'; import { getDateByPicker } from '/@/utils';
//日期个性化选择 //日期个性化选择
const fieldPickers = reactive({ const fieldPickers = reactive({});
});
const [registerBpmModal, { openModal: bpmPicModal }] = useModal(); const [registerBpmModal, { openModal: bpmPicModal }] = useModal();
const queryParam = reactive<any>({}); const [refFlowHistoryDrawer, { openDrawer }] = useDrawer();
const refFlowHistory = ref(); const queryParam = reactive<any>({});
const deployId = ref('');
const dataId = ref('');
// 审批记录抽屉
const drawerHistoryVisible = ref(false);
const [registerModal, {openModal}] = useModal(); const [registerModal, {openModal}] = useModal();
const { prefixCls,tableContext,onExportXls,onImportXls } = useListPage({ const { prefixCls,tableContext,onExportXls,onImportXls } = useListPage({
...@@ -149,11 +145,14 @@ ...@@ -149,11 +145,14 @@
} }
function handleShowHistory(record) { function handleShowHistory(record) {
drawerHistoryVisible.value = true; openDrawer(true,{
deployId.value = record.deployId; procInsId: record.procInsId,
dataId.value = record.id; dataId: record.id,
refFlowHistory.value.iniData(record); deployId: record.deployId,
});
} }
function getTableAction(record){ function getTableAction(record){
return [ return [
{ {
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
:currentFlowNode="node" :currentFlowNode="node"
:nextFlowNode="workflowNodes[index+1]" :nextFlowNode="workflowNodes[index+1]"
@open-multi-form="handleOpenMultiForm" @open-multi-form="handleOpenMultiForm"
:todo-list="todoList"
/> />
</div> </div>
<div v-else class="no-form"> <div v-else class="no-form">
...@@ -50,10 +51,12 @@ ...@@ -50,10 +51,12 @@
import { ref, nextTick, onMounted, defineAsyncComponent, h } from 'vue'; import { ref, nextTick, onMounted, defineAsyncComponent, h } from 'vue';
import { getNodesByTableName } from '/@/components/Process/api/definition'; import { getNodesByTableName } from '/@/components/Process/api/definition';
import { definitionStart, definitionStartByDeployId,addMyTaskFlow } from "/@/components/Process/api/definition"; import { definitionStart, definitionStartByDeployId,addMyTaskFlow } from "/@/components/Process/api/definition";
import { todoListAll } from "/@/components/Process/api/todo";
import WorkFlowFormDrawer from '/@/views/common/WorkFlowFormDrawer.vue'; import WorkFlowFormDrawer from '/@/views/common/WorkFlowFormDrawer.vue';
import TaskAssigneeDrawer from '/@/views/common/TaskAssigneeDrawer.vue' import TaskAssigneeDrawer from '/@/views/common/TaskAssigneeDrawer.vue'
import { useDrawer } from '/@/components/Drawer'; import { useDrawer } from '/@/components/Drawer';
const [ registerAssigneeDrawer, { openDrawer: openAssigneeDrawer }] = useDrawer(); const [ registerAssigneeDrawer, { openDrawer: openAssigneeDrawer }] = useDrawer();
const formTableName = "st_problem_check"; const formTableName = "st_problem_check";
...@@ -74,6 +77,8 @@ ...@@ -74,6 +77,8 @@
const formData = ref<any>({}); const formData = ref<any>({});
const customNextApi = ref<any>(null); const customNextApi = ref<any>(null);
const todoList = ref<any[]>([]);
// 抽屉相关状态 // 抽屉相关状态
const drawerVisible = ref(false); const drawerVisible = ref(false);
const drawerTitle = ref('表单处理'); const drawerTitle = ref('表单处理');
...@@ -154,7 +159,6 @@ ...@@ -154,7 +159,6 @@
if (startResRaw?.instanceId) { if (startResRaw?.instanceId) {
procInsId.value = startResRaw.instanceId; procInsId.value = startResRaw.instanceId;
alert(procInsId.value)
myTaskFlow["taskId"] = startResRaw.taskId; myTaskFlow["taskId"] = startResRaw.taskId;
myTaskFlow["deployId"] = startResRaw.deployId; myTaskFlow["deployId"] = startResRaw.deployId;
myTaskFlow["procInsId"] = startResRaw.instanceId; myTaskFlow["procInsId"] = startResRaw.instanceId;
...@@ -265,6 +269,7 @@ ...@@ -265,6 +269,7 @@
const currentFormComponent = getCurrentFormComponent(); const currentFormComponent = getCurrentFormComponent();
if (currentFormComponent && typeof currentFormComponent.handleUpdate === 'function') { if (currentFormComponent && typeof currentFormComponent.handleUpdate === 'function') {
const beforeNode = workflowNodes.value[currentMultiFormIndex.value-1]; const beforeNode = workflowNodes.value[currentMultiFormIndex.value-1];
alert(currentMultiFormIndex.value)
alert(JSON.stringify(beforeNode)) alert(JSON.stringify(beforeNode))
await currentFormComponent.handleUpdate(dataId,beforeNode); await currentFormComponent.handleUpdate(dataId,beforeNode);
} else { } else {
...@@ -272,7 +277,6 @@ ...@@ -272,7 +277,6 @@
} }
} }
async function handleOpenMultiForm(data: any) { async function handleOpenMultiForm(data: any) {
deployId.value = currentNode.value.deployId || ''; deployId.value = currentNode.value.deployId || '';
...@@ -281,7 +285,8 @@ ...@@ -281,7 +285,8 @@
dataId.value = data.id || ''; dataId.value = data.id || '';
currentNode.value = workflowNodes.value[currentMultiFormIndex.value]; currentNode.value = workflowNodes.value[currentMultiFormIndex.value];
currentProcDefId.value = currentNode.value.procDefId || ''; currentProcDefId.value = currentNode.value.procDefId || '';
const isApprovalNode = JSON.parse(currentNode.value["isApprove"] || 'false'); const isApprovalNode = JSON.parse(currentNode.value["isApprove"]);
if(isApprovalNode) { if(isApprovalNode) {
isShowApprovalPanel.value = true; isShowApprovalPanel.value = true;
} else { } else {
...@@ -295,6 +300,7 @@ ...@@ -295,6 +300,7 @@
await nextTick(); await nextTick();
try { try {
const nodes = await getNodesByTableName(formTableName); const nodes = await getNodesByTableName(formTableName);
todoList.value = await todoListAll();
workflowNodes.value = nodes; workflowNodes.value = nodes;
if (workflowNodes.value && workflowNodes.value.length > 0) { if (workflowNodes.value && workflowNodes.value.length > 0) {
workflowNodes.value.forEach(node => { workflowNodes.value.forEach(node => {
......
...@@ -54,6 +54,12 @@ public class FlowTaskController { ...@@ -54,6 +54,12 @@ public class FlowTaskController {
return flowTaskService.todoList(pageNum, pageSize); return flowTaskService.todoList(pageNum, pageSize);
} }
@GetMapping(value = "/todoListAll")
public Result todoListAll() {
return flowTaskService.todoListAll();
}
@GetMapping(value = "/finishedList") @GetMapping(value = "/finishedList")
public Result finishedList( public Result finishedList(
@RequestParam Integer pageNum, @RequestParam Integer pageNum,
......
...@@ -177,6 +177,7 @@ public interface IFlowTaskService { ...@@ -177,6 +177,7 @@ public interface IFlowTaskService {
public Result getMyTaskFlow(FlowTaskVo flowTaskVo); public Result getMyTaskFlow(FlowTaskVo flowTaskVo);
public Result<List<String>> todoListAll();
} }
...@@ -1263,6 +1263,30 @@ public class FlowTaskServiceImpl extends FlowServiceFactory implements IFlowTask ...@@ -1263,6 +1263,30 @@ public class FlowTaskServiceImpl extends FlowServiceFactory implements IFlowTask
return Result.OK(); return Result.OK();
} }
@Override
public Result<List<String>> todoListAll() {
String userId = iFlowThirdService.getLoginUser().getId();
String userName = iFlowThirdService.getLoginUser().getUsername();
List<String> userRoleIds = iFlowThirdService.getUserRoleIdsByUserId(userName);
List<String> retList = new ArrayList<>();
TaskQuery taskQuery = taskService.createTaskQuery()
.active()
.includeProcessVariables()
.or()
.taskAssignee(userId)
.taskCandidateUser(userId)
.taskCandidateGroupIn(userRoleIds)
.endOr()
.orderByTaskCreateTime().desc();
List<Task> taskList = taskQuery.list();
for(Task task: taskList) {
retList.add(task.getProcessInstanceId());
}
return Result.OK(retList);
}
/** /**
* 代办任务列表 * 代办任务列表
* *
......
...@@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage; ...@@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.metadata.TableInfo; import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper; import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import dev.langchain4j.internal.Utils;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
...@@ -25,6 +26,7 @@ import org.springframework.util.CollectionUtils; ...@@ -25,6 +26,7 @@ import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.ModelAndView;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
...@@ -62,13 +64,17 @@ public class StProblemCheckController extends JeecgController<StProblemCheck, IS ...@@ -62,13 +64,17 @@ public class StProblemCheckController extends JeecgController<StProblemCheck, IS
@RequestParam(name="pageNo", defaultValue="1") Integer pageNo, @RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
@RequestParam(name="pageSize", defaultValue="10") Integer pageSize, @RequestParam(name="pageSize", defaultValue="10") Integer pageSize,
HttpServletRequest req) { HttpServletRequest req) {
QueryWrapper<StProblemCheck> queryWrapper = QueryGenerator.initQueryWrapper(stProblemCheck, req.getParameterMap()); QueryWrapper<StProblemCheck> queryWrapper = QueryGenerator.initQueryWrapper(stProblemCheck, req.getParameterMap());
List<String> todoList = stProblemCheck.getTodolist();
if(Utils.isNullOrEmpty(todoList)) {
//return Result.OK(null);
} else {
queryWrapper.in("procInsId", todoList);
}
Page<StProblemCheck> page = new Page<StProblemCheck>(pageNo, pageSize); Page<StProblemCheck> page = new Page<StProblemCheck>(pageNo, pageSize);
IPage<StProblemCheck> pageList = stProblemCheckService.page(page, queryWrapper); IPage<StProblemCheck> pageList = stProblemCheckService.page(page, queryWrapper);
return Result.OK(pageList); return Result.OK(pageList);
} }
......
package org.jeecg.modules.stm.problem.entity; package org.jeecg.modules.stm.problem.entity;
import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonFormat;
...@@ -12,6 +13,7 @@ import org.jeecgframework.poi.excel.annotation.Excel; ...@@ -12,6 +13,7 @@ import org.jeecgframework.poi.excel.annotation.Excel;
import org.springframework.format.annotation.DateTimeFormat; import org.springframework.format.annotation.DateTimeFormat;
import java.io.Serializable; import java.io.Serializable;
import java.util.List;
/** /**
* @Description: 问题整改 * @Description: 问题整改
...@@ -166,4 +168,8 @@ public class StProblemCheck implements Serializable { ...@@ -166,4 +168,8 @@ public class StProblemCheck implements Serializable {
/**流程节点ID*/ /**流程节点ID*/
private java.lang.String bmpNodeId; private java.lang.String bmpNodeId;
// 当前用户需要处理的工作流 实例ID
@TableField(exist = false)
private java.util.List todolist;
} }
...@@ -150,6 +150,12 @@ public class StProblemCheckArchive implements Serializable { ...@@ -150,6 +150,12 @@ public class StProblemCheckArchive implements Serializable {
@Excel(name = "流程状态", width = 15) @Excel(name = "流程状态", width = 15)
@Schema(description = "流程状态") @Schema(description = "流程状态")
private java.lang.String bpmStatus; private java.lang.String bpmStatus;
/**流程实例ID*/
@Excel(name = "流程实例ID", width = 15)
@Schema(description = "流程实例ID")
private java.lang.String procInsId;
/**部署ID*/ /**部署ID*/
@Excel(name = "部署ID", width = 15) @Excel(name = "部署ID", width = 15)
@Schema(description = "部署ID") @Schema(description = "部署ID")
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论