feat(homeworks,island,classisland,desktop,web,server): 作业按天查看与教室机器录入 + 提醒上课时段暂存规则 + 灵动岛边距/跟随鼠标屏幕
- 作业:新增 Homework.assignDate(本地日期 YYYY-MM-DD;UTC 切片在晚上会把今天的作业算成明天),列表按天过滤与排序,新增 GET /homeworks?date= 与 GET /homeworks/days(日期高亮)供客户端与 Web 共用;客户端作业页改为"看作业 + 录作业"(不再显示完成状态),支持快捷短语(存本机配置,「设置 → 作业录入」可增删/恢复默认) - 教室机器录入:POST /homeworks 去掉 requireRole,权限下沉到 homeworks.service(staff 或本班班级账号);班级账号的 sub 是班级 id,写 createdBy 前换成该班班主任,避免撞 User 外键 - 提醒类型:ClassIslandPush.kind(notification / call)。通知类上课时段暂存、下课补弹,叫人/紧急立即弹;客户端灵动岛与 ClassIsland 插件共用同一套规则 - 灵动岛:新增 marginX / marginY(默认仍 8px,不动老外观)与「跟随鼠标屏幕」;文案统一成"灵动岛 / ClassIsland" - 设置页:新增「ClassIsland 联动」(联动状态 + 通知模式)与「作业录入」分区 - 校验:verify:e2e 增补 assignDate 默认当天 / ?date= 过滤 / days / 非法日期 422 / 班级账号录入 201 与跨班 403;verify:classisland 与插件静态契约增补上课时段暂存断言(57/57) - 文档:README 与 AGENTS.md 同步(作业按天、上课时段策略、两个方向的开关表、新增踩坑) 门禁:pnpm lint 0 error、pnpm typecheck 四包通过、verify:classisland-plugin 57/57 通过。 未跑:verify:e2e / verify:classisland(需后端启动)、verify:web / verify:desktop(需先构建产物)。
This commit is contained in:
1 parent
d0830f6830
commit
7536abfc95
33 files changed
+1236
-162
No files matched your search
@@ -242,14 +242,30 @@ public sealed class BridgeService : INotifyPropertyChanged, IDisposable
|
||||
|
||||
var entryCount = 0;
|
||||
var layoutCount = 0;
|
||||
// 开关关着时也要留下原因:否则日志只有"上报成功:仅状态",
|
||||
// 用户会以为"服务端拿不到 ClassIsland 课表"是插件坏了。
|
||||
if (includeSchedule && !_settings.UploadSchedule)
|
||||
{
|
||||
_logger.LogInformation(
|
||||
"班级小助手联动:本机设置里「上报课表到班级小助手」是关闭的,本次只上报状态;" +
|
||||
"需要把教室课表同步到班级小助手请打开该开关");
|
||||
}
|
||||
|
||||
if (includeSchedule && _settings.UploadSchedule && profile is not null)
|
||||
{
|
||||
var entries = ScheduleMapper.MapAllClassPlans(profile, out var warnings);
|
||||
foreach (var warning in warnings) _logger.LogWarning("班级小助手联动:{Warning}", warning);
|
||||
entryCount = entries.Count;
|
||||
request.Schedule = new SchedulePayloadDto { Mode = "merge", Entries = entries };
|
||||
// 补上 endTime 之外的字段由服务端按需处理;课表为空时不发,免得把服务端已有课表"合并"没了
|
||||
if (entries.Count == 0) request.Schedule = null;
|
||||
// 课表为空时不发(否则会把服务端已有课表"合并"成空),但**必须把原因写清楚**:
|
||||
// 日志里只出现"仅状态"时,用户会以为上报失败,实际是 ClassIsland 里还没有课表。
|
||||
if (entries.Count == 0)
|
||||
{
|
||||
request.Schedule = null;
|
||||
_logger.LogWarning(
|
||||
"班级小助手联动:ClassIsland 里没有**启用的课表**(0 条),本次未上报课表。" +
|
||||
"请在 ClassIsland 里排好课表,或在 Web 端打开「镜像课表」由班级小助手下发一份");
|
||||
}
|
||||
|
||||
var layout = ResolvePrimaryTimeLayout(profile);
|
||||
if (layout is not null)
|
||||
@@ -285,7 +301,9 @@ public sealed class BridgeService : INotifyPropertyChanged, IDisposable
|
||||
|
||||
var detail = entryCount > 0
|
||||
? $"课表 {entryCount} 节 / 节次 {layoutCount} 条"
|
||||
: "仅状态";
|
||||
: _settings.UploadSchedule
|
||||
? "仅状态(ClassIsland 里还没有启用的课表)"
|
||||
: "仅状态(本机「上报课表到班级小助手」开关已关闭)";
|
||||
SetState(true, $"上报成功({reason}):{detail},服务端第 {data.Week} 周",
|
||||
entryCount, layoutCount, data.Week);
|
||||
|
||||
@@ -371,8 +389,11 @@ public sealed class BridgeService : INotifyPropertyChanged, IDisposable
|
||||
var (result, plan) = await _client.PullClassPlanAsync(_settings, CancellationToken.None).ConfigureAwait(false);
|
||||
if (!result.Ok || plan is null)
|
||||
{
|
||||
// 服务端在"镜像开关没开"时会返回 data=null —— 这不是错误,只记信息
|
||||
_logger.LogInformation("班级小助手联动:跳过课表镜像({Message})", result.Message);
|
||||
// 服务端在"镜像开关没开"时会返回 data=null —— 这不是错误,但要告诉用户去哪儿开
|
||||
_logger.LogInformation(
|
||||
"班级小助手联动:跳过课表镜像({Message})。" +
|
||||
"需要在 Web 端「ClassIsland 联动」页给这台设备打开「镜像课表」,然后点一次「立即上报」或等下一个上报周期",
|
||||
result.Message);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user