# Worksheet 数据库设计说明 更新日期:2026-10-14。配套 [数据库设计文档](./数据库设计文档.md) 和 [SQL 执行说明](../../apps/server/prisma/sql/README.md)。本文说明已经确认的模型及边界,不表示小程序或业务 API 已完成改造。 ## 1. 需求与选择 现有小程序的 worksheet 对应一个可打印功能,多次生成可以得到不同结果。未来涂色、剪纸等功能复用同一种绘制方法,但需要选择不同底图;一份内容还可能包含多个 SVG 或图片,例如“小猫涂色”需要线框与彩色参考图,并有用于内容列表的效果预览。 只在 worksheets 放单个 asset_id 无法表达多份内容及每份内容的多个输入。固定 outline_asset_id/reference_asset_id 能满足一对文件,却无法容纳多个同用途文件。完整 template 模型又容易提前引入独立布局、组合引擎、版本编辑等尚无明确需求的能力。 因此采用 worksheet → 完整内容资源 → 文件关联 → assets。资源条目只管理标题、预览、发布状态和少量参数差异;文件关联只管理用途和顺序,不建设通用模板系统。四张表不要求四套后台页面,一个内容编辑表单即可维护全部关系。 ## 2. 各层职责 | 层级 | 表 | 职责 | | -------- | ------------------------- | ------------------------------------------------------------------------ | | 功能 | worksheets | 功能身份、分类、收藏和统计;生成方式、绘制实现、共用参数、入口封面 | | 内容 | worksheet_resources | 用户可选择的完整内容,例如“小猫涂色”;标题、内容预览、状态及轻量参数覆盖 | | 文件输入 | worksheet_resource_assets | 内容需要哪些文件;outline/reference 用途及同用途处理顺序 | | 文件 | assets | 七牛或已核实 HTTPS 文件的稳定引用、格式、大小、校验摘要及状态 | ```mermaid erDiagram worksheets ||--o{ worksheet_resources : "一个功能有多份内容" worksheet_resources ||--o{ worksheet_resource_assets : "一份内容有多个文件" assets ||--o{ worksheet_resource_assets : "文件可重复利用" assets ||--o{ worksheet_resources : "内容预览" assets ||--o{ worksheets : "功能封面" ``` 基础 SVG、图片及较大的路径 JSON 放七牛,数据库不存临时签名 URL。参数 JSON 只保存小型、经过校验的配置,不存绘制代码。 ## 3. worksheet ID 与 renderer 的分工 现有 [数学注册表](../../../doodle-mini/miniprogram/mathPages/mathDraw/registry.ts) 已将 addition-5、addition-10 等业务 ID 映射到同一 addition 实现及不同模式,说明功能身份与绘制实现并非一一对应。 | 标识或配置 | 作用 | | --------------------- | --------------------------------------------------------------------- | | worksheet.id | 稳定业务入口,用于路由、收藏、分享、统计及资源归属 | | renderer_key | 从客户端已注册实现中选择绘制方法;多个 worksheet 可共用,不设唯一约束 | | generation_mode | procedural 算法生成;resource 由完整内容资源驱动,不是“是否随机” | | render_config | 同一功能共用参数和默认模式 | | worksheet_resource.id | 用户本次选中的具体内容 | | config_override | 内容与共用参数的少量差异,可空 | 调用顺序:通过 worksheetId 获取配置 → 选择 renderer → 根据需要选择内容 → 解析文件引用 → 绘制。仍由客户端执行绘制;增加新 renderer 需要发布客户端代码,数据库配置不能凭空增加算法。 保留原 path?id=worksheetId、旧 ID 和分享路径。renderer_key 允许 NULL 仅为了兼容已登记的旧映射;新功能发布必须设置已支持标识。未知标识或缺少必须文件时返回明确错误,不默认绘制为另一个功能。 ## 4. 预览与多文件示例 ```text worksheet:动物涂色 renderer_key:coloring generation_mode:resource render_config:统一纸张尺寸、边距 preview_asset_id:功能入口封面 worksheet_resource:小猫 preview_asset_id:小猫列表效果图 config_override:无 文件关联: outline / 0:小猫线框 SVG outline / 1:补充线框 SVG(绘制实现支持时) reference / 0:小猫彩色参考 PNG ``` - 功能封面用于首页和分类入口,保持原 previewImg 契约。 - 内容预览用于内容选择列表,每条内容各有 previewImg;通过分页接口返回,不把所有预览塞进 worksheet 详情。 - reference 用于绘制页面的对照展示;outline 是实际线框输入。参考图是否打印由 renderer 决定,不因关联就自动加入打印结果。 - 三种用途可以引用同一资产,也可以使用独立文件;资产去重不等于业务内容合并。 - 关联文件默认共同服务一份内容,不是随机候选池;随机选“小猫或恐龙”应选择内容条目。素材池抽取是另一种明确规则。 assets.purpose 描述文件管理用途,新增 worksheet_source;role 描述文件在该内容中的用法,仅支持 outline/reference。参考图可复用 preview 文件,SVG/PNG/JSON 格式由文件元数据和 renderer 校验,不作为 role。 ## 5. 轻量配置、发布和权限 参数顺序是 renderer 默认值 → worksheet 共用参数 → 内容覆盖 → 允许的用户参数。首期采用按 renderer 定义的顶层参数覆盖,仅允许边距、缩放方式等明确字段;不支持任意 JSON 深度合并、脚本或文件级配置。 同用途文件按 sort_order、id 稳定排序;顺序不是通用图层 z-index。数量、排布及格式要求由 renderer 定义,不在数据库中新增绘制需求规则表。 管理员维护内容及关联;普通用户只能读取已发布功能下的已发布内容。发布需校验 renderer 支持、必须文件及其数量、资源 ready 状态、格式、参数范围和访问策略。SQL 外键只保证引用存在,不能替代发布状态或文件真实存在的检查。私有资源按策略生成访问地址,不暴露七牛密钥。 首期仅上下架,不硬删除功能或内容。关联采用 RESTRICT,删除共享资产前核对所有封面、内容预览、文件关联及其他引用;软删除同样须由服务检查。发布/修改/关联及管理审计使用同一事务,不在事务内等待七牛上传。内容及文件关联修改由服务同时维护资源 updated_at、父功能 content_updated_at/updated_at,不增加通用更新时间触发器。 ## 6. 收藏、下载与旧数据 favorites 统一保存功能和具体内容收藏:worksheet_resource_id 为 NULL 表示功能,非 NULL 表示“小猫涂色”等完整内容,不直接收藏单个 asset。两种部分唯一索引分别去重;同用户可同时收藏功能及其中多个资源,不自动联动,不新增 resource_favorites 表。旧查询/数量/取消必须限定 NULL,内容查询和取消显式按资源目标。仅功能收藏增减 worksheets.likes,内容收藏不新增资源 likes。下载增加可空 worksheet_resource_id,记录选择的完整内容,而不是只记录其中一个文件。资源驱动的新下载要求资源 ID,校验归属及发布状态;算法生成和旧历史允许为空。相同 exportId 的重试同时核对功能和内容 ID,保持事件一致性。 下载同时维护功能与有明确归属的内容累计计数,只有新日志成功插入时同事务各加一次,失败全部回滚,重复 exportId 不加数。功能旧累计值不分摊资源,资源计数不与功能计数相加;个人注销删日志不回减任一层累计量。不增加资源收藏计数或 seed。资源 ID 是逻辑关联,缺失或隐藏的历史内容不导致整条记录丢失,也不泄露未发布详情。这个 ID 只表示选择过什么内容,不保证精确复现原打印结果;未来确需复现时另行设计选中素材、参数、随机种子及不可变版本快照。 增量升级保留旧 worksheet ID/path、预览、计数和历史,添加 procedural 默认值、NULL renderer_key、空共用配置;新内容表为空。导入按实际实现核对模式与映射,不从题型 ID 猜 renderer,不把旧预览图自动当作线框。新空库用最新 002/003;旧库依次使用未执行的 004/005/006/007/008,不重跑建表基线。Prisma 迁移历史接入时需登记对应结构版本。 ## 7. 覆盖范围与后续扩展 | 场景 | 当前模型 | | ------------------------------------- | ------------------------------------------------------ | | 线框配参考图、独立列表预览 | 直接支持 | | 多个同用途 SVG、资源文件共享 | 数据模型支持;客户端 renderer 须实现处理规则 | | 同一绘制实现用于不同功能和内容 | 直接支持 | | 部分内容调整少量绘制参数 | config_override 白名单覆盖 | | 多页内容、每页不同文件布局 | 尚未表达页归属;真实需要时增加页结构 | | 背景、装饰图层、单文件位置/透明度配置 | 首期不开放;同步扩展角色及 renderer 后再设计文件级配置 | | 素材池随机组合 | 首期不把关联解释为候选池,后续明确选取协议 | | 下载历史精确重现、版本编辑及回滚 | 当前不承诺;后续设计不可变内容版本与生成快照 | 当前只落实已经确定的身份、完整内容、文件用途、独立预览和少量配置差异,保留扩展点,但不预先建设模板引擎、通用图层系统或版本平台。 ## 8. 内容分类与适用年级 categories 保持内容分类;worksheet_grades 用两列联合主键表达功能适用于哪些年级,支持多个及不连续年级。Web 年级菜单再按分类筛选,是两个维度的组合查询,不复制分类树。年级名称和排序暂用固定配置,不新增年级字典表。 旧 worksheets.grade 保留兼容,但其值可能由年龄区间推算,不能成为适用范围的唯一依据。006 仅建空关系表,不自动回填。经管理员审核后写入完整 grades,新筛选以关系表为准;空关系表示未配置,不表示全年级,0 表示幼小衔接。使用 EXISTS 查询防止多选年级导致重复结果。 资源条目暂继承功能适用年级;若同功能下内容难度跨年级明显不同,当前模型不提供资源级年级过滤,须先明确产品规则再扩展。年级与年龄独立维护,不根据年龄自动生成关系。详见数据库设计文档 4.6 节。 ## 9. 功能与资源的新鲜度、热度和下载 功能早已固定不代表内容停止更新。功能和内容各增加可空 first_published_at,分别表达首次公开发布时间。新 isNew 按统一新品时间窗口派生,不新增资源布尔新品字段;草稿创建时间、参数更新时间、新增资源或重新上架时间不能替代首次发布时间。未知旧时间不回填为 now()/created_at,也不在重发时伪装新品。 worksheet.is_new 暂保留兼容:新接口以时间派生为准,旧接口仅在历史发布时间未知时可临时沿用原标记。worksheet.is_hot 定义为功能级人工运营推荐,与下载排行榜独立,不自动赋给资源。资源首期按真实 downloads 排名,不新增人工热门标记;若运营明确需要资源推荐,再扩展。 007 给内容条目增加 downloads,默认 0、非负,与 worksheet 总下载量分别维护。成功保存完整“小猫”内容一次:新增一条 download_logs,功能 +1,小猫 +1;关联两张 SVG 不代表下载两次。算法生成或旧事件无可信内容 ID,只更新功能;不能从资源文件访问次数推断打印成功。 事务按用户 → 功能 → 内容加锁,检查归属和发布状态,只有首次插入日志才加数;同一 exportId 的功能/内容 ID 不一致报冲突。失败回滚两层计数。正常下载仅更新业务时间,不更新内容/首次发布时间。功能历史基数和 seed 保留,不平均分配资源、不要求功能总量等于资源之和;删除个人日志不扣累计下载。 当前表结构支持这套规则,具体发布时间设置、isNew 派生、计数事务及兼容 DTO 后续由服务端实现;本次没有改变小程序现有显示逻辑。 ## 10. 收藏具体底图的兼容调整 008 给统一 favorites 增加可空内容 ID,并将原 userId+worksheetId 全局唯一约束改为两个部分唯一索引。旧收藏保留原 ID、时间、归属且新列为 NULL,不猜测具体底图。新资源收藏的 worksheetId 从服务端读取,关系插入时重新核对父功能、内容发布状态及归属。 列表默认仅功能,资源/all 通过显式 target 选择;返回目标类型及资源独立预览。取消精确定位收藏记录或资源 ID,旧按功能取消不得删除内容收藏。资源缺失或下架只使详情不可用,内容 ID 不清空,仍可取消。注销清理两种收藏,仅功能关系贡献影响功能 likes。 数据库不强制资源外键以保留历史,发布内容不允许重新归属另一 worksheet。需要收藏某次算法生成结果、保存用户涂色进度或精确结果快照时另行设计;当前资源收藏只表示选中的完整底图内容。