becomer
|
021ac7f7bd
|
v1.2.49:请假审批人「候选为空可不选」+ 新增抄送人(非必填,候选取自审批人列表)——① 审批人校验放宽(实测驱动):ysdwl「大四学生请假」needApproval=1 但审批节点(政工队伍应用管理员)未配置人员,obtainApproveFlow 返回空列表,旧逻辑强制必选导致用户无法提交;现前端在候选为空时不显示必选星号、提示「该校未配置审批人,可不选」,校验仅在有候选时要求选择;后端 execute 校验同步改为「needApproval=1 且候选非空才必填」(服务端自行查候选,避免前端被绕过),候选为空时记录日志放行;② 抄送人功能:ccInfo 从硬编码空结构改为按用户选择构造(BuildLeaveCcInfo),按 userWid 去重、按 userId 是否纯数字分组 teachers/students(personType 0/1,官方结构含 name2Id/dept/sex/teacherName 字段);前端抄送人区显示条件与 needApproval 解耦(候选同源 obtainApproveFlow,类型+时间齐全即加载),蓝色复选框多选、非必填,类型/时间变化后自动清理失效选择;③ 静默降级:候选加载失败不再弹错(避免每次切换类型红字打扰),需审批时提交由后端复核并给明确提示;④ 新增 TestBuildLeaveCcInfo 覆盖学生/教师分组、空列表、表单携带;go test ./...、go vet、vue-tsc、npm run build 全过
ci/woodpecker/tag/build Pipeline was successful
|
2026-09-14 14:47:26 +08:00 |
|
becomer
|
7639912d7c
|
v1.2.45:请假申请功能落地(后端链路 + 前端请假弹窗),前端 tab 改「请/销假」、请假/销假按钮并排平分——① 功能:新增请假接口组(GET /leave/types 类型列表含权威开关、POST /leave/apply-approvers 审批人、POST /leave/apply SSE 同步执行),cpdaily/leave_apply.go 封装 checkOnceLeave + queryLeaveTypes + queryLeaveTypeCfg + obtainApproveFlow + apply 提交全链路;前端 LeaveView 新增请假申请弹窗(类型选择/起止时间/离校开关与三字段/请假原因含字数校验/一键定位/图片附件/审批人选择),日志区同时展示请假与销假记录并以徽标区分;② 关键差异(对比老版本 + 只读实测三校样本):queryLeaveTypes 返回的 needApproval/enableAttach 等开关全为 null,权威开关只在 queryLeaveTypeCfg(老版本逐类型再查一次,本实现按同样方式合并后返回,单类型 cfg 失败不阻塞列表);/leave/apply 为明文 JSON body + 仅 Cpdaily-Extension 头(与销假的 bodyString+sign 加密链路不同,实测确认);mustOut=1 时强制离校且开关不可改;审批人接口时间必须精确到秒(yyyy-MM-dd HH:mm:ss,datetime-local 值自动补秒);③ 服务端复核:execute 时重新查 cfg 并校验 disableTime/原因字数下限/needApproval 必选审批人,再做 checkOnceLeave 资格检查,全部失败均落日志;日志表新增 action 字段(apply/report)延续同表记录;限流扣费与销假同规则(2m×3/1h×6/24h×10,VIP 免扣非 VIP 成功扣 sign_count);④ 全程只读实测(checkOnceLeave/queryLeaveTypes/queryLeaveTypeCfg,未调用 /leave/apply 提交),新增 4 个单测覆盖类型合并/资格检查/表单构造(离校与不离校两分支)/提交,go test ./...、go vet、前端 build、vue-tsc 全过
ci/woodpecker/tag/build Pipeline was successful
|
2026-09-14 12:13:47 +08:00 |
|
becomer
|
2f20eebccd
|
v1.2.44:销假功能完整落地(后端 SSE 同步执行 + 前端销假页重写),并按真实接口实测修正位置/审批人语义——① 功能:新增 /leave 路由组(pending-list 待销假列表 / approvers 审批人 / execute SSE 执行 / logs 日志 CRUD),cpdaily/leave.go 封装 listOther+detailOther+obtainApproveFlow+report 全链路,cp_leave_logs 落库成败日志,用户级限流(2m×3/1h×6/24h×10),VIP 免扣非 VIP 成功扣 sign_count,图片经 OBS 浏览器直传(taskType=leave);前端 api/leave.ts + LeaveView.vue 重写(销假按钮/日志区/待销假弹窗/销假表单弹窗);② 规定销假位置修正:老版本取 leaveExtends[0](续假位置,实测近乎全空)或注释的 detail.applyLocation(请假提交时定位),均非学校规定位置;实测真实返回 reportPlaces[](address/经纬度/radius 米/设置人),已改为解析并前端列表选择+预填经纬度,用户可在规定位置间切换;③ 多校差异适配:实测 ynu/whit/lzufe 三校样本确认 leaveType.reportApplyFlow 控制销假是否需选审批人(ynu=1,whit/lzufe=0)、enableAttach 控制图片上传(ynu=1,其余=0),前端按开关自适应渲染审批人选择器与图片组件,提交时按需携带 approverWid;④ 解析 bug 修复:leaveType.code 真实为数字(3/12/2),原声明 string 导致 detailOther 全部解析失败(即"规定位置拿不到"的根因),改为 interface{} 承接并同时产出文本/数字双形式;obtainApproveFlow 要求时间精确到秒(yyyy-MM-dd HH:mm:ss),已自动补秒;⑤ 全程只读实测(listOther/detailOther/obtainApproveFlow,未调用任何 /report 提交),新增/重写 4 个单测覆盖开关解析/规定位置/审批人/提交表单,go test ./...、go vet、前端 build、vue-tsc 全过
ci/woodpecker/tag/build Pipeline was successful
|
2026-09-14 11:44:37 +08:00 |
|
becomer
|
3aee45be80
|
v1.2.43:滑块验证码改为「激活窗口等待 + 打码值窄序列」策略,推翻 ±12 扫描——① 决定性发现:服务端 open 后存在约 1.3~1.7s 激活延迟,延迟内提交任何值(含真值)都返回 errorCode=0;激活后接受以真值为中心的 ±8 宽区间(实测上缘 +8、下缘 -6~-8,相对打码值),打码平台返回值即为区间中心(误差 0±1),此前观测到的「打码偏差 -8~+9」实为快速扫描跨过激活窗口的落点伪影,并非识别误差;② 策略改造:slider.go 单轮流程改为 取图 → 打码 → 等待至 open+2.5s(抖动裕度)→ 按 v、v+1、v-1 窄序列提交(候选间隔 350ms,首候选通常即命中),全部失败仍换图重试(最多 5 轮),提交次数上界从 125 次降至 15 次;③ 新增激活等待回归测试(mock 复刻 300ms 拒绝窗口,断言等待后首个候选命中且不重发),重写候选命中/枚举耗尽测试(3×5=15 次 verify 上界),新增 v-1 命中用例;④ 真实账号端到端实测 3/3 一次通过(gapX=75/96/122 均 offset=0 直接命中,全程约 4s,302 ST 票据 → 7 cookies),go test ./...、go vet 全过
ci/woodpecker/tag/build Pipeline was successful
|
2026-09-14 00:29:25 +08:00 |
|
becomer
|
46c8a554ff
|
v1.2.42:华侨大学(hqdx)CAS 滑块验证码登录完整落地——① sign 协议:POST /authserver/common/verifySliderCaptcha.htl 提交 sign=AES-128-CBC-PKCS7(key=openSliderCaptcha 小图 base64 解码末 16 字节 safeSecure、iv=16 位随机、明文=64 位随机前缀+JSON{canvasLength:280,moveLength,tracks}),响应 errorCode=1 通过 / 0 失败,moveLength 为缺口真实值精确整数(±1 无容差),失败不消费图片、仅成功才作废;② 识别与连发策略:打码平台 /slider 识别打码值 v 后在同一张图上按 v、v±1…v±12(±12 窗口 25 候选)顺序连发,任一命中即止,全部失败换图重试(最多 5 轮 + 递增等待);实测打码偏差分布 -8~+9(另偶发识别失败图靠换图覆盖),故窗口取 ±12 留裕度;③ 流程接入:login_cas.go 按配置 sliderIds 分流滑块学校,casLogin 的表单选择器 #pwdLoginDiv 适配 hqu 登录页三表单布局(账密字段),滑块通过后 captcha 留空提交登录;hqdx 特判强制走 CAS(IAP 账密接口 FAIL_UPNOTMATCH 不兼容);④ 新增 slider.go + slider_test.go:sign 加解密/载荷/轨迹校验、候选命中、换图重试、5 图全失败(125 次 verify 上界)mock 全覆盖。实测:华侨大学真实账号端到端登录成功(3.11s,首图 +9 偏差命中 → 302 ST 票据 → CASTGC/JSESSIONID/MOD_AUTH_CAS 等 7 cookies),go test ./...、go vet 全过
ci/woodpecker/tag/build Pipeline was successful
|
2026-09-13 23:46:28 +08:00 |
|
becomer
|
1507b386bc
|
v1.2.41:许昌学院(xcu)单独适配 CAS 登录 + MFA 验证方式解析兼容 xcuTheme 弹窗布局——① 许昌学院:平台接口返回 joinType=CLOUD(IsIap=true),但其 IAP 账密接口 /iap/doLogin 与通用密码加密格式不兼容(实测 RSA hex/base64 多种编码均返回 FAIL_UPNOTMATCH,无法走通);学校真实链路为校园网关 302 → 学校 CAS(authserver.xcu.edu.cn)账密 + 多因子认证 → 回调 /iap/loginSuccess?sessionToken=... 建立网关会话,故在 CpdailyLogin 中对 xcu 特判强制走 CAS,登录入口由 ampUrl(casp.xcu.edu.cn,service 与 cookie 域不匹配)替换为 wecloud 网关 /portal/login(service 指向 xcu.campusphere.net,cookie 正确落在 wec-* 任务接口所在域),新增 login_xcu.go;② MFA 解析:许昌学院定制主题 xcuTheme 将验证方式渲染在「选择认证方式」弹窗中(div.other_type_button[id],id 即方式编号),原选择器均不匹配导致解析出 0 个方式(只能靠兜底),mfaMethodSelectors 新增 .other_type_button 兼容该布局;新增单测 5 个(xcu 入口计算 2 个 + MFA 弹窗布局 3 个),go test ./... 全过;已用真实账号端到端验证:CpdailyLogin → 网关入口 → CAS 账密成功 → MFA 触发并解析出 [{3 短信验证码 default:true}](修复前为 0 个)
ci/woodpecker/tag/build Pipeline was successful
|
2026-09-13 21:50:54 +08:00 |
|
becomer
|
1a15b359f8
|
v1.2.40:扫码签到(signMode=2)提交格式修复 + MFA 验证方式「全列表选择」改造——① 扫码签到:平台对二维码任务校验 qrUuid,旧格式(带 signInstanceWid 无 qrUuid)响应虽为 SUCCESS 但不落签到记录(假成功),现提交体改为 qrUuid 替代 signInstanceWid(不并存、不含经纬度、跳过定位校验),新增 qrcode.go 用 gozxing 解码二维码图片提取 uuid(URL uuid= 后 32 位串),空白 qrUuid 必失败;成功与否以提交后复核 isSigned 为唯一判据,已用真实任务(云大 2026.09.13 年级大会签到)闭环验证;② MFA:登录触发后不再自动发码,改为解析 reAuthLoginView 页面 Tab 渲染的全部支持验证方式(.mobile-reauth-tab-item/.reauth-tab-item/.reauth-tab-more-item/.changeReAuthTypes 多布局兼容、跳过注释块、过滤非动态码方式、空列表用当前方式兜底)随 4281 返回(authMethods/defaultType),用户选择后调新增接口 POST /api/auth/login/mfa/send 发送验证码(所选≠当前先调 changeReAuthType.do 切换并同步会话,响应含 mobile/codeTime),新增业务码 4284(发送失败)与 4282(验证码错误可重试)/4283(会话过期需重登)区分;前端登录页 MFA 弹窗改为「选择验证方式→输入验证码」两阶段,选择态/校验态失败判定与登录失败弹窗解耦,输入态支持「更换验证方式」回退;新增后端单测 10 个(MFA 方式解析含真实样本、规范化、发码全流程 mock)+ 扫码表单解析测试,go test ./...、go vet、前端 build、vue-tsc 全部通过
ci/woodpecker/tag/build Pipeline was successful
|
2026-09-13 21:03:51 +08:00 |
|
becomer
|
f23ab1a261
|
v1.2.39 补充:MFA access token 服务端校验宽限——存量已签发 token 无需重新登录即可平滑过渡到 2 小时——已签发的 JWT 因签名保护无法原地修改,且 MFA 通道 access/refresh 同 TTL、刷新窗口实际不存在(refresh 与 access 同时过期,前端又仅在 401 时被动刷新),存量用户(如杨蕊宁)原本只能重新登录换发新 token;现 ValidateToken 对已过期的 MFA access token(issuer=cpdaily-new 且携带 iat)按「签发时间 + 当前 MfaAccessExpire」再放行一次,配置调大后存量 1h token 自动延用至 2 小时窗口;refresh 不享受宽限(严格按自身 exp 校验),避免出现刷新窗口导致会话被滑动静默续期、违背 MFA 短会话设计。新增 jwt_test.go 覆盖 7 个场景:宽限内放行(存量 1h token 过期 30 分钟)、超 2h 拒绝、refresh 拒绝、非 MFA 拒绝、正常有效期放行、错误签名拒绝、缺 iat 拒绝。全部测试与 go vet 通过
ci/woodpecker/tag/build Pipeline was successful
|
2026-09-13 18:28:16 +08:00 |
|
becomer
|
84a602ae3b
|
v1.2.39:MFA 通道短期 JWT 有效期从 1 小时调整为 2 小时——MFA 学校(如云南大学)第三方会话无法自动续期,token 需与第三方 Cookie 有效期对齐;实测 whit 学校 MOD_AUTH_CAS cookie 签发后超过 1.5 小时仍有效(校验接口返回 errCode=0),说明第三方会话寿命大于 1 小时,故将 MFA 短期 token 放宽到 2 小时。新增独立配置项 mfaAccessExpire(默认 7200 秒,未配置时 Load 自动采用,服务器部署新版本无需修改配置文件即生效),不再复用普通登录的 accessExpire(仍为 1 小时),MFA 专属调整不影响常规登录链路;登录签发(finalizeLogin)与刷新重签(RefreshTokens 的 MFA 分支)同步改用新配置。注意:MFA 通道 access/refresh 同 TTL(现 2 小时),已签发的旧 token 无法原地延长,需重新登录后生效
|
2026-09-13 18:22:49 +08:00 |
|
becomer
|
35a2f1e432
|
v1.2.38:修复云南大学 CAS 登录 MFA 流程被 302 踢回登录页的两个根因——① simpleCookieJar 此前按 cookie 名处理删除指令,而云大 CAS 先发 CASTGC=TGT-...(Path=/authserver)再发删除指令 CASTGC=; Max-Age=0; path=/authserver/(尾部多一斜杠,Path 不匹配),浏览器与标准库 jar 按 RFC 6265 精确匹配作用域不会删除 TGT,按名删除把有效 TGT 一并误删,导致 reAuthLoginView.do 因检查不到 SSO 会话而 302 踢回登录页、MFA 页面无法渲染;现改为跳过删除指令与空值 cookie(不入库也不删除,同时避免发送空值 CASTGC 的历史问题),同名残留会在下次登录时被 CAS 重新 Set-Cookie 覆盖,离线 diff 验证与标准库 jar 对 MFA URL 的输出一致;② resty 默认重定向策略在跨 host 请求时把 User-Agent 替换为 go-resty/2.x(redirect.go checkHostAndAddHeaders),而 wisedu 定制 CAS 按请求 UA 分流渲染移动端/PC 模板,campusphere 网关跳转 ids.ynu.edu.cn 必然跨 host,UA 被替换后 CAS 渲染 PC 模板(25824 字节)导致 MFA 流程校验失败,现自定义 RedirectPolicy 在跨 host 重定向时保留原 UA,移动端模板(14283 字节)正常渲染。云大真实账号端到端验证通过:登录页移动模板 → POST 302 MFA → reAuthLoginView.do 200(29730 字节)→ reAuthType=3(短信通道)解析成功 → dynamicCodeByReauth.do 发码返回 success(短信实发至用户手机)
ci/woodpecker/tag/build Pipeline was successful
|
2026-09-13 17:59:19 +08:00 |
|
becomer
|
98689f68f4
|
v1.2.37:修复 MFA 通道登录丢失邀请码导致邀请奖励不生效的问题——v1.2.35 抽取 finalizeLogin 公共函数时,MFAVerify 调用传了空邀请码且 Redis 暂存的 mfaSession 未保存 InviteCode,导致经 MFA 验证码流程注册的新用户不建立邀请关系、不发放邀请奖励;现 startMFALogin 暂存会话时一并保存登录请求中的 inviteCode,验证成功注册时正常传入 findOrCreateUser,与普通登录通道行为完全一致
ci/woodpecker/tag/build Pipeline was successful
|
2026-09-12 14:56:04 +08:00 |
|
becomer
|
3632cb642e
|
v1.2.36:MFA 触发响应改为 HTTP 200 + 专用业务码,修复前端误弹「登录失败」弹窗的问题——登录触发多因子认证时不再返回 401(会被前端 catch 走登录失败 Dialog 路径),改为 code 4281(需MFA,data 含 mfaToken/expiresIn);验证码提交失败区分 code 4282(验证码错误可重试,弹窗保留清空重输)与 code 4283(验证会话过期/失效,关闭弹窗引导重新登录),cpdaily 包新增 ErrMFASessionExpired 哨兵错误供 errors.Is 判定;前端登录成功分支按 code 4281 弹出独立的多因子认证验证码弹窗,MFA 提交按 0/4282/4283 精确分支处理,与普通登录错误提示彻底解耦
ci/woodpecker/tag/build Pipeline was successful
|
2026-09-12 14:42:50 +08:00 |
|
becomer
|
47401e7388
|
v1.2.35:多因子认证(MFA)登录全流程支持——CAS 账密登录 302 到 reAuthCheck/reAuthLoginView.do?isMultifactor=true 时不再误判为登录成功,自动解析 MFA 页面参数(reAuthType/service/reAuthUserId)并调用 dynamicCode/getDynamicCodeByReauth.do 自动发送验证码;CAS 会话按域暂存 Redis(mfa_session:<token>,10 分钟 TTL,密码 AES 加密),新增 POST /api/auth/login/mfa 接口提交验证码(reAuthSubmit.do)→ CAS 票据交换 → activateSession → 与普通登录一致的注册/更新流程;MFA 通道登录签发短期 JWT(access/refresh 均与第三方 Cookie 有效期对齐,默认 1 小时,Claims 携带 mfa 标记且刷新不延长会话),静默重登遇 MFA 学校返回明确提示需重新登录;前端登录页处理 needMFA 响应弹出多因子认证 Dialog(验证码输入/10 分钟倒计时/输错可重试),验证成功后进入正常登录态。已用待适配学校(合肥幼儿师范高等专科学校)真实账号端到端验证:发码→收码→提交→reAuth_success→用户注册成功→第三方接口可正常拉取用户信息
ci/woodpecker/tag/build Pipeline was successful
|
2026-09-12 14:32:13 +08:00 |
|
becomer
|
e7e106c606
|
v1.2.28:验证码字体子集化——用 fonttools pyftsubset 从 Sour Gummy ExtraBold 提取仅含 0-9 的数字子集(验证码只需数字),嵌入体积从 58KB 降至 3.3KB,cmap 仅保留 U+0030-0039,渲染效果不变
ci/woodpecker/tag/build Pipeline was successful
|
2026-09-12 10:44:28 +08:00 |
|
becomer
|
240e1226ef
|
v1.2.27:验证码全面改版为可爱风——弃用 7x9 像素点阵,嵌入 Sour Gummy ExtraBold 开源字体(OFL 授权,猫啃网)渲染数字,字符按字形包围盒精确居中并随机旋转 ±10°,白描边贴纸效果;画布 180x60 且代码级保障最小尺寸,四周统一 15px 留白;干扰线改为绘制在数字上层的贯穿式弯曲斜线(强制大倾角、四向随机、线身带 1~2 个正弦拱似抛物线/波浪),专用冷色色池避开红粉;马卡龙背景+白色气泡+糖珠点缀;引入 golang.org/x/image 字体渲染依赖
ci/woodpecker/tag/build Pipeline was successful
|
2026-09-12 10:41:00 +08:00 |
|
becomer
|
643e706335
|
v1.2.26:记录用户登录 IP——认证中间件当天首次更新登录时间时同步写入客户端真实 IP(优先 nginx 转发的 X-Real-IP,其次 X-Forwarded-For 首段,兜底 RemoteAddr),真实登录接口同样记录;后台用户列表新增「最后登录」列(IP+时间)、详情弹窗新增最后登录IP展示
ci/woodpecker/tag/build Pipeline was successful
|
2026-09-11 23:27:59 +08:00 |
|
becomer
|
7a4507903f
|
v1.2.23:修复任务状态两个问题——1)跨天状态不重置:昨日成功后今天仍显示绿色对勾且无法执行,改为列表查询时按当天成功日志惰性重置为待执行;2)打卡完成后列表仍显示未签到/不刷新:成功后本地乐观更新+延迟校正刷新,显示以本地当天成功优先,并增加切回页面自动刷新
ci/woodpecker/tag/build Pipeline was successful
|
2026-09-11 22:16:23 +08:00 |
|
becomer
|
764bae23fc
|
v1.2.21:认证中间件补当天登录标记——token 长期有效不重新登录时,当天首次请求条件更新 last_login_at,修正后台当天登录人数统计
ci/woodpecker/tag/build Pipeline was successful
|
2026-09-11 14:24:40 +08:00 |
|
becomer
|
5de7852786
|
v1.2.19:修复签到图片直传OBS被拒(改用接口返回formData字段集);执行时自动将base64照片上传换正式URL;验证码创建/校验改multipart;表单必填项为空执行前拦截
ci/woodpecker/tag/build Pipeline was successful
|
2026-09-10 18:06:10 +08:00 |
|
becomer
|
bc4e739e09
|
v1.2.17:hfnu 切换为标准 IAP 登录(绕过学校 SSO 拒绝单点登录跳转);忘记密码提示改为打开学校官方登录地址测试登录或找回密码
ci/woodpecker/tag/build Pipeline was successful
|
2026-09-10 11:14:37 +08:00 |
|
becomer
|
81b2942cad
|
v1.2.16:hfnu 专属登录适配;拒绝改为单条记录;修复拒绝按钮换行与真实 IP 获取
- 新增 login_hfnu.go:合肥师范学院老式 jasig CAS 专用登录(URL 重写 jsessionid + 强制验证码),识别学校端 SSO 跳转被拒故障并明确报错
- 拒绝待适配学校改为仅拒绝当前记录,邮件只通知该条记录联系邮箱,不再批量拒绝同校其他记录
- 管理页操作按钮加 whitespace-nowrap 修复换行
- TrustedProxies 增加 127.0.0.1,配合 frpc PROXY protocol 透传恢复真实客户端 IP
|
2026-09-09 23:11:41 +08:00 |
|
becomer
|
4b1dea3d3c
|
待适配学校支持拒绝操作:拒绝必填理由并邮件通知联系邮箱
ci/woodpecker/tag/build Pipeline was successful
- 新增管理端接口 POST /admin/pending-schools/:id/reject,拒绝理由必填(≤500字)
- 拒绝时该校全部待处理记录标记为 rejected 并保存理由
- 新增 NotifySchoolRejected 邮件模板,拒绝理由 HTML 转义后发送至该校全部联系邮箱
- 列表接口返回 rejectReason 并支持 status=rejected 筛选
- 管理页新增拒绝按钮(组级+行级)、拒绝理由弹窗、已拒绝状态标签与理由展示、已拒绝筛选
|
2026-09-09 22:31:06 +08:00 |
|
becomer
|
0d665ad0fe
|
重构任务详情获取:执行时严格按任务名从当天列表实时匹配,移除全部兜底回退
ci/woodpecker/tag/build Pipeline was successful
- 执行链路新增 FetchTodayTaskDetail:仅用当天任务列表按任务名匹配未签实例,
wid 每次执行时实时获取;匹配失败直接报明确错误(未找到/今日已签),不再退回配置 wid
- 预览/历史预填充改用 GetTaskDetailByWid 纯 wid 查询,无隐式回退
- 删除 findLatestTaskInstance 与 fetchTaskDetail 的 allowFallback 递归回退逻辑
- RealTitle 直接取列表真实任务名,去掉二次匹配
|
2026-09-08 23:12:29 +08:00 |
|
becomer
|
67d925bb91
|
refactor: 任务实例 wid 改为执行时实时获取,配置快照仅作兜底
ci/woodpecker/tag/build Pipeline was successful
- 任务执行入口优先按任务名从当天列表实时匹配未签到的实例,
循环任务跨天不再依赖配置时保存的 signWid/signInstanceWid 快照
- 月度列表中的历史漏签实例不再被误当作可提交目标
(历史实例提交会被今日校园判定"已结束")
- 当天列表无可用实例(无同名任务/接口异常)时退回配置 wid 兜底,
详情为空再按任务名匹配近期已签实例还原表单结构
|
2026-09-08 22:59:29 +08:00 |
|
becomer
|
bf0e1656ab
|
fix: 循环签到/查寝任务自动切换到当日任务实例,修复"查寝已结束"
ci/woodpecker/tag/build Pipeline was successful
循环任务(如每日晚归寝打卡)每天生成新的 signInstanceWid,历史实例的
详情接口仍可返回数据,导致原有的"详情为空才回退"逻辑不触发,提交到
过期实例被今日校园判定为"查寝已结束"。
现在获取任务详情时,若当日列表中同名任务存在未签到的实例且与详情返回
的实例不一致,自动切换到当日实例后再填充表单提交。
|
2026-09-08 22:51:03 +08:00 |
|
becomer
|
99c16652a7
|
feat: 后台用户管理新增 VIP 列
ci/woodpecker/tag/build Pipeline was successful
- 列表接口返回 vipStatus(active/expired/none)与 vipExpireAt
- 表格新增 VIP 列:有效显示金色徽标+到期日期,过期显示已过期,未开通显示非VIP
|
2026-09-08 22:31:42 +08:00 |
|
becomer
|
cc4aa1c00e
|
feat: 后台当天执行总次数可点击查看执行日志明细
ci/woodpecker/tag/build Pipeline was successful
- 后端新增 GET /admin/task-logs 接口:按日期(默认当天)、成功/失败状态、
关键字(用户名/姓名/任务标题)筛选,联表 sys_user 返回用户与学校信息,分页返回
- 前端用户管理页「当天执行总次数」卡片改为可点击,弹出日志明细弹窗
- 弹窗支持日期切换(可查历史日期)、状态筛选、关键字搜索与分页浏览
|
2026-09-08 22:12:41 +08:00 |
|
becomer
|
a9dbc2661d
|
feat: 设备码绑定改为非强制 + 随机绑定入口
ci/woodpecker/tag/build Pipeline was successful
- 登录后不再强制跳转设备绑定页(MobileLayout 移除拦截)
- 新建签到任务时检测未绑定设备码,弹窗提示「请先在个人中心绑定设备码」并支持跳转
- 个人中心设备码栏新增「随机」按钮:随机生成 UUID 设备码直接绑定,
前端连续两次风险确认(随机后现有手机会提示频繁切换设备无法签到)
- 后端新增 POST /device/random-bind(登录态,随机 UUID v4 绑定,mobile_type=manual)
- 新手引导在「新建每日签到任务」前新增「先绑定设备码」步骤
|
2026-09-08 20:15:24 +08:00 |
|
becomer
|
74422b1848
|
fix: VIP 卡默认价改为周卡 30 元 / 月卡 100 元(对齐单次扣费 6 元的定价逻辑)
ci/woodpecker/tag/build Pipeline was successful
|
2026-09-08 12:40:20 +08:00 |
|
becomer
|
84f87cd168
|
feat: VIP CDK 改为周卡/月卡两档(7天/30天),价格分开配置
ci/woodpecker/tag/build Pipeline was successful
- 后端:vip_price_week(周卡,默认5元)/ vip_price_month(月卡,默认15元),
VIP CDK 仅支持 7/30 天,vip-info 返回双价格
- 后台:生成弹窗改为周卡/月卡选择,设置页拆分周卡/月卡售价两项
- 前台:开通按钮展示 周¥x · 月¥y 双价格
|
2026-09-08 12:29:59 +08:00 |
|
becomer
|
17a71b1e2a
|
feat: 新增 VIP 功能(CDK 兑换开通、徽标展示、免扣次数、后台管理)
ci/woodpecker/tag/build Pipeline was successful
- 数据库:sys_user.vip_expire_at、cdk_codes type/vip_days、系统设置 vip_price
- 后端:CDK 生成支持 count/vip 类型(VIP 默认 30 天),兑换延长 VIP 到期时间,/cdk/vip-info 查询售价
- 任务执行:VIP 有效期内的用户跳过次数扣减
- 前台:个人中心 VIP 徽标(反光动画)+ 到期时间 + CDK 兑换弹窗
- 后台:CDK 生成弹窗类型选择 + 系统设置 VIP 月卡售价项
|
2026-09-08 12:19:23 +08:00 |
|
becomer
|
2cac0cdfee
|
fix: 查寝历史位置超出签到范围时自动改用最近签到点提交
ci/woodpecker/tag/build Pipeline was successful
学校老师频繁调整查寝组签到点(小半径500~1000m),历史记录位置
卡在边缘(如距边角修正1仅540m),配置一变即触发"位置不在签到
范围内"。提交前校验历史位置与 signPlaceSelected 各点距离,全部
出界时自动改用最近签到点坐标,位置在范围内则继续沿用历史记录。
|
2026-09-07 21:51:18 +08:00 |
|
becomer
|
75d334680b
|
feat: 用户新建工单时邮件提醒管理员
ci/woodpecker/tag/build Pipeline was successful
复用待适配学校通知模式: GetAdminEmails + SendMailAsync, 邮件含标题/
用户/学校/内容摘要(HTML转义防注入, 500字截断), 仅新建工单触发。
|
2026-09-06 18:37:53 +08:00 |
|
becomer
|
35fa5a6560
|
feat: 后台用户管理展示邀请人
ci/woodpecker/tag/build Pipeline was successful
- sys_user 新增 inviter_id 字段, 注册时记录邀请关系
- ListUsers/GetUserDetail 返回 inviterId/inviterName(姓名优先)
- 前端用户列表加邀请人列, 详情弹窗加邀请人卡片
- 历史数据通过系统公告(邀请奖励到账/新人注册奖励 同刻配对)回填
|
2026-09-05 22:06:52 +08:00 |
|
becomer
|
dbd3c88d32
|
fix: 修复芜湖职业技术大学等CAS学校登录入口错选问题
ci/woodpecker/tag/build Pipeline was successful
getCasValidLoginUrl 原来按 AmpUrl/AmpUrl2 顺序取第一个可用URL, 部分学校
AmpUrl 是自研门户(ehall), 登录后cookie落在门户域, 与后续签到/查寝任务
接口所在campusphere网关域不匹配, 导致姓名同步失败且任务拉取返回302页面。
芜湖与安徽师范结构同构(网关+AmpUrl2), 修改为先取campusphere/wec网关入口。
|
2026-09-04 21:33:05 +08:00 |
|
becomer
|
33e29573ca
|
fix: 验证码限流改令牌桶(同IP 5分钟最多10次), 前端显示限流提示不再静默失败
ci/woodpecker/tag/build Pipeline was successful
原 SetNX 固定 10 秒/次:共享出口 IP 下易互相挤占且失败时前端静默,
表现为"验证码不显示且无提示"。改为 Redis Lua 原子令牌桶(容量10、速率
每30s回补1个),429 返回动态等待文案;登录主验证码、失败工单弹窗、
兑换弹窗三处加载失败均展示错误提示并支持点击重试。
|
2026-09-04 18:46:02 +08:00 |
|
becomer
|
4a80382b60
|
fix: 全局时间统一北京时间(Asia/Shanghai), 修复记录与展示偏移8小时
ci/woodpecker/tag/build Pipeline was successful
根因: 运行容器默认 UTC 且后端未设时区, time.Now()/gorm 时间戳/DSN
loc=Local/手动 Format 全部按 UTC, 导致展示为"美国时间"、月度与每日
边界错位。修复:
- main.go 在 database.Init 前固定 time.Local=Asia/Shanghai
(DSN loc=Local 随之一致, 一处生效覆盖全部业务点)
- pending_school.go 今日判断改北京时间当日0点(原 Truncate 按UTC午夜偏移8h)
- Dockerfile/build.yml/compose 加 TZ=Asia/Shanghai 双保险
配套: 存量 datetime 列已 +8h 迁移(备份 /root/cpdaily-backup-pre-tz-*.sql)
|
2026-09-03 21:06:59 +08:00 |
|
becomer
|
664d8a2594
|
feat: 新手引导改为数据库记录判定, 跨设备一致(用户选项: 存量未看过 v2 也会弹一次)
ci/woodpecker/tag/build Pipeline was successful
- SysUser 新增 guide_version 字段(GORM 自动迁移加列, 存量默认空)
- GET /auth/userinfo 返回 guideVersion; 新增 POST /auth/guide/complete
记录用户已看完当前版本引导(v2)
- 前端移除 localStorage 完成标记: 登录后按 userInfo.guideVersion
判定是否展示引导, 关闭/完成引导后上报写库 → 换设备不再重复打扰
- ?guide=1 测试强播入口保留, 且强播来源关闭引导时不上报数据库,
便于 QA 反复重测而不污染账号引导状态
|
2026-09-03 16:17:42 +08:00 |
|
becomer
|
d442f538e1
|
feat: 新手引导升级为 spotlight 真实页面高亮引导, 邀请奖励积分动态读取系统配置
ci/woodpecker/tag/build Pipeline failed
- 引导改为遮罩挖洞高亮真实 DOM 元素 + 气泡 tooltip, 四步跨首页/个人中心, 全屏拦截点击由气泡推进
- GUIDE_DONE_KEY 升级为 xz_guide_v2_done, 所有存量用户重走一遍引导
- 引导完成前不查询公告强制弹窗, 关闭引导后统一补齐
- HomeView/ProfileView 目标元素增加 data-guide 标记, 支持懒加载轮询等待与无任务降级分支
- 后端 GetMyInviteInfo/GenerateMyInviteCode 返回 inviterRewardPerInvite/inviteeRewardPerInvite
- ProfileView 与引导气泡邀请奖励文案动态化, 接口失败降级泛指文案
|
2026-09-03 15:43:32 +08:00 |
|
becomer
|
a75d57f309
|
feat: CDK分页/禁用恢复/生成结果复制 + 引导v2四步并延迟公告查询
ci/woodpecker/tag/build Pipeline was successful
- CDK列表服务端分页(状态筛选/关键字/汇总统计),修复admin全量列表Preload缺失关联问题
- CDK禁用/恢复接口(代理限自己、admin全部),用户管理补充每页条数选择
- 生成CDK后弹窗展示全部CDK并支持复制全部/单个
- 新手引导新增第4步(邀请好友赚积分),引导升级v2机制:所有现有用户重新走一次
- 公告强制弹窗延迟到引导完成后查询,避免弹窗冲突;移除路由调试请求
|
2026-09-03 15:18:49 +08:00 |
|
becomer
|
fc3bfe09f4
|
feat: 验证码走Redis防刷 + 新用户首次登录三步引导
ci/woodpecker/tag/build Pipeline was successful
- 验证码存储迁移 Redis(TTL 5 分钟自动过期,不再内存无限增长),
Redis 不可用时兜底内存存储,不影响登录可用性
- 验证码生成接口按客户端 IP 限频(10 秒/次,SetNX),移除每次
打印验证码的调试日志,防止日志刷屏
- 登录响应新增 firstLogin 标记,新注册用户首次进入自动展示全屏
三步新手引导:个人中心积分兑换次数→首页新建签到任务→执行任务
|
2026-09-03 15:11:10 +08:00 |
|
becomer
|
b49ef238dd
|
feat: 修复IAP登录错误识别/邮件通知/IP过滤
ci/woodpecker/tag/build Pipeline was successful
- IAP doLogin resultCode 兼容字符串枚举:FAIL_UPNOTMATCH→"用户名或密码不匹配"、
CAPTCHA_NOTMATCH→"验证码错误",未知结果码记录响应日志便于诊断
- 学校无可用登录地址时返回友好提示(替代 "Get \"\"" 技术性报错)
- 待适配学校 IP 提取真实公网地址(过滤 X-Forwarded-For 链中 127.0.0.1/内网)
- 新增邮件服务:后台可配置 SMTP 与管理员邮箱;新待适配提交异步提醒管理员、
适配完成异步通知学校全部联系邮箱;支持测试邮件发送
|
2026-09-03 13:09:42 +08:00 |
|
becomer
|
7c3e2be828
|
fix: 任务实例过期后详情为空——自动匹配最新实例,恢复图片字段与签到
ci/woodpecker/tag/build Pipeline was successful
问题:晚查寝等循环任务保存的 signInstanceWid 过期后,detailSignInstance
返回空数据,导致:1) 表单编辑页丢失必填的"签到照片"字段(isPhoto判定失效);
2) 执行签到报"请求参数SignInstanceWid为空"。
修复:
- FetchTaskDetail 详情为空时自动按同名任务匹配最新可用实例重试
(当天未签实例优先,其次历史已签实例)
- ParseTaskForm 图片字段判定增加历史记录 isPhoto 兜底
|
2026-09-02 20:25:43 +08:00 |
|
becomer
|
aa0ecfc4f1
|
feat: 后台用户管理改版——新列与当天统计
ci/woodpecker/tag/build Pipeline was successful
- 列表列调整:学工号/真实姓名/设备码(脱敏缩略+一键复制完整值)/
可执行/已执行(累计成功执行次数)/积分/邀请数/今天执行状态/创建时间
- 顶部统计卡片:当天执行总次数、成功执行总次数、当天新增用户数、当天登录用户数
- ListUsers 接口新增 executedCount、todayStatus 与 todayStats 统计
|
2026-09-01 22:30:50 +08:00 |
|
becomer
|
0b019ab4b9
|
fix: 任务名查重 + 验证码空识别结果直接重试,避免提交空验证码
ci/woodpecker/tag/build Pipeline was successful
- CreateTask 禁止同一用户创建相同 title 的任务
- submitCaptcha:AI 识别结果为空或场景码为空时直接报错重试,
不再向今日校园提交空验证码(修复"验证码的值不能为空")
|
2026-09-01 22:08:17 +08:00 |
|
becomer
|
3a26aaa155
|
fix: 公告target绑定类型防串台 + 绑定设备页增加退出登录
ci/woodpecker/tag/build Pipeline was successful
- 公告查询/已读校验中 target_user_id 未与 target_type 绑定,用户表与代理表自增 ID 重叠(均为 1000 起)导致管理员在后台收到发给前台用户的公告;现改为 target_type 与 target_user_id 联合匹配
- 绑定设备页底部增加退出登录按钮,未扫码时可随时退出当前账号,避免一直卡在绑定页
|
2026-08-30 22:21:36 +08:00 |
|
becomer
|
14270ab02d
|
fix: 南昌理工登录重试时刷新公钥 + 流水线 tag 事件触发条件修复
ci/woodpecker/tag/build Pipeline was successful
- nut_login:每次 attempt 重新获取 CAS 动态公钥(密钥对随登录页刷新轮换,
旧公钥加密会致服务端解密失败误报"用户名或密码错误")
- nut_login:"用户名或密码错误"也纳入重试(OCR 误识别时 CAS 可能统一提示),
最多 3 次尝试后仍失败才返回错误
- woodpecker:when 条件 branch:[v*] 改为 tag:v*(tag 事件无分支名,
v1.1.18 推送被过滤未触发构建)
|
2026-08-30 22:14:42 +08:00 |
|
becomer
|
edd4e90719
|
fix: 修复提交IP记录为反代网关地址 + 邀请码只读 + 待适配页展示已适配学校
ci/woodpecker/tag/build Pipeline was successful
- 后端:fiber 配置 TrustedProxies(172.22.0.0/16)+X-Forwarded-For,待适配学校提交记录真实客户端 IP
- 后端:pending-schools 列表 status=completed 时正确过滤已完成记录
- 前端:登录页邀请码由邀请链接自动带入,改为 disabled 不可编辑
- 前端:待适配学校页面顶部展示已适配学校列表,学校分组标注"已适配"徽标
|
2026-08-30 22:12:39 +08:00 |
|
becomer
|
2f93e24a39
|
fix: 适配南昌理工学院自研 CAS→IAP 混合登录(学校ID匹配,独立于通用IAP/CAS逻辑)
ci/woodpecker/tag/build Pipeline was successful
该校登录链路与标准金智 IAP/Apereo CAS 均不同:
- /portal/login → /iap/login 页面实际转发到学校自研 CAS(my.nut.edu.cn/cas/login),
表单为 username/password/authcode/execution/_eventId 风格
- 登录成功后 302 回跳 /iap/loginSuccess?sessionToken=xxx&ticket=ST-... 建立 IAP 会话
- 密码加密特殊:先反转,明文块按小端 16-bit digit 装配后直接 m^e mod n
(无 PKCS#1 填充),公钥由 /cas/v2/getPubKey 动态获取,hex 空格分隔
- 每次登录均需图形验证码(/cas/kaptcha),OCR 识别失败自动重试最多3次
新增 nut_login.go 专用实现,CpdailyLogin 按 school.ID 匹配路由,不动通用 IAP/CAS 代码。
|
2026-08-30 22:03:09 +08:00 |
|
becomer
|
49e1cef31c
|
fix: 任务类型 tag 不换行 + 图片上传 loading 动画 + 移除照片提示文案
ci/woodpecker/tag/build Pipeline was successful
1. 任务列表/标题选择/日志三处任务类型 tag 加 shrink-0 whitespace-nowrap,
标题加 min-w-0 truncate,标题过长不再挤换行
2. 创建与编辑表单的图片区域上传中显示旋转 loading
3. 移除签到照片字段下方的"您可以上传多张图片"提示
|
2026-08-23 19:49:28 +08:00 |
|