/** * QQ 适配器专属设置。 * * 这些项只在 QQ 平台生效(面板、切片、番剧选集表格、卡片 OCR), * 定义集中在 \`qqFields.json\` —— 两边共用同一份: * 1. Koishi 控制台的插件配置表单(\`qq\` 折叠组,见 \`src/index.ts\`); * 2. WebUI(\`/kkk\` 的「QQ 适配器」分类,见 \`scripts/patch-webui.mjs\`)。 * 改一处两边同步,不会出现「WebUI 有、控制台没有」。 */ import type { Schema } from 'koishi' import fields from './qqFields.json' export interface QqField { key: string group: string /** checkboxGroup = 多选(取值来自 options) */ type: 'boolean' | 'number' | 'string' | 'checkboxGroup' default: any label: string description: string /** checkboxGroup 的候选(面板/控制台都从这份生成) */ options?: Array<{ value: string; label: string }> min?: number max?: number secret?: boolean /** 只对 WebUI 有意义:renderIn 为 app 的字段,界面上归到这个小标题下 */ section?: string /** * 只对 WebUI 有意义:这个字段在什么条件下才可以编辑。 * `danmaku` = 只有把「强制不烧录弹幕」关掉(也就是打开弹幕功能)之后才能改。 */ editableWhen?: string } export const QQ_FIELDS = fields as QqField[] /** 表单里 QQ 分组的字段名 */ export const QQ_KEYS = QQ_FIELDS.map((field) => field.key) /** 缺省值表 */ export const QQ_DEFAULTS: Record = Object.fromEntries(QQ_FIELDS.map((field) => [field.key, field.default])) /** * 读当前值:优先读新的 \`config.qq.*\`,其次兼容早期写在顶层的同名字段,最后回退默认值。 */ export function readQqOptions (config: any): Record { const group = config?.qq ?? {} const result: Record = {} for (const field of QQ_FIELDS) { const value = group[field.key] ?? config?.[field.key] result[field.key] = value === undefined || value === null ? field.default : value } return result } /** * 生成控制台表单里的 QQ 分组。 * * \`Schema.intersect\` 里的分组名会被 \`apply\` 摊平回顶层(见 \`src/index.ts\`), * 插件内部照旧读 \`config.qqPanel\` 这种扁平字段。 */ export function buildQqSchema (Schema: Schema): Schema { const shape: Record = {} for (const field of QQ_FIELDS) { if (field.type === 'checkboxGroup') { const values = (field.options ?? []).map((option) => option.value) shape[field.key] = Schema.array(Schema.union(values.length ? values : [Schema.string()])) .default(field.default ?? []) .description(field.description) continue } const base = field.type === 'boolean' ? Schema.boolean() : field.type === 'number' ? Schema.number() : Schema.string() shape[field.key] = base.default(field.default).description(field.description) } return Schema.object(shape) }