在这里插入图片描述
在这里插入图片描述

实例:课程表管理(Course)|技术:14 门课程、坐标分布、色板分配

一、种子数据的设计目标

实例 15 的种子数据要撑起「课表网格 + 冲突检测 + 当天列表」,设计目标:

  1. 14 门课程:课表格子饱满——5 天有课、格子有内容;
  2. 坐标分布合理:覆盖周一~周六 6 天、不同节次——网格有「课表感」;
  3. 连堂示例:高等数学(周一 1-2 节)、大学英语(周一 3-4 节)、数据结构(周二 1-2 节)、操作系统(周三 3-4 节)、大学物理(周四 1-2 节)——连堂块可见;
  4. 色板覆盖:每门课不同颜色——色块区分课程;
  5. 周六有课:软件工程(周六第 1 节)——「周六也上课」的真实校园场景;
  6. 周日无课:休息日——验证空节次占位格。

二、14 门课程种子数据

# 课程 老师 教室 周几 节次 颜色 教学周 备注
1 高等数学 王教授 A101 周一 第1节 蓝 #3B82F6 1-16 带教材
2 高等数学 王教授 A101 周一 第2节 蓝 #3B82F6 1-16 (连堂)
3 大学英语 李老师 B203 周一 第3节 绿 #10B981 1-16 听力练习
4 大学英语 李老师 B203 周一 第4节 绿 #10B981 1-16 (连堂)
5 数据结构 陈教授 C305 周二 第1节 紫 #8B5CF6 1-16 带电脑
6 数据结构 陈教授 C305 周二 第2节 紫 #8B5CF6 1-16 (连堂)
7 体育 张教练 操场 周二 第5节 橙 #F59E0B 1-16 穿运动服
8 操作系统 刘教授 C401 周三 第3节 红 #EF4444 1-16 期中考试
9 操作系统 刘教授 C401 周三 第4节 红 #EF4444 1-16 (连堂)
10 大学物理 赵教授 A305 周四 第1节 青 #06B6D4 1-16 带计算器
11 大学物理 赵教授 A305 周四 第2节 青 #06B6D4 1-16 (连堂)
12 马克思主义原理 周老师 D102 周五 第3节 黄绿 #84CC16 1-16 大课
13 计算机网络 孙老师 C208 周五 第5节 粉 #EC4899 1-12 实验课
14 软件工程 吴教授 C109 周六 第1节 橙红 #F97316 1-16 小组项目

设计要点

  • 坐标分布:周一 4 门(2 节连堂 × 2)、周二 3 门(1 连堂 + 1 单节)、周三 2 门(1 连堂)、周四 2 门(1 连堂)、周五 2 门(单节 × 2)、周六 1 门、周日空——周一最忙、周末递减,符合真实课表;
  • 连堂视觉:高等数学周一 1-2 节同色相邻——课表里并成「蓝色连堂块」;
  • 色板 10 色覆盖:蓝/绿/紫/橙/红/青/黄绿/粉/橙红——每门课可区分;
  • 教学周差异:计算机网络 ‘1-12’(前 12 周上,实验课)——与默认 ‘1-16’ 不同,展示 weeks 字段的意义;
  • 周日空:切到周日 → 8 个格子全空(浅灰占位格)——验证空位渲染。

三、代码实现

const seed: CourseSeed[] = [ /* 14 门,见第二节表格 */ ];
for (const s of seed) {
  const values: relationalStore.ValuesBucket = {
    name: s.name, teacher: s.teacher, location: s.location,
    weekday: s.weekday, section: s.section, color: s.color,
    weeks: s.weeks, remark: s.remark,
  };
  await store.insert(CourseDao.TABLE, values);
}
hilog.info(DOMAIN, TAG, '已填充 14 门课程种子数据');

幂等保护:查 course COUNT,非空即返回——重复启动不重复填充。CourseSeed 接口:与 Course 一致(无 id)。

四、注入后的课表效果预测

区块 预期效果
标题栏 「共 14 门课程」
周一 第 1-2 节蓝色「高等数学 王教授 · A101」连堂块 + 第 3-4 节绿色「大学英语」连堂块,其余格空
周二 第 1-2 节紫色「数据结构」连堂 + 第 5 节橙色「体育」
周三 第 3-4 节红色「操作系统」连堂
周四 第 1-2 节青色「大学物理」连堂
周五 第 3 节黄绿「马克思主义原理」+ 第 5 节粉色「计算机网络」
周六 第 1 节橙红「软件工程」
周日 8 个浅灰空位格
当天列表 切周一 → 「周一 · 共 4 节课」+ 4 行明细(节次圆标 + 课程名 + 时间老师教室)

演示脚本:指着课表说「我一周 14 门课,周一最忙——上午两节高数、两节英语,都是连堂」→ 切周二「数据结构连堂加下午体育」→ 切周日「周日没课,格子全空」→ 点周一的蓝色高数块 → 菜单「查看详情」→ 弹窗显示「王教授 · A101 / 周一 第1节 / 08:00-08:45 / 教学周:1-16」。

五、验证方法

  1. hilog 日志:搜 CourseDao,看到「已填充 14 门课程种子数据」;
  2. 页面显示:标题栏「14 门」、周一 4 门、周日全空、当天列表正确;
  3. 数据库直查
    SELECT COUNT(*) FROM course;  -- 14
    SELECT weekday, COUNT(*) FROM course GROUP BY weekday ORDER BY weekday;
    -- 1:4 2:3 3:2 4:2 5:2 6:1 7:0
    SELECT name, weekday, section FROM course WHERE weekday = 1 ORDER BY section;
    -- 高等数学 1,2 / 大学英语 3,4
    SELECT * FROM course WHERE weekday = 1 AND section = 3;  -- 大学英语(冲突检测命中)
    
  4. 交互验证:切周日看空位格、点色块看详情菜单、删除课程后格子变空、添加课程冲突提示。

六、FAQ

Q1:为什么周一最忙(4 门)、周六只有 1 门?
A:真实课表「周一最忙、周末递减」——种子复现典型分布。周一上午两门连堂(高数 + 英语)是常见排课,周六 1 门(软件工程)展示「周六上课」场景。坐标分布模拟真实校园,不是平均撒数据。

Q2:连堂为什么是两条记录而不是「起止节次」字段?
A:两条记录让「格子填充」最简单——每节次查格子,有课就显示色块;相邻同色自然连成块。若用「起止节次」字段(section_start + section_end),查询要处理区间匹配(section BETWEEN start AND end),网格渲染更复杂。「逐格记录」换取「逐格渲染」的简单

Q3:为什么周日不排课?
A:周日是休息日——8 个空位格验证「空节次占位渲染」(浅灰块)。种子要覆盖「有课」与「无课」两种状态,空位渲染是课表网格的重要视觉(否则无法区分「没课」与「加载失败」)。

Q4:计算机网络为什么教学周是 1-12?
A:真实教务里实验课只上部分周(前 12 周)——weeks: '1-12' 展示教学周字段的多样性。Demo 不解析(纯展示),进阶可在课程详情里「本周是否上课」判断(解析 ‘1-12’ 区间)。字段先存、解析后做

Q5:为什么 5 门课带备注?
A:备注(带教材/听力练习/穿运动服/期中考试/带计算器/实验课/大课/小组项目)是真实课表的信息(提醒带什么、考试预警)。备注让课表「有人味」——不是干巴巴的课名。

Q6:色板 10 色只用了 9 色,够吗?
A:14 门课 9 种颜色(两门连堂同色)——每门课颜色可区分(同课连堂同色)。色板 10 色留 1 余量,新增课程有颜色可选。「色块区分课程」的前提是颜色不重复,连堂同色恰好利用了这个特性。

七、文章小结

本篇文章展示了实例 15 的种子数据:14 门课程(周一最忙 4 门 → 周六 1 门 → 周日空的坐标分布 + 5 组连堂 + 9 色覆盖 + 教学周差异 + 备注)。核心是「课表感的种子设计」——连堂相邻成块、周日空位验证占位渲染、计算机网络 1-12 周展示字段多样性。课表网格一开屏就格子饱满、色块分明。

下一篇(15-5)是实例 15 的收官文章,展示 CoursePage 全量代码与运行效果。

八、种子数据全量表:时间列补全与逐条核对

第二节的表格缺「时间段」列——课表格子显示节次序号,但详情弹窗要展示起止时间。按「单节 45 分钟、课间 10 分钟、午休 12:00-14:00」的校园作息补全:

# 课程 老师 教室 周几 节次 时间段 颜色 教学周 备注
1 高等数学 王教授 A101 周一 第1节 08:00-08:45 蓝 #3B82F6 1-16 带教材
2 高等数学 王教授 A101 周一 第2节 08:55-09:40 蓝 #3B82F6 1-16 (连堂)
3 大学英语 李老师 B203 周一 第3节 10:00-10:45 绿 #10B981 1-16 听力练习
4 大学英语 李老师 B203 周一 第4节 10:55-11:40 绿 #10B981 1-16 (连堂)
5 数据结构 陈教授 C305 周二 第1节 08:00-08:45 紫 #8B5CF6 1-16 带电脑
6 数据结构 陈教授 C305 周二 第2节 08:55-09:40 紫 #8B5CF6 1-16 (连堂)
7 体育 张教练 操场 周二 第5节 14:00-14:45 橙 #F59E0B 1-16 穿运动服
8 操作系统 刘教授 C401 周三 第3节 10:00-10:45 红 #EF4444 1-16 期中考试
9 操作系统 刘教授 C401 周三 第4节 10:55-11:40 红 #EF4444 1-16 (连堂)
10 大学物理 赵教授 A305 周四 第1节 08:00-08:45 青 #06B6D4 1-16 带计算器
11 大学物理 赵教授 A305 周四 第2节 08:55-09:40 青 #06B6D4 1-16 (连堂)
12 马克思主义原理 周老师 D102 周五 第3节 10:00-10:45 黄绿 #84CC16 1-16 大课
13 计算机网络 孙老师 C208 周五 第5节 14:00-14:45 粉 #EC4899 1-12 实验课
14 软件工程 吴教授 C109 周六 第1节 08:00-08:45 橙红 #F97316 1-16 小组项目

时间映射规则:第 1/3/5/7 节整点开始(08:00 / 10:00 / 14:00 / 16:00),单节 45 分钟、课间 10 分钟,第 5 节从 14:00 起(午休两小时)。种子只存「节次序号」,时间段由 sectionTime(section) 映射函数生成——作息规则一处定义全局生效,不冗余存时间字段

九、种子设计复盘:三个「课表感」来源

1. 分布复盘:周一最忙 → 周日空

周几 课程数 占比 视觉
周一 4 28.6% 上午两连堂,饱满
周二 3 21.4% 连堂 + 下午体育
周三 2 14.3% 一个连堂
周四 2 14.3% 一个连堂
周五 2 14.3% 两个单节
周六 1 7.1% 单节点缀
周日 0 0% 全空

课程数从周一 4 门单调递减到周日 0 门——真实课表「前紧后松」的曲线。为什么刻意这样分布?冲突检测、当天列表、空位渲染三个功能都需要「有课的日子 + 没课的日子」同时存在才能演示;若平均撒数据(每天 2 门),「周日全空」「周一最忙」的视觉差异就消失了,课表感大打折扣。

2. 连堂视觉复盘:同色相邻自然成块

高等数学两节同为蓝 #3B82F6、大学英语两节同为绿 #10B981——网格中两格同色相邻,人眼自动把「周一 1-2 节」合并成一块蓝色、「3-4 节」合并成一块绿色。连堂视觉靠「同课同色 + 坐标相邻」两个条件自然形成,零合并逻辑:color 相同且 section 相差 1 即视觉连堂,不需要额外的「连堂标记」字段——种子设计替渲染层省掉了合并算法。

3. 教学周差异复盘:‘1-16’ 与 ‘1-12’ 并存

14 门课中 13 门 weeks=‘1-16’(全学期),只有计算机网络 weeks=‘1-12’(实验课前 12 周)——字段多样性体现在同一字段的不同取值,而非新增字段。Demo 阶段 weeks 只存不解析,网格渲染不判断「本周是否上课」;进阶做周视图时再解析区间(parseWeeks('1-12') 判断当前周命中)。这是「先存数据、后做语义」的种子设计原则——数据层先把多样性存下来,语义留给后续功能演进。

十、initSeedData 完整实现

interface CourseSeed {
  name: string; teacher: string; location: string;
  weekday: number; section: number; color: string;
  weeks: string; remark: string;
}

static async initSeedData(context: common.Context): Promise<void> {
  const store = await CourseDao.getStore(context);
  const count = await CourseDao.count(context);  // 幂等保护:已有数据不重复填充
  if (count > 0) {
    hilog.info(DOMAIN, TAG, '已有 %{public}d 门课程,跳过种子填充', count);
    return;
  }
  const seed: CourseSeed[] = [
    { name: '高等数学', teacher: '王教授', location: 'A101', weekday: 1, section: 1, color: '#3B82F6', weeks: '1-16', remark: '带教材' },
    { name: '高等数学', teacher: '王教授', location: 'A101', weekday: 1, section: 2, color: '#3B82F6', weeks: '1-16', remark: '(连堂)' },
    // … 其余 12 条与第八节表格逐条对应,字段结构同上
  ];
  for (const s of seed) {
    const values: relationalStore.ValuesBucket = {
      name: s.name, teacher: s.teacher, location: s.location,
      weekday: s.weekday, section: s.section, color: s.color,
      weeks: s.weeks, remark: s.remark,
    };
    await store.insert(CourseDao.TABLE, values);
  }
  hilog.info(DOMAIN, TAG, '已填充 14 门课程种子数据');
}

三个关键点:①count > 0 提前 return——页面重复进入、应用重启都不会产生重复课程,幂等是种子数据的底线;②CourseSeed 无 id 字段,主键交给数据库自增——种子结构与查询出的 Course 仅差 id 一列;③逐条 insert 而非批量——14 条量级毫秒完成、不需要事务,单条失败可凭 hilog 报错行单独定位。

十一、注入后的课表效果预测

视角 预测效果
网格整体 周一蓝绿两连堂、周二紫连堂 + 橙体育、周三红连堂、周四青连堂、周五黄绿 + 粉单节、周六橙红孤块、周日 8 个浅灰空位格
标题栏 「共 14 门课程」
当天列表 切周一 → 「周一 · 共 4 节课」+ 4 行明细;切周日 → 空态「今天没课」
冲突检测 新增「周一 第3节」→ 命中大学英语 → 弹「该时段已有课」
周视图(进阶) 第 13 周起计算机网络格子变空(weeks=‘1-12’ 解析生效)

十二、验证 SQL 全集

-- 1) 总数与课程去重
SELECT COUNT(*) FROM course;               -- 14
SELECT COUNT(DISTINCT name) FROM course;   -- 9(14 条记录去重后 9 门课)

-- 2) 每天课程数:验证周一最忙 → 周日空
SELECT weekday, COUNT(*) AS cnt FROM course
GROUP BY weekday ORDER BY weekday;         -- 1:4 2:3 3:2 4:2 5:2 6:1 7:0

-- 3) 连堂校验:同课同天多条
SELECT name, weekday, MIN(section) AS startSection, MAX(section) AS endSection
FROM course GROUP BY name, weekday
HAVING COUNT(*) > 1;                       -- 5 组连堂

-- 4) 教学周差异
SELECT name, weeks FROM course WHERE weeks <> '1-16';  -- 计算机网络 1-12

-- 5) 冲突检测命中(模拟新增「周一 第3节」)
SELECT * FROM course WHERE weekday = 1 AND section = 3;  -- 大学英语

解读GROUP BY weekday 一行看出分布曲线(4→0 递减);HAVING COUNT(*) > 1 把连堂课程找出来(同课同天多条 = 连堂);weeks <> '1-16' 直接暴露教学周差异——三句话对应三个设计目标,验证种子没有「撒偏」。

十三、FAQ 补充

Q7:为什么时间不存字段,要由节次映射?
A:作息表是全局规则(第 1 节 08:00 全课表一致)——存节次序号,sectionTime(section) 一处定义、14 门课共享;若每行存时间字段,改一次作息要 UPDATE 14 行。全局规则抽成函数,不冗余进每行数据

Q8:周日 0 门,当天列表会怎样?
A:切周日 → 当天列表显示空态「周日 · 共 0 节课」+ 空提示文案。种子特意留周日空——空态 UI 和空位格一样需要真实数据触发,不留空就无法演示「没课」的状态。

Q9:为什么逐条 insert 不用事务?
A:14 条全内存数据、insert 毫秒级,失败概率极低;事务用于「多表一致性」,单表种子不值得。若未来种子上百条,再包 beginTransaction() 批量提速。

Q10:计算机网络第 13 周会怎样?
A:Demo 阶段照样显示(weeks 只存不解析);进阶周视图解析 ‘1-12’,第 13 周起该格变空。这就是「字段先存、语义后做」的演进路径——种子数据为未来功能预留了验证样本。

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐