Files
classhelper-island-refactor…/out/sections/10-settings.md
T
ClassIsland Prompt Kit 22c1784bab feat: ClassIsland / ClassHelper 灵动岛提示词套件
- 重构版主提示词(14 parts,面向 ClassHelper 灵动岛重构)
- ClassIsland 全量规格提示词(20 parts,含分卷与逐章版本)
- 投喂指南、分卷、逐节文件
- 调研记录、一致性基线、生成与质检脚本
2026-11-12 21:59:58 +08:00

69 KiB
Raw Blame History

10. 设置中心

本节规定「应用设置」窗口(ClassIsland 对应 SettingsWindowNew)的全部实现细节。实现者必须把它实现为 ClassHelper desktop-client 渲染进程中的一个独立 BrowserWindow(Electron BrowserWindow,URL 固定为 #/settings),窗口内是 Vue 3 + Vue Router + Element Plus 的单页应用;所有页面、控件、默认值、禁用条件、生效时机必须逐项对齐本节的规格。所有设置项必须落到一个 Pinia store(store 名固定为 useSettingsStore),字段名沿用本节给出的 JSON 字段名(即 ClassIsland Settings 的属性名),以便与主界面(岛)共享。

10.1 设置窗口外壳(必须逐像素对齐)

  1. 窗口参数。必须创建宽度 1240、高度 550、最小宽度 560 的 BrowserWindow;minWidth: 560,width: 1240,height: 550,标题为「应用设置」,图标使用 AppLogo.ico,show: false 首帧就绪后再 show()(对应 repos/ClassIsland/ClassIsland/Views/SettingsWindowNew.axaml:16-22)。
  2. 窗口样式。必须无系统标题栏(frame: false / titleBarStyle: 'hidden'),启用 Mica/Acrylic 类背景(Windows 11 21H2+ 且 WinUI Composition 可用时才启用 Mica,其余平台退回纯色背景;证据 repos/ClassIsland/ClassIsland.Core/Controls/MyWindow.cs:215-229)。Electron 中不得调用会破坏逐像素透明与 Mica 的 setBackgroundMaterial(),改用 backgroundMaterial: 'mica'(Windows 11)或窗口样式类实现;不得同时叠加两层不透明背景。
  3. 自定义标题栏。高度必须为 48px,必须 -webkit-app-region: drag(对应 viewModel.TitleBar.Height = 48,repos/ClassIsland/ClassIsland/Views/SettingsWindowNew.axaml.cs:135),其内部所有按钮必须 -webkit-app-region: no-drag。标题栏从左到右必须依次为:
    • 返回按钮:宽 48px、高 40px、margin: 0 -8px,tooltip「返回」,仅在路由可以后退时显示(:127-136);
    • 导航窗格切换按钮:宽 48px,margin: 0 -8px -8px,仅在 NavigationView 折叠为 minimal 模式时显示(:137-144);
    • 图标:18×18,margin: 12px 4px,pointer-events: none(:146-153);
    • 标题文字:font-size: 12px,垂直居中,pointer-events: none(:155-159);
    • 右侧区,间距 8px:需要重启按钮(accent 样式,tooltip「部分设置需要重启才能生效,点击以重启应用。」,文案「需要重启」,带重启图标)、版本号文本(font-size: 14px,次级前景色,tooltip「应用版本」)、「更多选项…」透明图标按钮(:162-250);
    • 窗口控制按钮预留位:右侧必须保留 140px 空白区域(:252);在 macOS 上左侧还需预留 60px 红绿灯空位(:120-126)。
  4. 「更多选项…」菜单必须按以下顺序与文案渲染(:176-249):
    1. 实验性功能…(图标 E508)→ 打开宽度 332px 的右侧抽屉;
    2. 调试窗口规则…(F485)→ 打开 WindowRuleDebugWindow;
    3. 创建快捷方式…(E0B1,仅 Windows/Linux,Windows/macOS 分支按源码 OnPlatform)→ 子菜单:创建桌面快捷方式(E62F)、创建开始菜单快捷方式(E06F)、创建快捷换课图标(E15F,仅 Windows);
    4. 数据迁移…(E083)→ 打开 DataTransferWindow 模态对话框;
    5. 分隔线;
    6. 集控选项…(E2B4)→ 跳转 classisland://app/settings/management?ci_keepHistory=true;
    7. 加入管理…(E2B6,未启用集控时显示)、退出管理…(E2B8,已启用时显示);
    8. 分隔线;
    9. 日志…(E510)→ 打开 AppLogsWindow;
    10. 导出诊断数据(E601)→ 先弹确认对话框,再保存 .zip;
    11. 重启到恢复模式(F4C5)→ 需「退出应用」授权等级;
    12. 分隔线;
    13. 打开日志目录…(E889)、打开数据目录…(E881)、打开应用目录…(E885)。
  5. 打开行为。必须单例:首次打开前必须校验「编辑设置」授权等级(ManagementService.CredentialConfig.EditSettingsAuthorizeLevel,默认「无」即不校验),校验失败直接返回、不显示窗口(SettingsWindowNew.axaml.cs:458-480)。已打开时若最小化则还原并 focus()。必须支持从 URI classisland://app/settings/<pageId>[?ci_keepHistory=true] 直接打开指定页(OpenUri,:490-499)。
  6. 首帧遮罩。窗口首次渲染完成前,必须以不透明底色覆盖整窗并居中显示 96×96 的 AppLogo@384w.png,导航完成后再淡出/移除(SettingsWindowNew.axaml:258-264,ViewModel.IsCoverVisible 初始 true)。
  7. 关闭行为。用户点关闭按钮时不得退出应用:必须拦截 close 事件,改为 hide(),并依次执行「保存设置」「保存组件配置」「保存自动化配置」;随后按缓存策略清理页面缓存并触发 GC(SettingsWindowNew.axaml.cs:501-518)。仅当关闭原因是应用退出或系统关机时才真正关闭。
  8. 需要重启提示。任何页面通过命令请求重启时,必须把 IsRequestedRestart 置 true,标题栏出现「需要重启」accent 按钮;点击后弹出模态对话框:标题「需要重启」,正文「部分设置需要重启以应用更改。」,主按钮「重启」,关闭按钮「取消」,默认聚焦主按钮;确认后调用应用重启(SettingsWindowNew.axaml.cs:536-560)。
  9. 回声洞(加载彩蛋)。当 ShowEchoCaveWhenSettingsPageLoading === true 且正在导航、且管理策略未禁用彩蛋时,页面左下角显示一行提示:margin: 32px 8px 8px 16px,opacity: 0.75,图标 EA8A + 文本,文本取 Assets/Tellings.txt 的逐行内容并随机洗牌、不重复播放;文案禁用时整块隐藏(SettingsWindowNew.axaml:71-91、.cs:262-288)。管理策略 DisableEasterEggs 为真时必须隐藏。

10.2 导航结构(左侧 NavigationView)

  1. 形态。必须使用 NavigationView 的 Auto 模式:宽屏时左侧固定导航窗格,宽度必须为 283px(SettingsWindowNew.axaml:52-60 的 OpenPaneLength="283"),内容区占剩余宽度;窄屏时折叠为汉堡菜单(minimal 模式),且此时不得显示 NavigationView 自带的窗格切换按钮,改用标题栏内的自定义切换按钮(:62-64)。
  2. 响应式阈值。窗口宽度 < 800 时进入压缩模式;窗口最大化时强制退出压缩模式(SettingsWindowNew.axaml.cs:437-446)。压缩模式下:标题容器与内容宽度自适应,不再受 960px 限制;宽度恢复后重新展开导航。
  3. 导航项来源。设置页面必须由「注册表」驱动:每个页面注册 {id, name, unSelectedIconGlyph, selectedIconGlyph, category, groupId, hideDefault, useFullWidth, hidePageTitle};导航项按 category 枚举升序分块,块内保持注册顺序;每个 category 块之间必须插入一条分隔线(最后一个块后不加)(SettingsWindowNew.axaml.cs:145-227)。
  4. 分类与顺序(SettingsPageCategory 枚举 Internal=0、External=1、About=2、Debug=3;repos/ClassIsland/ClassIsland.Core/Enums/SettingsWindow/SettingsPageCategory.cs:6-24)。注册顺序决定同块内次序(App.Services.xaml.cs:156-184):
    • 分组「通用」(id classisland.general,图标 EF27,展开后子项顺序):基本、时钟、存储、隐私、翻新与迎新、高级;
    • 分组「主界面」(id classisland.mainwindow,图标 EC85):组件、外观、窗口;
    • Internal 无分组:提醒、天气、自动化、更新(仅当 UpdateService.AllowedPackageTypes 包含当前打包类型时注册);
    • External:插件、主题;
    • Debug:测试页面(仅开发)、调试;
    • About:关于 ClassIsland、集控、集控凭据设置、集控策略(后两者 hideDefault = true,不出现在默认导航中,仅通过 URI 打开)、出错啦!(hideDefault = true,错误页)。
  5. 分组渲染规则。同一分组只渲染一个可展开的父项,分组内页面为子项;首次导航到子项时父项必须自动展开;选中子项时父项必须显示 IsChildSelected 状态(SettingsWindowNew.axaml.cs:849-877)。
  6. 过滤规则(管理员策略)。满足以下任一条件的页面必须从导航中移除且不可通过 URI 进入:
    • HideDefault === true;
    • 策略 DisableSettingsEditing 为真且页面 category ∈ {Internal, External};
    • 策略 DisableDebugMenu 为真且 category = Debug;
    • Settings.IsDebugOptionsEnabled === false 且 category = Debug(SettingsWindowNew.axaml.cs:150-158)。
    • 当 DisableSettingsEditing 为真时,窗口必须以「关于」页作为启动页(同文件 :125-128)。
  7. 面包屑/标题。内容区顶部必须有页面标题(TitleTextBlockStyle,字号约 28px【推断】),容器 margin: 12px 16px 0;当页面声明 useFullWidth 时不做 960px 限宽,否则标题容器 max-width: 960px;当页面声明 hidePageTitle 时整块不渲染(SettingsWindowNew.axaml:92-104)。
  8. 后退栈。默认每次从导航栏切换页面都必须清空后退栈(不允许跨页返回);仅当 URI 带 ci_keepHistory=true 时保留后退栈(SettingsWindowNew.axaml.cs:372-395)。ClassIsland 没有「设置搜索/全局搜索框」,本实现不得擅自添加搜索框;若产品确需增强,只能作为 P2 可选增强(默认关闭、独立开关、并在界面标注为非原版功能)。
  9. 导航动画与骨架。页面切换必须播放淡入(SettingsService.Settings.AnimationLevel >= 1 时),并在导航期间把 IsNavigating 置真以暂停交互、显示回声洞。

10.3 页面容器与通用控件(必须映射到 Element Plus)

  1. 页面容器。所有普通设置页必须使用 padding 为 12px 12px 18px 12px、max-width: 960px、子项间距 4px 的纵向容器(repos/ClassIsland/ClassIsland.Core/StylesBase.axaml:67-71、ThemeBase.axaml:37 的 SettingsContainerWidth = 960)。在 CSS 中实现为 .settings-container { margin: 12px 12px 18px 12px; max-width: 960px; display: flex; flex-direction: column; gap: 4px; }。
  2. 页面内分区标题。使用「图标 + 文本」的行内标题(IconText),margin: 0 0 4px;分区之间使用 Separator(margin: 0 12px 0 4px)。Element Plus 中必须用 <div class="settings-section-title"> 实现。
  3. SettingsExpander(可展开设置卡片)。必须实现为「卡片行」组件:左侧为 20×20 图标(导航图标尺寸 20,见 ThemeBase.axaml:42)+ 标题 + 描述(次级文本,font-size: 12px,可换行),右侧为 footer 控件(开关/下拉/滑块/按钮/数值框);展开后下方追加若干 SettingsExpanderItem 子行,子行左边距约 36px【推断】。Element Plus 映射:<el-collapse> 或自定义 .settings-card(background: CardBackgroundFillColorDefaultBrush、border: 1px solid CardStrokeColorDefaultBrush、border-radius: 4px、行高约 64px【推断】)。
  4. 开关。所有布尔设置必须使用开关(ToggleSwitch),打开态文本「开」、关闭态文本「关」(StylesBase.axaml:95-98)。Element Plus 中必须使用 <el-switch> 并在需要文字时设置 active-text="开" inactive-text="关";在卡片右侧显示时隐藏开关内部文本,只保留轨道(对应 SettingsExpanderItem 内 ToggleSwitch 的 PART_ContentPresenter 隐藏,StylesBase.axaml:100-106)。
  5. 数值框(Field)。带单位后缀的数值框必须使用「前缀/后缀字段」组件:宽度 175px,后缀如 px/秒/周/天/次/ms(见各页);数值框内部使用 SpinButtonPlacementMode="Inline",最小值 1、最大值 40(字体大小)等按页指定(AppearanceSettingsPage.axaml:485-496)。Element Plus 映射:<el-input-number controls-position="right"> 外面包一层 .field(后缀绝对定位在右侧,padding-right: 24px)。
  6. 滑块。带数值提示的滑块必须使用 auto-tooltip 行为:拖动时在指针位置显示格式化后的值(StylesBase.axaml:178-191),格式化字符串按页指定(F1/F2)。Element Plus <el-slider :show-tooltip="true"> 已等价。
  7. 抽屉(DrawerHost)。设置页内的所有「编辑/管理」弹层必须使用右侧抽屉:placement: right,宽度由内容决定(见各页),带半透明遮罩(SmokeFillColorDefaultBrush)和 box-shadow: 0 0 8px rgba(0,0,0,0.2)(repos/ClassIsland/ClassIsland.Core/Controls/DrawerHost.axaml:16-37)。动画:250ms cubic-bezier(0, 0, 0, 1) 同时作用于位移与透明度,遮罩同步淡入(同文件 :42-59);AnimationLevel === 0 时不得播放动画。必须支持按 Esc 关闭、点击遮罩关闭(DrawerHost.axaml.cs:78-89、:115-118)。Element Plus 映射:<el-drawer direction="rtl" :size="...">,并把过渡曲线覆盖为 cubic-bezier(0,0,0,1)。
  8. 卡片组(cardContainer)。关于/集控/恢复等页面使用的「卡片列表」:子项间距 1px、首项圆角 4px 4px 0 0、末项圆角 0 0 4px 4px、单项圆角 4px(StylesBase.axaml:255-263)。
  9. 其它通用类:l-instructive(次级说明文本,opacity 约 0.75);items-valign-center(行内垂直居中);animated-intro(入场时子元素依次淡入,AnimationLevel >= 1 时启用);Foreground="IndianRed" 表示危险操作。实现时必须提供等价 CSS 类,颜色映射见 part 3。

10.4 每个设置页的逐项规格

以下每页都必须按「标题/图标 → 分区 → 控件 → 绑定字段 → 默认值 → 枚举 → 生效时机 → 禁用条件」实现。默认值来源统一为 repos/ClassIsland/ClassIsland/Models/Settings.cs 的字段初始化(下文以 Settings.cs:行号 标注)。

10.4.1 基本(id general,图标无自定义 → 默认 EF27/EF26,分组「通用」)

源文件 Views/SettingPages/GeneralSettingsPage.axaml。

  1. 顶部公告区:当 ShowSellingAnnouncement 为真时显示 Warning 级 InfoBar,固定文案「ClassIsland 是开源免费的软件,官方没有提供任何形式的付费支持服务,源代码仓库地址在 https://github.com/ClassIsland/ClassIsland/。如果您通过有偿协助等付费方式取得本应用,在遇到问题时请在与卖家约定的服务框架下,优先向卖家求助。如果卖家没有提供您预期的服务,请退款或通过其它形式积极维护您的合法权益。」(:32-36)。
  2. 行为分区(图标 E84F,标题「行为」):
    • 开机自启:开关,绑定 DesktopService.IsAutoStartEnabled(桌面集成,不写入 Settings.json),说明「在您的系统启动时自动运行本应用。」(:55-62);
    • 注册 Url 协议:开关,绑定 DesktopService.IsUrlSchemeRegistered,仅 Windows/Linux 显示,说明含 classisland://(:64-76);
    • 学期开始时间:日期选择器,宽度 120px,绑定 SingleWeekStartTime,默认「今天所在周的周日」(Settings.cs:37-38),说明「设置学期首日,该日期将作为多周轮换课表的计算起点和每周的第一天。」;右侧附「调整多周轮换偏移…」按钮(图标 E324)打开飞层 WeekOffsetSettingsControl(:78-117);
    • 最大多周轮换周数(子项):数值框最小 2、最大 9、格式 0、后缀「周」,绑定 MultiWeekRotationMaxCycle,默认 4(Settings.cs:61);
    • 点击托盘图标行为:下拉,绑定 TaskBarIconClickBehavior,默认 Windows=0、其他平台=4(Settings.cs:102)。选项(5 项):打开主菜单(仅 Windows 可用)、打开档案编辑窗口、显示/隐藏主界面、打开换课窗口、打开设置窗口;macOS 隐藏整项;Linux 说明追加「此选项可能因为桌面环境差异而无法工作。」(:121-161);
    • 教学安全模式:开关绑定 IsCriticalSafeMode(默认 false,Settings.cs:207),右侧下拉绑定 CriticalSafeModeMethod(仅在开启时显示,宽度 135px),选项:退出应用(0)、静默重启应用(1)、显示通知(2)、忽略(不推荐)(3);关闭时显示禁用状态的「显示崩溃报告」下拉(:163-189);
    • 显示启动加载界面:开关绑定 IsSplashEnabled(默认 false,Settings.cs:115)。展开后子项:启动图标(文本框 min-width: 150、max-width: 250,水印「(默认图标)」,绑定 SplashCustomLogoSource,右侧附带图片文件选择按钮)、启动文字(文本框 min-width: 200、max-width: 300,水印「正在启动…」,绑定 SplashCustomText)、显示详细状态信息(开关,绑定 ShowDetailedStatusOnSplash,默认 false,Settings.cs:222)、「自定义启动界面功能已被您所在的组织禁用。」(当 DisableSplashCustomize 时替换上面三项)、「预览启动界面」(可点击行,图标 E44E,点击显示 5 秒启动界面并置 IsSplashPreviewing,行尾显示 24×24 进度环)(:191-243)。
  3. 界面分区(图标 F485,标题「界面」):
    • 隐藏窗口:TabControl(compact)切换 HideMode(默认 0)。
      • 「基础模式」页:三个复选框——上课时(HideOnClass,默认 false)、前台是最大化窗口时(HideOnMaxWindow,默认 false)、前台是全屏窗口时(HideOnFullscreen,默认 false);
      • 「高级模式」页:按钮「编辑规则集…」(图标 F17E)打开宽度 600px 的规则集抽屉(HideRules)(:249-278);
    • 动画级别:下拉宽度 120px,绑定 AnimationLevel,默认 1(标准),选项:禁用(0)、标准(1)、华丽(2)。修改后必须请求重启(GeneralSettingsPage.axaml.cs:37-44)(:281-293);
    • 禁用动画等待:开关绑定 IsWaitForTransientDisabled,默认 false,修改后必须请求重启(Settings.cs:206、.axaml.cs:37-44);
    • 降低主界面进度条精度:开关绑定 ReduceProgressAccuracy,默认 true(Settings.cs:1853)(:306-312)。

10.4.2 时钟(id clock,图标 E4C4/E4C3,分组「通用」)

源 ClockSettingsPage.axaml。

  1. 顶部时钟:文本 HH:mm:ss,font-size: 36px,font-weight: 500;下方为日期长格式文本(次级说明样式)(:15-20)。
  2. 「使用精确时间」卡片:开关绑定 IsExactTimeEnabled(默认 true,Settings.cs:140),展开后子项:
    • 「时间服务器」文本框绑定 ExactTimeServer,默认 ntp.aliyun.com(Settings.cs:139);
    • 「立即同步」按钮(图标 E0B5),下方显示 ExactTimeService.SyncStatusMessage 状态文本(:24-53)。
  3. 「时间偏移」卡片:右侧带「秒」后缀的数值框(min-width: 147,Inline 步进),绑定 TimeOffsetSeconds,默认 0(Settings.cs:141);展开后子项:
    • 「自动时间偏移」:数值框(同样 min-width: 147,绑定 TimeAutoAdjustSeconds,默认 0,Settings.cs:147)与开关(绑定 IsTimeAutoAdjustEnabled,默认 false,Settings.cs:146)并排,开关关闭时数值框禁用;
    • 「对齐铃声」(可点击行,无图标)→ 打开 TimeAdjustmentWindow(详见 part 11)(:56-91)。

10.4.3 存储(id storage,图标 E6B7/E6B6,分组「通用」)

源 StorageSettingsPage.axaml。

  1. 当存在配置文件错误(ConfigureFileHelper.Errors.Count > 0)时,顶部显示 Warning InfoBar:「ClassIsland 部分配置文件已损坏且无法加载,这些配置文件已恢复至默认值。」带「详细信息…」按钮(图标 EC2E)跳转 classisland://app/config-errors(:17-28)。
  2. 备份分区(图标 E081,标题「备份」):
    • 「启用自动备份」:开关绑定 IsAutoBackupEnabled,默认 true(Settings.cs:187)。展开后子项:
      • 自动备份间隔:数值框最小 0、宽 150px、后缀「天」、Inline,绑定 AutoBackupIntervalDays,默认 7(Settings.cs:191);
      • 自动备份上限:数值框最小 0、宽 150px、后缀「个」,绑定 AutoBackupLimit,默认 16;说明「设置为 0 则为无上限。」(Settings.cs:190);
      • 上次成功自动备份:只读展示 LastAutoBackupTime(Settings.cs:188)。
    • 「手动备份」卡片:右侧在有操作时显示 20×20 进度环,成功后显示 E423 图标(tooltip「备份成功。」)。子项:立即备份(点击,备份中禁用)、查看备份文件…(EC2D)、恢复备份…(EC2D,说明「重启到恢复模式并恢复到指定的备份。」)、备份文件占用大小(只读 BackupFilesSize,默认「计算中...」,Settings.cs:189)。手动备份内容必须包含 Config/ 全部配置文件、Profiles/ 档案文件与 Settings.json(:76-107)。

10.4.4 隐私(id privacy,图标 EF65/EF64,分组「通用」)

源 PrivacySettingsPage.axaml。必须实现:

  1. 标题「匿名使用情况分析」(SubtitleTextBlockStyle),正文「本应用将通过 SentrySDK 来收集本应用中的使用情况与错误信息,以改进本应用。您的信息会匿名上传,不会包含您的个人信息。您可以自行启用或禁用此功能。」;下方「更多信息请见《ClassIsland 隐私政策》。」(超链接打开隐私政策)(:18-31)。
  2. 「启用匿名使用情况分析」卡片:开关绑定 IsSentryEnabled(存储于本地全局存储,默认 true;Settings.cs:518-535)。说明中必须保留「为了确保环境块完全刷新,可能需要重启计算机才能使本设置完全生效。」(:33-39)。策略 CanPolicyDisable(容器 Tag)语义:允许被集控禁用【推断】。

10.4.5 翻新与迎新(id refreshing,图标 E0B8/E0B9,分组「通用」)

源 RefreshingSettingsPage.axaml。实现要点:

  1. 「定期翻新」卡片:开关绑定 IsRefreshingToastEnabled(默认 true,Settings.cs:1865);说明「当在长时间未启动 ClassIsland 的寒假/暑假等学期结束后的长假后启动 ClassIsland 时,显示桌面通知询问是否重新设置应用的部分设置以适应新学期。」展开后子项为「默认翻新范围」(文本)+ 4 个复选框:
    • 档案(RefreshingScopes.Profile),勾选后的副作用文案必须变为「将创建并切换到一个全新的配置文件。」;
    • 课表(RefreshingScopes.ProfileClassPlans)、时间表(RefreshingScopes.ProfileTimeLayouts)——仅当「档案」未勾选时显示,并在其右侧提供「选择保留的内容…」按钮(图标 F1A8)打开 RefreshingScopesConfigDialog;「课表」「时间表」互斥逻辑:不勾选「档案」时才出现;
    • 组件配置(RefreshingScopes.Components,副作用文案「将禁用已经启用的插件。」适用于插件项);
    • 自动化(RefreshingScopes.Automations);
    • 插件(RefreshingScopes.Plugins,勾选后描述为「将禁用已经启用的插件。」);
    • 「立即翻新」(可点击行,图标 E44E)(:14-58)。
  2. 「迎新模式」卡片:开关绑定 RefreshingToastIsOnboardingGuide(默认 false,Settings.cs:1869);说明必须包含「此选项在生效一次后将自动关闭。」;展开后子项:通知标题(文本框 min-width: 120、max-width: 450,绑定 OnboardingToastTitle,默认见 RefreshingService.DefaultOnboardingToastTitle)、通知内容(多行文本框,AcceptsReturn,绑定 OnboardingToastBody)、「重置为默认值」、「测试通知」(:61-86)。
  3. 分区「通知选项」(图标 E408):
    • 「通知显示间隔」:数值框最小 1、最大 33550337、格式 0、后缀「天」,绑定 RefreshingToastThresholdDays,默认 20(Settings.cs:1866);子项「在下次启动时显示通知」:开关绑定 ShowRefreshingToastOnNextStart(默认 false),开关开启时旁边额外显示「立即退出应用」按钮(:92-118);
    • 「最高通知显示次数」:数值框最小 1、最大 16、后缀「次」,绑定 MaxRefreshingToastCounts,默认 5(Settings.cs:1873);子项显示「剩余通知次数:{LeftRefreshingToastCounts}」,当剩余次数 !== 0 时显示「清空」按钮(:121-154)。

10.4.6 高级(id advanced,图标 F49F/F49E,分组「通用」)

源 AdvancedSettingsPage.axaml。

  1. 顶部必须显示不可关闭的 Warning InfoBar:标题「小心!」,正文「修改本页面的设置存在风险,请谨慎操作。」(:13-16)。
  2. 「自动禁用异常插件」开关:绑定 AutoDisableCorruptPlugins,默认 true(Settings.cs:1844)(:18-25)。
  3. 「渲染模式」下拉(仅 Windows 显示):选项「默认(0)/软件(不推荐)(1)/AngleEgl(2)/Wgl(3)/Vulkan(4)」,修改后重启生效,此设置仅本设备生效(:28-46)。
  4. 「使用系统标题栏」开关(仅 Windows 且非 arm64):需重启【推断】(:49-61)。
  5. 「兼容缩放模式」开关(仅 Linux):忽略 QT_SCREEN_SCALE_FACTORS 等环境变量;需重启【推断】(:63-74)。

10.4.7 组件(id components,图标 E06F/E06F,分组「主界面」)

源 ComponentsSettingsPage.axaml(644 行,非 settings-container 结构,必须自绘三栏式编辑器)。

  1. 整体布局:外层 margin: 12px 0,6 行:0 Auto(占位)、1 Auto(配置方案栏)、2 行高 64(最小 43.2、最大 250,行列表)、3 Auto(分隔条 height: 2px,margin: 0 -12px)、4 *(组件库/设置区)、5 Auto(InfoBar)(:162-171)。
  2. 配置方案栏:左侧说明文本「以下组件将显示在主界面上,从组件库拖动组件以添加组件。」;右侧:字段「配置方案」+ 下拉(min-width: 150、max-width: 300,绑定 CurrentComponentConfig,默认 "Default",Settings.cs:159)、刷新按钮(E0B5)、新建…(E00D)、打开配置文件夹…(E88D)(:174-205)。
  3. 主界面行列表:每行高 40px,结构为「拖拽把手(宽 20)+ 组件横向列表 + 选中态操作区」。选中某行时右侧浮出操作区:padding: 4px、圆角 4px、背景 AcrylicBackgroundFillColorBaseBrush,内含 4 个按钮:主要行开关(E994,tooltip「此行是主要行」)、提醒开关(E02B,tooltip「此行可以显示提醒」)、在下方插入一行(E00D)、删除(E61D,IndianRed)(:207-288)。
  4. 组件横向列表:高度 40px,水平滚动;每项 = 拖拽把手 + 14×14 图标 + 名称 + 选中时出现的「更多选项…」(EBAC)菜单与「查看子组件」(EC30,仅容器组件)与删除按钮(E61D)。「更多选项」菜单项固定顺序:向上移动一行(E197)、向下移动一行(E0CB)、移动到选中的容器(E280)、从容器组件移出(E286)、分隔线、包裹到新容器(子菜单列出全部容器组件,带图标)、创建副本(EEB9)(:27-155)。
  5. 子组件视图:选中容器组件并点击「查看子组件」后,在组件设置区上方出现卡片(圆角 4px、边框 CardStrokeColorDefaultBrush、背景 CardBackgroundFillColorDefaultBrush),头部 padding: 8px,含「返回上一层级」按钮(E0C7)、标题「此组件的子组件」、「关闭」按钮(E671)(:296-340)。
  6. 下方 TabControl:compact、max-width: 960px、内容拉伸,四个页签:
    • 组件库(按来源分组,组名 font-weight: 600;每个组件项高 50px:拖拽把手宽 24 + 32×32 图标 + 名称 + 12px 描述;每组使用 WrapPanel,目标宽度 225px 自动换列)(:348-413);
    • 组件设置(仅在选中组件时显示,渲染该组件的设置控件)(:414-417);
    • 高级设置(选中组件的通用高级设置,含「按规则隐藏」开关与规则集编辑)(:418-422);
    • 行设置(选中行时显示):按规则隐藏(开关+编辑规则集按钮)、分体主界面(下拉:继承(0)/禁用(1)/启用(2))、分区「外观」(图标 EC4A):行不透明度滑块(0.1–1,步进 0.05,F2)、自定义背景颜色(颜色选择器+开关)、自定义背景不透明度(滑块 0~1)、自定义背景圆角半径(滑块 0–20,步进 0.5,F1)、分区「字体」(图标 F26F):字体大小(1–40px 四档,覆盖外观设置)、字体颜色(颜色选择器+开关)(:423-614)。
  7. 右下角浮动工具条(选中组件时):AnimatedIconButton「编辑…」(图标 F17E,仅在「按规则隐藏」开启时可点)+ 复选框「按规则隐藏」(绑定 SelectedComponentSettings.HideOnRule)(:617-631)。
  8. 底部 InfoBar:「新功能:现在可以使用⌈编辑模式⌋更加直观地编辑主界面上的组件!」+「进入编辑模式」按钮 → classisland://app/edit?fromSettingsPage=true(:634-642)。

10.4.8 外观(id appearance,图标 E51E/E51D,分组「主界面」)

源 AppearanceSettingsPage.axaml。必须严格按下列默认值实现(值来源 Settings.cs):

  1. 「界面缩放」:滑块宽 180px,最小 0.75、最大 2.5、步进 0.05、吸附、拖动显示 F2,绑定 Scale,默认 1.0(Settings.cs:86)(:27-40)。
  2. 「背景颜色」:颜色选择器(仅自定义开启时显示,margin-right: 6px)+ 开关,绑定 BackgroundColor(默认 Black)与 IsCustomBackgroundColorEnabled(默认 false)(Settings.cs:33-34)。
  3. 「背景不透明度」:滑块 0–1、步进 0.05、F2,绑定 Opacity,默认 0.5(Settings.cs:64)。
  4. 「圆角半径」:滑块 0–20、步进 0.5、F1,绑定 RadiusX,默认 8.0(Settings.cs:183;Y 半径 RadiusY 同为 8.0,本页只暴露 X)。
  5. 「行间隔」:滑块 0–150、步进 5、F1,宽 130px;右侧数值框宽 125px、最小 0;绑定 MainWindowLineVerticalMargin,默认 5(Settings.cs:219)。
  6. 「分体主界面」:开关绑定 IsIslandSeperated,默认 false(Settings.cs:1852),说明「启用后组件会分开。」。
  7. 分区「主题」(图标 E51E,标题「主题」):
    • 「应用主题」下拉:跟随系统(0)/明亮(1)/黑暗(2),绑定 Theme,默认 2(Settings.cs:32),每项带图标(E5CB/F465/F44B);
    • 「主题色来源」下拉:自定义(0)/系统壁纸(1,禁用隐藏)/系统(2,默认)/屏幕主题色(3,禁用隐藏),绑定 ColorSource,默认 2(Settings.cs:83);
    • 「强调色」颜色选择器:仅在 ColorSource === 0 时显示,绑定 PrimaryColor,默认 #00BFFF(Colors.DeepSkyBlue,Settings.cs:35);副色 SecondaryColor 默认 #7FFFD4(Aquamarine),本页未暴露【推断:仅由主题使用】。
  8. 分区「字体」(图标 F26F,标题「字体」):
    • 「自定义字体」下拉:max-dropdown-height: 360px,弹出层宽 280px,底部右对齐;每项按自身字体渲染、单行截断、height: 20px,默认项显示文本「HarmonyOS Sans SC(默认)」;绑定 MainWindowFont,默认 MainWindow.DefaultFontFamilyKey(Settings.cs:95);
    • 「自定义字重」下拉:选项 Thin/ExtraLight/Light/Normal/Medium(默认)/SemiBold/Bold/ExtraBold/Black/ExtraBlack,每项以对应字重预览;绑定 MainWindowFontWeight2(整型,默认 (int)FontWeight.Medium = 500,Settings.cs:101);
    • 「字体大小」四行:次级字体大小(默认 14)、正文字体大小(16)、强调字体大小(18)、大号字体大小(20);均为「px」后缀数值框,范围 1–40,宽 175px(Settings.cs:197-200);
    • 「字体颜色」:颜色选择器(仅开启时)+ 开关,绑定 CustomForegroundColor(默认 #1E90FF,DodgerBlue)与 IsCustomForegroundColorEnabled(默认 false)(Settings.cs:202-203)。
  9. 底部 TabControl(compact)两个页签:
    • 「字体预览」:只读可编辑文本框,font-size: 17px、padding: 8px、居中;内容必须为四行:「当有一天你不再纠结于答案 当我们又重逢于天涯或沧海」/「语文 数学 英语 历史 物理 政治 化学 生物 地理」/「the quick brown fox jumps over a lazy dog」/「THE QUICK BROWN FOX JUMPS OVER A LAZY DOG」/「8:00-12:00 1234567890 +-*/」;应用当前字体与字重(:553-569);
    • 「字号预览」:字段「测试文本」+ 四行分别以四种字号渲染同一文本(:570-591)。

10.4.9 窗口(id window,图标 F485/F484,分组「主界面」)

源 WindowSettingsPage.axaml。

  1. 停靠位置选择器(:24-127):左侧为 220px 高的模拟屏幕边框(border: 8px solid TextFillColorPrimaryBrush、圆角 4px),屏幕底部叠加 16px 高的模拟任务栏(背景 #99000000,左端 E064 图标 10×10、margin: 3px,右端时间文本 8px Light)。屏幕内 6 个单选按钮,分两行三列,分别对应 WindowDockingLocation 值 0(左上)、1(上中,默认)、2(右上)、3(左下)、4(下中)、5(右下)(默认值 Settings.cs:48)。右侧:字段「向右偏移」(WindowDockingOffsetX,默认 0,Settings.cs:49)、「向下偏移」(WindowDockingOffsetY,默认 0,Settings.cs:50)、「显示器」下拉(列出所有屏幕:「图标 + 显示名 (宽x高)」,绑定 WindowDockingMonitorIndex,默认 0,Settings.cs:51)、「刷新显示器列表」按钮(E0B5)、说明文本「应用会以左图的位置显示在指定的显示器上。如果指定的显示器不存在,那么应用会显示在主显示器上。」。
  2. InfoBar:RawInput 初始化失败时显示 Warning「初始化 RawInput 失败,将使用兼容模式判断光标位置。详细请查看日志。」;启用 RawInput 时显示「使用原始输入判断鼠标位置时,如果前台窗口的进程以管理员身份运行,可能会出现无法判定鼠标位置的情况。以管理员身份运行 ClassIsland 可以解决此问题。」(:130-138)。
  3. 「窗口层级」(:141-188):下拉默认选中 WindowLayer,默认 1(置顶);选项:置底(0)、置顶(1)。子项「窗口层级设置频率」下拉绑定 WindowTopmostRecheckMode(默认 0):窗口层级变化时(默认)(0)、前台窗口变化时(1)、「每 50ms」(2,后带橙色 F431 图标)、「每 1ms」(3,后带橙红色 F431 图标)。
  4. 「指针移入淡化」(:191-236):开关绑定 IsMouseInFadingEnabled(默认 true,Settings.cs:193);子项:
    • 「使用原始输入」开关(仅 Windows),绑定 UseRawInput,默认 false(Settings.cs:192);
    • 「触屏点击后自动恢复时间」:数值框 width: 150px、最小 0、后缀「ms」、Inline,绑定 TouchInFadingDurationMs,默认 0(Settings.cs:195);仅当启用原始输入时显示;
    • 「反转指针移入淡化」开关:绑定 IsMouseInFadingReversed,默认 false(Settings.cs:194)。
  5. 「使用原始屏幕尺寸」 开关:绑定 IsIgnoreWorkAreaEnabled,默认 false(Settings.cs:1835-1838),说明「若启用,主界面调整位置时将忽略系统工作区设置(通常包括任务栏和部分顶栏应用)。」(:239-245)。
  6. 「录制模式」 开关:绑定 IsScreenRecordingModeEnabled,默认 false(Settings.cs:1861),说明必须包含「这会导致主界面窗口显示在任务栏中且主界面窗口只会在一个虚拟桌面上显示」(:248-254)。
  7. 「阻止截图」(仅 Windows):开关绑定 IsWindowCaptureBlockingEnabled,默认 false(Settings.cs:1862)(:256-267)。

10.4.10 提醒(id notification,图标 E02B/E02A,分组:Internal 无分组)

源 NotificationSettingsPage.axaml(497 行)。必须实现为「左列表 + 右详情」两栏布局(ListDetailView,两栏等分;容器 margin: 12px;压缩阈值 800px,压缩时变为列表→详情可返回的单栏,见 Controls/ListDetailView.axaml.cs:49-56、.axaml:46-71)。

  1. 左栏:
    • 「启用提醒」卡片:开关绑定 IsNotificationEnabled,默认 true(Settings.cs:91);说明「启用提醒后,将会在对重要事件发出醒目提醒。拖动提醒提供方以调整对应类型提醒的优先级。」(:64-72);
    • 当所有主界面行都关闭提醒时显示 Warning InfoBar:「提醒可能无法显示」「您禁用了所有主界面行的提醒功能,这可能会导致所有提醒都无法显示。要修复此问题,您需要在【组件】页面至少为一个主界面行开启提醒。」+「前往【组件】页面」按钮(:74-83);
    • TabControl(compact):页签「提醒提供方」= 提供方列表;页签「高级设置」= 全局提醒设置。
      • 提供方列表项:拖拽把手 + 24×24 图标(margin: 6px 6px 10px 6px)+ 名称(font-size: 16px,font-weight: 700)+ 描述(12px 次级)+ 右侧设置指示器;选中项的底部展开「提醒渠道」Expander(仅有渠道时显示),渠道列表项:24×24 图标 + 名称 14px Medium + 描述 12px(:86-204);
      • 高级设置页:见下 4 小节。
  2. 右栏(选中提供方后):
    • 页签「基本设置」:渲染该提供方的设置控件;无设置时居中显示 72×72 图标 EF26 + 「该提醒提供方没有设置。」(:372-390);
    • 页签「高级设置」:首行「对此提醒来源启用特殊高级设置」开关(绑定 ProviderSettings.IsSettingsEnabled,说明「启用后,此处的设置将覆盖全局设置和提醒请求中要求的设置。」),随后 InfoBar 提示同样文案;四个开关:启用提醒语音(IsSpeechEnabled)、启用提醒强调特效(IsNotificationEffectEnabled)、启用提醒音效(IsNotificationSoundEnabled,展开后含「自定义音效」文本框 + 文件选择)、置顶提醒(IsNotificationTopmostEnabled)(:391-495)。
  3. 全局高级设置四组:
    • 「启用提醒语音」开关 AllowNotificationSpeech(默认 false,Settings.cs:153)→ 子项:复选框「默认启用」IsSpeechEnabled(默认 true,Settings.cs:135)、语音引擎下拉(SelectedSpeechProvider,默认 "classisland.speech.edgeTts",Settings.cs:1847)、语音引擎设置控件(动态)、语音音量滑块(0–1,步进 0.01,F2,宽 150px,绑定 SpeechVolume,默认 1.0)、测试朗读文本框、测试语音按钮(:223-281);
    • 「启用提醒强调特效」开关 AllowNotificationEffect(默认 true,Settings.cs:154)→ 子项「默认启用」IsNotificationEffectEnabled(默认 true,Settings.cs:142)(:285-297);
    • 「启用提醒音效」开关 AllowNotificationSound(默认 false,Settings.cs:155)→ 子项:「默认启用」IsNotificationSoundEnabled(默认 true)、音效音量滑块(NotificationSoundVolume,默认 1.0,Settings.cs:182)、自定义音效(文本框 150px,水印「(默认音效)」,NotificationSoundPath 默认空,附音频文件选择按钮)(:300-349);
    • 「置顶提醒」开关 AllowNotificationTopmost(默认 true,Settings.cs:156)→ 子项「默认启用」IsNotificationTopmostEnabled(默认 true,Settings.cs:149)(:352-364)。

10.4.11 天气(id weather,图标 F44F/F44E,分组:Internal 无分组)

源 WeatherSettingsPage.axaml。

  1. 天气预览卡(:68-150):背景 ControlFillColorDefaultBrush,padding: 20px,圆角 12px,内部行间距 16px。三列:
    • 左:天气图标(宽 52–120、高 52)+ 温度(font-size: 32px SemiBold,单位 18px)+ 「更新于 HH:mm」(12px,opacity: 0.6);
    • 中(间距 28px):湿度、空气质量、风力三组,每组标签 12px(opacity: 0.8)+ 图标 14px + 数值 Medium;
    • 右:刷新按钮 40×40(图标 E0B5);刷新中改为 40×40 进度环;
    • 灾害预警列表:每条为 Expander(padding: 12px 8px,margin-top: 4px),头图为 22×22 图标 + 标题;展开显示详情(13px,opacity: 0.8)。
  2. 位置设置(:154-275):卡片右侧用 Chip ListBox 切换 WeatherLocationSource,两个选项「选择城市」(0)、「坐标定位」(1,仅平台支持定位时显示,默认 0,Settings.cs:1840)。子项:
    • 城市选择(仅 0):显示 CityName(默认「北京 (北京, 中国)」,Settings.cs:100)+ 「编辑城市」按钮(E7C9,主色)→ 打开宽 320px 的城市搜索抽屉:标题「搜索城市」、搜索框(水印「搜索城市或省份…」,右侧加载时显示 24×24 进度环)、结果单选列表(每项 RadioButton)、空态「找不到符合条件的城市。请更换搜索关键字,然后再试一次。」(:26-64);
    • 位置坐标(仅 1):经度/纬度文本框(min-width: 75px,前缀「经度/纬度」、后缀「°」),支持「显示坐标」遮罩(模糊 blur(16px) + opacity: 0.75 + 禁止命中,过渡 150ms 曲线 cubic-bezier(0,1,0,1))、「自动定位」按钮(EBD2)(:191-258);
    • 自动获取位置(仅 1):开关 AutoRefreshWeatherLocation,默认 false(Settings.cs:1841)。
  3. 分区「外观与高级设置」(图标 E713):
    • 「天气图标包」下拉:选项来自注册的天气图标模板,绑定 WeatherIconId,默认 "classisland.weatherIcons.lucide"(Settings.cs:1849),min-width: 120px;
    • 「排除的气象预警」:文本域(宽 260px、max-height: 200px、多行),绑定 ExcludedWeatherAlerts(字符串集合,一行一条);说明「包含以下字符串的预警将不会显示,一行一条排除项。」;
    • 「不使用 TLS 协议获取天气」开关:绑定 NoTLSWeatherRequests,默认 false(Settings.cs:1842)。
  4. 底部提示块(ControlFillColorDefaultBrush、圆角 8px、padding: 12px、font-size: 12px、opacity: 0.8):必须含两个跳转链接「【提醒】页面」→ classisland://app/settings/notification、「【组件】页面」→ classisland://app/settings/components(:321-329)。

10.4.12 自动化(id automation,图标 EEF1/EEF0,分组:Internal 无分组)

源 AutomationSettingsPage.axaml。

  1. 首次使用须知页(IsAutomationWarningVisible === true 时整页替换,默认 true,Settings.cs:161):居中,顶部 75×75 应用图标 + 箭头(E00C,25px,左右 margin: 16px)+ 75×75 自动化图标;标题「自动化」;正文两行(带全角缩进)「 欢迎使用自动化!」「 自动化可以使 ClassIsland 根据条件自行动出行动,」「 比如修改应用设置、打开应用,等等。」;「阅读自动化帮助」链接按钮(E C2D,主色);警告框(SystemFillColorCautionBackgroundBrush,padding: 10px 10px 14px,圆角 4px):图标 F430 + 「警告」+ 正文「自动化允许自动修改 ClassIsland 的各项设置,并调用」「 外部程序,可能有一定安全风险。」「 不当的自动化编写可能对正常教学造成影响,请勿滥用。」;底部 accent 按钮「同意并开始使用自动化」(E424)(:333-400)。
  2. 主界面(两栏 ListDetailView):左栏:
    • 「启用自动化」卡片:开关绑定 IsAutomationEnabled(默认 false,Settings.cs:160),右侧带「帮助…」按钮(E23C,tooltip「打开自动化帮助文档…」);该卡片自适应宽度阈值必须设为 495px(:25-49);
    • 操作行:「添加自动化」按钮(E00D,主色,tooltip「添加一个自动化。」);右侧配置方案下拉(min-width: 120、max-width: 150,绑定 CurrentAutomationConfig,默认 "Default",Settings.cs:162,打开下拉时刷新列表)+「新建…」(E689)+「打开…」(E88D);
    • 自动化列表:每项高 42px,结构 拖拽把手(20) + 名称(13px Medium) + WorkflowProgressIndicator(透明度 0→1,过渡 100ms) + 启用开关;列表项可拖拽排序(垂直方向阈值 3px)(:87-157)。
  3. 右栏标题区(选中自动化后):自动化名称文本框(min-width: 150、font-size: 15px Medium、水印「自动化名称」)+「启用恢复」复选框(tooltip「该自动化是否启用恢复。」)+ 运行状态控件 + 分隔竖线(1×25px,TextFillColorDisabledBrush)+「复制」按钮(E58B)+「删除」按钮(E61D,IndianRed);该组容器最小宽度按恢复开关状态为 359px 或 391px(:161-217)。
  4. 右栏编辑器(三个 Expander,均默认展开,间距 margin: 2px 2px 2px 10px,标题栏背景 CustomizedAccentBarBackground1Brush):
    • 「当事件触发时」(图标 E84F):触发器设置控件(绑定 Triggers);
    • 「并且满足规则集时」(图标 F17E):标题行右侧开关绑定 IsConditionEnabled;关闭时显示「工作流运行时不会考虑规则集。」;
    • 「触发行动」(图标 E01F):行动设置控件(绑定 ActionSet);
    • 若 ActionSet.IsRevertEnabled 为真,底部显示提示行(图标 E01D)「当规则集不再满足时,将自动恢复行动。」(:223-323)。
  5. 未选中自动化时的空态:居中 75×75 贴纸(光辉矢愿_瞄准.png,缺失时回退图标 EEF1)+ 「在左侧选择或添加一个自动化,然后在此处进行设置。」+「阅读自动化帮助」链接(:299-320)。

10.4.13 更新(id update,图标 E161/E160,分组:Internal 无分组;仅当打包类型允许更新时注册)

源 UpdateSettingsPage.axaml。

  1. 状态头部:左侧 48px FluentIcon,图标随 LastUpdateStatus 变化;当「正在下载更新」时图标以 1s 无限循环旋转(cubic-bezier(0.50,0.25,0.50,0.75),0°→360°)(:77-134)。右侧第一行 font-size: 24px Medium 的状态文案;第二行:已是最新时显示「上次检查更新时间:{LastCheckUpdateTime}」,否则显示「发现新版本:{DistributionInfo.Version}」。
  2. InfoBar:网络错误(Error,可关闭,标题「更新时发生错误,请检查您的网络连接并重试。」+ 异常消息)、部署错误(Error,可关闭,标题「部署时发生错误,请稍后重试。」)、已部署(Informational,标题「更新将在重启后应用」,正文「已成功部署更新,下次启动应用时将启动新版本。您也可以现在重启以立即使用新版本的 ClassIsland。」)(:135-152)。
  3. 操作按钮(随状态切换,AnimatedPanel 自适应换行,非 Idle 时整体禁用):
    • 已是最新:「检查更新」(accent);
    • 有更新:「下载并安装」(accent SplitButton,Flyout 含「仅下载」)、「检查更新」;
    • 已下载:「安装更新」(accent);
    • 已部署:「重启并应用更新」(accent);
    • 非「已是最新/已部署」状态另有一个「检查更新」普通按钮(:153-225)。
  4. 下载进度区(非 Idle 时可见):ProgressBar(max = DownloadingCountTotal,value = DownloadedCount,非「下载更新」状态或进度不确定时为 indeterminate)+ 状态文案(UpdateWorkingStatus 映射);另有两个按钮「查看下载状态」(打开宽度 450px 的下载任务抽屉)、「取消」(仅下载中显示)(:227-277)。
  5. TabControl(compact,Idle 时可用):
    • 「更新日志」:Markdown 渲染 NewVersionChangeLogDocument;已是最新时显示 81×81 贴纸(光辉矢愿_遨游.png)+ 「已经是最新版啦,真棒,夸夸你哦♪」(禁用彩蛋时改为「真棒,您已更新到最新版本!」)+「查看更新日志」按钮(打开宽度 500px 的更新日志抽屉)(:291-341);
    • 「更新设置」:「更新模式」下拉(从不自动更新(0)/自动检查更新并通知(1)/自动检查更新并下载(2)/自动检查更新并安装(3),绑定 UpdateMode,默认 3,Settings.cs:77);「更新通道」下拉(选项来自分发元数据,绑定 SelectedUpdateChannelV3,默认 Guid.Empty,Settings.cs:1854)+ 当前通道描述 + 「强制检查更新」(可点击行,图标 E44E,说明「强制将应用更新到当前通道上的最新版本,即使此版本比应用当前版本更旧。」)(:342-385);
    • 「(debug)调试设置」页签仅开发版显示:覆盖 PDC 根 Url(DebugPhainonRootUrlOverride)、覆盖子频道(DebugSubChannelOverride)、覆盖元数据公钥(DebugPublicKeyOverride,多行)(:386-399)。

10.4.14 插件(id classisland.plugins,图标 E071/E071,External;[FullWidthPage] 全宽)

源 PluginsSettingsPage.axaml(884 行)。

  1. 首次使用警告页(IsPluginMarketWarningVisible,默认 true,Settings.cs:204):居中,75×75 应用图标 + E00C(25px)+ 75×75 插件图标 E070;标题「插件」;正文「欢迎使用插件!插件可以扩展 ClassIsland 的功能,比如添加一个组件,或者和其它软件联动,等等。」;警告框(宽 320px,SystemFillColorCautionBackgroundBrush,圆角 4px,padding: 8px)文案必须完整保留(含「插件可以以 ClassIsland 的身份使用各项系统资源并请求任意权限……」);底部 accent 按钮「同意并开始使用插件」(E424)。整个主界面在此状态下必须 IsEnabled=false(:509-511、:768-823)。
  2. 主布局:两栏,左栏 margin: 4px 0:
    • 顶部搜索框(水印「搜索插件…」,左侧 EEF3 图标,padding: 26px 4px、border-thickness: 0),支持 Enter/输入过滤(:518-531);
    • 下方工具栏:TabStrip(市场(0)/已安装(1),compact)+「刷新」按钮(E0B5)+「更多选项…」(EBAC)菜单:从缓存重载插件源(E0B5)、管理插件源…(E99A)、插件更新设置…(E161)、分隔线、从本地安装…(E071)、分隔线、打开插件文件夹…(E88D);加载插件源时工具栏下方显示不确定 ProgressBar(:532-576);
    • 插件列表项:48×48 图标(margin-right: 6px)+ 名称(16px Medium)+ 描述(12px)+ 右侧状态图标组(下载量、Stars、卸载待重启、需重启 E0BC、错误 E808、有更新 E1A0、已安装 E5AC,均 16×16)+ 操作按钮组(安装/更新 28×28 圆角按钮、进度环 28×28、重启按钮、启用复选框);本地插件项 opacity 规则:未加载本地插件 0.75、已加载 1、市场项 1(:577-756);
    • 空列表模板:居中 72×72 贴纸(光辉矢愿_不可以看.png)+ 「找不到符合条件的插件,请调整筛选条件后重试」(本地且无插件时改为「还没有安装任何插件,不妨去插件市场看看吧」+「前往插件市场」按钮 F08B)(:461-505)。
  3. 右栏详情(选中插件):头部 60×60 图标(margin-right: 8px)+ 名称(24px Medium)+ 元信息行「版本 | 项目主页 | 作者 |」+ 状态胶囊(圆角 999px、padding: 10px 3px):已加载(SystemFillColorSuccessBackgroundBrush,E426)、已禁用(CardBackgroundFillColorSecondaryBrush,E673)、错误(SystemFillColorCriticalBackgroundBrush,E673)、未加载;操作区:已启用复选框、更新按钮(E1A0)、移除按钮(E61D)、撤销移除(E625)、安装(E0D3)、重启以应用更改(E0BD)、OS 不兼容 Warning InfoBar、下载进度条、下载失败 Error InfoBar(含「更换插件镜像源」链接)(:30-221);
    • 详情 TabStrip(compact)三个页签:概览(Markdown 渲染插件 README,加载时顶部 3px 不确定进度条)、错误信息(仅异常时显示页签,可选择文本)、依赖项(DataGrid:列「插件 ID」*、列「必选?」80px 复选框列,font-size: 14px)(:222-293)。
  4. 插件更新设置抽屉(宽 320px):两个复选框「插件有更新时通知我」(IsPluginsUpdateNotificationEnabled,默认 true,Settings.cs:1859)、「自动更新插件」(IsPluginsAutoUpdateEnabled,默认 true,Settings.cs:1858)(:297-308)。
  5. 管理插件源抽屉(宽 500px):内置插件源镜像下拉(OfficialSelectedMirror,默认 "github";镜像字典默认含 github→https://github.com、ghproxy→https://mirror.ghproxy.com/https://github.com、moeyy→https://github.moeyy.xyz/https://github.com,Settings.cs:171-176);复选框「忽略 SSL/TLS 证书错误」(IgnoreSslForPluginMirrors,默认 false);自定义插件源表格(列:Url 4* 可编辑、镜像 * 下拉),上方「添加」「删除」按钮(:310-384)。
  6. 安装确认对话框:宽约 400【推断】,内容为插件预览卡片(图标 48×48 圆角 4px、名称 16px Bold、作者 12px opacity: 0.7、版本 v{0}、描述 12px),底部警告条「安装未知来源的插件可能存在风险。」(SystemFillColorCautionBackgroundBrush、padding: 10px、圆角 6px),max-height: 400px 滚动(:387-459)。
  7. 拖拽安装遮罩:整页半透明遮罩(opacity: 0.75)+ 居中卡片(max-width: 420px、圆角 12px、padding: 20px、ControlFillColorDefaultBrush 背景、CardStrokeColorDefaultBrush 边框):80px 图标(合法 E162 / 非法 EA39)+ 粗体提示 + 副提示 + 「共 N 个文件,识别到 M 个插件包」(12px,opacity: 0.55)。解析本地插件时另显示全屏遮罩 + 64×64 进度环 + 「正在解析...」(:825-882)。

10.4.15 主题(id classisland.themes,图标 E6AF/E6AE,External)

源 ThemesSettingsPage.axaml。

  1. 首次使用警告页(IsThemeWarningVisible,默认 true,Settings.cs:1848):75×75 应用图标 + E00C + 主题图标 E6AF(75×75);标题「主题」;正文「欢迎使用主题!主题可以修改甚至完全重塑 ClassIsland 主界面的外观。您可以使用主题功能打造出独一无二的 ClassIsland 界面。」;警告框宽 320px(SystemFillColorCautionBackgroundBrush,圆角 4px,padding: 8px)文案必须完整保留(含「主题在加载过程中会转译为可执行代码,可以以 ClassIsland 的身份和权限执行任意代码」);accent 按钮「同意并开始使用主题」(E424)(:309-366)。
  2. InfoBar(同意后可见):消息「在启用了支持的主题(如 Fluent)后,您可以在直接【外观】设置中开启【分体主界面】选项使主界面分开。……」,右侧「前往【外观】设置」链接;受 IsThemeSeparateInfoVisible 控制可关闭(:77-84)。
  3. 工具栏:TabStrip(市场(0)/已安装(1),compact);右侧 4 个透明按钮:刷新市场(E0B5)、重载主题(E0BD)、打开主题文件夹…(E88D)、主题加载顺序(E13F)(:86-112)。
  4. 主题卡片网格:ListBox + WrapPanel(item-height: 150px,行为按目标宽度 328px 自动换列)。卡片:圆角 4px、边框 1px、裁剪溢出;结构 = 横幅图(UniformToFill)+ 底部渐变遮罩(不透明遮罩从 0%/65% 透明到 100% 不透明)+ 底部文字区(名称 16px Medium + 作者 12px + 网站按钮 E905)+ 右侧操作(错误 E808 红色、更多选项 EBAC:打开主题文件夹…/打包主题…/卸载主题/撤销卸载、安装按钮 E0D2 28×28 主色圆角 14px、更新按钮 E1A0、下载进度环 28×28、重启按钮 E0BC、启用开关);未加载的本地主题 opacity: 0.8(:120-307)。
  5. 主题加载顺序抽屉(宽 300px):标题「主题加载顺序」,说明「主题将按照以下的顺序加载,后加载的主题可以覆盖前面主题的样式。拖动以对主题进行排序。」;列表项 = 拖拽把手 + 主题名;仅支持垂直拖拽(水平阈值 33550336 即禁用、垂直阈值 3px)(:35-67)。
  6. 错误信息抽屉(宽 450px):标题「错误信息」+ 只读等宽文本框(:24-30)。

10.4.16 调试(id debug,图标 E2C8/E2C7,Debug)

源 DebugPage.axaml。仅当 IsDebugOptionsEnabled 为真且未禁用调试菜单时出现在导航中;页内必须整体受 DisableDebugMenu 控制可见性。

  1. 顶部不可关闭 Error InfoBar:「仅供调试,除非你能知道您在做什么,请不要使用以下按钮。」(:17-20)。
  2. 「启用调试菜单」卡片:开关 IsDebugOptionsEnabled(默认 false,Settings.cs:79);子项:调试菜单开关 IsDebugEnabled(默认 false)、主窗口调试界面开关 IsMainWindowDebugEnabled(默认 false)。
  3. 「调试时间偏移」:日期选择器 + 时间选择器(含秒)+「重置」按钮;修改后必须以 DebugTimeOffsetSeconds(默认 0,Settings.cs:112)驱动全局时间;DebugTimeSpeed 默认 1.0(Settings.cs:111)。
  4. 「课程服务」四个可点击行:触发上课、触发下课、启动主计时器、停止主计时器。
  5. 「应用设置」三个可点击行:覆盖设置版本、显示插件使用须知(重置 IsPluginMarketWarningVisible = true)、显示自动化使用须知(重置 IsAutomationWarningVisible = true)。
  6. 「功能测试」:转储课表关系图、打开 Markdown 文档、显示测试通知、测试定位、「正在集控管理」开关(只读显示)。
  7. 「垃圾回收」:整卡可点击,执行 GC.Collect()。
  8. 「时间流速」:数值框(min-width: 102,绑定 DebugTimeSpeed)+ 重置按钮(E4CC)。
  9. 「危险操作」:崩溃测试、崩溃测试(延迟 3 秒)、崩溃测试(Task)、崩溃测试(扔到栈顶)、Environment.FailFast();(:22-130)。

10.4.17 关于 ClassIsland(id about,图标 E9E4/E9E3,About)

源 AboutSettingsPage.axaml。必须实现为「吸顶大图 + 卡片组」:

  1. 头部:StickyScrollViewer(折叠后高度 58px),头部内容最大高度 300px,横幅图 BannerMain_App2.png 居中最大宽 960px,底部叠加标题「关于 ClassIsland」(TitleTextBlockStyle);头部背景为 #0d1111,左右各一块径向渐变(#ff0c0e1f → #ff0d1111),渐变光晕出现动画:延迟 250ms、时长 200ms、曲线 cubic-bezier(0,0,0,1),透明度 0 → 1;横幅文字区不透明度随滚动由 StickyScrollViewer.HeaderFadingOpacity 渐隐(:117-186)。
  2. 四张卡片(默认全部展开):
    • 「ClassIsland」卡片:AppLogo.png 图标,右侧显示版本号(12px,次级色);子项正文「本项目基于 GNU General Public License v3.0 获得许可。」+「开放源代码许可」「隐私政策」超链接(超链接 padding: 4px、margin: 2px)+「Copyright (c) 2023-{当前年份} HelloWRC」;子项「常用链接」:项目主页、帮助文档、GitHub、加入社区;
    • 「遇到问题?」卡片:问题反馈/功能建议、功能投票、查看诊断信息(诊断信息抽屉 550×400,等宽字体只读文本框);
    • 「鸣谢」卡片:贡献人员(抽屉宽 300px,含说明、刷新按钮、名单列表:头像 32×32 圆角 16px + 姓名 15px + 贡献 11px Light)、第三方库(抽屉宽 300px,列表项由图标 E07D、包名 14px Bold、网站/许可证链接组成;许可证文本抽屉为等宽只读文本框);
    • 「回声洞」卡片:可点击行内逐字打字机效果显示随机文案(点击后重播)(:188-309);
    • 底部居中文案(13px,次级):「谨以此应用,献给现在或曾经陪伴着我的同学们。愿时光流转,各位能与所念之人重逢。」(:311-316)。

10.4.18 集控 / 集控凭据 / 集控策略(id management、management.credentials、management.policy,About,hideDefault)

源 ManagementSettingsPage.axaml、ManagementCredentialsSettingsPage.axaml、ManagementPolicySettingsPage.axaml。

  1. 集控页三组卡片:信息卡(标题「集控」+ 说明;受管时追加「您目前正在受 {OrganizationName} 的管理。」)、「加入管理」(未受管时显示;点击打开 JoinManagementDialog)、「了解更多」(跳转文档);「管理」卡(未受管时显示):「密码保护设置…」→ classisland://app/settings/management.credentials?ci_keepHistory=true、「限制策略…」→ classisland://app/settings/management.policy?ci_keepHistory=true;「客户端信息」卡:CUID(只读)、受管时显示 ID;受管时另显示「服务端信息」卡(服务端类型)(:17-115)。
  2. 集控策略页(必须整页在未通过「编辑策略」授权时保持锁定:IsEnabled 取 IsLocked 的反):
    • InfoBar:「部分策略设置可能需要重启才能生效。」+「重启应用」按钮;
    • 分区「档案」(图标 E699):禁止编辑档案(DisableProfileEditing)、禁止编辑课表(DisableProfileClassPlanEditing)、禁止编辑时间表(DisableProfileTimeLayoutEditing)、禁止编辑科目(DisableProfileSubjectsEditing),说明文案必须保留「临时换课和启用临时课表功能不受影响。」;
    • 分区「应用设置」(图标 EF27):禁止编辑应用设置(DisableSettingsEditing)、禁止自定义启动加载界面(DisableSplashCustomize)、禁用调试菜单(DisableDebugMenu);
    • 分区「杂项」(图标 EBAA):允许退出集控(AllowExitManagement)、禁用彩蛋(DisableEasterEggs)(:17-111)。
  3. 集控凭据页:
    • 分区「认证」(图标 EAF2):「用户认证方式」「管理员认证方式」两个 CredentialEditControl(可增删认证方式、可拖拽排序);
    • 分区「操作授权等级」(图标 E350):8 行「左标签 + 右下拉(无/用户/管理员)」,标签与绑定依次为:编辑授权设置(EditAuthorizeSettingsAuthorizeLevel)、编辑策略(EditPolicyAuthorizeLevel)、退出集控(ExitManagementAuthorizeLevel)、编辑课表(EditProfileAuthorizeLevel)、编辑应用设置(EditSettingsAuthorizeLevel)、换课(ChangeLessonsAuthorizeLevel)、退出应用(ExitApplicationAuthorizeLevel);图标依次 E350/E2B4/E2B8/E6BB/EF27/E15F/E0DF(:19-99)。

10.4.19 出错啦 / 404 页(id _error,About,hideDefault)

源 ErrorSettingsPage.axaml。居中布局(spacing: 8px):80×80 贴纸(帕姆_哭哭.png,缺失回退 E6BF 80px)→ 导航异常时显示「欧呦,出错啦!」(Subtitle)+「在尝试导航到请求的的页面时发生了一个未知错误,详细请见应用日志。」(13px);页面不存在时显示「404」(Subtitle)+「找不到请求的页面。」(13px)(:11-34)。

10.5 设置持久化、缓存与叠层(行为级要求)

  1. 即时保存。任何设置项的值发生变化后,必须立刻把整个配置(config.json,ClassIsland 对应 Settings.json)写盘(ClassIsland 在每个属性 setter 触发 OnPropertyChanged 后调用 SaveSettings(propertyName),见 repos/ClassIsland/ClassIsland/Services/SettingsService.cs:261-280、:171-179)。实现时:Pinia store 的每个 action 必须在修改状态后调度一次持久化(Electron 主进程写 userData/config/Settings.json),允许 requestAnimationFrame 级别的合并,但不得设置超过 300ms 的防抖【推断:300ms 为工程上限,源码为同步写盘】。
  2. 禁止自动保存的字段。标注 [JsonIgnore] 的派生字段(如 IsSentryEnabled 实际存于本地全局存储、ShowSellingAnnouncement)必须写入独立的 localStorage/global.json,不得写进 Settings.json(Settings.cs:518-535、:2615-2628)。
  3. 页面缓存策略。SettingsPagesCachePolicy:0 = 不缓存页面实例;1 = 仅在设置窗口打开期间缓存;>=2 = 跨打开会话缓存【推断:源码仅在 >=1 缓存、<=1 时关闭窗口清空,2 语义由此推得】(Settings.cs:213、SettingsWindowNew.axaml.cs:425-428、:513-516)。实现时映射为 Vue 的 <keep-alive :include> 控制:0 不缓存该页组件;1 缓存到窗口关闭;2 缓存到进程结束。
  4. 设置叠层(SettingsOverlay)。必须实现「叠层」机制以支持自动化/集控临时改设置:SettingsOverlays 为 Dictionary<propertyName, OrderedDictionary<key, value>>,JSON 键名必须序列化为 SettingsOverlay(旧版兼容,Settings.cs:263-273)。AddSettingsOverlay(guid, name, value) 的语义:首次写入时把当前值保存到键 "@",随后写入 guid 键并立即应用;RemoveSettingsOverlay(guid, name) 移除后必须以集合中最后一个值回滚属性,集合仅剩 1 项(即只剩 "@")时删除整个属性条目(SettingsService.cs:191-259)。任何用户在设置界面手动修改某属性时,必须移除该属性的全部叠层(同文件 :261-266)。
  5. 管理员策略限制。策略值来自集控清单(本地无集控时来自 Management.json),设置页必须在渲染时读取;对禁止编辑的页面必须整页禁用(如提醒页 IsEnabled = !DisableSettingsEditing,NotificationSettingsPage.axaml:44),而不是仅隐藏控件。策略项与设置项冲突时,以策略为准。
  6. 重启类设置。至少以下设置必须标记为「需要重启」并触发重启提示:AnimationLevel、IsWaitForTransientDisabled(GeneralSettingsPage.axaml.cs:37-44)、渲染模式、使用系统标题栏、兼容缩放模式(AdvancedSettingsPage,源码通过 ViewModel 写入设备级配置;重启需求为【推断】)。实现时必须提供统一的 requestRestart(reason) 接口。
  7. 不存在的功能。源码中没有设置搜索、没有「恢复默认值」全局按钮、没有设置项级重置按钮。实现者不得编造;如需增加,必须作为 P2 可选增强并在文档中标注。
  8. 文案常量集中。设置窗口与全部设置页的中文文案必须集中放在常量文件(固定路径 src/renderer/constants/texts.zh-CN.ts,按页面分节,与 part 11 的其它窗口共用同一文件),组件内只引用常量键、不得散落中文字面量;文案内容以本 part 与 part 11 给出的中文原文为准,后续接入 i18n 时以该常量文件为唯一来源。

10.6 键盘与交互细节

  1. Esc:优先关闭打开的抽屉;无抽屉时关闭「更多选项」菜单;再无效时不做任何事(不得关闭设置窗口)。
  2. 后退:Alt+← 不做映射(源码无此绑定)【推断:FluentAvalonia NavigationView 默认无该快捷键】;后退仅通过标题栏/页面内返回按钮触发。
  3. 拖动排序(组件行、提醒提供方、自动化、主题顺序)必须实现「水平方向禁用」的排序行为:HorizontalDragThreshold = 33550336、VerticalDragThreshold = 3,即只允许垂直拖动(多页一致,如 NotificationSettingsPage.axaml:92-102、ThemesSettingsPage.axaml:54-65)。
  4. 悬停提示必须使用 ToolTip,延迟约 400ms【推断】;滑块拖动时必须实时显示数值 tooltip。

10.7 验收标准

实现完成后,必须逐条自测并全部通过:

  1. 设置窗口首次打开宽 1240、高 550;把宽度拖到 799 时进入压缩导航,拖到 800 时恢复,最大化时导航始终展开。
  2. 左侧导航顺序与本文 10.2 第 4 条完全一致;「通用」与「主界面」为可展开分组,分组之间与分类块之间存在分隔线;「关于」块排在最后且不出现「集控凭据设置/集控策略/出错啦」。
  3. 打开「外观」页,把「背景不透明度」拖到 0.30 后关闭设置窗口再重开,值仍为 0.30,且 config.json 中 opacity 为 0.3(即时保存生效)。
  4. 打开「组件」页,能从组件库拖拽一个组件到某一行、能插入行、能删除行、能切换「主要行/提醒」开关,且变更立即写入组件配置。
  5. 打开「提醒」页,窗口宽度 < 800 时变为单栏、选中提供方后进入详情并可返回。
  6. 打开「天气」页,点击「编辑城市」弹出自右侧宽 320px 的抽屉,Esc 可关闭,遮罩点击可关闭,动画时长 250ms。
  7. 打开「主题」首次警告页点「同意并开始使用主题」后,警告页不再出现且主题网格可加载。
  8. 触发任何「需要重启」的设置后,标题栏出现「需要重启」按钮,点击弹出标题「需要重启」的对话框,「重启」按钮为默认按钮。
  9. 管理策略勾选「禁止编辑应用设置」并重启后:非关于类设置页从导航消失,窗口默认落在「关于 ClassIsland」。
  10. 所有数值与枚举必须与本文列出的默认值一致(可用 config.json 全文比对;每一处偏差都算失败)。