资讯详情

SSM警务辅助人员管理系统:排班考勤与小程序联调实战

📅 2026/10/22 8:09:11 | 华诺云谱 👁 阅读
SSM警务辅助人员管理系统:排班考勤与小程序联调实战
简介这是一份基于微信小程序的警务辅助人员管理系统毕业设计项目面向计算机相关专业学生和需要搭建小程序管理后台的开发者。系统使用微信小程序前端技术后端采用Spring、SpringMVC、MyBatisSSM框架配合MySQL数据库覆盖用户管理、警辅人员信息维护、任务分配等核心功能可直接运行或二次改造整体采用模块化设计便于扩展维护。压缩包内共1024个文件包含Java源码、Vue后台管理页面、小程序前端页面、SQL数据库脚本以及安装运行批处理与配置文件包体仅18.18MB目录结构清晰。其中PNG、SVG等图片用于界面图标JS、WXML、WXSS构成小程序端逻辑与样式JAVA、VM等支撑后端服务。目前已有124人学习下载适合作为毕业设计参考、课程实践或小程序与SSM整合开发的完整示例有助于理解前后端分离流程和移动端管理系统落地。1. 警务辅助人员管理系统到底是做什么的为什么值得自己搭一套警务辅助人员管理系统加 SSM 后缀这个标题基本就把技术栈和业务场景都说清楚了后端是 Spring SpringMVC MyBatis前端有一个微信小程序端核心要解决的是辅警队伍日常管理里最让人头疼的排班、考勤、任务记录和月底考核汇总。以前很多基层单位用的是Excel 表 微信群接龙的方式排班靠手写、打卡靠拍照、考核靠月底对聊天记录数据对不上就是一笔糊涂账。这套系统要做的就是把人员档案、排班计划、打卡记录、任务派发和考核统计全部电子化让管理人员能实时看到谁在岗、谁没到、谁这个月迟到了几次。我按这个方向做过类似的项目可以明确说这类系统业务复杂度不算高真正难的反而在数据模型和权限设计上。如果你是刚开始做毕设或者第一次接触企业级内部管理系统SSM 这套组合仍然是很好的学习样板因为分层清楚、事务和拦截器配置直观出了问题容易排查。这篇笔记不讲虚的直接从工程结构、数据库表设计、登录鉴权、小程序联调一直写到高频踩坑照着做能省掉不少试错时间。2. SSM 选型与工程落地一个可复现的分层骨架2.1 为什么很多这类系统还在用 SSM而不是一上来就 Spring Boot看到标题里的 ssm 后缀很多人第一反应是都什么年代了还用 SSM。但实际交付环境里SSM 的选择往往不是技术落后而是会被现有条件卡住。比如我接触过的某内部管理系统部署在旧服务器上装的是老版本 JDK 和 Tomcat统一运维团队只认 war 包如果直接引入 Spring Boot 的嵌入式容器反而会跟现有监控脚本冲突。SSM 打出来的 war 包放到 Tomcat webapps 下就能跑升级路径清晰对部署环境的要求低很多。另一个理由是代码审查和二次开发的门槛。SSM 的配置都在 XML 里SpringMVC 的拦截器、MyBatis 的 SQL 映射、事务管理是分开的三块新来的同事接手时能顺着配置文件把请求链路读下来。Spring Boot 把一切都自动装配了虽然写起来爽但出了问题排查链路反而长。对这种要长期维护的内部管理系统可读性和可维护性比开发速度重要。还有一点是权限控制。警务辅助人员管理系统一般都涉及按角色控制菜单、按岗位控制数据范围SpringMVC 拦截器加方法级注解的方式能精细地管理接口权限实现在代码里很直观。所以如果你拿到的资源包是 ssm 结构我建议先别急着改造成 Spring Boot把原有骨架吃透再考虑要不要迁移。2.2 Maven 依赖最小集少了哪个会在启动时翻车我先贴一份可用到项目里的核心 pom 依赖标注了每个依赖的作用。版本号按主流兼容组合给实际使用时要跟你本机 JDK 和数据库版本对齐。properties project.build.sourceEncodingUTF-8/project.build.sourceEncoding maven.compiler.source1.8/maven.compiler.source maven.compiler.target1.8/maven.compiler.target /properties dependencies !-- Spring MVC 核心自带 spring-context -- dependency groupIdorg.springframework/groupId artifactIdspring-webmvc/artifactId version4.3.30.RELEASE/version /dependency !-- MyBatis 和 Spring 整合包 -- dependency groupIdorg.mybatis/groupId artifactIdmybatis/artifactId version3.5.6/version /dependency dependency groupIdorg.mybatis/groupId artifactIdmybatis-spring/artifactId version1.3.3/version /dependency !-- Druid 连接池 -- dependency groupIdcom.alibaba/groupId artifactIddruid/artifactId version1.1.21/version /dependency !-- MySQL 驱动MySQL 5.7 用 5.1.49MySQL 8.x 换 8.0.11 -- dependency groupIdmysql/groupId artifactIdmysql-connector-java/artifactId version5.1.49/version /dependency !-- JSON 序列化小程序端接口返回数据用 -- dependency groupIdcom.fasterxml.jackson.core/groupId artifactIdjackson-databind/artifactId version2.9.10/version /dependency !-- Servlet API编译时需要Tomcat 里已有 -- dependency groupIdjavax.servlet/groupId artifactIdjavax.servlet-api/artifactId version3.1.0/version scopeprovided/scope /dependency /dependencies这段依赖要注意三个点。第一spring-webmvc 会传递引入 spring-context 和 spring-web不需要再单独重复引入 Spring 核心包否则容易出现版本冲突。第二mysql-connector-java 的版本必须和数据库实际版本匹配5.1.49 连 MySQL 8.x 会报认证插件不兼容那个报错经常被误判成密码错误。第三javax.servlet-api 的 scope 必须是 provided如果漏掉Tomcat 启动时会因为 jar 包冲突直接报 NoSuchMethodError。2.3 Spring 与 MyBatis 配置骨架把三层结构串起来SSM 整合最关键的配置是 spring-mvc.xml 和 spring-mybatis.xml 这两份文件。很多人第一次搭 SSM 项目翻车原因无外乎漏了组件扫描、漏了 Mapper 扫描或者拦截器把静态资源也拦了。下面是我的配置习惯!-- spring-mvc.xml -- context:component-scan base-packagecom.example.workerhelper.controller/ mvc:annotation-driven / !-- 后台管理页面用的 JSP 视图解析器小程序接口走 ResponseBody 不经过这里 -- bean classorg.springframework.web.servlet.view.InternalResourceViewResolver property nameprefix value/WEB-INF/views// property namesuffix value.jsp/ /bean !-- 静态资源放行不然 css/js 全会被拦截器拦住 -- mvc:resources mapping/static/** location/static//!-- spring-mybatis.xml -- bean iddataSource classcom.alibaba.druid.pool.DruidDataSource property namedriverClassName valuecom.mysql.jdbc.Driver/ property nameurl valuejdbc:mysql://127.0.0.1:3306/worker_helper?useUnicodetrueamp;characterEncodingutf8amp;serverTimezoneAsia/Shanghai/ property nameusername valueroot/ property namepassword value你的密码/ /bean bean idsqlSessionFactory classorg.mybatis.spring.SqlSessionFactoryBean property namedataSource refdataSource/ property namemapperLocations valueclasspath*:mapper/*.xml/ property nameconfigLocation valueclasspath:mybatis-config.xml/ /bean bean classorg.mybatis.spring.mapper.MapperScannerConfigurer property namebasePackage valuecom.example.workerhelper.mapper/ /bean bean idtransactionManager classorg.springframework.jdbc.datasource.DataSourceTransactionManager property namedataSource refdataSource/ /bean tx:annotation-driven transaction-managertransactionManager/这里有两个我踩过的坑必须单独说明。MpperScannerConfigurer 的 basePackage 要填 Mapper 接口所在的包不是 XML 文件所在目录填错的结果是 Service 层注入 Mapper 时报 NoSuchBeanDefinitionException。另外 SQL 映射文件路径 classpath*:mapper/*.xml 里不要写 src/main/resources 这个前缀编译后那层目录是不存在的。启动顺序上我一般先把 Spring 容器跑起来再部署到 Tomcat这样报错信息能区分是容器问题还是 Web 环境问题。3. 数据模型与权限设计把排班、考勤、考核装进几张核心表3.1 用户、角色、岗位为什么要拆成三张表而不是一个字段解决警务辅助人员管理系统里最容易犯的设计错误是在 sys_user 表里放一个 role 字段填队长内勤辅警。表面上看省事实际运行一个月就会后悔一个人既负责带班又要参与执勤角色是多个的数据查询时的 in 条件会越写越复杂改权限还要直接 update 用户表做不了权限审计。RBAC 那套经典的三张表在这种场景同样适用。CREATE TABLE sys_user ( id BIGINT NOT NULL AUTO_INCREMENT COMMENT 用户ID, username VARCHAR(32) NOT NULL COMMENT 登录账号, password VARCHAR(128) NOT NULL COMMENT 密码密文禁止明文, real_name VARCHAR(32) NOT NULL COMMENT 真实姓名, org_id BIGINT NOT NULL COMMENT 所属部门ID, phone VARCHAR(20) COMMENT 手机号, id_card VARCHAR(18) COMMENT 身份证号脱敏展示, status TINYINT DEFAULT 1 COMMENT 1启用 0停用, last_login_time DATETIME COMMENT 最近登录时间, PRIMARY KEY (id), UNIQUE KEY uk_username (username) ) ENGINEInnoDB COMMENT用户表; CREATE TABLE sys_role ( id BIGINT NOT NULL COMMENT 角色ID, role_code VARCHAR(32) NOT NULL COMMENT 角色编码, role_name VARCHAR(50) NOT NULL COMMENT 角色名称, PRIMARY KEY (id) ) ENGINEInnoDB COMMENT角色表; CREATE TABLE sys_user_role ( user_id BIGINT NOT NULL, role_id BIGINT NOT NULL, PRIMARY KEY (user_id, role_id), KEY idx_role_id (role_id) ) ENGINEInnoDB COMMENT用户角色关联表; CREATE TABLE sys_org ( id BIGINT NOT NULL, parent_id BIGINT DEFAULT 0 COMMENT 上级部门ID0表示根节点, org_name VARCHAR(50) NOT NULL, PRIMARY KEY (id) ) ENGINEInnoDB COMMENT部门/岗位组织表;sys_org 表是用来组织岗位维度的大队、中队、班组都放在这里通过 parent_id 形成树形结构。这样做的好处是排班统计可以按班组维度汇总而不用在 SQL 里硬编码单位名称。密码字段我用的是 BCrypt 加密后存密文绝不放明文后面登录鉴权会再提到。身份证号这里要注意小程序端展示时要做脱敏中间几位打星号避免完整身份证号落到客户端日志里。3.2 排班计划与打卡记录状态字段怎么设计才算合理排班和考勤是这个系统的核心业务两张表的设计直接决定月底统计好不好写。排班计划表记录谁在什么时间到什么岗位考勤记录表记录实际打卡时间和位置。这里有一个容易被忽略的点排班和考勤要用 plan_id 关联而不是直接拿 user_id 和时间段去匹配否则以后排班调整了、调休补班了考勤记录会完全对不上。CREATE TABLE shift_plan ( id BIGINT NOT NULL AUTO_INCREMENT, plan_date DATE NOT NULL COMMENT 排班日期, user_id BIGINT NOT NULL COMMENT 人员ID, post VARCHAR(50) NOT NULL COMMENT 执勤岗位/点位名称, shift_start DATETIME NOT NULL COMMENT 上班时间, shift_end DATETIME NOT NULL COMMENT 下班时间, plan_status TINYINT DEFAULT 0 COMMENT 0未发布 1已发布 2已取消, creator_id BIGINT NOT NULL COMMENT 排班录入人, create_time DATETIME DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), KEY idx_user_date (user_id, plan_date) ) ENGINEInnoDB COMMENT排班计划表; CREATE TABLE attendance_record ( id BIGINT NOT NULL AUTO_INCREMENT, plan_id BIGINT NOT NULL COMMENT 关联排班ID, user_id BIGINT NOT NULL COMMENT 人员ID冗余便于统计, check_in_time DATETIME COMMENT 签到时间, check_out_time DATETIME COMMENT 签退时间, in_lat DECIMAL(10,6) COMMENT 签到纬度, in_lng DECIMAL(10,6) COMMENT 签到经度, in_address VARCHAR(255) COMMENT 签到地址描述, in_status TINYINT DEFAULT 0 COMMENT 0未签到 1正常 2迟到 3缺卡, out_status TINYINT DEFAULT 0 COMMENT 0未签退 1正常 2早退 3缺卡, work_hours DECIMAL(5,2) COMMENT 工作时长单位小时, PRIMARY KEY (id), UNIQUE KEY uk_plan_user (plan_id, user_id), KEY idx_user_month (user_id, check_in_time) ) ENGINEInnoDB COMMENT考勤打卡记录表;plan_id 和 user_id 上的唯一索引非常关键这是打卡幂等的最后一道防线哪怕代码里并发判断漏了数据库也会拦住重复签到。in_status 和 out_status 是两个独立字段不要把迟到和早退塞进同一个字段否则一天内既迟到又早退时只能保留一个状态统计就会出错。打卡记录生成后不允许直接修改如果真的录错了要走一个异常处理流程把这个逻辑做到管理后台里。3.3 统计查询口径为什么迟到次数必须从排班表开始算月底考核的核心是一张统计表每个人出勤多少天、迟到多少次、缺卡多少次。很多第一次写这需求的人会从 attendance_record 表直接 GROUP BY结果就是没打卡的人、被取消的班次全都算不进去数字怎么都对不上。正确做法是以 shift_plan 作为主表LEFT JOIN 考勤记录用排班状态过滤掉已取消的班次。SELECT u.real_name AS 姓名, COUNT(DISTINCT sp.plan_date) AS 应出勤天数, SUM(CASE WHEN a.in_status 1 THEN 1 ELSE 0 END) AS 正常签到次数, SUM(CASE WHEN a.in_status 2 THEN 1 ELSE 0 END) AS 迟到次数, SUM(CASE WHEN a.check_in_time IS NULL THEN 1 ELSE 0 END) AS 缺卡次数, ROUND(SUM(a.work_hours), 1) AS 总工时 FROM shift_plan sp LEFT JOIN attendance_record a ON a.plan_id sp.id LEFT JOIN sys_user u ON u.id sp.user_id WHERE sp.plan_date BETWEEN 2025-03-01 AND 2025-03-31 AND sp.plan_status 1 GROUP BY u.id, u.real_name ORDER BY u.real_name;这个 SQL 的关键在 COUNT(DISTINCT sp.plan_date)如果一个人一天内被安排了早晚两个班次不加 DISTINCT 就会把同一天算成两个出勤日。缺卡次数的判断条件是 check_in_time IS NULL不是 in_status 3因为状态字段可能有初始化异常但时间字段是物理事实。月份参数建议用 Java 代码拼接不要直接拼字符串进 SQL用 MyBatis 的 #{monthStart} 和 #{monthEnd} 传参避免注入风险。4. 登录鉴权与小程序端联调从账号密码到打卡回传4.1 为什么小程序端不能用 Session改用 Token 更省事SSM 后台管理系统用 Session 没问题但微信小程序端每次请求都是独立的网络连接Cookie 的传递和处理在开发者工具里时好时坏真机上更不可控。所以这类系统我一般直接用 Token 方案用户登录成功后后端生成一个随机 Token 存到 Redis 或者数据库表返回给前端前端每次请求把它塞进 header 的 X-Token 字段。后端用拦截器统一校验。mvc:interceptors mvc:interceptor mvc:mapping path/api/**/ !-- 登录接口必须放行 -- mvc:exclude-mapping path/api/auth/login/ bean classcom.example.workerhelper.interceptor.ApiAuthInterceptor/ /mvc:interceptor /mvc:interceptors拦截器里做的事很简单取 header 里的 X-Token去 Redis 或数据库查一下是否存在且未过期把 userId 放到 ThreadLocal 里供后续 Controller 使用。没有 Token 或已过期就直接返回 401。注意 exclude-mapping 除了 login 别漏掉验证码接口如果小程序端有获取验证码的入口也要放行否则就会遇到那个经典问题登录页验证码图片加载不出来。4.2 小程序端请求封装统一带着 Token 请求接口并处理 401小程序端我不建议每个页面直接调 wx.request太容易出问题。统一封装一个 request 方法登录态维护、错误提示、状态码处理全在这一个文件里解决。const BASE_URL http://192.168.1.20:8080/worker-helper; function request(path, method GET, data {}) { return new Promise((resolve, reject) { wx.request({ url: BASE_URL path, method: method, data: data, header: { Content-Type: application/json, X-Token: wx.getStorageSync(token) || }, success(res) { // 登录过期统一跳登录页 if (res.statusCode 401) { wx.removeStorageSync(token); wx.removeStorageSync(userInfo); wx.navigateTo({ url: /pages/login/login }); reject(new Error(登录已过期)); return; } // 业务状态码0 表示成功 if (res.data res.data.code 0) { resolve(res.data.data); } else { wx.showToast({ title: res.data.message || 请求失败, icon: none }); reject(new Error(res.data.message || 请求失败)); } }, fail(err) { wx.showToast({ title: 网络请求失败, icon: none }); reject(err); } }); }); } module.exports { request, BASE_URL };这里有一个很重要的约定HTTP 状态码和业务状态码是两码事。401 表示登录态失效用 HTTP 状态码表达业务失败比如不在打卡范围用 JSON 里的 code 和 message 表达。如果你在业务失败时也返回 HTTP 200那前端就不能在 success 里判断 res.statusCode要看 res.data.code我这里统一是 code 0 为成功。BASE_URL 改成变量开发环境用局域网 IP生产环境必须换成已备案的 HTTPS 域名否则小程序发布审核直接不通过。4.3 打卡接口时间窗口、位置围栏和幂等控制打卡接口是这类系统里最容易出安全事故的接口如果只有一个签到按钮辅警在家也可以打卡月底考核就失去意义。所以后端必须做三件事时间窗口校验、位置距离校验、重复打卡校验。public ResultVoid checkIn(Long planId, BigDecimal lat, BigDecimal lng, String address) { ShiftPlan plan shiftPlanMapper.selectById(planId); if (plan null || plan.getPlanStatus() ! 1) { return Result.fail(排班不存在或未发布); } // 时间窗口允许上班前30分钟签到下班后2小时内签退 Date now new Date(); if (now.before(DateUtils.addMinutes(plan.getShiftStart(), -30))) { return Result.fail(还未到签到时间); } // 位置围栏和岗位坐标距离超过500米判为无效打卡 double distance haversine(plan.getLat(), plan.getLng(), lat, lng); if (distance 500) { return Result.fail(不在打卡范围); } // 幂等控制同一排班只能签到一次 AttendanceRecord record attendanceRecordMapper.selectByPlanAndUser(planId, currentUserId()); if (record ! null record.getCheckInTime() ! null) { return Result.fail(已签到请勿重复操作); } // 写入考勤记录状态根据时间是否超过 shift_start 判定 ... }距离计算用 Haversine 公式不要用简单的勾股定理纬度跨度和经度跨度在实际距离上并不等价。500 米这个阈值看着合理但如果是大型园区或商圈点位岗位坐标和实际岗亭位置可能差出三四百米建议把阈值放到数据库配置表里不要写死在代码里。时间窗口也一样不同班次的宽严程度不同有的岗位要求提前 15 分钟到位做成可配置项以后调整成本低很多。5. 五个高频踩坑和排查记录照着这条能少熬两个夜5.1 查询字段全是 null但数据库里明明有值这个坑几乎是 SSM 项目必遇。现象是 MyBatis 执行 SQL 正常返回了一条数据但 JSON 输出里业务字段全是 nullid 却有值。原因基本是 mybatis-config.xml 里没有开启驼峰映射数据库列名 shift_start 无法自动对应 Java 属性 shiftStart。解决方式是在 mybatis-config.xml 里加配置configuration settings setting namemapUnderscoreToCamelCase valuetrue/ /settings /configuration加了之后如果还有个别字段对不上就要检查实体类属性名是不是真的跟数据库列名对应比如 is_deleted 这类 boolean 字段MyBatis 映射有时会出歧义。另外提醒一句开启驼峰映射后resultType 里如果又手动写了 resultMap那 resultMap 里的 column 配置优先级更高两边标准要一致不要混着用。5.2 时间字段总是差 8 小时现象是后端日志打印的时间是正确的 15:00数据库存的也是 15:00但小程序端拿到数据后显示 23:00。原因出在 JDBC 连接串没有指定时区MySQL 驱动默认用了服务器会话时区而你的应用服务器和数据库服务器时区配置不一致。解决方式是在 jdbc url 上显式加上 serverTimezone 参数jdbc:mysql://127.0.0.1:3306/worker_helper?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai这里要注意Asia/Shanghai 这种写法在某些老版本驱动里不支持会报 unrecognized timezone需要把 MySQL 驱动升级到 5.1.39 以上。如果公司数据库服务器在云上别只看数据库服务器本地时间要确认 JDBC 会话时区真正生效的值是什么很多时候两边都是 Asia/Shanghai但连接池初始化时用了默认时区。5.3 头像一超过 1MB 上传就报错小文件没问题现象是上传 500KB 的头像正常超过 1MB 直接抛异常后台日志一堆报错。原因有两个Tomcat 对 multipart 请求有默认大小限制Spring 的 multipartResolver 也有自己的 maxUploadSize任何一个触发都会失败。修改方案是把两个限制一起调大!-- spring-mvc.xml -- bean idmultipartResolver classorg.springframework.web.multipart.commons.CommonsMultipartResolver property namemaxUploadSize value10485760/ property namemaxInMemorySize value1048576/ /bean如果项目用的是 Servlet 3.0 的 MultipartConfig还要在 web.xml 里配置 max-file-size 和 max-request-size。这里有个容易忽略的细节头像文件本身不大但小程序端传图经常是多张 base64 一起传base64 会比原图大三分之一左右按 10MB 配置是够用的。调大之后还要关注服务器磁盘和请求超时时间图片处理建议异步化。5.4 开发者工具能请求通手机一打开就连接失败这个坑最容易让人怀疑人生。现象是微信开发者工具里接口全部正常数据加载流畅但一用手机真机调试所有请求全部 timeout。原因不是代码问题而是开发者工具默认不校验合法域名相当于帮你放行了一切请求真机上微信会强制检查域名配置同时你的后端只监听了 127.0.0.1手机当然访问不到。解决分两步。第一步开发阶段把后端的监听地址从 127.0.0.1 改成 0.0.0.0电脑防火墙放行对应端口手机和电脑连同一个局域网用电脑的局域网 IP 访问。第二步生产环境必须准备一个已备案的 HTTPS 域名在小程序后台把 request 合法域名配置上去后端用 Nginx 做分发。这个流程没法绕开早准备早省心。5.5 打卡距离算不准几百米的偏差从哪来现象是用户在打卡点楼下显示不在打卡范围或者明明离点位很远却签到成功。原因大概率是坐标系混用了。微信小程序 wx.getLocation 默认返回的是 gcj02 坐标系也就是高德和腾讯地图在用的坐标系但如果你后端存储的岗位坐标是从 GPS 设备直接采的 WGS84 坐标两者相差几百米直接算距离就废了。解决方式是统一坐标系。小程序端明确请求 gcj02 坐标后端所有点位坐标也用 gcj02 存储地图选点的时候用高德或腾讯地图的坐标拾取器不要自己去采集 GPS。如果确实要接入 GPS 设备数据写一个坐标转换工具类把 WGS84 转成 gcj02这个转换算法网上有成熟的实现但一定要验证边界值尤其在高纬度地区偏移会明显。6. 从能跑到好用重构优先级、接口验证与日常巡检6.1 让系统能长期用下去的四个重构点第一登录 Token 一定要落库或者放到 Redis。一开始为了省事用内存 Map 存 Token重启一次服务所有人掉线而且多实例部署时 A 实例发的 Token B 实例不认识。改成数据库表或者 Redis 之后这个问题才算根治。第二给核心操作加日志。谁改了排班、谁删了考勤记录这种操作要留痕出纠纷时能查得到我用了一个简单的操作日志表AOP 注解切入维护成本很低。第三统计口径固化到系统里做配置考勤规则的参数比如打卡范围阈值、迟到判定时间、允许提前签到分钟数全部抽到配置表不要在代码里翻常量。第四数据库定时备份。这类系统一旦跑起来就是天天用数据丢了等于白做我习惯用 cron 每天凌晨备份。6.2 四个接口的自动化验证用例每次改完代码不要只点页面用脚本把核心链路走一遍。我一般会写一个验证脚本模拟登录、查排班、打卡、看统计的全流程BASEhttp://127.0.0.1:8080/worker-helper/api # 1. 登录并提取 token TOKEN$(curl -s -X POST $BASE/auth/login \ -H Content-Type: application/json \ -d {username:admin,password:123456} \ | python3 -c import sys,json; print(json.load(sys.stdin)[data][token])) # 2. 查看今日排班 curl -s $BASE/shift/plan/today \ -H X-Token: $TOKEN \ -H Content-Type: application/json # 3. 模拟打卡 curl -s -X POST $BASE/attendance/check-in \ -H X-Token: $TOKEN \ -H Content-Type: application/json \ -d {planId:1,lat:31.2304,lng:121.4737,address:测试点位} # 4. 统计当月出勤 curl -s $BASE/stat/month?month2025-03 \ -H X-Token: $TOKEN这个脚本每次跑通说明从登录到打卡到统计的主链路没问题。除了接口层面我还会跑一遍异常场景不带 Token 请求、重复打卡、在错误位置打卡确认返回的 code 和 message 都符合预期。接口联调这种事最怕的就是改了一个查询条件结果统计口径悄悄变了月底对不上账才发现。我做这类系统有个习惯每次改完接口后隔几天就把验证脚本跑一遍不只是为了测试更是提醒自己别在能跑和好用之间原地踏步。这类管理系统业务不高深但逐步完善起来的东西才真的会被一线人员接受。如果这套流程你也照做了相信很快能稳定下来如果中间遇到没写到的坑希望能回来翻翻这篇文章再对比一遍。希望帮到你。本文还有配套的精品资源点击获取
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑