252 Commits

Author SHA1 Message Date
becomer 13faba27b6 修复请假自定义选项字段值类型:提交 optionSeq 数字而非选项文本
ci/woodpecker/tag/build Pipeline was successful
现象:请假成功但查看该单详情报 For input string: "是"(服务端返回 code -1),
且列表接口随之整体报错。

根因:自定义附加字段的选项值应提交 optionSeq(数字),此前提交 optionContent("是")。
服务端把文本存进数字字段,导致该单详情(及含它的列表)解析崩溃。
证据:官方 ReApply 分包提交前把服务端的 optionContent 反查成 optionSeq 再提交;
提交体 fieldValue 为数字。

改动:前端选项字段提交 Number(optionSeq);文本字段仍提交字符串。
验证:用该校真实类型配置在浏览器核对,提交体为 {"fieldValue":1,...}。

注:已被坏数据写入的那张单需要单独处理(见后续说明)。
v1.2.138
2026-10-07 19:01:13 +08:00
becomer 46a4bd3b80 请假附加信息:selfDefineAnswers 补 fieldType,与官方前端一致
ci/woodpecker/tag/build Pipeline was successful
官方 Apply 分包构造:selfDefineAnswers = selfDefineFields.map(c => ({fieldWid, fieldName, fieldValue, fieldType}))。
此前漏了 fieldType,补上以降低服务端校验拒绝风险。构建/vue-tsc 通过。
v1.2.137
2026-10-07 18:42:02 +08:00
becomer 248e28858b 修复新套请假「请检查附加信息是否全部填写正确」
ci/woodpecker/tag/build Pipeline was successful
根因(用该校真实类型配置核对):typeWid=1873「离校请假」详情里
- isRequiredEvidenceFile=true(证明材料必填),但类型列表接口返回 false,
  我们的映射只看了 isVisibledEvidenceFile,未透传必填开关 → 漏检附件
- selfDefineFields 有必填自定义字段「当天是否返校」(fieldWid=2422),
  我们完全未采集,提交时 selfDefineAnswers 恒为 [] → 服务端拒绝

改动:
- LeaveType 增 requireEvidence/evidenceMin/selfDefineFields 并映射(取详情字段)
- LeaveNewFormDetail 暴露 selfDefineFields;提交体 selfDefineAnswers 从请求透传
- ExecuteLeaveApplyRequest 增 selfDefineAnswers
- 前端:请假表单渲染自定义字段(单选/文本),必填校验(附加字段 + 证明材料最少张数),
  附件标签按 requireEvidence 显示「必传」
- api/leave.ts 补 SelfDefineField/SelfDefineAnswer 类型

验证:用该校真实类型配置在浏览器核对,表单出现「当天是否返校」、附件标注「必传」。
未做提交(按用户要求)。构建/go vet/test/vue-tsc 通过。
v1.2.136
2026-10-07 18:40:37 +08:00
becomer 005ce14013 工作日志签到:改为选择校区,用该校区规定经纬度签到
ci/woodpecker/tag/build Pipeline was successful
按需求把签到项的「获取 GPS 定位」改为「选择校区」:用户选所在校区,直接使用该校区
规定的经纬度(学校按点位半径校验)。不再依赖设备定位。

- 后端透传签到范围点(地址/经纬度/半径)到 formItems;新增 WorklogScopePoints 复用
  查寝的 SignPlace 解析与 coordsWithinSignRange 距离判定;执行时校验坐标是否在范围内,
  不在则明确拒绝并提示(不伪造定位)
- 前端签到字段渲染校区下拉,选中即把该校区的 lat,lng 写入字段 content
- 移除 GPS 定位按钮与相关函数

验证:用真实范围数据(许东/奶槐等校区)在浏览器核对,下拉正确列出校区,选择后
显示"已选:某某校区"并写入坐标。构建/go vet/test/vue-tsc 均通过。
v1.2.135
2026-10-06 19:44:24 +08:00
becomer d2d4847171 工作日志签到项:编辑页提供「获取当前位置」,坐标取真实 GPS
ci/woodpecker/tag/build Pipeline was successful
实测确认真实字段定义:值班签到 fieldType=5、signCondition=true,
templateScopes 给出 4 个校区点位(含经纬度与半径 500/600m)——即学校按点位半径校验,
与查寝同理,需真实定位;signScopeWids 是允许签到的范围点位 id(非坐标)。

- 前端:isWorklogSign 字段渲染「获取当前位置」按钮,调用 navigator.geolocation
  取真实经纬度写入该字段 content("lat,lng"),已定位显示回显与「重新定位」
- 后端:执行时从签到字段 content 解析坐标传 submitSign;缺定位时提示先获取定位
- FormItem 类型补 isWorklogSign/signScopeWids

验证:用任务 315 真实数据在浏览器核对,签到字段正确渲染为定位按钮,其余字段正常。
构建/go vet/test/vue-tsc 均通过。未做真实提交。
v1.2.134
2026-10-06 19:37:00 +08:00
becomer 22e84f86a4 工作日志签到项修正:按 signCondition 判定,坐标取用户定位
ci/woodpecker/tag/build Pipeline was successful
用教师账号查真实 detail 字段定义,纠正两处误判:
- 「值班签到」(fieldType=5) 的 signCondition=true 且 signScopeWids 非空,
  确属签到项(此前误判为普通时间字段而移除了标记)
- signScopeWids 是「允许签到的范围点位 id」,不是坐标;submitSign 应传用户定位
  (与签到任务一致:取表单 lon/lat 字段),此前误用 templateScopes 取坐标

改动:
- WorklogField 增 SignCondition;formItems 透传 signCondition/signScopeWids
- 执行逻辑改按 SignCondition 判定签到项;坐标取表单 lon/lat;缺定位时给出明确
  提示(请先在编辑中填写定位),不再静默跳过
- 移除 worklogScopePoint(用范围点当坐标的错误实现)

未验证:签到项在编辑页的定位填写入口尚未在前端提供,端到端未实测。
v1.2.133
2026-10-06 19:16:51 +08:00
becomer 7fb15d17c8 修复工作日志字段在打卡页不渲染,导致必填校验报「缺少值班时间/记录/签到」
ci/woodpecker/tag/build Pipeline was successful
现象:教师账号执行「学管值班」报「签到信息未配置完整,缺少:值班时间、值班记录、值班签到」。
根因:打卡页表单渲染只覆盖 type 0/1(文本)、2/3(单选多选)、图片、二维码;
工作日志用到的 type 5(日期时间)、7(日期时间)、9(多行文本)没有任何 v-else-if 匹配,
字段根本不渲染,用户填不了 → 保存为空 → 执行前必填校验拦截。

修复:
- 前端加三类渲染分支(5/7 → datetime-local 输入;9 → textarea),并加兜底分支
  (未识别类型按文本渲染),避免今后再出现「字段静默丢弃」;内置 toLocalInput 回显
- 模型枚举补 ItemTypeDate(5)/ItemTypeDateTime(7)/ItemTypeTextarea(9)
- 去掉误导性的 isWorklogSign 标记:实测「值班签到」signScopeWids 为空、是 type 5 普通
  可填字段,并非定位签到项(此前照第三方实现误判)

验证:用任务 315 真实 formData 在浏览器核对,编辑弹窗正确渲染全部 6 字段
(2 个 datetime + 1 个 textarea + 单选)。构建/vue-tsc 通过。

未验证:该 type 5「值班签到」的真实填写要求(时间点还是留空由后端处理)待真实使用确认。
v1.2.132
2026-10-06 19:14:57 +08:00
becomer c8f77ca030 工作日志提交:回传完整字段对象(仅覆盖 value)
ci/woodpecker/tag/build Pipeline was successful
官方前端提交时把服务器返回的字段对象原样回传、只改 value;此前仅回传自建模型的
少数字段,字段不全可能导致提交失败或丢数据。改为 WorklogField 自定义 Unmarshal
保留完整原始对象,SubmitWorklog 优先回传该对象并覆盖 value,缺原始对象时退化为
最小结构 {wid,value}。构建/vet/test 通过。
v1.2.131
2026-10-06 18:38:15 +08:00
becomer 145810759e 修复教师账号点「新的打卡任务」误报「登录凭证已过期」
ci/woodpecker/tag/build Pipeline was successful
根因:FetchAllRecentTasks 只看 sign/sleep_check 是否成功来判断会话有效性。
教师账号在学生端签到/查寝套件本无权限(返回 cpdaily_cookie_expired),
两类都失败 → 误判会话失效 → 上层报「登录凭证已过期」,而账号实际刚登录。

修复:会话有效判据改为「任一打卡套件成功」——签到/查寝、返校登记、工作日志
任一返回成功即认为会话有效;仅当全部失败且首个错误表明登录态失效才返回错误。
教师账号经工作日志返回成功,任务列表正常(实测识别到「学管值班」)。
新增 appendUnique 去重单测。
v1.2.130
2026-10-06 18:26:07 +08:00
becomer 7110743cca 工作日志:按真实教师账号响应校正字段与结构(端到端验证通过)
ci/woodpecker/tag/build Pipeline was successful
用教师账号 18334727775 实测,纠正照第三方 Python 推断的错误假设:
- 模板为两级结构:分组 row + templateVoList[].wid,提交用子模板 wid(非分组 wid)
- list 行字段是 subjects(非 form),detail 返回 form
- 字段标识为数字 wid + colName(field001..);fieldType 1文本/2单选/5,7时间日期/9多行
- 单选项在 fieldItems[].content;isOtherItems 在 detail 为数字、template/detail 为布尔,
  新增 FlexBool 兼容,否则整体解析失败(实测踩到)

实测结果:5 个子模板、识别 1 个未提交「学管值班」(signWid=26:2234)、
详情 6 字段正确解析(含值班签到 type5 定位项标记 isWorklogSign)。
go build/vet/test 全过,vue-tsc 无新增错误。
v1.2.129
2026-10-06 13:35:30 +08:00
becomer ab99efe877 工作日志:收窄权限判定,避免吞掉登录失效
isWorklogForbidden 只认「无权/没有权限」文案,不再把 HTTP 401 当权限拒绝:
401 既可能是学生账号被角色校验拒绝,也可能是教师登录态失效,一并吞掉会掩盖续期需求。
401(HTML 认证页)改由 isWorklogUnauthorized 识别并仅记 debug,聚合任务时不再告警。
新增权限判定单测。
2026-10-06 13:32:38 +08:00
becomer 3028dbfc86 工作日志定位签到:坐标改取字段 templateScopes(去掉占位空值)
ci/woodpecker/tag/build Pipeline was successful
定位签到项自带学校配置的签到范围点(templateScopes[0] 的 address/longitude/latitude),
据此提交;缺坐标则跳过该签到项并记日志,避免提交空坐标被判无效。
移除先前依赖用户定位的占位实现。
v1.2.128
2026-10-06 13:30:15 +08:00
becomer de700ae6c8 接入教师端「工作日志」任务类型(集成进现有打卡链路)
ci/woodpecker/tag/build Pipeline was successful
接口来自公开逆向实现(两个开源项目互相印证,见 spec://worklog_api.md),
未再扫描 H5;独立套件 /wec-counselor-worklog-apps,服务端按角色校验(学生 401)。

- service/worklog.go:模板列表/日志列表/详情/模板详情/建单/定位签到/提交,
  响应解析含 code!=0 与空 message 回退;字段宽泛解析(isRequired/signScopeWids/templateScopes)
- FetchWorklogTasks 产出统一任务项,SignWid="formWid:worklogWid";学生账号被拒静默跳过
- handler:GetTaskForm 增 worklog 分支(字段转通用 formItems);新增 executeWorklogTask(SSE)
- 执行分流 ExecuteTask 增 TaskTypeWorklog;前端加「工作日志」标签与配色
- 单测:响应错误/空 message/非 JSON/成功解析/字段解析/提交体形状

未验证(无教师会话):真实字段名与流程、定位签到坐标来源(当前占位空值)。
v1.2.127
2026-10-06 13:29:11 +08:00
becomer 47510c7848 修复通化师范学院(thnu)无法登录:CAS 请求补浏览器 Accept 头
ci/woodpecker/tag/build Pipeline was successful
根因:该校统一认证 authserver.thnu.edu.cn 前置 WAF 按请求头指纹判定客户端,
仅带 User-Agent、缺少 Accept 类头会被判为机器人,整站返回 429(空 body),
登录页取不到表单(bodyLen=262 的拦截响应)。

修复:newSessionClient 统一补 Accept / Accept-Language。实测分离验证——
移动 UA 无 Accept → 429;移动 UA + Accept/Accept-Language → 200。
保留原移动 UA,不影响 wisedu 按 UA 渲染移动/PC 模板。

实测 202318010111 登录成功(err=nil,拿到 MOD_AUTH_CAS/CASTGC/JSESSIONID 等 5 个 cookie)。
v1.2.126
2026-10-06 13:16:41 +08:00
becomer b4357f746f v1.2.125:打卡页骨架与界面一致;后台执行日志类型不再换行
ci/woodpecker/tag/build Pipeline was successful
- 打卡页加载骨架改为与主内容同结构:品牌渐变头卡(标题+四宫格+主按钮)、
  带左侧色条的任务行、日志时间线;头卡占位用固定白色透明度,暗色下与真实卡片一致
- 后台「执行日志明细」类型列 64→104px,改用 adm-badge(nowrap)并按类型配色,
  「返校登记」等长标签单行显示
v1.2.125
2026-10-05 22:59:14 +08:00
becomer 5042c869b1 v1.2.124:各页底部导航滚动收窄行为统一
ci/woodpecker/tag/build Pipeline was successful
收窄门槛 COLLAPSE_MIN_RANGE 200→80px:此前可滚动距离不足 200px 的页面(如「我的」约 170px)
从不收窄,与打卡/请假页表现不一致。方向阈值 32→24px、顶部展开区 40→24px,
保留同向累计阈值与回弹夹取,底部回弹/小幅来回不抖动。
v1.2.124
2026-10-05 18:05:51 +08:00
becomer 96e1c3d1f2 v1.2.123:修复登录页选择学校后再次搜索并重新弹出下拉框
ci/woodpecker/tag/build Pipeline was successful
原因:选中学校时把输入框写成学校全名,watch 把这次写入当成用户输入,
以全名重新请求并重新打开下拉框;且无防抖、无过期响应保护。

- 写回全名时跳过搜索;选中后再改输入则清空选择并重新搜索
- 300ms 防抖 + 请求序号,丢弃过期响应
- 已选中学校时聚焦输入框不再弹出列表
v1.2.123
2026-10-05 18:01:58 +08:00
becomer ad9b4f4ee3 v1.2.122:登录页文案调整;切换手机号登录时提示会踢下线 App
ci/woodpecker/tag/build Pipeline was successful
- 功能标签「自动打卡」改为「人脸签到」
- 去掉卡片副标题与底部密码说明
- 点「手机号登录」弹窗提示:会导致今日校园 App 被踢下线,重新登录 App 即可,不影响 App 功能
v1.2.122
2026-10-05 17:55:09 +08:00
becomer ae4ca4a00e v1.2.121:请销假页新增「续假」入口;登录页重构美化
ci/woodpecker/tag/build Pipeline was successful
续假入口
- 头卡改为「请假 / 销假 / 续假」三按钮,续假打开只含可续假请假单的列表
- 列表按模式过滤:销假只看可销假单,续假只看可续假单;空态说明续假条件(休假中 + 学校允许)
- LeaveItem 增 canReport(列表含仅可续假的单,销假模式据此排除)

登录页
- 品牌渐变头图(问候语 + 功能标签 + 细网格),登录卡片上浮压住头图
- 滑块分段控件切换学工号/手机号;输入行改为图标 + 原生输入,整行聚焦高亮,已选学校带勾
- 验证码块统一尺寸并带刷新角标;短信按钮倒计时文案;主按钮固定品牌色
- 登录逻辑不变(已验证验证码加载、学校选择、/auth/login 提交体)
v1.2.121
2026-10-05 17:41:01 +08:00
becomer e7dac20a02 v1.2.120:续假支持旧套(wec-counselor-leave-apps)
ci/woodpecker/tag/build Pipeline was successful
从旧套真实 H5 JS(刷新 cookie 后拉取 home.*.js)确认旧套续假为独立接口:
POST /wec-counselor-leave-apps/leave/saveExtend,body = 请假申请体 + leaveId + extendReason
+ extendHolidayAutoDefineVos,带 Cpdaily-Extension 头。

- service:BuildLeaveExtendForm + SubmitLeaveExtend(复用 BuildLeaveApplyForm)
- handler:ExecuteLeaveApply 旧套分支按 req.IsExtend 走 saveExtend;
  待销假列表 FetchLeaveList 从行 isAllowedExtend 置 canExtend
- extend-prefill:旧套用 FetchLeaveDetail 返回类型 code + 原结束时间作预填
- 前端续假入口已 flavor 无关,新旧套共用

注:旧套无「休假中可续假」真实假单实测,extendInfos 等按官方 JS 逻辑实现,上线后按真实报错微调。
v1.2.120
2026-10-05 17:22:26 +08:00
becomer 8fd132fc64 v1.2.119:新增续假功能(新套 wec-counselor-leave-new-apps)
ci/woodpecker/tag/build Pipeline was successful
调研:从真实新套 H5 JS(ReApply chunk)确认续假 = 复用 /stu/leave/apply,
body 带 reApply:true/isExtend:true/leaveId/extendId;预填用 /stu/leave/queryReplyLeaveDetail。

后端:
- BuildLeaveNewApplyForm 补 reApply/extendId(LeaveID/IsExtend 已有)
- FetchLeaveNewReplyDetail(queryReplyLeaveDetail) 续假预填
- ExecuteLeaveApply 续假分支:取 extendId 后按续假体提交
- 新增 POST /leave/extend-prefill
- 待销假列表放宽为「可销假 或 isAllowExtend」,LeaveItem 增 canExtend/typeWid/isLeaveOut

前端:
- 待销假列表每项拆「销假 / 续假」按钮,仅 canExtend 显示续假
- 点续假调 extend-prefill 预填(类型锁定、开始时间=原结束时间、原因/离校带入),复用请假弹窗,标题/按钮随续假态切换
- 提交带 isExtend/extendLeaveId

限制:旧套(leave-apps)续假未实现(其 H5 走 OAuth 中转拿不到 JS),仅新套学校显示入口。
v1.2.119
2026-10-05 17:02:30 +08:00
becomer f27603f724 v1.2.118:查寝二维码点击先选「拍照扫码 / 相册选图」
ci/woodpecker/tag/build Pipeline was successful
- 二维码字段改为单一入口「获取二维码」,点击弹出底部选择卡:
  拍照扫码(打开摄像头)/ 相册选图(原图片解析),不再默认直接开摄像头
- 选择弹层 z-[120] 高于创建任务表单弹窗,避免被盖住
v1.2.118
2026-10-05 16:18:04 +08:00
becomer 5bb39454b8 v1.2.117:查寝二维码支持摄像头实时扫码
ci/woodpecker/tag/build Pipeline was successful
- 新增 QrScanner 组件:getUserMedia 调后置摄像头 + jsQR 每 120ms 识别一帧,命中即写入二维码ID
- 识别用整帧下采样(480→720 两档),取景框仅作视觉引导:object-cover 会放大裁切画面,
  只扫中心区时近距离对准反而扫不到(实测复现)
- 支持手电筒(设备支持时);非 HTTPS / 权限被拒 / 无设备分别给出可操作的提示
- 保留「选图」回退到原有图片解析;扫码页 z-[400] 且显式恢复 pointer-events
  (reka modal 会把 body 设为 pointer-events:none,否则扫码页按钮点不动)
v1.2.117
2026-10-05 16:07:38 +08:00
becomer b928c7ceb0 v1.2.116:邀请码改为登录即自动生成,移除手动生成入口
ci/woodpecker/tag/build Pipeline was successful
后端
- 删除 POST /auth/generate-invite 及 GenerateMyInviteCode
- 新用户注册时生成邀请码;唯一索引冲突(仅 invite_code 索引)自动换码重试,最多 8 次
- 老用户登录(用户名 / 学工号匹配)缺邀请码时补发;GET /auth/my-invite 兜底补发
- 服务启动时批量补齐存量空邀请码(幂等;条件更新 invite_code 为空才写,并发安全)
- 邀请码改用 crypto/rand,字符集去掉 0/O/1/I/L;旧实现按纳秒取模,可预测且并发注册易撞码
- 测试:单元测试 + MySQL 集成测试(设置 INVITE_IT_DSN 时运行,已在 8.4.11 上通过)

前端
- 「我的」移除「生成我的邀请码」按钮与 getMyInvite API;新手引导去掉对应目标与文案
v1.2.116
2026-10-04 11:09:47 +08:00
becomer 79d531f340 v1.2.115:修复后台页面无法向下滚动、公告弹窗底部按钮被截断
ci/woodpecker/tag/build Pipeline was successful
- 后台内容区 <main> 恢复为滚动容器(h-dvh + overflow-y-auto):html/body 为手机外壳设了 overflow:hidden,
  v1.2.114 去掉 main 的 overflow-y-auto 后长页面(用户管理等)超出部分无法滚动
- 新建/编辑公告弹窗:标题栏与底部操作栏固定、表单区独立滚动,面板高度限制在视口内,并补充「取消」按钮
v1.2.115
2026-10-02 23:07:58 +08:00
becomer 99e01dc338 v1.2.114:后台管理界面重构美化与样式修复
ci/woodpecker/tag/build Pipeline was successful
- 新增后台组件类 adm-*(页头/卡片/统计卡/表格/徽标/行内操作/分段筛选/分页/空状态),亮暗两套,各页统一套用
- 外壳:侧栏分组(概览/运营/系统)+ 品牌区 + 选中左侧色条;桌面顶栏面包屑 + 公告入口;手机端玻璃顶栏显示当前页名
- 仪表盘:欢迎横幅展示余额与费率,统计卡新增 CDK 使用率;CDK 页统计卡可点击按状态筛选
- 工单详情改为卡片内对话视图;系统设置改两列网格;代理列表加头像首字母
- 修复:暗色下 bg-blue-500/bg-green-500 白字看不清(改固定品牌/成功色)、text-gray-300 占位符对比不足、
  残留的蓝色主题色、工单状态色映射统一
v1.2.114
2026-10-02 22:54:01 +08:00
becomer 02dcd6fc32 v1.2.113:重构个人中心
ci/woodpecker/tag/build Pipeline was successful
- 头图改左对齐:头像 + 姓名 + 学校,补充学院/班级标签,细网格纹理
- 新增会员卡压在头图下沿:VIP 黑金(显示到期日与剩余天数)/ 普通用户珍珠白,主按钮「开通 VIP / 续费」
- 数据三宫格:可执行次数(点击兑换)/ 邀请积分(够 1 直接换次数,不够提示规则)/ 已邀请人数
- 邀请卡:薰衣草渐变,邀请码大字展示 + 复制按钮,奖励规则一句话说明,「点此填写」他人邀请码
- 功能菜单改 iOS 分组列表:设备码带「已授权/随机/未绑定」状态标签;工单显示新回复数
- 新手引导文案同步新布局;暗色下紫色按钮改固定色保证白字对比度
v1.2.113
2026-10-02 19:58:12 +08:00
becomer 51f3641a0c v1.2.112:重构首页置顶公告;打卡日志改时间线、任务行精修
ci/woodpecker/tag/build Pipeline was successful
- 置顶公告新组件 PinnedNotice:一次一条上下翻页轮播(N/M 计数),长文本先停顿再横向滚到末尾,
  点击打开底部面板查看全部全文;切后台 / 减弱动态效果时暂停;柠檬暖色卡片,亮暗各一套配色
- 打卡日志:状态圆点 + 竖线时间线,相对时间(刚刚 / N 分钟前 / 今天 / 昨天),失败原因直接展示,空状态带说明
- 任务行:左侧状态色条,执行按钮改品牌渐变圆形主按钮,编辑/删除降级为图标按钮
- 贴边竖条(收藏本站 / 无法请销假 / 网课)位置统一上移避开引导入口;收藏本站改柠檬底深棕字
- 修复 scoped 样式中 `:global(.dark) .x` 被编译为仅 `.dark` 导致暗色覆盖失效(请销假头卡暗色此前未生效)
v1.2.112
2026-10-02 19:38:36 +08:00
becomer 9f2f705457 v1.2.111:修复线上暗色主题全站灰底;重做外观切换控件
ci/woodpecker/tag/build Pipeline was successful
- 根因:postbuild-css 解包 :where() 时直接去壳,Tailwind 暗色变体 `.x:where(.dark, .dark *)` 被拆成
  `.x.dark, .dark *`,`.dark *` 成为全局规则,暗色下所有元素被刷上同一背景/边框(开发服务器不经后处理,故本地截图正常)。
  改为先展开逗号列表(`.dark .x`),并在产物中出现全局 `.dark *` 规则时直接构建失败
- 外观切换改为整宽三段分段控件 + 滑动高亮,窄屏不再挤压换行
- 我的页对比度:续费 VIP / 兑换按钮改固定深棕字(≥4.6:1),奖励数字改 amber-600
v1.2.111
2026-10-02 15:21:16 +08:00
becomer 301a4fb971 v1.2.110:打卡/请销假页头像行上下间距统一为 16px(原上 12px、下 28px)
ci/woodpecker/tag/build Pipeline was successful
v1.2.110
2026-10-02 14:31:36 +08:00
becomer df40b2ae73 v1.2.109:顶部安全区仅在主屏幕全屏模式生效,修复浏览器/App 内顶栏下移
ci/woodpecker/tag/build Pipeline was successful
部分浏览器与 App 内置 WebView 已把网页放在状态栏下方,却仍上报 safe-area-inset-top,
叠加后头像行凭空下移约 47px。改为 --safe-top 变量,仅 display-mode: standalone/fullscreen 时取 env() 值。
v1.2.109
2026-10-02 14:13:41 +08:00
becomer 317bf4b5a1 v1.2.108:修复新手引导末步页面左移;新版本提示更及时
ci/woodpecker/tag/build Pipeline was successful
- 引导定位 scrollIntoView 改为 inline:nearest,不再横向滚动 overflow:hidden 的头卡容器(装饰光斑超出边界导致整块左移 45px);头卡改用 overflow:clip 兜底
- UpdateChecker:检查间隔 5 分钟→2 分钟、首检 30s→10s;页面回到前台(切回标签/唤起 App)时补查;修正 prompting 在 finally 中被清零导致的并发防护失效
v1.2.108
2026-10-02 13:59:40 +08:00
becomer 1c112fe3dc v1.2.107:修复打卡页横向撑宽、底部导航滚动时缩放抖动
ci/woodpecker/tag/build Pipeline was successful
- 页面包裹层 grid 列宽锁定为容器宽度(grid-cols-1),置顶公告走马灯不再把整页撑到数千像素宽
- TabBar 收窄逻辑防抖:可滚动距离 <200px 的页面不收窄;scrollTop 夹在 [0,max] 忽略 iOS 回弹;同向滚动超过 32px 才切换;到底部不再强制展开
v1.2.107
2026-10-02 13:47:41 +08:00
becomer 2f7113ba5e v1.2.106:前端改版——薄荷汽水配色 + 轻量液态玻璃(iOS 26 风格)
ci/woodpecker/tag/build Pipeline was successful
- 设计令牌:重映射 Tailwind 色阶为薄荷汽水色板(品牌薄荷青/天空蓝/柠檬/珊瑚),统一圆角、柔和阴影;亮暗两套色板按 WCAG AA 校验
- 外壳:悬浮液态玻璃胶囊 TabBar(滑动高亮、滚动收窄)、透明→玻璃顶栏、切页淡入、居中玻璃 Toast
- 主题:新增「自动/浅色/深色」三档切换(我的页),自动模式保留按时间切换
- 页面:首页/请销假渐变头卡、登录/绑定设备/工单/个人中心精修;后台换主色与导航样式
- 可读性:清理 8–11px 小字号(最小 12px),提高辅助文字灰度对比
- 降级:不支持 backdrop-filter / 减弱透明度 → 实底;减弱动态效果 → 关闭动画
v1.2.106
2026-10-02 13:33:46 +08:00
becomer 441c40a8cc v1.2.105:封号(禁用)后所有接口即时拦截,返回自定义封号原因
ci/woodpecker/tag/build Pipeline was successful
- 现状:禁用仅在登录时校验,已登录用户持有效 token 仍可调用所有接口。
- 修复:JWT 中间件在每个受保护接口校验用户状态,禁用则返回 HTTP 403 + 业务码 4030,
  message 为封号时自定义的原因(为空时兜底文案)。
- 前端:拦截 403/4030,清除登录态、弹出封号原因并跳登录页,不触发 token 刷新死循环。
- 复用现有后台「禁用/启用」入口与 disabled_reason(用户管理页已具备)。
v1.2.105
2026-10-02 11:09:29 +08:00
becomer 002c6b8570 v1.2.104:放开「今日已签到」拦截,允许对已签到实例重新提交
ci/woodpecker/tag/build Pipeline was successful
- 现象:用户想对已签到的任务重新打卡(如首次位置填错),被后台以
  「今日已签到,无需重复执行」拦截(该提示由 FetchTodayTaskDetail 本地判断返回,
  非今日校园)。
- 修复:执行打卡时若当天无未签到实例但存在已签到实例,不再拦截,改用该已签到实例
  重新提交;是否真正接受由今日校园服务端决定(实测已能发出请求,受学校侧风控约束)。
v1.2.104
2026-10-02 10:49:11 +08:00
becomer 2a53ab7041 v1.2.103:修复范围外签到被强制改回学校坐标(打卡地点显示成学校)
ci/woodpecker/tag/build Pipeline was successful
- 现象:用户 2025050021(安康学院)签到任务填的是家(广东省广州市天河区大观路,
  且「是否范围外签到=是」),执行后实际打卡地点变成学校(安康学院)。
- 根因:执行打卡前无条件调用 AdjustSubmitFormToSignRange——当填写坐标不在任何
  学校签到范围内时,自动把坐标+地址改成最近的学校签到点。用户本就是「范围外签到」,
  被强行改回学校坐标,导致实际打卡点变成学校。
- 修复:仅在「范围内签到」时执行坐标自动回退;「范围外签到」(isMalposition=是/1)
  尊重用户填写的位置,不调整。新增 isOutOfRangeSign 判定与单测。
v1.2.103
2026-10-02 10:24:10 +08:00
becomer 12db9217d1 v1.2.102:修复兰州理工大学登录(CAS-PaaS 定制 CAS,密码 RSA/base64 加密)
ci/woodpecker/tag/build Pipeline was successful
- 现象:用户 262030500019 登录报「当前学校已有用户正常登录,请检查…」,
  实际是账密登录失败(IAP doLogin 报 FAIL_UPNOTMATCH)。
- 根因:该校平台标 joinType=CLOUD(IsIap),但实际为 CAS-PaaS 定制统一身份认证
  (cas-paas.lut.edu.cn/cas/login),密码需 RSA(JSEncrypt)加密后以
  "__RSA__"+密文 提交;通用 casLogin 提交明文密码被拒。
  且 JSEncrypt 的密文是 base64,而本仓库 RSA 工具输出 hex,直接提交亦不通过。
- 修复:
  1) 新增 CAS-PaaS 适配(login_caspaas.go):按登录页特征(/cas/jwt/publicKey、
     __RSA__)自动识别,拉公钥、RSA(PKCS#1 v1.5) 加密密码并转 base64,前缀 "__RSA__"。
  2) casLogin 解析表单后自动命中 CAS-PaaS 加密。
  3) 新增兰州理工特判(login_lut.go)强制走 CAS(其 IAP 不可用)。
- 实测:真实账号 262030500019 登录成功,拿到 MOD_AUTH_CAS/CASTGC。
v1.2.102
2026-09-30 23:52:25 +08:00
becomer bd274a0414 v1.2.101:销假错误透传学校原始 message,修正 2210990000 被误译为「需上传附件」
ci/woodpecker/tag/build Pipeline was successful
- 现象:用户 3241804227(旧套)已上传附件仍报「需要上传附件」。
- 根因:学校端错误码 2210990000 是通用码,可表示多种原因(实测:1161 为
  「需要添加附件才能完成销假」,1219 为「设备更换,无法查看,请联系管理老师」);
  原实现把所有 2210990000 一律硬编码为「该请假销假需要上传附件图片」,覆盖了
  学校真实 message,导致「设备更换」被误报成「需上传附件」。
- 修复:优先透传学校返回的 message;仅当 message 为空/failed 时按码兜底。
v1.2.101
2026-09-30 15:46:28 +08:00
becomer ad9dd3e638 v1.2.100:验证码限流 IP 改用 utils.ClientIP,与登录 IP 取值一致
ci/woodpecker/tag/build Pipeline was successful
短信验证码与图片验证码的限流此前用 c.IP(),与登录 IP 记录所用的 utils.ClientIP 不一致,
导致限流按错误的 IP 计数(可能所有用户共用一个桶,出现"刚打开就提示需等 15 秒")。
统一改用 utils.ClientIP(c)。
v1.2.100
2026-09-29 22:22:47 +08:00
becomer 0a49dc0080 v1.2.99:修复新套请假「是否离校」被类型默认值覆盖导致提交成「否」
ci/woodpecker/tag/build Pipeline was successful
- 根因:新套 leaveType.extendInfoBean.isLeaveOut 官方语义是「是否离校」的初始默认值
  (0=无默认 / 1=默认是 / 2=默认否),并非强制开关;且提交体 leaveOutInfo.isLeaveOut
  学校端只认 1=是 / 2=否。原实现把它当强制值,当类型默认值=0 时把用户选择的「是」
  覆盖成 0,学校端因 0 非合法枚举而显示为「否」(兰州交通大学 12261216 即此现象)。
- 修复:提交值以用户选择为准并规范为枚举 1/2(leaveNewOutStatusValue);不再用类型默认值
  覆盖用户选择;类型列表不再把 isLeaveOut 误映射为 mustOut,改为透传 OutStatusDefault
  供前端设置开关初始状态(1=默认是,其余=默认否,用户可改)。
- 新增单测锁定枚举映射。
v1.2.99
2026-09-29 21:50:23 +08:00
becomer 48926ed72f v1.2.98:新手引导步骤调整(设备码前置 + 填写邀请码/兑换积分拆为两步)
ci/woodpecker/tag/build Pipeline was successful
- 前两步对调:第 1 步改为「先绑定设备码」,第 2 步拆分为两步——
  「填写邀请码」与「兑换积分」,其后依次为新建任务、执行签到、推广赚积分、VIP。
- 同步更新按步骤索引的硬编码逻辑(示例卡 mock 场景 2/3 → 3/4)。
- GUIDE_VERSION v3→v4(前后端),让老用户重新看到新引导。
v1.2.98
2026-09-29 11:57:44 +08:00
becomer c1573f77ac v1.2.97:邀请逻辑整改(登录去邀请码 + 推广信息合并 + 填邀请码绑定)
ci/woodpecker/tag/build Pipeline was successful
1. 登录不再需要邀请码:登录页移除邀请码展示/URL ?invite= 传参;登录/注册不再携带
   邀请关系;取消「直接注册奖励(register_reward)」。新用户注册不发放任何积分。
2. 底部导航「个人中心」→「我的」。
3. 个人中心将「邀请链接」「邀请信息」合并为「推广信息」卡片:
   - 左:邀请码 + 复制按钮(改为只复制邀请码)
   - 右:奖励积分 + 兑换按钮
   - 下方:邀请好友即可获得 x 积分
   - 无邀请人用户显示「填写邀请码」→ 弹窗输入 → 提交校验设备码(未绑定提示
     「请先绑定设备码」)→ 绑定邀请人并给双方发积分(每人仅可绑定一次)。
4. 后端新增 POST /auth/bind-invite;GetMyInviteInfo/Generate 返回 hasInviter。
5. 新手引导文案与锚点更新(去掉登录携码/链接语义),GUIDE_VERSION v2→v3。
6. 后台设置移除「直接注册奖励积分」项。
v1.2.97
2026-09-29 11:40:31 +08:00
becomer d588d10c4c v1.2.96:底部导航移除网课 + 「可执行次数」文案 + 置顶公告满宽右→左无缝滚动
ci/woodpecker/tag/build Pipeline was successful
1. 底部导航栏取消「网课」tab。
2. 个人中心「可签到次数」改为「可执行次数」(VIP 文案同步为「VIP 执行次数」)。
3. 置顶公告:去掉 warning 边框、整行满宽;改为右→左循环滚动,渲染两组内容
   translateX(-50%) 无缝接回开头,单条也持续滚动。
v1.2.96
2026-09-29 10:39:38 +08:00
becomer 7dac485769 v1.2.95:兑换弹窗验证码错误改为在验证码行提示,并在失败后自动刷新验证码
ci/woodpecker/tag/build Pipeline was successful
- 问题:CDK 兑换/VIP 续费弹窗中,验证码错误或过期时错误红字显示在「兑换码」框下方,
  让用户误以为是兑换码出错。
- 修复:验证码类错误(message 含「验证码」)改为在「验证码」输入行下方红字提示,
  兑换码框不再误标红;验证码错误后自动刷新验证码并清空输入,便于直接重试。
v1.2.95
2026-09-29 10:22:26 +08:00
becomer 195702c14f v1.2.94:修复销假图片上传入口被 enableAttach 隐藏导致无法上传附件
ci/woodpecker/tag/build Pipeline was successful
- 现象:用户 25074105001(吉林医药学院,旧套)销假时表单只显示经纬度/地址,
  提交报「该请假销假需要上传图片附件」,无法完成销假。
- 根因:旧套 leaveType.enableAttach 字段不可靠(多所旧套学校恒为 0),
  前端以此字段控制销假图片上传入口显隐,导致该字段为 0 时上传入口不显示;
  而部分学校销假实际强制要求附件(提交返回 2210990000)。
- 修复:销假图片上传入口改为始终显示(可选,不填则不携带),
  并附提示「部分学校销假要求上传,如提交提示需要附件请在此上传」。
v1.2.94
2026-09-28 15:26:42 +08:00
becomer df550bf2ac v1.2.93:工单未读回复徽标 + 公告面板未关闭工单通知排序靠前
ci/woodpecker/tag/build Pipeline was successful
1. 个人中心「工单与反馈」入口新增未读回复条数徽标(工单通知未读数)。
2. 右上角公告(铃铛)面板:工单通知分区把「未关闭工单」的通知排到前面
   (后端 ListTicketNotifications 附带 ticketStatus,前端按 status≠closed 优先排序)。
v1.2.93
2026-09-28 15:21:00 +08:00
becomer 75a642f3a2 v1.2.92:兑换签到次数弹窗增加「邀请积分可免费兑换」引导提示
ci/woodpecker/tag/build Pipeline was successful
当邀请奖励积分满 1(canRedeem,可免费兑换)时,在「兑换签到次数」弹窗内
提示用户关闭本弹窗,改用下方「邀请信息」处的兑换按钮用积分兑换(无需兑换码)。
v1.2.92
2026-09-28 11:32:07 +08:00
becomer d2ca858816 v1.2.91:修复请假审批人获取失败被静默吞掉导致误报「未配置审批人」
ci/woodpecker/tag/build Pipeline was successful
- 现象:用户 124509440(西藏民族大学)提交请假时提示「未配置审批人」,
  实际学校有 2 个审批人(谷一墨、黄操)。经 headless 浏览器复现,根因是:
  当请假起止时间填写有误(如开始≥结束)时,后端 getApproveFlowList 返回
  「结束时间要晚于开始时间」,前端 loadApplyApprovers 的 catch 静默清空候选,
  界面遂显示「该校该请假类型未配置审批人,可不选」,误导用户以为接口取不到人。
- 修复:捕获并展示真实错误(applyApproversError),该错误时不再显示
  「未配置审批人」文案;切换类型/时间时重置错误态。
- 说明:后端各接口实测正常(对多种类型/时间均返回 2 个审批人),本次仅改前端提示。
v1.2.91
2026-09-28 11:23:15 +08:00
becomer 84f746fa2d v1.2.90:后台用户管理执行次数弹窗补全「返校登记」类型中文
ci/woodpecker/tag/build Pipeline was successful
taskTypeLabel 未覆盖 return_register,导致该类型日志显示英文原名,
补上「返校登记」中文映射。
v1.2.90
2026-09-27 18:25:20 +08:00