# 功能需求规格文档 — ECS 考勤管理 > 本文档描述 ECS 电子班牌模块「考勤管理」功能的完整需求规格。 > 技能将根据此文档生成后端 + 前端代码。 --- ## 1. 基础信息 | 属性 | 值 | |------|-----| | 功能中文名 | 考勤管理 | | 功能简写 | attend | | 所属模块 | ruoyi-modules/ruoyi-ecs | | 主表名 | t_ecs_attend | | 从表名 | 无 | | 是否多租户 | 是 | | 数据库类型 | kingbase(人大金仓) | | 描述 | 管理学员考勤记录,数据由考勤设备上传,支持查看、查询、导出;同时支持手工考勤补签(选择教室→班级→班级下学员) | --- ## 2. 接口清单 ### 2.1 主表接口 | 接口 | HTTP | 路径(后端) | 前端路径 | 权限字符 | |------|------|-------------|----------|----------| | 列表 | GET | /attend/list | /ecs/attend/list | ecs:attend:list | | 详情 | GET | /attend/{id} | /ecs/attend/{id} | ecs:attend:query | | 新增(手工考勤) | POST | /attend/ | /ecs/attend/ | ecs:attend:add | | 导出数据 | POST | /attend/export | /ecs/attend/export | ecs:attend:export | > **说明**:考勤记录主要来自设备上传,本模块提供查看、查询和导出功能。手工考勤为补签场景,需关联选择教室、班级、班级下学员。不支持编辑、删除、导入操作。 ### 2.2 补充接口 无 --- ## 3. 字段属性速查表 | 属性 | 含义 | 可选值 | 说明 | |------|------|--------|------| | `fieldName` | 字段名(驼峰) | — | 代码变量名 | | `columnName` | 列名(下划线) | — | 数据库列名 | | `fieldType` | Java类型 | String/Long/Integer/BigDecimal/Date | | | `inDb` | 是否在表中存在 | true/false | false=纯前端计算字段 | | `inTable` | 列表是否显示 | true/false | 生成表格列 | | `inQuery` | 是否查询字段 | true/false | 生成搜索条件 | | `queryType` | 查询方式 | eq/like/between | 精确/模糊/范围 | | `inForm` | 是否表单字段 | true/false | 生成表单项 | | `inAdd` | 新增表单显示 | true/false | | | `inEdit` | 编辑表单显示 | true/false | | | `required` | 是否必填 | true/false | 生成校验注解 | | `dictType` | 字典类型 | 字典标识 | 有值=字典下拉,否则普通输入 | | `relation` | 关联选择配置 | 对象 | 有值=弹出选择框 | | `component` | 前端组件类型 | input/select/inputNumber/datetime/textarea | 默认根据类型推断 | | `width` | 表格列宽 | 数字(px) | 默认auto | | `sort` | 排序 | 数字 | 越小越靠前 | | `excelExport` | Excel导出 | true/false | 默认true | | `lockRule` | 操作锁定规则 | 对象 | 有值=按此字段值控制行级操作权限 | --- ## 4. 字段清单 ### 4.1 主表 `t_ecs_attend` ```yaml fields: # ---------- 主键 ---------- - fieldName: attendId columnName: attend_id fieldType: Long inDb: true inTable: false inForm: false remark: 主键,详情时传递 # ---------- 学员关联 ---------- - fieldName: userId columnName: user_id fieldType: Long inDb: true inTable: false inQuery: false inForm: true inAdd: true inEdit: false required: true relation: table: t_pt_user_account idField: pt_user_id nameField: real_name title: 选择学员 path: /backstage/userAccount/selectUserAccount cascade: dependsOn: classId description: 选择班级后,只能选择该班级下的学员 component: userSelect remark: 学员Id(关联学员表,级联依赖班级) - fieldName: userNumb column_name: user_numb fieldType: String inDb: true inTable: true inQuery: true queryType: like inForm: false component: input width: 120 sort: 4 excelExport: true remark: 学号(冗余存储) - fieldName: realName columnName: real_name fieldType: String inDb: true inTable: true inQuery: true queryType: like inForm: false component: input width: 120 sort: 3 excelExport: true remark: 学员姓名(冗余存储) # ---------- 班级关联 ---------- - fieldName: classId columnName: class_id fieldType: Long inDb: true inTable: false inQuery: false inForm: true inAdd: true inEdit: false required: true relation: table: t_ecs_class idField: class_id nameField: class_name title: 选择班级 path: /ecs/class/selectClass component: classSelect remark: 班级Id(关联班级表) - fieldName: className columnName: class_name fieldType: String inDb: true inTable: true inQuery: true queryType: like inForm: false component: input width: 150 sort: 1 excelExport: true remark: 班级名称(冗余存储) # ---------- 教室关联 ---------- - fieldName: roomId columnName: room_id fieldType: Long inDb: true inTable: false inQuery: false inForm: true inAdd: true inEdit: false required: true relation: table: t_pt_room idField: room_id nameField: room_name title: 选择教室 path: /backstage/room/selectRoom component: roomSelect remark: 教室Id(关联教室表) - fieldName: roomName columnName: room_name fieldType: String inDb: true inTable: true inQuery: false inForm: false component: input width: 150 sort: 5 excelExport: true remark: 教室名称(冗余存储) # ---------- 考勤信息 ---------- - fieldName: checkTime columnName: check_time fieldType: Date inDb: true inTable: true inQuery: false inForm: true inAdd: true inEdit: false required: true component: datetime width: 180 sort: 6 excelExport: true remark: 考勤时间 - fieldName: checkType columnName: check_type fieldType: Integer inDb: true inTable: false inQuery: false inForm: true inAdd: true inEdit: false required: true dictType: check_type component: select excelExport: true remark: 考勤方式:0-刷卡,1-人脸 - fieldName: uploadTime columnName: upload_time fieldType: Date inDb: true inTable: true inQuery: false inForm: false component: datetime width: 180 sort: 7 excelExport: true remark: 上传时间 # ---------- 推送状态 ---------- - fieldName: pushStatus columnName: push_status fieldType: Integer inDb: true inTable: true inQuery: true queryType: eq inForm: false required: false dictType: push_status component: select width: 100 sort: 8 excelExport: true remark: 推送状态:0-未推送,1-推送成功,2-推送失败 - fieldName: pushTime columnName: push_time fieldType: Date inDb: true inTable: true inQuery: false inForm: false component: datetime width: 180 sort: 9 excelExport: true remark: 推送时间 - fieldName: pushRetry columnName: push_retry fieldType: Integer inDb: true inTable: false inQuery: false inForm: false component: inputNumber width: 80 excelExport: false remark: 推送尝试次数 # ---------- 公共字段(所有表统一包含,多租户表增加 tenant_id) ---------- # 通用字段定义(无需在字段清单中重复写,建表时自动追加): # | 字段 | Java类型 | 说明 | # | ------------- | --------------- | ------------------ | # | del_flag | Integer | 逻辑删除:0-未删除,1-已删除 | # | create_dept | Long | 创建部门 | # | create_by | Long | 创建者 | # | create_time | Date | 创建时间 | # | update_by | Long | 最后修改者 | # | update_time | Date | 最后修改时间 | # | tenant_id | Long | 租户ID(多租户表包含) | - fieldName: delFlag columnName: del_flag fieldType: Integer inDb: true inTable: false inForm: false - fieldName: createTime columnName: create_time fieldType: Date inDb: true inTable: false inQuery: false inForm: false component: datetime ``` --- ## 5. VO 结构 ### 5.1 主表列表 VO ```yaml AttendVo: - attendId # 主键 - className # 班级名称 - realName # 学员姓名 - userNumb # 学号 - roomName # 教室名称 - checkTime # 考勤时间 - uploadTime # 上传时间 - pushStatus # 推送状态 - pushTime # 推送时间 ``` ### 5.2 主表明细 VO ```yaml AttendDetailVo: includes: AttendVo additional: - userId # 学员Id - userNumb # 学号 - realName # 学员姓名 - classId # 班级Id - className # 班级名称 - roomId # 教室Id - roomName # 教室名称 - checkTime # 考勤时间 - checkType # 考勤方式 - uploadTime # 上传时间 - pushStatus # 推送状态 - pushTime # 推送时间 - pushRetry # 推送尝试次数 ``` --- ## 6. 特殊需求 ```yaml special: excelImport: false # 不支持导入 excelExport: true # 支持导出 # 手工考勤新增时的特殊规则 addRules: - fieldName: roomId required: true message: 请选择教室 - fieldName: classId required: true message: 请选择班级 - fieldName: userId required: true message: 请选择学员 cascade: true dependsOn: classId description: 先选班级,再选该班级下的学员 - fieldName: checkTime required: true message: 请填写考勤时间 - fieldName: checkType required: true message: 请选择考勤方式 # 级联选择规则 cascadeRules: - field: userId dependsOn: classId description: 选择班级后,学员列表过滤为该班级下的学员 apiPath: /backstage/userAccount/selectUserAccount apiParams: classId: ${classId} dubboExpose: false # 不暴露 Dubbo 服务 ``` --- ## 7. 字典项 | 字典类型 | 枚举值 | 说明 | |----------|--------|------| | `check_type` | 0=刷卡, 1=人脸 | 考勤方式 | | `push_status` | 0=未推送, 1=推送成功, 2=推送失败 | 推送状态 | --- ## 8. 建表语句 > **通用字段**:所有表统一包含以下字段(建表语句自动追加,无需在字段清单中重复): > > | 字段 | 类型 | 说明 | > | ------------- | -------------------- | ------------------ | > | del_flag | character(1 char) | 逻辑删除:0-未删除,1-已删除 | > | create_dept | bigint | 创建部门 | > | create_by | bigint | 创建者 | > | create_time | timestamp | 创建时间 | > | update_by | bigint | 更新者 | > | update_time | timestamp | 更新时间 | > | tenant_id | bigint | 租户ID(多租户表) | ### 8.1 主表 `t_ecs_attend` ```sql -- ============================================ -- ECS 考勤记录表(kingbase/人大金仓) -- ============================================ CREATE TABLE "dbo"."t_ecs_attend" ( "attend_id" bigint NOT NULL, "user_id" bigint NOT NULL, "user_numb" character varying(50 char) NOT NULL DEFAULT ''::varchar, "real_name" character varying(100 char) NOT NULL DEFAULT ''::varchar, "class_id" bigint NOT NULL, "class_name" character varying(100 char) NOT NULL DEFAULT ''::varchar, "room_id" bigint NOT NULL, "room_name" character varying(100 char) NOT NULL DEFAULT ''::varchar, "check_time" timestamp NOT NULL, "check_type" integer NOT NULL DEFAULT 0, "upload_time" timestamp, "push_status" integer NOT NULL DEFAULT 0, "push_time" timestamp, "push_retry" integer NOT NULL DEFAULT 0, -- 通用字段(自动追加) "del_flag" character(1 char) NOT NULL DEFAULT '0'::bpchar, "create_dept" bigint, "create_by" bigint, "create_time" timestamp, "update_by" bigint, "update_time" timestamp, "tenant_id" bigint, CONSTRAINT "t_ecs_attend_pkey" PRIMARY KEY ("attend_id") ); -- 表注释 ALTER TABLE "dbo"."t_ecs_attend" COMMENT 'ECS考勤记录表'; -- 列注释 ALTER TABLE "dbo"."t_ecs_attend" MODIFY "attend_id" COMMENT '主键'; ALTER TABLE "dbo"."t_ecs_attend" MODIFY "user_id" COMMENT '学员Id'; ALTER TABLE "dbo"."t_ecs_attend" MODIFY "user_numb" COMMENT '学号'; ALTER TABLE "dbo"."t_ecs_attend" MODIFY "real_name" COMMENT '学员姓名'; ALTER TABLE "dbo"."t_ecs_attend" MODIFY "class_id" COMMENT '班级Id'; ALTER TABLE "dbo"."t_ecs_attend" MODIFY "class_name" COMMENT '班级名称'; ALTER TABLE "dbo"."t_ecs_attend" MODIFY "room_id" COMMENT '教室Id'; ALTER TABLE "dbo"."t_ecs_attend" MODIFY "room_name" COMMENT '教室名称'; ALTER TABLE "dbo"."t_ecs_attend" MODIFY "check_time" COMMENT '考勤时间'; ALTER TABLE "dbo"."t_ecs_attend" MODIFY "check_type" COMMENT '考勤方式:0-刷卡,1-人脸'; ALTER TABLE "dbo"."t_ecs_attend" MODIFY "upload_time" COMMENT '上传时间'; ALTER TABLE "dbo"."t_ecs_attend" MODIFY "push_status" COMMENT '推送状态:0-未推送,1-推送成功,2-推送失败'; ALTER TABLE "dbo"."t_ecs_attend" MODIFY "push_time" COMMENT '推送时间'; ALTER TABLE "dbo"."t_ecs_attend" MODIFY "push_retry" COMMENT '推送尝试次数'; -- 索引 CREATE INDEX "idx_ecs_attend_class_id" ON "dbo"."t_ecs_attend" ("class_id"); CREATE INDEX "idx_ecs_attend_user_id" ON "dbo"."t_ecs_attend" ("user_id"); CREATE INDEX "idx_ecs_attend_check_time" ON "dbo"."t_ecs_attend" ("check_time"); CREATE INDEX "idx_ecs_attend_push_status" ON "dbo"."t_ecs_attend" ("push_status"); ``` --- ## 9. 备注 1. **数据冗余设计**:学员姓名(`realName`)、学号(`userNumb`)、班级名称(`className`)、教室名称(`roomName`)采用冗余存储策略,避免关联查询性能问题。当学员/班级/教室信息变更时需考虑是否同步更新历史记录。 2. **只读模型**:考勤记录主要由设备自动上传,不支持编辑和删除操作,确保数据的不可篡改性。本模块提供查看、查询、导出功能。 3. **推送机制**:`pushStatus` 记录推送状态,`pushRetry` 记录重试次数,支持后续定时任务扫描推送失败记录进行重试。 4. **手工考勤**:新增操作即「手工考勤」,用于补签场景。表单填写顺序为:选择教室 → 选择班级 → 选择学员(级联:选完班级后只能选该班级下的学员) → 选择考勤方式 → 填写考勤时间。 5. **关联实体说明**: - 教室 → 关联 `t_pt_room` 表(通过 backstage 模块的 RemotePtRoomService) - 班级 → 关联 `t_ecs_class` 表(ECS 模块内部) - 学员 → 关联 `t_pt_user_account` 表(通过 backstage 模块的 RemoteUserAccountService),**级联依赖班级**,只显示所选班级下的学员 6. **级联选择**:userId 级联依赖 classId,前端实现时班级选择变更后需清空学员已选值,并按新班级过滤学员列表。