- 重构版主提示词(14 parts,面向 ClassHelper 灵动岛重构) - ClassIsland 全量规格提示词(20 parts,含分卷与逐章版本) - 投喂指南、分卷、逐节文件 - 调研记录、一致性基线、生成与质检脚本
27 KiB
15. 资源清单(图标 / 字体 / 音效 / 天气图标 / 教程 / 本地化)
本节要求实现者按清单准备并放置资源,不得缺项、不得自行替换为网络图片。所有路径均以 ClassIsland 仓库为参照;实现时统一放到 packages/desktop-client/src/renderer/assets/(渲染进程资源)与 packages/desktop-client/resources/(打包资源)两处,并通过构建脚本生成多尺寸产物(见 15.9)。
15.1 应用图标
15.1.1 主图标(多尺寸 PNG)
| 文件 | 尺寸 | 用途 | 证据 |
|---|---|---|---|
Assets/AppLogo.png |
192×192 | 应用内窗口图标、关于页、欢迎页 Logo | ClassIsland/Assets/AppLogo.png;App.axaml:29-31;WelcomePage.axaml:29-33 |
Assets/AppLogo@48w.png |
48×48 | 小尺寸(任务栏/列表) | 实测文件头 |
Assets/AppLogo@384w.png |
384×384 | 中尺寸(设置页/关于页展示) | 实测文件头 |
Assets/AppLogo@768w.png |
768×768 | 大尺寸(高分屏) | 实测文件头 |
Assets/AppLogo_Fade.png |
192×193 | 淡入用的半透明 Logo(启动/遮罩) | 实测文件头 |
Assets/AppLogo_Monochrome.png |
2715×2003 | 单色 Logo(水印/背景纹样) | 实测文件头 |
Assets/AppLogo_AppLogo.svg |
矢量 | 可缩放图标源 | 文件名 |
Assets/AppLogo.ico |
多尺寸 ICO:16/24/32/48/64/256×2 | Windows 可执行文件图标 | 解析 ICO 头得 7 个条目 |
Assets/FreedesktopIcons/AppLogo@128w.png |
128×128 | Linux Freedesktop 图标 | 实测文件头 |
AppLogo@32w.png(ClassIsland.Desktop/Assets/) |
32×32 | Windows 任务栏/托盘小图标 | 实测文件头 |
15.1.2 macOS 图标集(ClassIsland.Desktop/Assets/AppLogo.xcassets/AppIcon.appiconset/)
必须提供:16×16(1x/2x)、32×32(1x/2x)、128×128(1x/2x)、256×256(1x/2x)、512×512(1x/2x)、以及无后缀的 192/384/768 三档。实测目录内共 16 个 PNG,命名遵循 AppLogo_<尺寸>_<倍率>.png 与 AppLogo@<宽>w.png 两种规则,实现时按 electron-builder 的 icon.icns 要求重新生成即可,但必须保留这两个命名族以免资源引用失效。
15.1.3 Windows 打包瓦片(ClassIsland.Packaging/Images/)
| 资源 | 尺寸(100%/200%/400%) | 用途 |
|---|---|---|
Square44x44Logo |
44 / 88 / 176 | 开始菜单小图标 |
Square44x44Logo.targetsize-16/24/48/256 |
16/24/48/256 | 任务栏/Alt-Tab 变体 |
Square150x150Logo |
150 / 300 / 600 | 开始菜单中等图标 |
Wide310x150Logo |
310×150 / 620×300 / 1240×600 | 宽幅磁贴 |
LargeTile |
310 / 620 / 1240 | 大磁贴 |
SmallTile |
71 / 142 / 284 | 小磁贴 |
StoreLogo |
50 / 100 / 200 | 商店图标 |
SplashScreen |
620×300 / 1240×600 / 2480×1200 | 系统级启动图(与自绘闪屏无关) |
LockScreenLogo |
48×48 | 锁屏 |
(以上均为实测文件头尺寸;ClassIsland/Images/ 下另有一份 .scale-200 版本,实现时只保留打包用的那份即可。)
15.1.4 其他图标
| 资源 | 尺寸 | 用途 |
|---|---|---|
Assets/Marketplace/Logo.png |
512×512 | 插件/主题市场 Logo |
Assets/Marketplace/Logo@256w/128w/64w.png |
256/128/64 | 市场图标多尺寸 |
Assets/Marketplace/Logo.svg |
矢量 | 市场矢量源 |
ClassIsland.ExamplePlugin/icon.png |
510×510 | 示例插件图标(插件必须自带 510×510 图标) |
ClassIsland.Launcher/Assets/AppLogo.ico |
18 条目 ICO(16–256) | 启动器图标 |
验收要求:所有图标必须本地打包、离线可用;PNG 必须由同一矢量源派生,不得出现「不同尺寸风格不一致」;ICO 必须内嵌 16/24/32/48/64/256 六档。
15.2 字体
15.2.1 正文/界面字体:HarmonyOS Sans SC
| 文件 | 字重 | 用途 | 证据 |
|---|---|---|---|
Assets/Fonts/HarmonyOS_Sans_SC_Light.ttf |
300 | 轻量标题/水印 | 文件名 |
Assets/Fonts/HarmonyOS_Sans_SC_Regular.ttf |
400 | 正文 | 文件名 |
Assets/Fonts/HarmonyOS_Sans_SC_Medium.ttf |
500 | 默认字重(岛内主文字) | Settings.cs:101 |
Assets/Fonts/HarmonyOS_Sans_SC_Bold.ttf |
700 | 标题/强调 | 文件名 |
- 字体族注册名:
HarmonyOS Sans SC;全局资源键AppFont,字体栈见 part 03 §3.2.1(Assets/Fonts/Fonts.axaml:3;Assets/Fonts/Fonts.xaml:3)。 - 许可:
Assets/Fonts/LICENSE.txt为「HarmonyOS Sans Fonts License Agreement」,版权归华为;分发时必须原样保留该许可文件,且不得单独售卖字体。应用本体为 GPL-3.0(LICENSE.txt),字体许可与代码许可分离。 - 实现要求:把 4 个 ttf 放进 Electron 打包资源,
@font-face声明 4 个font-weight,font-display: swap;禁止声明font-display: block(会白屏到字体加载完)。
15.2.2 图标字体(三套,必须全部内置)
| 字体 | 文件 | 大小 | 附带映射 | 用途 | 证据 |
|---|---|---|---|---|---|
| Fluent System Icons | ClassIsland.Core/Assets/Fonts/FluentSystemIcons-Resizable.ttf |
1,472,748 B | FluentSystemIcons-Resizable.json(262,830 B) |
全局 UI 图标(Segoe Fluent 风格) | AppBase.cs:142;ThemeBase.axaml:46 |
| Lucide | ClassIsland.Core/Assets/Fonts/lucide.ttf |
715,192 B | lucide.json(45,030 B) |
天气图标(默认)、部分 UI 图标 | AppBase.cs:147;ThemeBase.axaml:47 |
| SF Symbols | ClassIsland.Core/Assets/Fonts/SF-Symbols.ttf |
174,616 B | — | 天气图标(Apple 风格) | AppBase.cs:152 |
- 字体族名分别为
FluentSystemIcons-Resizable、lucide、SF-Symbols;Avalonia 资源 URI 形如avares://ClassIsland.Core/Assets/Fonts/#lucide,Web 实现改为@font-face { font-family:'lucide'; src:url('lucide.ttf') }并保留同名font-family。 - JSON 映射文件必须作为图标选择器数据源(Codepoint/名称表),不得只带 ttf 不带 json——图标选择器需要按名称搜索。
- 许可:应用整体 GPL-3.0;Fluent System Icons 与 Lucide 通常为 MIT/ISC【推断:仓库内未放独立许可文件,按上游项目许可执行】;SF Symbols 字体来自 Apple 符号集,仅允许在 Apple 平台或已获授权场景使用,跨平台分发时须评估并在「关于/许可」页声明。
15.2.3 字体相关的硬性要求
- 字体必须在应用启动首帧前注册完成(
document.fonts.ready前不得渲染最终布局,可用font-display: swap+ 骨架屏规避跳动)。 - 不得使用系统缺失字体作为唯一来源;
HarmonyOS Sans SC必须随包分发。 - 用户自定义字体(
MainWindowFont)只允许从系统已安装字体中选择(源码AppearanceSettingsPage.axaml:409-446枚举系统字体),实现时用queryLocalFonts()(需权限)或主进程枚举字体列表,二者都不可用时至少提供内置 4 字重 + 3 图标字体。 - 字体文件不得被 CSP 阻止:
font-src 'self'必须放行本地资源。
15.3 音效
| 资源 | 大小 | 用途 | 默认设置 | 证据 |
|---|---|---|---|---|
Assets/Media/Notification/1.wav |
130,012 B | 提醒音效(唯一内置音效) | IsNotificationSoundEnabled=true;NotificationSoundPath=""(表示使用内置音效);NotificationSoundVolume=1.0 |
实测文件;Settings.cs:144-145,1584-1593 |
| 自定义音效 | 用户文件 | 用户可指定本地音频路径 | 支持 wav/mp3 等系统可解码格式【推断】 | Settings.cs:1496-1505 |
| 语音合成 | 系统/Edge TTS | 提醒朗读 | IsSpeechEnabled=true;SpeechVolume=1.0;SpeechSource=0;Edge TTS 默认音色 zh-CN-XiaoxiaoNeural |
Settings.cs:135-139,1406-1428,1452-1461 |
实现要求:
- 音频必须用
HTMLAudioElement或 Web Audio 播放,不得在主进程用系统播放器;播放前需用户手势解锁(Electron 可用webPreferences.autoplayPolicy: 'no-user-gesture-required',但必须在配置中显式声明)。 - 音量 =
NotificationSoundVolume × 系统音量,范围 0–1;语音音量独立(SpeechVolume)。 - 同一条提醒只播一次音效(源码用
MaskSession.HasSoundsPlayed去重,MainWindowLine.cs:746-751);提醒队列切换时不得重复触发。 - 语音提供方必须可插拔:系统语音(Windows SAPI)、Edge TTS、GPT-SoVITS 三选一(
App.Services.xaml.cs:281-285注册三个 provider),默认走系统语音或 Edge TTS,且必须支持「无网络时降级到系统语音」。 - 内置音效 1.wav 必须打包进
resources/audio/,不得 CDN 引用。
15.4 天气图标(4 套模板)
15.4.1 模板注册表
| 模板 id | 显示名 | 默认 | 实现方式 | 尺寸参数 | 证据 |
|---|---|---|---|---|---|
classisland.weatherIcons.lucide |
Lucide(默认) | ✅ WeatherIconId="classisland.weatherIcons.lucide" |
Viewbox + LucideIcon |
16×16,FontSize 16,Margin 1 | App.Services.xaml.cs:287;Settings.cs:2106;LucideWeatherIconTemplate.axaml |
classisland.weatherIcons.fluentDesign |
Fluent Design | — | Viewbox + FluentIcon |
20×20,FontSize 24,Margin 0 1.2 0 -1.2 |
App.Services.xaml.cs:288;FluentDesignWeatherIconTemplate.axaml |
classisland.weatherIcons.sfSymbols |
SF Symbols | — | Viewbox + SFSymbolsIcon |
16×16 | App.Services.xaml.cs:289;SFSymbolsWeatherIconTemplate.axaml |
classisland.weatherIcons.simpleText |
纯文本 | — | 文本 + 分隔符 ~ |
文本随字号 | App.Services.xaml.cs:290;SimpleTextWeatherIconTemplate.axaml |
实现要求:模板必须可插拔(插件可注册新模板),模板注册信息至少包含 {id, name, renderer};切换模板立即生效且不需要重启(源码 WeatherService.LoadWeatherIconTemplate() 在设置变化时重新取模板,Services/WeatherService.cs:84-90)。
15.4.2 天气代码 → 名称 → 图标(必须完整映射,共 40 个代码)
数据源:小米天气状态表 Assets/XiaomiWeather/xiaomi_weather_status.json;图标映射:ClassIsland/Converters/WeatherConverters.cs。下表前端三列(Fluent/Lucide/SF)为源码私有区码位,后端实现时请原样保留码位,Web 端用 data-icon 名称 + 本地字体渲染。
| code | 天气名 | Fluent 码位 | Lucide 码位 | SF 码位 |
|---|---|---|---|---|
| 0 | 晴 | \uf465 |
\ue2b1 |
\uFE42 |
| 1 | 多云 | \uf44f |
\ue216 |
\uFDC9 |
| 2 | 阴 | \uf43d |
\ue217 |
\uFDF1 |
| 3 | 阵雨 | \uf455 |
\ue2fb |
\uFDE9 |
| 4 | 雷阵雨 | \uf46b |
\ue090 |
\uFDCD |
| 5 | 雷阵雨并伴有冰雹 | \uf46b |
\ue08f |
\uFDDD |
| 6 | 雨夹雪 | \uf459 |
\ue094 |
\uFDD4 |
| 7 | 小雨 | \uf43f |
\ue08e |
\uFDED |
| 8 | 中雨 | \uf453 |
\ue092 |
\uFDE9 |
| 9 | 大雨 | \uf453 |
\ue092 |
\uFDE5 |
| 10 | 暴雨 | \uf453 |
\ue093 |
\uFDE4 |
| 11 | 大暴雨 | \uf453 |
\ue093 |
\uFDE4 |
| 12 | 特大暴雨 | \uf453 |
\ue093 |
\uFDE4 |
| 13 | 阵雪 | \uf45d |
\ue376 |
\uFDD9 |
| 14 | 小雪 | \uf45b |
\ue094 |
\uFDD9 |
| 15 | 中雪 | \uf45b |
\ue094 |
\uFDD9 |
| 16 | 大雪 | \uf45b |
\ue094 |
\uFDD9 |
| 17 | 暴雪 | \uf45b |
\ue094 |
\uFDD9 |
| 18 | 雾 | \uf443 |
\ue214 |
\uFDE1 |
| 19 | 冻雨 | \uf461 |
\ue08f |
\uFDD5 |
| 20 | 沙尘暴 | \uf441 |
\ue218 |
\uFDB1 |
| 21 | 小雨-中雨 | \uf453 |
\ue092 |
\uFDED |
| 22 | 中雨-大雨 | \uf453 |
\ue092 |
\uFDE9 |
| 23 | 大雨-暴雨 | \uf453 |
\ue093 |
\uFDE5 |
| 24 | 暴雨-大暴雨 | \uf453 |
\ue093 |
\uFDE5 |
| 25 | 大暴雨-特大暴雨 | \uf453 |
\ue093 |
\uFDE5 |
| 26 | 小雪-中雪 | \uf45b |
\ue094 |
\uFDD9 |
| 27 | 中雪-大雪 | \uf45b |
\ue094 |
\uFDD9 |
| 28 | 大雪-暴雪 | \uf45b |
\ue094 |
\uFDD9 |
| 29 | 浮尘 | \uf449 |
\ue0f4 |
\uFE2E |
| 30 | 扬沙 | \uf441 |
\ue0f4 |
\uFE2E |
| 31 | 强沙尘暴 | \uf441 |
\ue218 |
\uFE2E |
| 32 | 飑 | \uf463 |
\ue093 |
\uFDAD |
| 33 | 龙卷风 | \uf463 |
\ue218 |
\uFDA3 |
| 34 | 弱高吹雪 | \uf45b |
\ue094 |
\uFDD9 |
| 35 | 轻雾 | \uf443 |
\ue214 |
\uFDE1 |
| 53 | 霾 | \uf449 |
\ue0f4 |
\uFDE1 |
| 301 | 雨 | \uf453 |
\ue092 |
\uFDE9 |
| 302 | 雪 | \uf45b |
\ue094 |
\uFDD9 |
| 99 及未知 | 未知 | \uee31 |
\ue091 |
\uFD8C |
实现硬要求:
- 未知代码必须回落到「未知」图标,不得抛异常或显示空白。
- 纯文本模板必须实现「今天~明天」的
~分隔符逻辑(模板内Separator仅在To场景可见,SimpleTextWeatherIconTemplate.axaml),且文本颜色跟随--ci-text-*。 - 天气图标颜色:晴天/温度等常规图标用前景色;雨天图标可选用
--ci-weather-rain(亮#0000FF/ 暗#00BFFF),见 part 03。
15.5 贴纸资源(HoYoStickers)
Assets/HoYoStickers/ 内共 22 个 PNG,按「角色_动作」命名,用于教程/提醒的图标表达式 sticker(名字)(App.axaml.cs:253 注册 IconExpressionHelper 的 sticker 处理器)。实现时必须支持 sticker(帕姆_嗨) 这种写法并渲染对应 PNG。
| 角色 | 尺寸 | 文件(动作) |
|---|---|---|
| 光辉矢愿 | 162×162(6 个) | 不可以看、回眸、小喇叭、想我了吗、瞄准、遨游 |
| 帕姆 | 510×510(5 个)/450×450(1 个) | 不可以、哭哭、嗨(450)、注意、点赞、震惊 |
| 昔涟 | 510×510(4 个) | 回眸、守护、收到、爱 |
| 白厄 | 510×510(6 个) | 再见、我吗、战斗、掉线、没事 |
实现要求:贴纸必须按原始比例缩放(object-fit: contain),不得拉伸;建议在 UI 中统一缩放到 96×96 或 128×128,并保留 image-rendering: -webkit-optimize-contrast 以求清晰。图标表达式解析器必须支持 fluent(码位)、lucide(码位)、sfsymbols(码位)、bitmap(路径)、sticker(名字) 五种前缀(App.axaml.cs:250-260),未知前缀回落为文本。
15.6 教程资源
15.6.1 教程定义文件(JSON)
内置教程组:Assets/Tutorials/classisland.getStarted.json(另有 classisland.sp.json、classisland.test.json 仅作开发样例,不要在正式版启用)。数据结构(逐字段实现):
| 层级 | 字段 | 类型 | 说明 |
|---|---|---|---|
| 顶层 | Id |
string | 教程组 id,如 classisland.getStarted |
| 顶层 | Title / Description |
string | 组标题/描述(中文) |
| 顶层 | Tutorials |
array | 教程条目列表 |
| 教程 | Id / Title / Description |
string | 教程 id/标题/描述 |
| 教程 | ActualBanner / Banner |
string | Banner 资源 URI(avares://) |
| 教程 | Ordinary |
int | 是否为普通教程(0/1) |
| 教程 | Paragraphs |
array | 段落列表 |
| 段落 | Id / Title / Description |
string | 段落标识/标题/描述 |
| 段落 | TopLevelClassName |
string | 目标窗口类名(如 ClassIsland.MainWindow) |
| 段落 | IsBarrierEnabled |
bool | 是否启用教程遮罩屏障 |
| 段落 | InitializeActions |
array | 进入段落时执行的行动 |
| 段落 | Content |
array | 每屏内容 |
| 内容 | Title / Content |
string | 标题/正文(中文) |
| 内容 | IconExpression |
string | 图标表达式(如 sticker(帕姆_嗨)) |
| 内容 | HeroImage |
string | 大图 URI(可空) |
| 内容 | TargetSelector / PointToTarget / ModalTarget |
string/bool | 指向的目标与是否模态 |
| 内容 | RightButtonText / LeftButtonText |
string | 按钮文案(可空) |
| 内容 | RightButtonActions / LeftButtonActions / InitializeActions |
array | 行动列表,元素为 {Kind:int, StringParameter:string} |
| 内容 | WaitForNextCommand / UseLightDismiss |
bool | 交互策略 |
| 内容 | Tag / Script / Xmlns |
string/object | 扩展位 |
(来源:Assets/Tutorials/classisland.getStarted.json:1-200+。行动 Kind 的具体枚举含义在源码 TutorialActionKind 中定义,实现时必须对照该枚举逐值映射,不得自行编号;本节不臆造枚举值。)
15.6.2 教程图片
| 组/条目 | 文件 | 大小 |
|---|---|---|
| welcome | banner.webp |
42,664 B |
| welcome | mainMenu.webp / openAppSettings.webp / openEditMode.webp / openProfileEditor.webp / openTutorial.webp |
约 25–27 KB/张 |
| componentsEditing | banner.webp / ruleset.webp |
28,292 / 48,738 B |
| profileEditing | banner.webp / 时间表.webp / 科目.webp / 课表.webp / 课表与时间表关系.webp |
25,900–109,912 B |
另有默认图:Assets/DefaultTutorialBanner.webp(10,416 B)、Assets/DefaultTutorialGroupBanner.webp(46,540 B),用作无 Banner 时的兜底。
要求:图片统一用 WebP(保留 .webp 扩展名),懒加载;教程播放时按窗口宽度自适应,不得变形。
15.7 本地化
15.7.1 现状(必须如实实现,不得虚构更多语言)
ClassIsland v2 的本地化是局部的,只覆盖两个命名空间(Assets/Localization/):
| 命名空间 | 资源文件 | 语言 |
|---|---|---|
SettingsPage(设置页) |
Localization.SettingsPage.resx(默认/中文)、.zh-Hans.resx、.zh-Hant.resx、.en.resx |
简体中文、繁体中文、英文 |
SettingsPage/General(常规设置子页) |
同上 4 个 | 同上 |
TrayMenu(托盘菜单) |
同上 4 个 | 同上 |
- 默认语言为中文(
resx无文化后缀文件即默认),并强制Thread.CurrentThread.CurrentUICulture = zh-CN(ClassIsland/App.axaml.cs:512-513)。 - 其余界面文案硬编码中文,没有资源化。因此「支持多语言」不是现状能力。
15.7.2 实现要求(在 Web 栈中的等价方案)
- 必须建立
i18n层(推荐vue-i18n),语言键命名与 resx 的Key保持一致,便于数据迁移。 - 首期必须提供 zh-Hans(默认)、zh-Hant、en 三份文案;其余界面文案随实现逐步资源化,不得伪造「已支持 N 种语言」。
- 语言切换必须持久化到配置,并立即刷新界面(无需重启);日期/时间格式必须跟随语言(
Intl.DateTimeFormat)。 - 本地化文件不得包含 HTML 标签;带占位符的文案必须使用命名参数(
{name}),禁止字符串拼接。 - 字体必须覆盖三语:英文用 HarmonyOS Sans SC 的拉丁字形即可;繁体中文若依赖系统字体兜底,必须在 fallback 栈中显式列出(
PingFang TC、Microsoft JhengHei)。
15.8 其他资源与文档
| 资源 | 用途 | 要求 | 证据 |
|---|---|---|---|
Assets/Documents/ChangeLog.md |
更新日志(关于页展示) | 必须随版本更新,按版本倒序 | 文件名 |
Assets/Documents/Privacy_.md |
隐私政策(关于页展示) | 必须原样保留;含 Sentry/上报说明 | 文件名 |
LICENSE.txt(根、各项目、Assets) |
GPL-3.0 许可证 | 必须随安装包分发 | LICENSE.txt |
Assets/TrustedPublicKeys/ClassIsland.MetadataPublisher.asc |
更新/市场元数据签名公钥 | 必须内置,用于校验更新包 | 文件名 |
Assets/ShortcutTemplates/ClassSwap.url、cn.classisland.app.desktop |
换课/桌面快捷方式模板 | Windows .url 与 Linux .desktop 两套 |
文件名 |
Assets/Highlighting/Lua.xshd |
自动化脚本 Lua 语法高亮定义 | 编辑器必须使用该配色 | 文件名 |
Assets/default-subjects.json |
默认科目表(23 个科目,含固定 GUID:语文/数学/英语/历史/政治/物理/化学/生物/地理/信息技术/体育/自习/通用技术/音乐/美术/选修课/社团/心理/早读/班会/周测 等) | 必须原样内置,GUID 不得重新生成(迁移依赖) | Assets/default-subjects.json |
Assets/AsciiLogo.txt |
ASCII 艺术 Logo(控制台/崩溃页) | 6 行,宽 63 字符 | 文件内容 |
Assets/Tellings.txt |
关于页/加载页随机「一句话」(含彩蛋) | 至少 20 条,需保留「关于页连续点击图标 10 次开调试」等提示 | 文件内容 |
Assets/dependencies.g.json |
NuGet 依赖许可清单(供「许可」页展示) | Web 栈需生成 licenses.json 等价物(npm 依赖 + 字体许可) |
Models/NugetLicenseInfo.cs、Views/WelcomePages/LicensePage.axaml |
Assets/XiaomiWeather/xiaomi_weather_status.json |
天气代码→中文名映射(40 条) | 与 15.4.2 表一致 | 文件内容 |
Assets/BannerMain_App2.png |
2031×600 | 关于页/更新页主视觉 | 实测文件头 |
Assets/Demo_MainMenu.png、Demo_OpenProfileSettingsWindow.png |
1608×878 | 教程/引导演示图 | 实测文件头 |
Assets/ClassIsland.ai |
矢量源文件 | 设计源文件,可不打包 | 文件名 |
Assets/XamlThemePreviews/classisland.fluent.png、classisland.classic.png |
1920×350 | 主题市场预览图(见 part 09) | 实测文件头 |
15.9 ClassHelper 侧资源落点
| 资源类别 | 落点 | 生成/校验方式 |
|---|---|---|
| 应用图标 | build/classhelper.png(源)+ 设计导出的 .ico |
用 pnpm icons 派生其余尺寸(与 ClassHelper 现有约定一致:图标源是 build/classhelper.png 与设计导出的 .ico,pnpm icons 派生其余资源) |
| Web 品牌图 | packages/web-admin/public/logo.png 或站点 /logo.png |
Web 用 /logo.png,客户端用 BRAND_LOGO_URL 常量(避免 file:// 绝对路径问题) |
| 字体 | packages/desktop-client/resources/fonts/ |
4 个 HarmonyOS TTF + 3 个图标 TTF + 2 个 JSON 映射;构建时校验文件存在与哈希 |
| 音效 | packages/desktop-client/resources/audio/1.wav |
校验大小 130,012 B(或替换为等价资源但保持单文件、可循环) |
| 贴纸 | packages/desktop-client/resources/stickers/ |
22 个 PNG,文件名保持中文原名(打包后可用 URL 编码访问) |
| 教程 | packages/desktop-client/resources/tutorials/ |
JSON + WebP;启动时校验 id 唯一 |
| 主题预览 | packages/desktop-client/resources/theme-previews/ |
1920×350 PNG 两张 |
| 许可清单 | packages/desktop-client/resources/licenses.json |
构建时从 package.json/node_modules 生成;必须包含字体与图标字体的许可条目 |
15.10 资源命名、加载与缓存规范
- 命名:图片用
kebab-case或保持中文原名(贴纸、教程图必须保留原名,因为教程 JSON 以名字引用);字体文件名保持上游原名(HarmonyOS_Sans_SC_Medium.ttf),不得改成medium.ttf之类丢失来源信息的名字;音效用1.wav这类稳定短名,便于设置里持久化路径。 - 目录约定:
renderer/assets/{icons,fonts,audio,stickers,tutorials,theme-previews}/,每类一个目录;禁止在组件目录里散落资源文件。 - 加载方式:
- 图标字体、正文 TTF 在应用启动时通过
@font-face预加载(crossorigin同源),并用document.fonts.load()显式触发; - 贴纸/教程图/主题预览图走懒加载(
loading="lazy"+ IntersectionObserver),未加载时显示Shimmer骨架(part 14 D9); - 音效在首次提醒时按需加载并缓存
AudioBuffer,不得每次播放都重新fetch。
- 图标字体、正文 TTF 在应用启动时通过
- 缓存:所有资源 URL 必须带内容哈希(构建期生成
asset-manifest.json),Electron 生产环境用file://+ 哈希避免陈旧缓存;开发环境禁用强缓存。 - 失败降级:图片加载失败必须显示「图裂了」占位(ClassIsland 的行为:
SystemFillColorCriticalBackgroundBrush底 + 提示「喔唷,图裂啦」,StylesBase.axaml:214-223),不得留白或抛错;字体加载失败必须回落系统字体并保持布局不跳变(用font-display: swap+ 固定行高)。 - 安全:禁止加载
http(s)远程图片作为 UI 资源;所有资源必须走打包路径,CSP 中img-src 'self' data:、font-src 'self'、media-src 'self'。 - 引用完整性:构建时扫描 CSS/TS/JSON 中的资源引用,所有引用必须命中
asset-manifest.json;反向扫描资源目录,未被引用的资源要么删除要么登记为「运行时动态加载」白名单。
15.11 资源版本与许可核对
- 「关于」页必须提供「许可」入口,展示:应用许可(GPL-3.0)、字体许可(HarmonyOS Sans License)、图标字体许可(Fluent/Lucide/SF)、贴纸素材来源、第三方依赖(npm 依赖清单)。ClassIsland 用生成文件
dependencies.g.json+LicensePage.axaml展示 NuGet 依赖,Web 实现必须生成等价的licenses.json。 - 每次发版必须核对:新增/替换的资源是否引入新的许可义务;贴纸、Banner、Demo 图是否为项目自有或有授权(HoYoStickers 为《崩坏:星穹铁道》同人素材,仅可作为内置彩蛋、不得用于商业宣传)。
- 版本号变更时必须同步「关于」页的
AppVersionLong展示(源码用编译期常量AppBase.AppVersionLong,Web 端改为读package.json.version)。
补充说明:ClassIsland 的「关于」页还会展示更新日志、隐私政策与致谢名单,这些内容都是随包分发的 Markdown 文档。实现时不得改为在线拉取——教室环境常常断网,关于页必须在离线时完整可读。更新日志与隐私政策的内容以 Assets/Documents/ 下的文件为准,发版时同步更新,不允许只改版本号不改日志。
15.12 验收标准
- 完整性:本节列出的资源 100% 存在于仓库;用脚本比对清单与文件,缺一项即失败(允许同一资源用等价格式替换,但必须在清单中登记变更)。
- 图标:
electron-builder打包后 Windows exe/installer、Linux AppImage、macOS icns 三端图标均正确;ICO 内嵌 6 档尺寸;任务栏/开始菜单/关于页三处图标一致。 - 字体:断网启动,界面仍显示 HarmonyOS Sans SC(非回退字体);图标字体全部可渲染(抽查 Fluent/Lucide/SF 各 3 个码位);
document.fonts.check()对 4 个正文字重与 3 个图标族返回 true。 - 字体许可:安装包内包含
fonts/LICENSE.txt(HarmonyOS 许可)与licenses.json;「关于 → 许可」页可查看并可滚动到底。 - 音效:默认配置下提醒有声音;把音量调到 0 静音;自定义音效路径失效时回落内置 1.wav 且不崩溃;同一条提醒只响一次。
- 天气图标:4 套模板均可切换且立即生效;40 个天气代码逐个渲染正确(截图对比名称与图标);未知代码 99 显示「未知」图标。
- 贴纸:
sticker(帕姆_嗨)在教程中正确显示;22 张贴纸全部可加载(无 404);比例不变形。 - 教程:
classisland.getStarted三个教程组可完整播放到结束;跳过后再次进入从第一步开始;教程图片无拉伸、无破图。 - 本地化:切换 en/zh-Hans/zh-Hant 后设置页与托盘菜单文案切换且立即生效;日期格式随之变化;其余页面若无翻译必须回落中文而不是显示 key。
- 离线:在完全断网、无缓存的干净环境中启动,所有资源(字体/图标/音效/贴纸/教程图)均本地可用,控制台无对外请求(除用户主动触发的天气/更新功能)。
- 体积:字体 + 图标 + 音效 + 贴纸 + 教程图的总增量不超过 30MB 打包后体积;超过时必须说明取舍(例如贴纸按需下载,但 ClassIsland 的语义是离线可用,默认应全量内置)。