feat: 添加审批历史页面,处于办公中心下

This commit is contained in:
2026-04-15 15:09:03 +08:00
parent f4dbe29d8e
commit 09f1adb63b
9 changed files with 105 additions and 50 deletions

View File

@@ -6,6 +6,7 @@ import com.ruoyi.common.core.domain.PageQuery;
import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType; import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.helper.LoginHelper;
import com.ruoyi.hrm.domain.bo.HrmFlowTaskBo; import com.ruoyi.hrm.domain.bo.HrmFlowTaskBo;
import com.ruoyi.hrm.domain.bo.HrmFlowTaskApproveBo; import com.ruoyi.hrm.domain.bo.HrmFlowTaskApproveBo;
import com.ruoyi.hrm.domain.bo.HrmSealStampBo; import com.ruoyi.hrm.domain.bo.HrmSealStampBo;
@@ -112,4 +113,14 @@ public class HrmFlowTaskController extends BaseController {
@RequestParam(required = false) String remark) { @RequestParam(required = false) String remark) {
return toAjax(service.transfer(taskId, newAssigneeUserId, actionUserId, remark)); return toAjax(service.transfer(taskId, newAssigneeUserId, actionUserId, remark));
} }
/**
* 审批历史列表:查询当前用户的审批历史,包含分页
*/
@GetMapping("/historyList")
public TableDataInfo<HrmFlowTaskVo> historyList(PageQuery pageQuery) {
// 使用若依自带的 LoginHelper 获取当前登录用户的 ID (类型是 Long)
Long userId = LoginHelper.getUserId();
// 调用 Service
return service.selectHistoryTaskList(userId, pageQuery);
}
} }

View File

@@ -2,6 +2,7 @@ package com.ruoyi.hrm.service;
import com.ruoyi.common.core.domain.PageQuery; import com.ruoyi.common.core.domain.PageQuery;
import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.hrm.domain.HrmFlowTask;
import com.ruoyi.hrm.domain.bo.HrmFlowTaskBo; import com.ruoyi.hrm.domain.bo.HrmFlowTaskBo;
import com.ruoyi.hrm.domain.vo.HrmFlowTaskVo; import com.ruoyi.hrm.domain.vo.HrmFlowTaskVo;
@@ -42,6 +43,10 @@ public interface IHrmFlowTaskService {
*/ */
Boolean transfer(Long taskId, Long newAssigneeUserId, Long actionUserId, String remark); Boolean transfer(Long taskId, Long newAssigneeUserId, Long actionUserId, String remark);
/**
* 查询当前用户的审批历史,并回填业务数据
*/
TableDataInfo<HrmFlowTaskVo> selectHistoryTaskList(Long userId, PageQuery pageQuery);
/** /**
* 根据业务类型 + 业务ID 查询当前待办任务pending用于详情页自动带出 currentTaskId * 根据业务类型 + 业务ID 查询当前待办任务pending用于详情页自动带出 currentTaskId
*/ */

View File

@@ -38,6 +38,7 @@ public class HrmFlowTaskServiceImpl implements IHrmFlowTaskService {
private final FlowAssigneeHelper assigneeHelper; private final FlowAssigneeHelper assigneeHelper;
private final BizStatusSyncHelper bizStatusSyncHelper; private final BizStatusSyncHelper bizStatusSyncHelper;
private final HrmFlowTaskMapper hrmFlowTaskMapper;
// 注入五个业务Mapper // 注入五个业务Mapper
private final HrmLeaveReqMapper leaveReqMapper; private final HrmLeaveReqMapper leaveReqMapper;
private final HrmTravelReqMapper travelReqMapper; private final HrmTravelReqMapper travelReqMapper;
@@ -397,4 +398,27 @@ public class HrmFlowTaskServiceImpl implements IHrmFlowTaskService {
lqw.orderByDesc(HrmFlowTask::getCreateTime); lqw.orderByDesc(HrmFlowTask::getCreateTime);
return lqw; return lqw;
} }
/**
* 查询当前用户的审批历史,回填业务数据以便前端复用页面
*/
@Override
public TableDataInfo<HrmFlowTaskVo> selectHistoryTaskList(Long userId, PageQuery pageQuery) {
LambdaQueryWrapper<HrmFlowTask> lqw = Wrappers.lambdaQuery();
lqw.eq(HrmFlowTask::getAssigneeUserId, userId);
lqw.ne(HrmFlowTask::getStatus, "pending");
lqw.orderByDesc(HrmFlowTask::getCreateTime);
Page<HrmFlowTaskVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
if (result.getRecords() != null && !result.getRecords().isEmpty()) {
fillBizData(result.getRecords());
}
return TableDataInfo.build(result);
}
} }

View File

@@ -174,12 +174,4 @@ public class WfTaskController {
} }
} }
} }
/**
* 审批历史列表
*/
@SaCheckPermission("workflow:task:historyList")
@GetMapping("/historyList")
public R historyList() {
return R.ok(flowTaskService.selectHistoryTaskList());
}
} }

View File

@@ -1,5 +1,6 @@
package com.ruoyi.workflow.service; package com.ruoyi.workflow.service;
import com.ruoyi.workflow.domain.FlowRecord; import com.ruoyi.workflow.domain.FlowRecord;
import com.ruoyi.workflow.domain.bo.WfTaskBo; import com.ruoyi.workflow.domain.bo.WfTaskBo;
import org.flowable.bpmn.model.FlowElement; import org.flowable.bpmn.model.FlowElement;
@@ -126,8 +127,4 @@ public interface IWfTaskService {
*/ */
Map<String, Boolean> checkTaskNodeType(String taskId); Map<String, Boolean> checkTaskNodeType(String taskId);
/**
* 查询当前用户的审批历史(排除待审批状态)
*/
List<HistoricTaskInstance> selectHistoryTaskList();
} }

View File

@@ -4,6 +4,8 @@ import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert; import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.AbstractWrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ruoyi.common.core.service.UserService; import com.ruoyi.common.core.service.UserService;
import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.helper.LoginHelper; import com.ruoyi.common.helper.LoginHelper;
@@ -790,20 +792,6 @@ public class WfTaskServiceImpl extends FlowServiceFactory implements IWfTaskServ
return result; return result;
} }
/**
* 查询当前用户的审批历史(排除待办任务)
*/
@Override
public List<HistoricTaskInstance> selectHistoryTaskList() {
// 获取当前登录用户ID
String userId = TaskUtils.getUserId();
// Flowable 原生查询:当前用户 + 已完成排除待办pending
return historyService.createHistoricTaskInstanceQuery()
.taskAssignee(userId) // 审批人是当前用户
.finished() // 已完成(排除待办)
.orderByHistoricTaskInstanceEndTime()
.desc() // 按完成时间倒序,最新的在最前面
.list();
}
} }

View File

@@ -238,6 +238,13 @@ export function delFlowInstance (instId) {
method: 'delete' method: 'delete'
}) })
} }
export function listHistoryFlowTask(query) {
return request({
url: '/hrm/flow/task/historyList',
method: 'get',
params: query
})
}
/** /**
* 查询实例对应的所有审批任务 * 查询实例对应的所有审批任务
@@ -247,4 +254,9 @@ export function listAssignTask (instId) {
url: `/hrm/flow/instance/tasks/${instId}`, url: `/hrm/flow/instance/tasks/${instId}`,
method: 'get' method: 'get'
}) })
/**
* 查询当前用户的审批历史
*/
} }

View File

@@ -29,34 +29,29 @@ const permission = {
}, },
}, },
actions: { actions: {
// 生成路由 GenerateRoutes({ commit }) {
GenerateRoutes({ commit }) {
return new Promise(resolve => { return new Promise(resolve => {
// 向后端请求路由数据
getRouters().then(res => { getRouters().then(res => {
// ================= 新增拦截代码:将页面注入到办公中心开始 =================
// 寻找后端传来的“办公中心”节点(根据路径或标题匹配)
const oaMenu = res.data.find(item => item.path === '/oa' || (item.meta && item.meta.title === '办公中心')); const oaMenu = res.data.find(item => item.path === '/oa' || (item.meta && item.meta.title === '办公中心'));
if (oaMenu) { if (oaMenu) {
if (!oaMenu.children) oaMenu.children = []; if (!oaMenu.children) oaMenu.children = [];
// 防重判断,避免代码热更新时重复添加导致菜单重复
const hasHistory = oaMenu.children.some(child => child.path === 'flowHistory'); const hasHistory = oaMenu.children.some(child => child.path === 'flowHistory');
if (!hasHistory) { if (!hasHistory) {
oaMenu.children.push({ oaMenu.children.push({
name: 'FlowHistory', name: 'HrmFlowHistory',
path: 'flowHistory', // 浏览器地址后缀,点击后地址变为 /oa/flowHistory path: 'flowHistory',
hidden: false, // 确保在左侧菜单显示 hidden: false,
// 【特别注意】:这里对应的是你存放 vue 文件的真实相对路径 component: 'hrm/flow/taskHistory',
// 根据你最初的代码,我推测在 hrm/flow 文件夹下。
// 如果你的文件名叫 taskHistory.vue请把下面的 flowHistory 改成 taskHistory
component: 'hrm/flow/flowHistory',
meta: { meta: {
title: '审批历史', title: '审批历史',
icon: 'date-range', // 菜单图标,支持 element 图标 icon: 'date-range',
noCache: false noCache: false
} }
}); });

View File

@@ -108,8 +108,7 @@
</template> </template>
<script> <script>
import { listHistoryFlowTask, listFlowAction, listFlowFormData } from '@/api/hrm/flow'
import { getTodoTaskByBiz, listFlowAction, listFlowFormData, listHistoryFlowTask } from '@/views/hrm/js/History'
import { listByIds } from '@/api/system/oss' import { listByIds } from '@/api/system/oss'
import { listUser } from '@/api/system/user' import { listUser } from '@/api/system/user'
@@ -127,6 +126,7 @@ export default {
return { return {
query: { status: undefined, pageNum: 1, pageSize: 50 }, query: { status: undefined, pageNum: 1, pageSize: 50 },
list: [], list: [],
total: 0,
loading: false, loading: false,
detailTask: null, detailTask: null,
actionList: [], actionList: [],
@@ -152,10 +152,18 @@ export default {
fetchList() { fetchList() {
this.loading = true this.loading = true
listHistoryFlowTask().then(res => {
this.list = res.data || res.rows || [] listHistoryFlowTask(this.query).then(res => {
if (!this.detailTask && this.list.length) this.openDetail(this.list[0])
}).finally(() => { this.loading = false }) this.list = res.rows || []
this.total = res.total || 0
if (!this.detailTask && this.list.length) {
this.openDetail(this.list[0])
}
}).finally(() => {
this.loading = false
})
}, },
async openDetail(row) { async openDetail(row) {
@@ -165,9 +173,32 @@ export default {
this.loadFormData(row) this.loadFormData(row)
}, },
loadActions(row) { if (!row || !row.instId) return; this.actionLoading = true; listFlowAction({ instId: row.instId }).then(res => { this.actionList = res.rows || [] }).finally(() => { this.actionLoading = false }) }, loadActions(row) {
loadFormData(row) { if (!row || !row.instId) return; this.formLoading = true; listFlowFormData({ instId: row.instId }).then(res => { this.formData = res.rows || [] }).finally(() => { this.formLoading = false }) }, if (!row || !row.instId) return;
copyTaskInfo() { if (!this.detailTask) return; const t = this.detailTask; const text = `任务ID:${t.taskId}\n实例:${t.instId}\n业务:${t.bizType}${t.bizId ? `#${t.bizId}` : ''}\n节点:${t.nodeId}\n状态:${t.status}`; navigator.clipboard.writeText(text).then(() => this.$message.success('已复制')) } this.actionLoading = true;
listFlowAction({ instId: row.instId }).then(res => {
this.actionList = res.rows || []
}).finally(() => {
this.actionLoading = false
})
},
loadFormData(row) {
if (!row || !row.instId) return;
this.formLoading = true;
listFlowFormData({ instId: row.instId }).then(res => {
this.formData = res.rows || []
}).finally(() => {
this.formLoading = false
})
},
copyTaskInfo() {
if (!this.detailTask) return;
const t = this.detailTask;
const text = `任务ID:${t.taskId}\n实例:${t.instId}\n业务:${t.bizType}${t.bizId ? `#${t.bizId}` : ''}\n节点:${t.nodeId}\n状态:${t.status}`;
navigator.clipboard.writeText(text).then(() => this.$message.success('已复制'))
}
} }
} }
</script> </script>