更新日志
v1.1.3(2026-09-14,竞品对标修复轮 · 第三段)
补齐 §7 里最后一项代码层可闭环的 GAP:G-08 调课 / 调休例外层。
新增
- 调课工具(设置 → 日期之间调课,或课表设置区入口):可以给任意一天设置
- 这天停课(不补);
- 整天调到本周另一天(目标日限制在同一自然周)。 课表页会给出反馈:调课过来的课程块带「调」角标,停课 / 调课的当天有一整列提示带(「停课」「调至周三」),不会让用户对着空白的一天猜数据是不是丢了。
- 例外是可撤销的:调课工具里列出本学期所有例外,点删除即恢复原样。
- 数据层新增
schedule_overrides表(schema v5),随导出 / 导入 / 本地快照一起走;导入时会校验类型(只允许停课 / 调课),非法值整体回滚。
修复
- 高|课表与通知会各说各话:课程提醒的排期现在与课表渲染共用同一份解析(
core/util/day_override.dart)。停课的那天不再发提醒;调到别的日子的课,提醒也跟着挪到目标日。
变更
- 原课表永不被修改。调课是「按日期生效的例外」,只影响指定日期所在的那一周;这是与竞品最大的做法差异 —— 直接把课表改掉会让之后每周都跟着错。
- 目标日已被占用的节次不会被静默丢弃:这部分课程留在原处,并在确认框里明确告知「其中 N 节因目标日该节次已被占用,会留在原处」。
- 跨周调课明确拒绝(日期选择器直接限制在本周内),而不是算出一个用户看不懂的结果。
- 例外块禁止长按拖拽:拖拽改的是原课表(之后每周都变),与「只改这一次」的意图冲突。
已知未完成(见 COMPETITIVE-ANALYSIS.md §7)
- 未做:课表背景图与贴纸(G-12 部分)、校历式假期自动标记(需校历数据源)。
- 环境受限:Android/iOS 桌面小组件(G-01)、锁屏与实时活动(G-16)、上课自动静音(G-17)、空教室查询(G-18)、真机性能对标(G-22)。
验证
flutter analyze:0 issuesflutter test:504 passed / 0 failed(v1.1.2 基线 470 → 504,新增 34 条锚点:例外解析规则 18、仓储不变量与级联 11、导入导出回环与非法类型 2、课表渲染接线 6 —— 覆盖「调到目标日」「今日视图单列也能看见调来的课」「停课」「不跨周误伤」「禁止拖拽」)
v1.1.2(2026-09-14,竞品对标修复轮 · 第二段)
接续 v1.1.1,把 §7 里剩余「代码层可闭环」的 GAP 清完:G-06 / G-09 / G-10 / G-11 / G-14 / G-19 / G-20 全部落地。至此外,只剩 G-08(调课例外层)与 G-12 的背景图/贴纸属于「未做」,G-01 / G-16 / G-17 / G-18 / G-22 属环境受限。
新增
- 「今日」视图(课表页右上角 →
/today):竖向今日时间轴(单列复用周视图网格,不会出现「周视图有这节课、今日视图没有」的偏差)+ 今天到期的作业 + 今天开考的考试(含跨夜考试提示)混排,当天没有安排时给出「去课表」引导。 - 成绩与 GPA 页(设置 → 成绩与 GPA):按课程录成绩项(分数 / 满分 / 权重 / 备注),自动算课程总评 → 4.0 制绩点 → 学分加权 GPA。支持 5 分制 / 150 分制折算;支持「目标分反推」(告诉你剩下那部分还需要考多少分,已达标与不可能达标会分开提示)。
- 课表长图导出:一键把当前周视图导出成图片(只截网格区、含周次与学期名),可直接分享。
- 课表分享码(设置 → 课表分享码):把整学期课表压成一段文本,同学粘贴即可导入。在本机生成、不经过任何服务器;别人手改过的码也能温和失败或钳制,不会把坏数据写进库。
- 放假倒计时(设置 → 放假倒计时):设定名称与目标日后,在「今日学习」卡片与今日页显示「距「寒假」还有 N 天」。目标日过去后自动不再显示。
- 课程「考核方式」字段:如「平时 30% + 期末 70%」,单独成一栏而不是挤进备注;随导入导出与分享码一起走。
修复
- 高|删除后无法挽回:此前只有课程管理页的删除能撤销。现在课程(两条入口)、作业、考试、成绩项删除后都提供 5 秒「撤销」,按原字段原样重建(含排课片段的周次集合与自定义上下课时间)。撤销为「重建」语义,因此得到的是新 id:关联的作业 / 考试需重新指定课程,课表内容本身完整恢复。
- 中|「今日」相关聚合逻辑散落:作业到期 / 考试开考 / 跨夜判断抽成
core/util/agenda.dart纯函数,避免今日视图与通知、小组件各算一套导致口径不一致。
变更
- 放假倒计时的目标日过期后不再显示(而不是显示负数天数),设置项会提示「目标日已过去,点击重新设置」,不留一个看起来坏掉的条目。
已知未完成(见 COMPETITIVE-ANALYSIS.md §7)
- 未做:调课 / 调休例外层(G-08)、课表背景图与贴纸(G-12 部分)。
- 环境受限:Android/iOS 桌面小组件(G-01)、锁屏与实时活动(G-16)、上课自动静音(G-17)、空教室查询(G-18)、真机性能对标(G-22)。
验证
flutter analyze:0 issuesflutter test:470 passed / 0 failed(v1.1.1 基线 417 → 470,新增 53 条锚点:今日聚合、GPA 换算与目标分反推、分享码编解码与坏码、长图合成、删除撤销的字段完整性、放假倒计时边界)
v1.1.1(2026-09-14,竞品对标修复轮)
依据
docs/COMPETITIVE-ANALYSIS.md的 22 条 GAP 清单,修复其中代码层可闭环的部分;需原生工程 / 真机 / 服务端的项已在文档中标注为环境受限。
新增
- 「从其他课表 App 导入」一级入口(
/import/competitor):迁移动线打通。识别 WakeUp / 超级课程表 / 小爱课程表 / 通用课表 JSON 并回显来源名称,识别不出时回落文字识别;导入前提示「只追加不覆盖」,整批写入包在同一事务里(失败不留半批数据)。入口三处可达:设置 → 数据、课表空态、引导页第 2 屏「现在就导入旧课表」。 - 课表当前时间线:今天所在周绘制红色时间线(按所在节次起止分钟线性插值,自定义作息也准),课间吸附到下一节、凌晨与放学后不画;今天已上完的课程整体降透明度。
- 课程块信息密度三档:仅课名 / 课名 + 地点 / 课名 + 地点 + 教师。
- 课表字号档位:小 / 标准 / 大(只作用于课表块与节次轴,不受系统字号影响)。
- 5 套预设皮肤一键套用:液态玻璃 / 纸感 / 紧凑 / 大字号 / 暗夜,一次写入主题色 + 玻璃强度 + 格子高度 + 圆角 + 字号 + 信息密度,之后仍可逐项微调。
- 自定义空课图片:空课表可显示本地图片(长按该行恢复默认;文件被删/移动自动回退默认样式)。
- 本地自动备份与一键恢复:启动时到期(24h)自动快照、手动立即备份、从最近快照恢复(恢复前自动留
prerestore底);自动快照只保留 5 份,手动快照不参与清理。 - 隐私承诺与无障碍声明:关于页新增条目式说明(无广告 / 不注册 / 本地优先 / 不追踪行踪 / 无障碍与字号),可直接用于商店页;引导页新增同主题收尾屏。
- 教务适配需求登记:教务入口说明改为「尚未接入、不索取学号密码」,并提供「登记我的学校」把需求写在本机。
修复
- 高|
GlassCapability导致 appInit 全组测试必崩:_systemWantsReducedMotion()直接取WidgetsBinding.instance,纯 Dart 单测未初始化 binding 时抛Binding has not yet been initialized,app_init_test.dart5 条用例长期失败(发布门禁实质失效)。改为读PlatformDispatcher.instance.accessibilityFeatures。 - 中|
flutter analyze恒为 2 issues:test/link_audit/io_link_test.dart未使用 null-aware element 语法,门禁无法归零。已修正。 - 中|设置页 4 个「有名字没实现」的入口(将课表添加到桌面 / 日期之间调课 / 自定义空课图片 / 清除浏览器缓存):前两项改为真实状态说明(含当下可用的替代方案与「规划中」徽标),后两项实装。设置页不再存在「点了没反应」的入口。
- 低|删除课程不可逆:删除后 SnackBar 提供「撤销」,按原字段重建课程与全部排课片段(含片段级自定义时间)。注意:外键已在删除时把作业/考试的
courseId置空,撤销得到的是新课程 id,关联需重新指定。
变更
- 竞品迁移与 AI 识别两条链路共用同一套解析与安全边界;竞品解析结果新增
sourceLabel字段用于回显来源。
已知未完成(见 COMPETITIVE-ANALYSIS.md §7)
- 未做:今日视图(G-06)、调课/调休例外层(G-08)、成绩与加权 GPA(G-10)、课程详情考核方式与附件(G-11)、长图导出(G-14)、分享码(G-19)、放假倒计时 UI(G-20)、任务/考试删除撤销(G-09 部分)。
- 环境受限:Android/iOS 桌面小组件(G-01)、锁屏与实时活动(G-16)、上课自动静音(G-17)、空教室查询(G-18)、真机性能对标(G-22)。
验证
flutter analyze:0 issuesflutter test:417 passed / 0 failed(新增 23 条锚点:时间线落点、外观档位解析、设置键兜底、竞品来源识别、快照文案)
v1.1.0(2026-09-03,build 2)
新增
- 课程编辑吸底「添加上课时间」按钮:不再随表单滚动消失,滑到任何位置都能一键追加排课(原「上课时间」标题行的小「添加」仍保留)。
- 节次时间弹窗改滚轮选盘:点击课表左侧节次轴弹出的时间编辑改用系统式 HH:mm 双滚轮(5 分钟粒度、CupertinoPicker),替换手输文本框。
- 课程色板 12 → 24 色(按色相环排列,同屏多课更易区分);图标库 14 → 104 个(文科/理科/信息工程/体育/音乐才艺/舞蹈表演/兴趣爱好/手作生活/语言九组——含摄影📹、游戏🎮、桌游♟️、露营🏕️、烘焙🍰、编织🧶、绘画🖌️ 等兴趣才艺场景)。
- 按课表(学期)独立作息时间表:每个课表可有自己的节次起止时间——学期专属作息优先,无专属时回退全局模板;修改只影响当前课表,不动全局与其他课表。课表绘制、「下一节」、通知排期、日历、编辑器全链路统一走学期作息。
- 课表页点节次轴改时间:点击左侧节次轴(如「1 / 08:00 / 08:45」)直接弹出该节次起止时间编辑弹窗,保存即写入当前课表的专属作息(首次修改自动把全局模板复制为该课表的基础)。
- 课程编辑「添加」排课复制上一条:连续添加排课片段时自动沿用上一条的周几/节次/周次/自定义时间,微调即可,不再每次从默认值填起。
- 课程块长按拖拽调课:长按课程块(350ms)即可拖到任意「周几 × 节次」格,松手落库;保持原有连排跨度与周次集合不变,移动到与既有课冲突的位置会提示「与《X》时间冲突」但仍放行(方便临时调课),拖到末尾越界节次自动上移保持完整跨度。PRD P1 项落地。
- 未来课表(暑假/寒假/下学期)提前排课:
- 新建学期提供快捷名称预设(按所选年份自动生成「2026 暑假 / 寒假 / 春季学期 / 秋季学期」);
- 开学日期选在未来时,默认不切换当前课表(副标题提示「提前排好课、到开学再切换」),可手动勾回;
- 多课表管理页与课表页的学期切换面板新增状态徽标(未开学/进行中/已结束)与完整日期区间(开学周一 ~ 末周周日);
- 未开学课表的空态引导改为「提前把假期或下学期的课排好,开学后即可直接使用」。
- 竞品课表导入:AI 识别页支持 WakeUp 课程表、超级课程表、小爱课程表导出的 JSON 文件,字段别名宽松匹配、单双周归一化、坏行跳过计数,导入前仍经预览确认。
- 宠物图鉴清单:内置
pet_manifest.json(144 只宠物元数据),离线可浏览图鉴。 - Android release 签名:
build.gradle.kts接入key.properties(缺失自动回落 debug 签名,CI 不阻断);出包流程见docs/PACKAGING.md。 - 出包指南:
docs/PACKAGING.md记录 Android/HarmonyOS 出包流程与鸿蒙端环境限制。
变更
- 玻璃强度三档差异拉大:设置里调「玻璃强度」此前几乎看不出变化——现在 weak 档近乎哑光薄纱(模糊降至 15%、透明度大降)、strong 档浓郁磨砂(模糊 2.4 倍、更不透明、高光更强),medium 保持基准,切换档位肉眼可辨。
- 节次轴紧凑化:左侧时间轴宽 54px → 38px(时间字号 8.5→8、右距 5→4、字距微收),7 列课表每列增宽约 2.3px,手机上课程块更宽更易读。
- 包体瘦身:安装资产从 ~95MB 压至 ~36MB(zip 16.3MB)。仅默认宠物「青霜幼龙」随包(2.3MB),其余 143 只改为 CDN 按需下载(未配置下载源时自动回退矢量绘制,离线零依赖)。接入步骤见
docs/pet-packaging.md。 - 鸿蒙深链导航时序:
HarmonyWidgetBridge仅在 build/layout/paint 阶段推迟到帧尾,其余直接导航,消除冷启动竞态。
修复
- 学期切换自愈加固(build 4):修好后自愈逻辑原在 build 期间直接
jumpToPage(build 期非法,实际被跳过导致修复无效)——回归测试暴露后改为帧尾(addPostFrameCallback)钳制周数并跳页。新增学期切换回归测试(手动周次 18 → 切 4 周学期,胶囊自愈回 1~4)。 - 测试专家对抗性审查(2026-09-05,build 3):全量代码审查 + 对抗性测试发现并修复 14 项缺陷——
- 致命|节次时间滚轮双轴互相覆盖:
_WheelPicker用late final固定初值且闭包引用对方轴的陈旧值,先滚小时再滚分钟会把上课时间存成「初始小时+新分钟」(如选 14:30 实际落库 08:30),直接污染整张课表作息。改为可变状态互相同步(新增 3 条对抗性回归)。 - 高|ICS 导出未按学期过滤:多学期时每门课对每个学期各生成一个事件(事件翻倍且一半锚错开学日),「仅导出某学期」也会带出其他学期的课。已按
course.termId过滤。 - 高|ICS TEXT 字段零转义:课程名/地点含换行、分号、逗号、反斜杠会破坏 VEVENT 结构(Google Calendar 等严格解析器拒收整份文件)。按 RFC 5545 转义。
- 高|JSON 导入零数值校验:
totalWeeks=-5会让课表页itemCount断言崩溃;totalWeeks=2e9会在解析器List.generate处 OOM;天文startDate溢出Duration。导入入口统一范围钳制(越界抛FormatException事务回滚)。 - 高|竞品导入
step别名错误:step是「连堂节数」却被放进结束节次别名表,超级课程表 2-3 连堂会被截断成 2-2(静默丢课)。已从别名表移除并单独按节数展开。 - 高|
WeekCodec.maxWeek=25与 UI 允许的 30 周学期冲突:第 26-30 周被静默吞掉,且再次编辑会被重写成整学期(二次数据损坏)。上限提升到 30。 - 高|当前课呼吸高亮永不启动:
_CourseBlock只在initState建动画,上课时刻到来后(30s 心跳刷新)无didUpdateWidget,正在上的课永远无高亮;反向场景动画空转。已补didUpdateWidget启停。 - 高|学期切换后周次越界不自愈:20 周学期翻到第 18 周后切到 4 周学期,顶部胶囊显示「第 18 周」而网格停在第 4 周。
_ensureInit检测学期/周数变化后钳制并跳页。 - 高|编辑页冲突检测用全局作息:学期有专属作息时误报/漏报(全 App 其他链路均已用学期作息)。改用
getPeriodsOfTerm。 - 中|拖拽落点冲突检测无分钟维度:候选片段不传分钟,「自定义时间横跨多节」的既有课漏检;且既有片段的自定义分钟传入后被忽略(死参数)。候选与既有片段均回填作息分钟。
- 中|极短自定义时间负高度崩溃:自定义 3 分钟的块换算高度 <4px 时
Positioned负高度触发布局断言。高度下限 12px。 - 中|节次下拉越界断言崩溃:
maxPeriods调小后打开旧课(或深链超界节次),DropdownButton.value不在 items 内直接断言崩溃。value 钳制兜底。 - 中|学分无范围校验:
-3、1e2均可入库。现要求 0~100。 - 低|其他:深链
/course/abc路由int.parse抛异常白屏(改tryParse兜底);学分 2.25 经toStringAsFixed(1)往返丢失为 2.3(改toString);清空周次的片段保存被静默展开成整学期(改为确认弹窗+跳过);「开学在未来 7 天自动取消切换」阈值随时钟漂移(改按日期比较)。
- 致命|节次时间滚轮双轴互相覆盖:
- 课程编辑页「添加上课时间」按钮撑满整屏(真机):
GlassButton.expanded只约束宽度不限高度,在 ScaffoldbottomNavigationBar的松约束下被撑到近整屏高——真机上点课程块进入编辑页后只看到一颗巨型蓝色胶囊,课程名称等表单被完全顶出屏幕(截图确认)。现横向撑满、纵向锁定 ≤64px,表单恢复可见。新增布局回归测试(按钮高度 ≤64、吸底、首屏可见「课程名称」)。 - 点击课程块手势串扰加固(真机):课表网格背景
DragTarget显式声明onMove/onLeave,避免在部分真机手势竞技场实现中抢占无负载普通点击;新增回归测试锁定「点课程块→编辑页、点节次轴→时间弹窗、长按>350ms 不触发点击」三条链路互不串扰。 - 界面中文化(日历/日期选择器):应用此前未接入 Flutter 本地化,日期选择器(日历弹窗)显示英文(CANCEL/OK/月份名)。已接入
flutter_localizations并固定zh_CN:月份标题「2026年9月」、按钮「取消/确定」、星期表头「一~日」全部中文。首版仅中文,与 PRD 一致。 - 手机端课名竖排紧凑 + 地点,垂直居中:7 列课表每列约 42-52px,窄列(<64px)课程块内容垂直居中显示;课名每行两个汉字,「高等数学」为「高等/数学」;块高有剩余时追加上课地点(
@A101形式、淡色小字),双节块可容纳约 8 行(长课名 + 地点都放得下),空间不足时优先课名。宽屏横排同样垂直居中。 - 自定义时间按比例绘制课程块:选了片段级自定义起止时间后,课程块不再占满整个节次区间——在节次区间内按时间比例计算实际高度与起点(如 1-2 节 100 分钟中自定义 75 分钟 → 块高 75%);无作息或时间缺失时回退整节次显示。
- 导入损坏课表文件时结构错误统一转为友好
FormatException(事务整体回滚,不留半套数据)。 WeekCodec周次解码剔除小数/负数/超上限值,防止脏数据产生幽灵周次。- ICS 导出按「学期专属作息优先、全局兜底」取节次时间。
- Windows 构建因
main.cpp中文字面量缺 BOM 导致 MSVC 解析失败的问题。
发布产物(Windows 构建主机)
- Windows:
artifacts/release-v1.1.0-*.zip(16.3MB/177 文件),启动烟雾验证通过。 - Android:
artifacts/haoxue-kechengbiao-android-v1.1.0-build4-*.apk×3 —— 通用 25.5MB / arm64 24.1MB / armv7 22.1MB(split-ABI 达 NFR ≤25MB); apksigner 验证正式证书(CN=haoxue)。 - HarmonyOS:本机无法出 hap —— 缺 flutter_harmony 引擎与 ohos 工程骨架 (DevEco 已装但未接 Flutter)。完整出包步骤与验证清单见
docs/PACKAGING.md, 需在具备引擎的机器或 CI 鸿蒙节点执行。
测试
- 测试套件 99 → 269 用例;
flutter analyze0 issues;lib 行覆盖 ~58%(业务逻辑层全覆盖,含数据库迁移 v1→v3、通知重排全链路、竞品解析、登录会话、鸿蒙卡片通道、周网格渲染)。
v1.0.0(2026-07-06,build 1)
- 首版:iOS 26 液态玻璃风格课表、课程/任务/考试管理、本地通知、月历视图、数据导入导出(JSON/ICS)、电子宠物、鸿蒙桌面卡片源码模板。