You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

558 lines
28 KiB
Markdown

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# 考勤相关功能
> 模块编码attendance
> 端侧:微信小程序
> 关联文档01-模块划分.mdv4.0、02-功能清单-小程序端.md§5、03-业务流转逻辑-小程序端.md§5、05-接口规范.md§9、06-项目技术要求.md
> 强制规范遵循 `07-前端界面开发规范.md`
## 功能概览
| 项目 | 说明 |
|------|------|
| 菜单名称 | 考勤打卡 |
| 子菜单 | 上班打卡 / 下班打卡 / 打卡记录 / 异常申诉 / 考勤日历 / 考勤审核 |
| 功能编号 | MP-AT-01 ~ MP-AT-06 |
| 权限编码 | attendance:record:*、attendance:appeal:*、attendance:supplement:* |
## 页面清单
### 页面1上班打卡
- **页面路径**`/pages/attendance/clock-in`
- **适用角色**:全部
- **页面元素**
- 当前时间显示(大字时钟)
- 打卡状态指示(未打卡/已打卡)
- 蓝牙扫描状态指示器
- 当前打卡点名称
- 蓝牙信号强度显示
- 打卡按钮
- 补录/申诉入口
- **查询条件**:无
- **列表字段**:无
- **界面布局**
- 顶部:当前时间大字显示
- 中部:打卡点信息 + 蓝牙状态
- 底部:打卡按钮(圆形大按钮)
- **操作按钮**
- 「上班打卡」→ 记录上班打卡权限attendance:record:create
- 「异常申诉」→ 跳转异常申诉页(蓝牙未检测到时显示)
**蓝牙策略判断逻辑**
- 调用 `GET /system/bluetooth-policy → attendance_check`
- 策略=REQUIRED必须连接指定打卡点蓝牙Beacon后才可打卡
- 验证Beacon属于本人班组打卡点
- 打卡成功记录 `check_method=BLUETOOTH`
- 策略=OPTIONAL可选蓝牙打卡或手动打卡
- 手动打卡:`check_method=MANUAL`
**需求追溯**
| 功能点编号 | 功能名称 | 文档来源 | 后续服务 | 关联功能 |
|------------|----------|----------|----------|----------|
| MP-AT-01 | 上班打卡 | 02-小程序端 §5 | 记录操作日志 | 考勤记录、打卡点管理 |
#### 交互流程要求
1. **页面加载流程**:页面加载时获取当前时间→查询蓝牙策略→策略=REQUIRED自动启动蓝牙扫描显示打卡状态已打卡/未打卡)
2. **查询/筛选交互流程**:无筛选操作
3. **表单填写与提交流程**:点击「上班打卡」→策略=REQUIRED自动扫描蓝牙→检测到打卡点Beacon→打卡成功check_method=BLUETOOTH策略=OPTIONAL选择打卡方式→蓝牙/手动打卡
4. **弹窗/弹层交互流程**:打卡成功弹出成功提示(显示打卡时间);蓝牙未检测到弹出提示"未检测到打卡点蓝牙"
5. **行内操作流程**:点击打卡按钮→执行打卡流程→显示结果;点击异常申诉→跳转异常申诉页
6. **异常与错误处理**:蓝牙未开启提示"请开启手机蓝牙";打卡失败显示重试;已打卡提示"今日已打卡";离线时数据暂存本地联网后同步
7. **联动/级联交互**:蓝牙策略与打卡流程联动;打卡状态实时更新
8. **权限控制交互表现**:所有登录用户可打卡;蓝牙权限被拒引导开启
#### 前端硬性约束
- **H1 防重复提交**:打卡按钮点击后立即 `loading=true` + `disabled=true` 防止重复点击;使用 pending 请求去重机制(同一请求未完成前不发送新请求);支持 `wx.requestTask.abort()` 取消前一次未完成的请求
- **H2 超时控制**GET 请求超时 15s、POST 请求超时 30s请求耗时 >3s 时自动调用 `wx.showLoading({ title: '加载中...', mask: true })` 提示用户等待
- **H3 二次确认**:无危险操作,无需二次确认
- **H4 脏数据检测**:本页面为操作型页面,无需表单脏数据检测
- **H7 文件上传**:无上传操作
- **H8 操作反馈**:打卡成功调用 `wx.showToast({ title: '打卡成功', icon: 'success' })`;网络异常时提示"网络异常,请检查网络后重试",提供重试按钮;离线暂存成功提示"已暂存本地,联网后将自动同步"
- **通用约束**:使用 uni-ui 组件库;所有可点击元素触控区域 ≥44px下拉刷新操作需防重复触发
#### 组件规范
| 元素 | 组件 | 配置参数 |
|------|------|----------|
| 当前时间 | `text` | font-size="48px"font-weight="bold",动态更新 |
| 打卡状态 | `uni-tag` | type: success(已打卡)/warning(未打卡) |
| 打卡按钮 | `button` | type="primary"圆形大按钮size=120px |
| 蓝牙状态指示 | `uni-icons` | type="bluetooth"size="22" |
| 打卡点名称 | `text` | font-size="14px" |
| 异常申诉 | `button` | type="default"size="mini" |
| 打卡结果 | `uni-popup` | type="dialog",显示打卡时间 |
#### 校验规则
| 字段 | 规则 | 错误提示 |
|------|------|----------|
| 蓝牙状态 | 策略=REQUIRED须开启蓝牙 | "请开启手机蓝牙" |
| Beacon验证 | 须属于本人班组打卡点 | "未检测到有效打卡点" |
| 打卡状态 | 未打卡才可打卡 | "今日已打卡" |
| 打卡时间 | 自动记录精确到秒 | — |
#### 响应式布局
- **适配机型**iPhone SE375px~ iPad mini768px打卡按钮居中
- **横竖屏适配策略**:竖屏垂直居中布局;横屏信息与按钮并排
- **手势交互规范**打卡按钮≥120px可点击区域申诉按钮≥44px
- **安全区域**:底部按钮适配底部安全区
---
### 页面2下班打卡
- **页面路径**`/pages/attendance/clock-out`
- **适用角色**:全部
- **页面元素**
- 当前时间显示(大字时钟)
- 打卡状态指示(未打卡/已打卡)
- 上班打卡时间显示
- 蓝牙扫描状态指示器
- 当前打卡点名称
- 打卡按钮
- 补录/申诉入口
- **查询条件**:无
- **列表字段**:无
- **界面布局**
- 顶部:当前时间 + 上班打卡时间
- 中部:打卡点信息 + 蓝牙状态
- 底部:打卡按钮(圆形大按钮)
- **操作按钮**
- 「下班打卡」→ 记录下班打卡权限attendance:record:create
- 「异常申诉」→ 跳转异常申诉页
**需求追溯**
| 功能点编号 | 功能名称 | 文档来源 | 后续服务 | 关联功能 |
|------------|----------|----------|----------|----------|
| MP-AT-02 | 下班打卡 | 02-小程序端 §5 | 记录操作日志 | 考勤记录 |
#### 交互流程要求
1. **页面加载流程**:页面加载时获取当前时间和上班打卡时间→查询蓝牙策略→自动扫描蓝牙(策略=REQUIRED显示打卡状态
2. **查询/筛选交互流程**:无筛选操作
3. **表单填写与提交流程**:点击「下班打卡」→策略=REQUIRED自动扫描蓝牙→打卡成功策略=OPTIONAL选择打卡方式→打卡
4. **弹窗/弹层交互流程**:打卡成功弹出成功提示(显示上下班时间);蓝牙未检测到弹出提示
5. **行内操作流程**:点击打卡按钮→执行打卡→显示结果;点击异常申诉→跳转异常申诉页
6. **异常与错误处理**:蓝牙未开启提示;下班未打上班卡提示"请先完成上班打卡";离线暂存
7. **联动/级联交互**:上班打卡时间与下班打卡联动展示
8. **权限控制交互表现**:所有登录用户可打卡
#### 前端硬性约束
- **H1 防重复提交**:打卡按钮点击后立即 `loading=true` + `disabled=true` 防止重复点击;使用 pending 请求去重机制(同一请求未完成前不发送新请求);支持 `wx.requestTask.abort()` 取消前一次未完成的请求
- **H2 超时控制**GET 请求超时 15s、POST 请求超时 30s请求耗时 >3s 时自动调用 `wx.showLoading({ title: '加载中...', mask: true })` 提示用户等待
- **H3 二次确认**:无危险操作,无需二次确认
- **H4 脏数据检测**:本页面为操作型页面,无需表单脏数据检测
- **H7 文件上传**:无上传操作
- **H8 操作反馈**:打卡成功调用 `wx.showToast({ title: '打卡成功', icon: 'success' })`;网络异常时提示"网络异常,请检查网络后重试",提供重试按钮;离线暂存成功提示"已暂存本地,联网后将自动同步"
- **通用约束**:使用 uni-ui 组件库;所有可点击元素触控区域 ≥44px
#### 组件规范
| 元素 | 组件 | 配置参数 |
|------|------|----------|
| 当前时间 | `text` | font-size="48px"font-weight="bold" |
| 上班打卡时间 | `text` | font-size="14px"color="#666" |
| 打卡状态 | `uni-tag` | type: success(已打卡)/warning(未打卡) |
| 打卡按钮 | `button` | type="primary"圆形大按钮size=120px |
| 蓝牙状态指示 | `uni-icons` | type="bluetooth"size="22" |
| 异常申诉 | `button` | type="default"size="mini" |
| 打卡结果 | `uni-popup` | type="dialog" |
#### 校验规则
| 字段 | 规则 | 错误提示 |
|------|------|----------|
| 上班打卡 | 须先完成上班打卡 | "请先完成上班打卡" |
| 蓝牙状态 | 策略=REQUIRED须蓝牙连接 | "请开启手机蓝牙" |
| 打卡状态 | 未打卡才可打卡 | "今日已打卡" |
#### 响应式布局
- **适配机型**iPhone SE375px~ iPad mini768px打卡按钮居中
- **横竖屏适配策略**:竖屏垂直居中布局;横屏信息与按钮并排
- **手势交互规范**打卡按钮≥120px可点击区域
- **安全区域**:底部按钮适配底部安全区
---
### 页面3打卡记录
- **页面路径**`/pages/attendance/records`
- **适用角色**:全部
- **页面元素**
- 月份选择器
- 统计信息卡片(出勤天数/迟到/早退/缺卡)
- 打卡记录列表
- 记录详情弹窗
- **查询条件**
- 月份筛选
- 状态筛选(全部/正常/迟到/早退/缺卡/补录)
- **列表字段**
| 字段 | 类型 | 说明 |
|------|------|------|
| 日期 | 日期 | 打卡日期 |
| 上班时间 | 时间 | 上班打卡时间 |
| 下班时间 | 时间 | 下班打卡时间 |
| 打卡方式 | 标签 | 蓝牙/手动/补录 |
| 状态 | 标签 | 正常/迟到/早退/缺卡 |
- **界面布局**
- 顶部:月份选择器 + 统计数字横向排列
- 中部:按日期分组的打卡记录列表
- 底部:无操作栏
- **操作按钮**
- 「查看详情」→ 查看打卡详情(含打卡点、蓝牙信息等)
- 「异常申诉」→ 对异常记录发起申诉
**需求追溯**
| 功能点编号 | 功能名称 | 文档来源 | 后续服务 | 关联功能 |
|------------|----------|----------|----------|----------|
| MP-AT-03 | 打卡记录 | 02-小程序端 §5 | 无 | 考勤日历 |
#### 交互流程要求
1. **页面加载流程**:页面加载时获取当月打卡记录和统计→渲染月份选择器和记录列表
2. **查询/筛选交互流程**:切换月份→重新加载;状态筛选(全部/正常/迟到/早退/缺卡/补录)→过滤记录
3. **表单填写与提交流程**:无表单提交操作
4. **弹窗/弹层交互流程**:点击查看详情→弹出打卡详情弹窗(含打卡点、蓝牙信息)
5. **行内操作流程**:点击查看详情→查看详情弹窗;点击异常申诉→跳转异常申诉页
6. **异常与错误处理**:记录加载失败显示重试;无记录显示空状态
7. **联动/级联交互**:月份和状态筛选与列表数据联动
8. **权限控制交互表现**:仅可查看本人打卡记录
#### 前端硬性约束
- **H1 防重复提交**:月份切换/状态筛选时防重复请求;列表加载期间禁用筛选操作;使用 pending 请求去重
- **H2 超时控制**GET 请求超时 15s列表加载 >3s 时调用 `wx.showLoading({ title: '加载中...', mask: true })`
- **H3 二次确认**:无危险操作,无需二次确认
- **H4 脏数据检测**:本页面为列表查看页,无需表单脏数据检测
- **H7 文件上传**:无上传操作
- **H8 操作反馈**:加载成功无提示(静默刷新);加载失败调用 `wx.showToast({ title: '加载失败', icon: 'none' })` 并显示重试按钮;网络异常时提示"网络异常,请检查网络后重试"
- **通用约束**:使用 uni-ui 组件库;所有可点击元素触控区域 ≥44px下拉刷新需防重复触发refreshing 标志位)
#### 组件规范
| 元素 | 组件 | 配置参数 |
|------|------|----------|
| 月份选择器 | `uni-datetime-picker` | type="date"fields="month" |
| 统计卡片 | `uni-card` | mode="center",四列等宽 |
| 状态筛选 | `uni-segmented-control` | :values="['全部','正常','迟到','早退','缺卡','补录']" |
| 记录列表 | `uni-list` + `uni-list-item` | clickable=true |
| 状态标签 | `uni-tag` | type: success(正常)/warning(迟到/早退)/error(缺卡)/primary(补录) |
| 详情弹窗 | `uni-popup` | type="bottom",显示打卡详情 |
| 打卡方式标签 | `uni-tag` | type: primary(蓝牙)/default(手动)/warning(补录)size="mini" |
#### 校验规则
| 字段 | 规则 | 错误提示 |
|------|------|----------|
| 记录列表 | 加载失败允许重试 | "加载失败,请重试" |
#### 响应式布局
- **适配机型**iPhone SE375px~ iPad mini768px卡片宽度自适应
- **横竖屏适配策略**:竖屏单列列表;横屏双列卡片
- **手势交互规范**记录项可点击区域≥44px
- **安全区域**:底部适配底部安全区
---
### 页面4异常申诉
- **页面路径**`/pages/attendance/appeal`
- **适用角色**:全部(蓝牙失灵/系统宕机时)
- **页面元素**
- 异常日期选择
- 异常类型选择(上班/下班/全天)
- 异常原因选择(蓝牙故障/手机异常/系统异常/忘记打卡/其他)
- 补充说明输入框(多行文本)
- 照片上传区补充证据≤9张
- 提交按钮
- **查询条件**:无
- **列表字段**:无
- **界面布局**
- 顶部:申诉模式提示
- 中部:原因选择 + 说明填写 + 照片上传
- 底部:提交按钮
- **操作按钮**
- 「提交申诉」→ 提交打卡异常申诉权限attendance:appeal:create
- 申诉提交后等待主管审核Web/小程序均可审核)
**需求追溯**
| 功能点编号 | 功能名称 | 文档来源 | 后续服务 | 关联功能 |
|------------|----------|----------|----------|----------|
| MP-AT-04 | 异常申诉 | 02-小程序端 §5 | 主管审核 | 考勤审核 |
#### 交互流程要求
1. **页面加载流程**:页面加载时初始化表单,获取异常类型字典
2. **查询/筛选交互流程**:无筛选操作
3. **表单填写与提交流程**:选择异常日期→选择异常类型(上班/下班/全天)→选择异常原因→填写补充说明→上传照片→点击提交申诉→确认弹窗→提交成功等待审核
4. **弹窗/弹层交互流程**:点击上传弹出选择(拍照/相册);提交前弹出确认弹窗
5. **行内操作流程**:选择日期→选择类型→选择原因→填写说明→上传照片→提交
6. **异常与错误处理**:图片上传失败提示重传;提交失败显示重试;离线暂存本地
7. **联动/级联交互**:异常类型与日期选择联动
8. **权限控制交互表现**:所有用户可提交异常申诉
#### 前端硬性约束
- **H1 防重复提交**:提交按钮点击后立即 `loading=true` + `disabled=true` 防止重复提交;使用 pending 请求去重机制(提交请求未返回前禁用按钮);支持 `wx.requestTask.abort()` 取消前一次未完成的提交
- **H2 超时控制**GET 请求超时 15s、POST 请求超时 30s、文件上传超时 60s上传耗时 >3s 时调用 `wx.showLoading({ title: '上传中...', mask: true })`
- **H3 二次确认**:提交申诉前必须调用 `wx.showModal({ title: '确认提交', content: '提交后将等待主管审核,确认提交申诉?', confirmText: '确认', cancelText: '取消' })` 进行二次确认,明确告知操作后果
- **H4 脏数据检测**:页面进入时对表单数据做 deep clone 快照;用户编辑过程中维护 isDirty 状态;`onUnload` / `onBackPress` 生命周期中检测到 isDirty 时弹出 `wx.showModal` 提示"未保存的修改将丢失,确定离开吗?",用户确认后才允许离开
- **H7 文件上传**:单张图片 ≤10MB超出时提示"图片大小不能超过10MB"并阻止上传;使用 `uni-file-picker``onProgress` 回调显示上传进度条;支持多图队列上传
- **H8 操作反馈**:提交成功调用 `wx.showToast({ title: '申诉已提交,请等待审核', icon: 'success' })`;网络异常时调用 `wx.showToast({ title: '网络异常,请检查网络后重试', icon: 'none' })` 并提供重试按钮;离线暂存提示"已暂存本地,联网后将自动同步"
- **通用约束**:使用 uni-ui 组件库;所有可点击元素触控区域 ≥44px选择器/输入框/按钮均 ≥44px
#### 组件规范
| 元素 | 组件 | 配置参数 |
|------|------|----------|
| 异常日期 | `uni-datetime-picker` | type="date" |
| 异常类型 | `uni-data-select` | :localdata="[{value:'clock_in',text:'上班'},{value:'clock_out',text:'下班'},{value:'all_day',text:'全天'}]" |
| 异常原因 | `uni-data-select` | :localdata="[{value:'bluetooth',text:'蓝牙故障'},{value:'phone',text:'手机异常'},{value:'system',text:'系统异常'},{value:'forget',text:'忘记打卡'},{value:'other',text:'其他'}]" |
| 补充说明 | `uni-easyinput` | type="textarea"maxlength="200":showWordLimit="true" |
| 照片上传 | `uni-file-picker` | limit="9"file-mediatype="image" |
| 提交按钮 | `button` | type="primary":loading="submitting" |
| 确认弹窗 | `uni-popup` | type="dialog" |
#### 校验规则
| 字段 | 规则 | 错误提示 |
|------|------|----------|
| 异常日期 | 必选 | "请选择异常日期" |
| 异常类型 | 必选 | "请选择异常类型" |
| 异常原因 | 必选 | "请选择异常原因" |
| 补充说明 | 最多200字 | "补充说明不能超过200字" |
| 照片 | 最多9张 | "照片最多上传9张" |
#### 响应式布局
- **适配机型**iPhone SE375px~ iPad mini768px表单宽度自适应
- **横竖屏适配策略**:竖屏垂直布局;横屏表单水平分组
- **手势交互规范**选择器≥44px提交按钮≥44px
- **安全区域**:底部提交按钮适配底部安全区
---
### 页面5考勤日历
- **页面路径**`/pages/attendance/calendar`
- **适用角色**:全部
- **页面元素**
- 月历视图(日历格子)
- 每日状态标记(颜色点)
- 点击日期显示详情弹窗
- 图例说明
- **查询条件**
- 月份切换(左右滑动)
- **列表字段**:无(日历模式)
- **界面布局**
- 顶部:月份切换 + 统计信息
- 中部:月历网格,每日格子中用颜色点标记状态
- 绿色:正常
- 黄色:迟到/早退
- 红色:缺卡
- 蓝色:补录
- 灰色:休息日
- 底部:图例说明
- **操作按钮**
- 「点击日期」→ 显示当日打卡详情弹窗
**需求追溯**
| 功能点编号 | 功能名称 | 文档来源 | 后续服务 | 关联功能 |
|------------|----------|----------|----------|----------|
| MP-AT-05 | 考勤日历 | 02-小程序端 §5 | 无 | 打卡记录 |
#### 交互流程要求
1. **页面加载流程**:页面加载时获取当月考勤日历数据→渲染月历视图和每日状态标记
2. **查询/筛选交互流程**:左右滑动切换月份→重新加载月历数据
3. **表单填写与提交流程**:无表单提交操作
4. **弹窗/弹层交互流程**:点击日期→弹出当日打卡详情弹窗(上班/下班时间、打卡方式、状态)
5. **行内操作流程**:点击日期→查看详情弹窗;左右滑动切换月份
6. **异常与错误处理**:日历数据加载失败显示重试
7. **联动/级联交互**:月份切换与日历数据联动
8. **权限控制交互表现**:仅可查看本人考勤日历
#### 前端硬性约束
- **H1 防重复提交**:月份切换(左右滑动)时防重复请求;滑动切换期间锁定请求,避免连续滑动触发多次请求
- **H2 超时控制**GET 请求超时 15s日历数据加载 >3s 时调用 `wx.showLoading({ title: '加载中...', mask: true })`
- **H3 二次确认**:无危险操作,无需二次确认
- **H4 脏数据检测**:本页面为只读详情页,无需表单脏数据检测
- **H7 文件上传**:无上传操作
- **H8 操作反馈**:加载成功无提示(静默刷新);加载失败调用 `wx.showToast({ title: '日历加载失败', icon: 'none' })` 并显示重试按钮;网络异常时提示"网络异常,请检查网络后重试"
- **通用约束**:使用 uni-ui 组件库;日期格子可点击区域 ≥44px
#### 组件规范
| 元素 | 组件 | 配置参数 |
|------|------|----------|
| 月历视图 | 自定义日历组件 | 7列网格日期格子44px |
| 状态标记点 | `view` | 圆形8px颜色动态绿/黄/红/蓝/灰) |
| 月份切换 | `uni-icons` | type="left"/"right"size="20"@click切换 |
| 详情弹窗 | `uni-popup` | type="bottom",显示当日打卡详情 |
| 图例说明 | `view` + `text` | 水平排列,颜色点+文字 |
#### 校验规则
| 字段 | 规则 | 错误提示 |
|------|------|----------|
| 日历数据 | 加载失败允许重试 | "日历加载失败,请重试" |
| 日期选择 | 只能查看,不可选择未来日期 | — |
#### 响应式布局
- **适配机型**iPhone SE375px~ iPad mini768px日历网格宽度自适应
- **横竖屏适配策略**竖屏7列日历网格横屏日历宽度适当增大详情弹窗更宽
- **手势交互规范**日期格子≥44px左右滑动切换月份点击日期≥44px
- **安全区域**:底部图例适配底部安全区
---
### 页面6考勤审核
- **页面路径**`/pages/attendance/review`
- **适用角色**:主管
- **页面元素**
- 待审核申诉列表
- 申诉详情查看
- 审核操作区(通过/驳回)
- 驳回原因输入框
- **查询条件**
- 状态筛选(待审核/已通过/已驳回)
- 日期筛选
- 人员筛选
- **列表字段**
| 字段 | 类型 | 说明 |
|------|------|------|
| 申诉人 | 文本 | 员工姓名 |
| 申诉日期 | 日期 | 异常打卡日期 |
| 异常类型 | 标签 | 上班/下班/全天 |
| 申诉原因 | 文本 | 原因摘要 |
| 提交时间 | 时间 | 申诉提交时间 |
| 审核状态 | 标签 | 待审核/已通过/已驳回 |
- **界面布局**
- 顶部:筛选条件
- 中部:申诉卡片列表
- 底部:审核操作按钮(通过/驳回)
- **操作按钮**
- 「通过」→ 系统自动补录打卡记录,标注"补录"权限attendance:appeal:approve
- 「驳回」→ 填写驳回原因,通知员工
**审核流程**
```
员工提交异常申诉(小程序端)
主管审核Web+小程序均可)
┌─审核通过─┐ ┌─审核驳回─┐
系统自动补录 通知员工
打卡记录 申诉未通过
标注"补录" 记录审核日志
记录审核日志
```
**需求追溯**
| 功能点编号 | 功能名称 | 文档来源 | 后续服务 | 关联功能 |
|------------|----------|----------|----------|----------|
| MP-AT-06 | 考勤审核 | 02-小程序端 §5 | 补录打卡记录 | 操作日志、考勤管理Web端 |
#### 交互流程要求
1. **页面加载流程**:页面加载时获取待审核申诉列表→显示骨架屏→渲染筛选条件和申诉列表
2. **查询/筛选交互流程**:状态/日期/人员筛选→切换筛选重新加载列表;下拉刷新
3. **表单填写与提交流程**:查看申诉详情→点击通过→系统自动补录打卡记录;点击驳回→填写驳回原因→确认驳回→通知员工
4. **弹窗/弹层交互流程**:点击通过弹出确认弹窗"确认通过申诉?";点击驳回弹出驳回原因输入弹窗
5. **行内操作流程**:点击通过→确认→补录生效;点击驳回→填写原因→确认→通知员工
6. **异常与错误处理**:审核操作失败显示重试;申诉已处理提示"该申诉已处理"
7. **联动/级联交互**审核通过后自动补录打卡记录标记is_supplement=true
8. **权限控制交互表现**仅主管可操作无attendance:appeal:approve权限时按钮置灰
#### 前端硬性约束
- **H1 防重复提交**:通过/驳回按钮点击后立即 `loading=true` + `disabled=true` 防止重复操作;使用 pending 请求去重机制(审核请求未返回前禁用按钮);筛选切换时防重复请求
- **H2 超时控制**GET 请求超时 15s、POST 请求超时 30s列表加载/审核操作 >3s 时调用 `wx.showLoading({ title: '处理中...', mask: true })`
- **H3 二次确认**:审核通过前必须调用 `wx.showModal({ title: '确认通过', content: '确认通过该申诉?通过后系统将自动补录打卡记录。', confirmText: '通过', cancelText: '取消' })`;驳回前必须调用 `wx.showModal({ title: '确认驳回', content: '确认驳回该申诉?驳回后将通知员工重新处理。', confirmText: '驳回', cancelText: '取消' })`
- **H4 脏数据检测**:驳回原因输入框维护 isDirty 状态;用户输入驳回原因但未提交就离开时,在 `onUnload` / `onBackPress` 中弹出提示
- **H7 文件上传**:无上传操作
- **H8 操作反馈**:审核通过成功调用 `wx.showToast({ title: '已通过,已自动补录打卡记录', icon: 'success' })`;审核驳回成功调用 `wx.showToast({ title: '已驳回', icon: 'success' })`;网络异常时调用 `wx.showToast({ title: '网络异常,请检查网络后重试', icon: 'none' })` 并提供重试按钮
- **通用约束**:使用 uni-ui 组件库;所有可点击元素触控区域 ≥44px通过/驳回按钮 ≥44px下拉刷新需防重复触发refreshing 标志位)
#### 组件规范
| 元素 | 组件 | 配置参数 |
|------|------|----------|
| 筛选条件 | `uni-data-select` | 状态/日期/人员三个选择器 |
| 申诉列表 | `uni-list` + `uni-list-item` | clickable=true |
| 审核状态标签 | `uni-tag` | type: warning(待审核)/success(已通过)/error(已驳回) |
| 通过按钮 | `button` | type="primary"size="mini"@click="approve" |
| 驳回按钮 | `button` | type="warn"size="mini"@click="reject" |
| 驳回原因弹窗 | `uni-popup` | type="bottom",含文本输入和确认按钮 |
| 驳回原因输入 | `uni-easyinput` | type="textarea"maxlength="200" |
| 确认弹窗 | `uni-popup` | type="dialog" |
| 下拉刷新 | `uni-refresher` | @onRefresh回调 |
#### 校验规则
| 字段 | 规则 | 错误提示 |
|------|------|----------|
| 驳回原因 | 驳回时必填 | "请填写驳回原因" |
| 驳回原因 | 最多200字 | "驳回原因不能超过200字" |
| 审核状态 | 须为待审核状态 | "该申诉已处理" |
#### 响应式布局
- **适配机型**iPhone SE375px~ iPad mini768px列表宽度自适应
- **横竖屏适配策略**:竖屏单列卡片;横屏双列卡片+底部弹窗更宽
- **手势交互规范**申诉项可点击区域≥44px通过/驳回按钮≥44px
- **安全区域**:底部操作区域适配底部安全区
---
## 业务规则
1. **蓝牙策略**:考勤打卡受蓝牙策略控制(`GET /system/bluetooth-policy → attendance_check`
2. **蓝牙强制打卡**:策略=REQUIRED时必须在指定打卡点连接蓝牙Beacon后才可打卡
- 验证Beacon属于本人班组打卡点
- 打卡成功记录 `check_method=BLUETOOTH` + Beacon标识
3. **非强制蓝牙**:策略=OPTIONAL时可选蓝牙打卡或手动打卡`check_method=MANUAL`
4. **打卡点验证**蓝牙打卡时验证Beacon属于本人班组绑定的打卡点
5. **打卡时间**:自动记录精确到秒
6. **异常申诉审核**主管在Web端或小程序端均可审核
7. **补录标记**:审核通过后系统自动补录打卡记录,标记 `is_supplement=true`
8. **操作日志**:所有打卡操作记录审计日志
9. **双端审批**打卡异常申诉支持Web+小程序双端审核
## 状态流转
### 打卡状态
```
未打卡 → 已打卡(正常/迟到/早退)
缺卡 → 异常申诉 → 审核通过 → 补录打卡(标记补录)
→ 审核驳回 → 保持缺卡
```
### 申诉审核状态
```
待审核 → 审核通过 → 系统补录打卡记录
→ 审核驳回 → 通知员工
```