基于SSM框架的业务代办流程管理系统 - 源码深度解析

JavaJavaScriptMavenHTMLCSSSSM框架MySQL
2026-03-254 浏览

文章摘要

本项目是一款基于SSM(Spring+Spring MVC+MyBatis)框架构建的业务代办流程管理系统,旨在为企业或团队提供标准化的代办事项处理与流转解决方案。系统的核心业务价值在于解决传统纸质或零散电子化代办管理中流程不透明、状态跟踪困难、协同效率低下的痛点。通过将代办任务数字化、流程化,系统...

在企业日常运营中,代办事项的处理效率直接影响着团队协作效能与事务推进的透明度。传统依赖纸质单据、电子邮件或即时通讯工具的代办管理方式,普遍存在流程节点不清晰、处理状态难以追踪、历史记录易丢失以及责任归属模糊等问题。这些问题不仅导致任务积压与逾期,也为团队协同与绩效评估带来了障碍。

为解决上述痛点,我们设计并实现了一套基于SSM(Spring + Spring MVC + MyBatis)技术栈的企业级代办流程协同平台。该平台将线下非标准化的代办事项转化为线上可配置、可追踪、可审计的数字化流程,旨在为企业内部行政、财务报销、客户服务等场景提供一套标准化的任务流转与协同解决方案。

技术架构与选型

系统采用经典的三层架构模式,确保各层职责分离,便于维护与扩展。

  • 表现层:基于Spring MVC框架构建,负责接收前端HTTP请求并进行路由分发。通过@Controller@RequestMapping等注解,实现了请求参数绑定、数据验证及视图解析。前端页面采用HTML、CSS和JavaScript构建,结合Ajax技术实现局部刷新,提升用户体验。
  • 业务逻辑层:由Spring框架的IoC容器统一管理各类Service组件。利用Spring的声明式事务管理(@Transactional),确保业务流程中涉及多个数据库操作时的一致性,例如代办任务的创建、分配、状态更新等操作在一个事务内完成。
  • 数据持久层:选用MyBatis作为ORM框架,通过XML映射文件或注解方式定义SQL语句,实现了Java对象与数据库表记录的灵活映射。MyBatis的动态SQL能力支持根据业务条件灵活拼接查询语句,满足复杂查询需求。
  • 数据库:使用MySQL作为关系型数据库存储核心业务数据,通过合理的表结构设计与索引优化,保障数据操作的高效性。

项目采用Maven进行依赖管理,统一了第三方库的版本,规范了项目结构。

核心数据模型设计

数据库设计是系统稳定性的基石。本系统共设计10张核心数据表,以下重点分析其中3个关键表的结构与设计思路。

1. 用户表 (user_table)

用户表是系统权限体系的基础,记录了所有系统用户的核心信息。

CREATE TABLE user_table (
    id INT PRIMARY KEY AUTO_INCREMENT,
    username VARCHAR(50) NOT NULL UNIQUE COMMENT '登录用户名',
    password VARCHAR(255) NOT NULL COMMENT '加密后的密码',
    real_name VARCHAR(50) NOT NULL COMMENT '用户真实姓名',
    role ENUM('admin', 'manager', 'staff') NOT NULL COMMENT '用户角色',
    department VARCHAR(100) COMMENT '所属部门',
    email VARCHAR(100),
    phone VARCHAR(20),
    status ENUM('active', 'inactive') DEFAULT 'active' COMMENT '账号状态',
    created_time DATETIME DEFAULT CURRENT_TIMESTAMP,
    last_login_time DATETIME
) COMMENT='系统用户表';

设计亮点分析

  • 角色枚举约束role字段使用MySQL的ENUM类型,严格限定用户角色为admin(管理员)、manager(部门主管)、staff(普通员工)三种,避免了无效数据的插入,同时在应用层便于进行基于角色的权限控制(RBAC)。
  • 状态管理status字段实现了用户的软删除或停用功能。将用户状态置为inactive而非直接删除记录,可以保留该用户的历史操作数据,满足审计要求。
  • 时间戳跟踪created_timelast_login_time分别记录了用户的创建时间和最后登录时间,为系统使用情况分析和用户行为追踪提供了数据支持。

2. 流程实例表 (process_instance)

流程实例表是系统的核心,记录了每一个代办事项的完整生命周期。

CREATE TABLE process_instance (
    instance_id VARCHAR(32) PRIMARY KEY COMMENT '流程实例ID,全局唯一',
    process_definition_key VARCHAR(50) NOT NULL COMMENT '关联的流程定义KEY',
    title VARCHAR(200) NOT NULL COMMENT '代办事项标题',
    initiator_id INT NOT NULL COMMENT '流程发起人ID',
    current_assignee_id INT COMMENT '当前处理人ID',
    status ENUM('draft', 'active', 'suspended', 'completed', 'cancelled') NOT NULL DEFAULT 'draft' COMMENT '实例状态',
    priority ENUM('low', 'medium', 'high', 'urgent') DEFAULT 'medium' COMMENT '优先级',
    created_time DATETIME DEFAULT CURRENT_TIMESTAMP,
    updated_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    FOREIGN KEY (initiator_id) REFERENCES user_table(id),
    FOREIGN KEY (current_assignee_id) REFERENCES user_table(id)
) COMMENT='流程实例表';

设计亮点分析

  • 状态机设计status字段明确定义了流程实例可能处于的几种状态,构成了一个清晰的状态机。例如,从draft(草稿)到active(活跃),再到completed(完成)或cancelled(取消),状态流转逻辑清晰,便于业务逻辑的实现和查询。
  • 优先级机制priority字段允许用户对代办事项进行分级,系统可以根据优先级进行任务排序或推送提醒,确保重要任务得到优先处理。
  • 时间戳自动更新updated_time字段通过ON UPDATE CURRENT_TIMESTAMP实现自动更新,任何对实例的修改都会记录更新时间,无需在代码中手动维护,简化了开发。

3. 任务操作记录表 (task_operation_log)

此表用于审计追踪,记录流程实例每一步的操作细节。

CREATE TABLE task_operation_log (
    log_id BIGINT PRIMARY KEY AUTO_INCREMENT,
    instance_id VARCHAR(32) NOT NULL COMMENT '关联的流程实例ID',
    operator_id INT NOT NULL COMMENT '操作人ID',
    from_assignee_id INT COMMENT '操作前处理人',
    to_assignee_id INT COMMENT '操作后处理人',
    operation_type VARCHAR(50) NOT NULL COMMENT '操作类型,如:create, claim, complete, transfer',
    operation_comment TEXT COMMENT '操作意见或备注',
    operation_time DATETIME DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (instance_id) REFERENCES process_instance(instance_id),
    FOREIGN KEY (operator_id) REFERENCES user_table(id)
) COMMENT='任务操作记录表';

设计亮点分析

  • 全链路追踪:通过记录from_assignee_idto_assignee_id,可以完整还原任务在用户间的流转路径。结合operation_typeoperation_comment,可以清晰地了解每一步“谁、在何时、做了什么、为什么这么做”。
  • 非侵入式审计:该表的设计使得审计功能的实现对核心业务代码侵入性极低。通过在Service层的方法调用后插入日志记录,即可实现全流程的追踪,符合设计模式中的“装饰器”或“切面”思想。

核心功能模块实现

1. 用户登录与权限验证

系统采用基于Session的传统身份认证机制。用户登录成功后,其基本信息(如用户ID、角色)会被存入Session中,用于后续的接口权限校验。

登录控制器代码示例:

@Controller
@RequestMapping("/auth")
public class LoginController {

    @Autowired
    private UserService userService;

    @PostMapping("/login")
    @ResponseBody
    public ResponseEntity<Map<String, Object>> login(@RequestParam String username,
                                                    @RequestParam String password,
                                                    HttpSession session) {
        Map<String, Object> result = new HashMap<>();
        try {
            // 调用Service进行用户名密码验证
            User user = userService.authenticate(username, password);
            if (user != null && "active".equals(user.getStatus())) {
                // 登录成功,将用户信息存入Session
                session.setAttribute("currentUser", user);
                result.put("success", true);
                result.put("message", "登录成功");
                result.put("role", user.getRole()); // 返回角色用于前端路由
            } else {
                result.put("success", false);
                result.put("message", "用户名或密码错误,或账号已被禁用");
            }
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", "系统错误,登录失败");
        }
        return ResponseEntity.ok(result);
    }
}

权限拦截器代码示例:

为了保证系统安全,对于需要登录才能访问的接口,我们配置了拦截器进行统一校验。

@Component
public class AuthenticationInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        HttpSession session = request.getSession();
        User currentUser = (User) session.getAttribute("currentUser");

        // 检查用户是否登录
        if (currentUser == null) {
            // 如果是Ajax请求,返回JSON错误信息
            if (isAjaxRequest(request)) {
                response.setContentType("application/json;charset=UTF-8");
                PrintWriter out = response.getWriter();
                out.write("{\"success\":false, \"message\":\"用户未登录或会话已过期\"}");
                out.flush();
            } else {
                // 普通请求重定向到登录页
                response.sendRedirect(request.getContextPath() + "/login.html");
            }
            return false;
        }
        return true;
    }

    private boolean isAjaxRequest(HttpServletRequest request) {
        return "XMLHttpRequest".equals(request.getHeader("X-Requested-With"));
    }
}

用户登录界面 图:用户登录界面,根据不同角色(用户、跑腿小哥、管理员)展示相应的入口。

2. 代办流程的创建与启动

流程的创建是系统的起点。核心逻辑在于初始化一个流程实例,并根据预定义的流程规则,设置第一处理人。

流程创建Service代码示例:

@Service
@Transactional
public class ProcessInstanceServiceImpl implements ProcessInstanceService {

    @Autowired
    private ProcessInstanceMapper processInstanceMapper;
    @Autowired
    private TaskOperationLogMapper logMapper;
    @Autowired
    private ProcessDefinitionService definitionService;

    @Override
    public String createProcessInstance(CreateProcessRequest request, User initiator) {
        // 1. 生成全局唯一的实例ID
        String instanceId = "PI_" + System.currentTimeMillis() + "_" + ThreadLocalRandom.current().nextInt(1000, 9999);

        // 2. 根据流程定义KEY,获取流程的起始节点信息(例如,第一处理人规则)
        ProcessDefinition definition = definitionService.getDefinitionByKey(request.getProcessDefinitionKey());
        Integer firstAssigneeId = definition.getFirstAssigneeId(); // 可能是具体用户ID,或根据规则计算

        // 3. 构建流程实例对象并保存
        ProcessInstance instance = new ProcessInstance();
        instance.setInstanceId(instanceId);
        instance.setProcessDefinitionKey(request.getProcessDefinitionKey());
        instance.setTitle(request.getTitle());
        instance.setInitiatorId(initiator.getId());
        instance.setCurrentAssigneeId(firstAssigneeId);
        instance.setStatus("active"); // 创建后直接激活
        instance.setPriority(request.getPriority());
        processInstanceMapper.insert(instance);

        // 4. 记录创建日志
        TaskOperationLog log = new TaskOperationLog();
        log.setInstanceId(instanceId);
        log.setOperatorId(initiator.getId());
        log.setOperationType("create");
        log.setOperationComment("创建了代办事项:" + request.getTitle());
        logMapper.insert(log);

        return instanceId;
    }
}

服务类型管理 图:管理员在创建流程前,可先定义不同的服务类型(即流程模板),每个类型可预设处理人、步骤等规则。

3. 任务处理与流程推动

这是系统的核心交互功能。当前处理人可以对任务执行“处理完成”、“转交他人”等操作,系统需要更新实例状态、当前处理人,并记录操作日志。

任务完成Service代码示例:

@Override
public void completeTask(String instanceId, String comment, User operator) {
    // 1. 查询当前流程实例
    ProcessInstance instance = processInstanceMapper.selectById(instanceId);
    if (instance == null || !"active".equals(instance.getStatus())) {
        throw new BusinessException("流程实例不存在或已结束");
    }
    // 2. 权限校验:当前操作人必须是任务的处理人
    if (!operator.getId().equals(instance.getCurrentAssigneeId())) {
        throw new BusinessException("无权限处理此任务");
    }

    // 3. 根据流程定义,获取下一步逻辑
    ProcessDefinition definition = definitionService.getDefinitionByKey(instance.getProcessDefinitionKey());
    Integer nextAssigneeId = definitionService.calculateNextAssignee(instance, "complete");

    if (nextAssigneeId == null) {
        // 没有下一步,流程结束
        instance.setStatus("completed");
        instance.setCurrentAssigneeId(null);
    } else {
        // 流转到下一步
        instance.setCurrentAssigneeId(nextAssigneeId);
        // 状态保持 'active'
    }

    // 4. 更新流程实例
    processInstanceMapper.update(instance);

    // 5. 记录完成操作日志
    TaskOperationLog log = new TaskOperationLog();
    log.setInstanceId(instanceId);
    log.setOperatorId(operator.getId());
    log.setFromAssigneeId(operator.getId());
    log.setToAssigneeId(nextAssigneeId);
    log.setOperationType("complete");
    log.setOperationComment(comment);
    logMapper.insert(log);

    // 6. 可在此处集成消息通知,通知下一处理人
    // notificationService.notifyNewTask(nextAssigneeId, instance);
}

订单管理界面 图:用户视角的订单(即代办事项)管理界面,可查看自己发起或处理的各项任务及其状态。

4. 我的待办与任务查询

系统为不同角色的用户提供了个性化的任务视图。例如,普通员工主要看到分配给自己的待办任务,而管理者可以看到整个部门的任务进展。

我的待办查询Mapper XML配置示例:

在MyBatis的Mapper XML文件中,使用动态SQL构建复杂的查询条件。

<!-- ProcessInstanceMapper.xml -->
<mapper namespace="com.xxx.mapper.ProcessInstanceMapper">
    <select id="selectMyTodoList" parameterType="map" resultMap="ProcessInstanceResultMap">
        SELECT
            pi.*,
            u1.real_name as initiator_name,
            u2.real_name as current_assignee_name
        FROM process_instance pi
        LEFT JOIN user_table u1 ON pi.initiator_id = u1.id
        LEFT JOIN user_table u2 ON pi.current_assignee_id = u2.id
        WHERE pi.status = 'active'
        <if test="currentUserId != null">
            AND pi.current_assignee_id = #{currentUserId}
        </if>
        <if test="department != null">
            AND u2.department = #{department} <!-- 部门主管查看本部门所有活跃任务 -->
        </if>
        <if test="priority != null">
            AND pi.priority = #{priority}
        </if>
        <if test="keyword != null and keyword != ''">
            AND (pi.title LIKE CONCAT('%', #{keyword}, '%'))
        </if>
        ORDER BY
            FIELD(pi.priority, 'urgent', 'high', 'medium', 'low'),
            pi.updated_time DESC
    </select>
</mapper>

对应的Service层调用:

@Service
public class ProcessQueryServiceImpl implements ProcessQueryService {

    @Autowired
    private ProcessInstanceMapper processInstanceMapper;

    @Override
    public PageInfo<ProcessInstanceVO> getMyTodoList(User currentUser, Integer pageNum, Integer pageSize, String keyword) {
        Map<String, Object> params = new HashMap<>();
        params.put("currentUserId", currentUser.getId());

        // 如果是部门主管,可以查看部门下所有任务,而非仅自己的
        if ("manager".equals(currentUser.getRole())) {
            params.remove("currentUserId"); // 移除个人ID条件
            params.put("department", currentUser.getDepartment());
        }

        params.put("keyword", keyword);

        // 使用PageHelper进行分页
        PageHelper.startPage(pageNum, pageSize);
        List<ProcessInstance> list = processInstanceMapper.selectMyTodoList(params);
        PageInfo<ProcessInstance> pageInfo = new PageInfo<>(list);

        // 将Entity转换为前端所需的VO(View Object)
        return convertToVOList(pageInfo);
    }
}

管理员订单管理 图:管理员拥有全局视角,可以查看、筛选和管理系统中的所有流程实例。

实体模型与业务对象

系统的核心业务对象(Entity)与数据库表一一对应,并通过MyBatis进行映射。以ProcessInstance实体为例:

@Data // Lombok注解,自动生成getter, setter等方法
public class ProcessInstance {
    private String instanceId;
    private String processDefinitionKey;
    private String title;
    private Integer initiatorId;
    private Integer currentAssigneeId;
    private String status;
    private String priority;
    private Date createdTime;
    private Date updatedTime;

    // 非数据库字段,用于关联查询结果的展示
    private String initiatorName;
    private String currentAssigneeName;
}

未来优化方向

  1. 集成工作流引擎:当前系统的流程逻辑相对简单(线性审批)。未来可集成如Activiti、Flowable等成熟的工作流引擎,以支持更复杂的流程模式,如并行网关、条件分支、子流程等,使流程配置更加灵活和强大。
  2. 强化消息推送机制:目前的任务通知可能依赖页面待办数字提醒。可以集成WebSocket实现实时推送,或对接企业微信、钉钉、邮件等渠道,确保处理人能够及时获知新任务,减少任务延迟。
  3. 数据分析与报表功能:基于积累的任务操作数据,开发数据分析看板。例如,统计各部门任务处理平均时长、任务积压情况、个人绩效等,为管理决策提供数据支持。可使用ECharts等前端图表库进行可视化展示。
  4. 移动端适配或APP开发:开发响应式前端或独立的移动端APP,让用户能够随时随地通过手机处理待办事项,进一步提升系统的便捷性和可用性。
  5. 微服务架构改造:随着业务复杂度的提升,可以考虑将单体应用拆分为微服务
本文关键词
SSM框架业务代办流程管理系统源码解析企业协同平台

上下篇

上一篇
没有更多文章
下一篇
没有更多文章