ecs-attend-requirements.md 15 KB

功能需求规格文档 — 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

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

AttendVo:
  - attendId          # 主键
  - className         # 班级名称
  - realName          # 学员姓名
  - userNumb          # 学号
  - roomName          # 教室名称
  - checkTime         # 考勤时间
  - uploadTime        # 上传时间
  - pushStatus        # 推送状态
  - pushTime          # 推送时间

5.2 主表明细 VO

AttendDetailVo:
  includes: AttendVo
  additional:
    - userId           # 学员Id
    - userNumb         # 学号
    - realName         # 学员姓名
    - classId          # 班级Id
    - className        # 班级名称
    - roomId           # 教室Id
    - roomName         # 教室名称
    - checkTime        # 考勤时间
    - checkType        # 考勤方式
    - uploadTime       # 上传时间
    - pushStatus       # 推送状态
    - pushTime         # 推送时间
    - pushRetry        # 推送尝试次数

6. 特殊需求

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

-- ============================================
-- 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,前端实现时班级选择变更后需清空学员已选值,并按新班级过滤学员列表。