diff --git a/Directory.Packages.props b/Directory.Packages.props index daa4de1..1a3166f 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -11,6 +11,7 @@ all + diff --git a/README.md b/README.md index b3057fa..993dcfe 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ Development 首次迁移会创建平台管理员 `admin@tiku.local`,随机临 默认开发入口: -- 平台管理端: +- 平台管理端:首次在 `Tiku.PlatformAdmin.Web` 执行 `npm install`;之后启动 `Tiku.Api` 时会在 Development 自动启动前端,访问 - Scalar: - OpenAPI: - Liveness: diff --git a/Tiku.Api/Configuration/ApplicationBuilderExtensions.cs b/Tiku.Api/Configuration/ApplicationBuilderExtensions.cs index 533216d..6f2d687 100644 --- a/Tiku.Api/Configuration/ApplicationBuilderExtensions.cs +++ b/Tiku.Api/Configuration/ApplicationBuilderExtensions.cs @@ -27,8 +27,6 @@ public static class ApplicationBuilderExtensions app.UseForwardedHeaders(); app.UseHttpsRedirection(); app.UseResponseCompression(); - app.UseDefaultFiles(); - app.UseStaticFiles(); app.UseRouting(); app.UseCors(CorsOptions.PolicyName); app.UseMiddleware(); diff --git a/Tiku.Api/Properties/launchSettings.json b/Tiku.Api/Properties/launchSettings.json index a0627a0..fd6b4bd 100644 --- a/Tiku.Api/Properties/launchSettings.json +++ b/Tiku.Api/Properties/launchSettings.json @@ -7,7 +7,8 @@ "launchBrowser": false, "applicationUrl": "http://localhost:5090", "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" + "ASPNETCORE_ENVIRONMENT": "Development", + "ASPNETCORE_HOSTINGSTARTUPASSEMBLIES": "Microsoft.AspNetCore.SpaProxy" } }, "https": { @@ -16,7 +17,8 @@ "launchBrowser": false, "applicationUrl": "https://localhost:7093;http://localhost:5090", "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" + "ASPNETCORE_ENVIRONMENT": "Development", + "ASPNETCORE_HOSTINGSTARTUPASSEMBLIES": "Microsoft.AspNetCore.SpaProxy" } } } diff --git a/Tiku.Api/Tiku.Api.csproj b/Tiku.Api/Tiku.Api.csproj index 7596c43..edbb1c5 100644 --- a/Tiku.Api/Tiku.Api.csproj +++ b/Tiku.Api/Tiku.Api.csproj @@ -6,6 +6,9 @@ enable true $(NoWarn);1591 + ..\Tiku.PlatformAdmin.Web\ + http://localhost:5173 + npm run dev @@ -16,6 +19,7 @@ + diff --git a/Tiku.Api/wwwroot/.gitkeep b/Tiku.Api/wwwroot/.gitkeep new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/Tiku.Api/wwwroot/.gitkeep @@ -0,0 +1 @@ + diff --git a/Tiku.Api/wwwroot/platform-admin/app.js b/Tiku.Api/wwwroot/platform-admin/app.js deleted file mode 100644 index 58a7bfd..0000000 --- a/Tiku.Api/wwwroot/platform-admin/app.js +++ /dev/null @@ -1,1756 +0,0 @@ -const mainView = document.querySelector('#mainView'); -const sideNav = document.querySelector('#sideNav'); -const pageTitle = document.querySelector('#pageTitle'); -const toast = document.querySelector('.toast'); -const app = document.querySelector('.platform-app'); -const overlayRoot = document.querySelector('#overlayRoot'); -const roleSelect = document.querySelector('#roleSelect'); -const scenarioSelect = document.querySelector('#scenarioSelect'); -const responseSelect = document.querySelector('#responseSelect'); -const menuButton = document.querySelector('#menuButton'); -const taskCount = document.querySelector('#taskCount'); -const alertCount = document.querySelector('#alertCount'); -const platformApi = window.GongxuePlatformApi; -const STORAGE_KEY = 'gongxue-platform-spec-v1.1'; -const TENANT_PORTAL_ORIGIN = 'http://127.0.0.1:4174/'; -const HISTORY_APP_KEY = 'gongxuePlatform'; -const API_CONNECTED_PAGES = new Set([ - 'overview', - 'tenants', - 'domains', - 'tenantDetail', - 'billingProfile', - 'subscriptions', - 'catalog', - 'saasFinance', - 'billing', - 'usage', - 'dunning', - 'bank', - 'crm', - 'sms', - 'paymentSettings', - 'staff', - 'roles', - 'audit', - 'alerts', -]); - -const pageMeta = { - overview: { id: 'P-01', title: '平台经营工作台', permission: 'platform:overview:read' }, - tenants: { id: 'P-02', title: '租户列表与创建', permission: 'platform:tenant:read' }, - domains: { id: 'P-02A', title: '租户域名与证书', permission: 'platform:tenant:read' }, - tenantDetail: { id: 'P-03', title: '租户详情与生命周期', permission: 'platform:tenant:read', level: 2 }, - billingProfile: { id: 'P-04', title: '租户账务资料', permission: 'platform:tenant:billing_profile', level: 3 }, - subscriptions: { id: 'P-05', title: 'SaaS 套餐与订阅', permission: 'platform:plan:read' }, - catalog: { id: 'P-05A', title: 'SaaS 商品与版本', permission: 'platform:plan:read' }, - saasFinance: { id: 'P-05B', title: 'SaaS 订单与交易', permission: 'platform:billing:read' }, - billing: { id: 'P-06', title: '服务费账单', permission: 'platform:billing:read' }, - usage: { id: 'P-07', title: '用量与超额计费', permission: 'platform:usage:read' }, - dunning: { id: 'P-08', title: '收款、逾期与催缴', permission: 'platform:billing:read' }, - bank: { id: 'P-09', title: '公共题库', permission: 'platform:question-bank:manage' }, - crm: { id: 'P-10', title: 'CRM 接入与线索流转', permission: 'platform:crm:read' }, - sms: { id: 'P-11', title: 'SMS 短信服务', permission: 'platform:sms:read' }, - paymentSettings: { id: 'P-12', title: '支付设置', permission: 'platform:payment:read' }, - staff: { id: 'P-13', title: '平台员工与权限', permission: 'platform:staff:read' }, - roles: { id: 'P-13A', title: '平台角色与功能', permission: 'platform:staff:read' }, - audit: { id: 'P-14', title: '平台审计日志', permission: 'platform:audit:read' }, - alerts: { id: 'P-15', title: '审计告警与通知', permission: 'platform:audit:alert' }, -}; - -const navGroups = [ - ['平台概览', [['overview', 'gauge', '经营工作台']]], - ['租户管理', [['tenants', 'building-2', '租户列表'], ['domains', 'globe-2', '域名与证书']]], - ['SaaS 商品与账务', [['catalog', 'packages', '商品与版本'], ['subscriptions', 'badge-check', '租户订阅'], ['saasFinance', 'landmark', '订单与交易'], ['billing', 'receipt-text', '服务费账单'], ['usage', 'chart-column-big', '用量与超额'], ['dunning', 'bell-ring', '收款与催缴']]], - ['平台资产', [['bank', 'database-zap', '公共题库']]], - ['租户能力', [['crm', 'handshake', 'CRM 接入'], ['sms', 'message-square-text', '短信服务'], ['paymentSettings', 'credit-card', '支付设置']]], - ['安全治理', [['staff', 'user-cog', '平台员工'], ['roles', 'shield-check', '角色与功能'], ['audit', 'scroll-text', '审计日志'], ['alerts', 'shield-alert', '告警与通知']]], -]; - -const roleDefinitions = { - super: { label: '超级管理员', permissions: ['*'] }, - tenant_ops: { label: '租户运营', permissions: ['platform:overview:read', 'platform:tenant:read', 'platform:tenant:write', 'platform:tenant:status', 'platform:tenant:billing_profile', 'platform:plan:read', 'platform:billing:read', 'platform:crm:read', 'platform:crm:write', 'platform:sms:read', 'platform:sms:write'] }, - finance: { label: '平台财务', permissions: ['platform:overview:read', 'platform:tenant:read', 'platform:tenant:billing_profile', 'platform:plan:read', 'platform:billing:read', 'platform:billing:write', 'platform:billing:payment', 'platform:billing:dunning', 'platform:billing:notification', 'platform:usage:read', 'platform:usage:write', 'platform:payment:read', 'platform:payment:write', 'platform:audit:read'] }, - audit: { label: '安全审计', permissions: ['platform:overview:read', 'platform:audit:read', 'platform:audit:export', 'platform:audit:alert', 'platform:audit:notification'] }, - bank_ops: { label: '题库运营', permissions: ['platform:dashboard:view', 'platform:question-bank:manage'] }, - readonly: { label: '只读观察员', permissions: ['platform:overview:read', 'platform:tenant:read', 'platform:plan:read', 'platform:billing:read', 'platform:crm:read', 'platform:sms:read', 'platform:payment:read', 'platform:audit:read'] }, -}; - -const seed = { - version: 11, - tenants: [ - { id: 'tenant_gongxue_tj', slug: 'gongxue-tj', name: '恭学教育 · 天津', legal: '天津恭学教育科技有限公司', brand: '恭学教育', shortName: '恭学天津', host: 'study.gongxue.cn', plan: '旗舰版', planCode: 'enterprise', status: '正常', billing: '正常', mode: '正式', students: 2846, questions: 42680, storageGB: 186, trafficTB: 1.8, expires: '2027-07-22', balance: 0, owner: '张校长', ownerPhone: '138****6008', createdAt: '2025-07-22 10:18' }, - { id: 'tenant_qihang_gd', slug: 'qihang-gd', name: '启航专升本 · 广东', legal: '广州启航教育咨询有限公司', brand: '启航专升本', shortName: '启航广东', host: 'study.qihangzsb.cn', plan: '专业版', planCode: 'pro', status: '正常', billing: '待付款', mode: '正式', students: 5280, questions: 68420, storageGB: 248, trafficTB: 3.2, expires: '2026-08-05', balance: 12800, owner: '林老师', ownerPhone: '139****2288', createdAt: '2025-08-05 09:12' }, - { id: 'tenant_bosi_sd', slug: 'bosi-sd', name: '博思升本 · 山东', legal: '山东博思教育集团有限公司', brand: '博思升本', shortName: '博思山东', host: 'tiku.bosiedu.cn', plan: '基础版', planCode: 'basic', status: '试用', billing: '正常', mode: '试用', students: 642, questions: 12860, storageGB: 42, trafficTB: .6, expires: '2026-08-12', balance: 0, owner: '孙老师', ownerPhone: '136****1209', createdAt: '2026-07-12 14:20' }, - { id: 'tenant_mingtu_hn', slug: 'mingtu-hn', name: '明途教育 · 河南', legal: '郑州明途教育科技有限公司', brand: '明途教育', shortName: '明途河南', host: 'learn.mingtu.cn', plan: '基础版', planCode: 'basic', status: '暂停', billing: '逾期', mode: '正式', students: 1280, questions: 18620, storageGB: 86, trafficTB: .9, expires: '2026-07-18', balance: 8600, owner: '魏校长', ownerPhone: '135****8806', createdAt: '2025-01-18 11:03' }, - { id: 'tenant_xuezhi_heb', slug: 'xuezhi-heb', name: '学知专接本 · 河北', legal: '石家庄学知教育有限公司', brand: '学知专接本', shortName: '学知河北', host: 'app.xuezhizjb.cn', plan: '专业版', planCode: 'pro', status: '正常', billing: '正常', mode: '正式', students: 3160, questions: 39860, storageGB: 164, trafficTB: 2.1, expires: '2027-01-08', balance: 0, owner: '赵老师', ownerPhone: '137****6116', createdAt: '2025-01-08 08:40' }, - { id: 'tenant_youcai_js', slug: 'youcai-js', name: '优才专转本 · 江苏', legal: '南京优才教育科技有限公司', brand: '优才专转本', shortName: '优才江苏', host: 'study.youcai.cn', plan: '专业版', planCode: 'pro', status: '待配置', billing: '正常', mode: '试用', students: 0, questions: 0, storageGB: 0, trafficTB: 0, expires: '', balance: 0, owner: '顾老师', ownerPhone: '138****1120', createdAt: '2026-07-22 16:08' }, - ], - domains: [], - saasCatalog: { features: [], limitDefinitions: [], offerings: [], versions: [] }, - saasOrders: [], - saasRefunds: [], - paymentChannels: [], - rebateSummary: {}, - crmLogs: [], - billingProfiles: { - tenant_gongxue_tj: { billingName: '天津恭学教育科技有限公司', taxId: '91120101MA07GX2026', contactName: '李会计', phone: '13800138000', email: 'finance@gongxue.cn', billingAddress: '天津市南开区科研西路 12 号', invoiceTitle: '天津恭学教育科技有限公司', type: '增值税专用发票', bankName: '招商银行天津南开支行', bankAccountMasked: '**** **** **** 8826' }, - tenant_qihang_gd: { billingName: '广州启航教育咨询有限公司', taxId: '91440101MA5QH2026X', contactName: '黄会计', phone: '13900139000', email: 'billing@qihangzsb.cn', billingAddress: '广州市天河区科韵路 18 号', invoiceTitle: '广州启航教育咨询有限公司', type: '增值税普通发票', bankName: '中国银行广州天河支行', bankAccountMasked: '**** **** **** 6672' }, - }, - plans: [ - { code: 'basic', name: '基础版', description: '适合单地区小型机构', cycle: '年度', amount: 4800, quotas: ['2,000 学生席位', '30,000 题目', '100 GB 存储', '基础内容运营'], tenantCount: 12 }, - { code: 'pro', name: '专业版', description: '适合成熟区域型机构', cycle: '年度', amount: 9800, quotas: ['8,000 学生席位', '100,000 题目', '500 GB 存储', 'CRM 与营销能力'], tenantCount: 24 }, - { code: 'enterprise', name: '旗舰版', description: '适合多校区与高内容规模', cycle: '年度', amount: 16800, quotas: ['20,000 学生席位', '300,000 题目', '2 TB 存储', '财务对账与高级审计'], tenantCount: 12 }, - ], - subscriptions: [ - { id: 'SUB-202607-001', tenantId: 'tenant_gongxue_tj', planCode: 'enterprise', status: '活跃', cycle: '年度', amount: 16800, start: '2026-07-22', expires: '2027-07-22', autoRenew: true }, - { id: 'SUB-202608-002', tenantId: 'tenant_qihang_gd', planCode: 'pro', status: '活跃', cycle: '年度', amount: 9800, start: '2025-08-05', expires: '2026-08-05', autoRenew: true }, - { id: 'SUB-TRIAL-003', tenantId: 'tenant_bosi_sd', planCode: 'basic', status: '试用中', cycle: '试用', amount: 0, start: '2026-07-12', expires: '2026-08-12', autoRenew: false }, - { id: 'SUB-202501-004', tenantId: 'tenant_mingtu_hn', planCode: 'basic', status: '暂停', cycle: '年度', amount: 4800, start: '2025-01-18', expires: '2026-07-18', autoRenew: false }, - { id: 'SUB-202601-005', tenantId: 'tenant_xuezhi_heb', planCode: 'pro', status: '活跃', cycle: '年度', amount: 9800, start: '2026-01-08', expires: '2027-01-08', autoRenew: true }, - ], - invoices: [ - { id: 'INV-202607-0018', tenantId: 'tenant_qihang_gd', type: '订阅服务费', period: '2026年7月', total: 12800, paid: 0, balance: 12800, due: '2026-08-05', status: '待付款', note: '2026年7月服务费' }, - { id: 'INV-202607-0017', tenantId: 'tenant_mingtu_hn', type: '订阅服务费', period: '2026年7月', total: 8600, paid: 0, balance: 8600, due: '2026-07-18', status: '已逾期', note: '2026年7月服务费' }, - { id: 'INV-202607-0016', tenantId: 'tenant_gongxue_tj', type: '订阅服务费', period: '2026年7月', total: 16800, paid: 16800, balance: 0, due: '2026-07-15', status: '已支付', note: '2026年7月服务费' }, - { id: 'INV-202607-0015', tenantId: 'tenant_xuezhi_heb', type: '订阅服务费', period: '2026年7月', total: 9800, paid: 9800, balance: 0, due: '2026-07-15', status: '已支付', note: '2026年7月服务费' }, - ], - billingPayments: [], - usage: [ - { tenantId: 'tenant_gongxue_tj', period: '2026-07', source: 'Worker 自动采集', students: 2846, questions: 42680, storageGB: 186, trafficTB: 1.8, overage: [], estimated: 0 }, - { tenantId: 'tenant_qihang_gd', period: '2026-07', source: 'Worker 自动采集', students: 5280, questions: 68420, storageGB: 248, trafficTB: 3.2, overage: ['流量'], estimated: 7820 }, - { tenantId: 'tenant_bosi_sd', period: '2026-07', source: 'Worker 自动采集', students: 642, questions: 12860, storageGB: 42, trafficTB: .6, overage: [], estimated: 0 }, - { tenantId: 'tenant_mingtu_hn', period: '2026-07', source: '人工补录', students: 1280, questions: 18620, storageGB: 86, trafficTB: .9, overage: ['题目', '存储'], estimated: 4260 }, - { tenantId: 'tenant_xuezhi_heb', period: '2026-07', source: 'Worker 自动采集', students: 3160, questions: 39860, storageGB: 164, trafficTB: 2.1, overage: [], estimated: 0 }, - ], - reminders: [ - { id: 'REM-260723-01', invoiceId: 'INV-202607-0017', tenantId: 'tenant_mingtu_hn', level: 3, channel: '邮件 + 短信', status: '已送达', date: '2026-07-23 09:20', message: '服务费账单已逾期 5 天,请尽快处理。' }, - { id: 'REM-260722-02', invoiceId: 'INV-202607-0018', tenantId: 'tenant_qihang_gd', level: 1, channel: '邮件', status: '已送达', date: '2026-07-22 15:40', message: '账单将在 13 天后到期。' }, - ], - dunningChannels: [ - { id: 'DUN-EMAIL', code: 'finance_email', name: '财务邮件', provider: 'SMTP', endpoint: 'finance@gongxue.cn', enabled: true, retry: 3 }, - { id: 'DUN-WX', code: 'finance_wecom', name: '财务企微群', provider: 'Webhook', endpoint: 'https://qyapi.weixin.qq.com/***', enabled: true, retry: 5 }, - ], - banks: [ - { id: 'QB-TJ-MATH', name: '高等数学公共题库', catalog: '天津专升本 / 高等数学', source: '平台自建', questions: 12860, version: 'v2026.7', status: '稳定版' }, - { id: 'QB-EN', name: '公共英语能力库', catalog: '全国 / 公共英语', source: '平台自建', questions: 86640, version: 'v2026.6', status: '稳定版' }, - { id: 'QB-SD', name: '山东专升本全科', catalog: '山东专升本', source: '合作内容方', questions: 52360, version: 'v2026.7', status: '稳定版' }, - ], - bankNodes: [ - { id: 'NODE-MATH', questionBankId: 'QB-TJ-MATH', parentId: null, name: '高等数学', nodeType: 'subject', depth: 0, sortOrder: 0, isActive: true, questionCount: 12860 }, - { id: 'NODE-MATH-01', questionBankId: 'QB-TJ-MATH', parentId: 'NODE-MATH', name: '函数、极限与连续', nodeType: 'chapter', depth: 1, sortOrder: 0, isActive: true, questionCount: 1260 }, - ], - bankQuestions: [], - bankImportResult: null, - crmConfigs: [ - { id: 'CRM-GX-TJ', tenantId: 'tenant_gongxue_tj', provider: '标准 CRM', endpoint: 'https://crm.gongxue.cn/open/leads', assignmentMode: '按地区轮转', pool: '天津升本线索池', enabled: true, status: '正常', timeout: 8, retry: 3, updatedAt: '2026-07-23 09:12' }, - { id: 'CRM-QH-GD', tenantId: 'tenant_qihang_gd', provider: '自建 CRM', endpoint: 'https://crm.qihangzsb.cn/api/leads', assignmentMode: '按校区容量', pool: '广东转化队列', enabled: true, status: '异常', timeout: 10, retry: 5, updatedAt: '2026-07-22 18:40' }, - { id: 'CRM-BS-SD', tenantId: 'tenant_bosi_sd', provider: '手工队列', endpoint: '-', assignmentMode: '手工分配', pool: '试用线索池', enabled: false, status: '未启用', timeout: 8, retry: 0, updatedAt: '2026-07-18 11:30' }, - ], - crmLeads: [ - { id: 'LEAD-260723-018', tenantId: 'tenant_qihang_gd', source: '公开课报名', student: '陈同学', phone: '139****8201', subject: '广东专升本英语', owner: '广州一校区', status: '推送失败', attempts: 4, lastError: 'CRM 422: campus required', createdAt: '2026-07-23 09:48' }, - { id: 'LEAD-260723-016', tenantId: 'tenant_gongxue_tj', source: '题库体验页', student: '王同学', phone: '138****2098', subject: '高等数学', owner: '天津转化组', status: '已推送', attempts: 1, lastError: '', createdAt: '2026-07-23 09:26' }, - { id: 'LEAD-260722-044', tenantId: 'tenant_mingtu_hn', source: '学生端留资', student: '李同学', phone: '135****6172', subject: '河南专升本语文', owner: '默认队列', status: '待推送', attempts: 0, lastError: '', createdAt: '2026-07-22 21:05' }, - ], - smsChannels: [ - { id: 'SMS-ALI-GX', tenantId: 'tenant_gongxue_tj', provider: '阿里云短信', signature: '恭学教育', scene: 'login,notice,dunning', status: '正常', enabled: true, secretRef: 'tenant/gongxue/sms/aliyun', quota: 50000, used: 21860, updatedAt: '2026-07-22 16:10' }, - { id: 'SMS-TENCENT-QH', tenantId: 'tenant_qihang_gd', provider: '腾讯云短信', signature: '启航专升本', scene: 'login,marketing', status: '模板待审', enabled: true, secretRef: 'tenant/qihang/sms/tencent', quota: 80000, used: 64220, updatedAt: '2026-07-21 19:30' }, - { id: 'SMS-GENERIC-BS', tenantId: 'tenant_bosi_sd', provider: '通用短信网关', signature: '博思升本', scene: 'login', status: '未启用', enabled: false, secretRef: 'redacted', quota: 10000, used: 0, updatedAt: '2026-07-18 10:00' }, - ], - smsTemplates: [ - { id: 'TPL-LOGIN-001', channelId: 'SMS-ALI-GX', code: 'student_login_otp', name: '学生登录验证码', type: '登录验证', status: '已通过', lastSend: '2026-07-23 09:58', successRate: '99.2%' }, - { id: 'TPL-DUN-001', channelId: 'SMS-ALI-GX', code: 'invoice_due_notice', name: '租户账单到期提醒', type: '平台催缴', status: '已通过', lastSend: '2026-07-23 09:20', successRate: '98.7%' }, - { id: 'TPL-MKT-009', channelId: 'SMS-TENCENT-QH', code: 'open_class_reminder', name: '公开课提醒', type: '营销触达', status: '审核中', lastSend: '-', successRate: '-' }, - ], - paymentApps: [ - { id: 'PAY-GX-STUDENT', tenantId: 'tenant_gongxue_tj', appName: '恭学学生端收款', provider: 'wechat_pay', mode: 'production', status: '正常', settlement: 'T+1 至租户商户号', secretRef: 'tenant/gongxue/pay/wechat', updatedAt: '2026-07-22 15:08' }, - { id: 'PAY-QH-ALI', tenantId: 'tenant_qihang_gd', appName: '启航课程收款', provider: 'alipay', mode: 'production', status: '证书即将过期', settlement: 'T+1 至租户支付宝商户', secretRef: 'tenant/qihang/pay/alipay', updatedAt: '2026-07-20 13:40' }, - { id: 'PAY-BS-MANUAL', tenantId: 'tenant_bosi_sd', appName: '试用线下收款', provider: 'manual', mode: 'sandbox', status: '未启用', settlement: '人工确认', secretRef: 'redacted', updatedAt: '2026-07-18 10:20' }, - ], - paymentEvents: [ - { id: 'PEVT-260723-031', appId: 'PAY-GX-STUDENT', orderNo: 'ORD-260723-2048', amount: 398, status: '支付成功', channel: '微信 JSAPI', notified: '已回调', updatedAt: '2026-07-23 09:56' }, - { id: 'PEVT-260723-029', appId: 'PAY-QH-ALI', orderNo: 'ORD-260723-2021', amount: 1280, status: '回调失败', channel: '支付宝 WAP', notified: '重试中', updatedAt: '2026-07-23 09:49' }, - { id: 'PEVT-260722-188', appId: 'PAY-BS-MANUAL', orderNo: 'ORD-260722-1098', amount: 99, status: '待确认', channel: '线下转账', notified: '无', updatedAt: '2026-07-22 20:18' }, - ], - platformPermissions: { - 'platform:dashboard:view': '平台总览', - 'platform:tenant:manage': '平台租户管理', - 'platform:staff:manage': '平台员工管理', - 'platform:role:manage': '平台角色权限管理', - 'platform:question-bank:manage': '平台公共题库运营', - 'platform:audit:view': '平台审计查询', - 'platform:billing:notification': '平台账务通知', - 'platform:saas-catalog:manage': 'SaaS 商品目录管理', - 'platform:saas-billing:manage': 'SaaS 订单与账务管理', - 'platform:crm:read': 'CRM 配置查询', - 'platform:crm:write': 'CRM 配置管理', - 'platform:sms:read': '短信服务查询', - 'platform:sms:write': '短信服务管理', - 'platform:payment:read': '支付设置查询', - 'platform:payment:write': '支付设置管理', - }, - platformRoles: [ - { id: 'role-super', code: 'platform_super_admin', name: '超级管理员', description: '拥有全部平台管理权限', permissionCodes: ['*'] }, - { id: 'role-tenant', code: 'platform_tenant_operator', name: '租户运营', description: '负责租户开通与生命周期管理', permissionCodes: ['platform:dashboard:view', 'platform:tenant:manage', 'platform:crm:read', 'platform:crm:write'] }, - { id: 'role-finance', code: 'platform_finance', name: '平台财务', description: '负责 SaaS 商品、订单、账务与支付', permissionCodes: ['platform:dashboard:view', 'platform:saas-catalog:manage', 'platform:saas-billing:manage', 'platform:billing:notification', 'platform:payment:read', 'platform:payment:write'] }, - { id: 'role-audit', code: 'platform_auditor', name: '安全审计', description: '查询审计日志与处理安全告警', permissionCodes: ['platform:dashboard:view', 'platform:audit:view'] }, - { id: 'role-bank', code: 'platform_question_bank_operator', name: '题库运营', description: '负责公共题库结构、题目与导入', permissionCodes: ['platform:dashboard:view', 'platform:question-bank:manage'] }, - ], - staff: [ - { id: 'STAFF-01', userId: 'STAFF-01', roleIds: ['role-super'], roleCodes: ['platform_super_admin'], name: '陈浩', email: 'chenhao@gongxue.cn', phone: '138****6600', role: '超级管理员', permissions: ['*'], status: '正常', lastActive: '刚刚' }, - { id: 'STAFF-02', authUserId: 'auth-zhoumin', username: 'zhoumin', name: '周敏', email: 'zhoumin@gongxue.cn', phone: '139****2188', role: '题库运营', permissions: ['platform:question-bank:manage'], status: '正常', lastActive: '8分钟前' }, - { id: 'STAFF-03', authUserId: 'auth-liujia', username: 'liujia', name: '刘佳', email: 'liujia@gongxue.cn', phone: '136****9028', role: '平台财务', permissions: ['platform:billing:read', 'platform:billing:write', 'platform:billing:payment', 'platform:usage:read', 'platform:usage:write'], status: '正常', lastActive: '21分钟前' }, - { id: 'STAFF-04', authUserId: 'auth-wanglei', username: 'wanglei', name: '王磊', email: 'wanglei@gongxue.cn', phone: '135****2086', role: '租户运营', permissions: ['platform:tenant:read', 'platform:tenant:write', 'platform:tenant:status'], status: '正常', lastActive: '1小时前' }, - { id: 'STAFF-05', authUserId: 'auth-sunchen', username: 'sunchen', name: '孙晨', email: 'sunchen@gongxue.cn', phone: '137****1118', role: '安全审计', permissions: ['platform:audit:read', 'platform:audit:alert'], status: '已停用', lastActive: '3天前' }, - ], - auditLogs: [ - { id: 'AUD-20260723-094218', time: '2026-07-23 09:42:18 CST', actor: '陈浩', role: '平台管理员', action: 'tenant.status.update', targetType: 'tenant', targetId: 'tenant_mingtu_hn', target: '明途教育 · 河南', severity: '高', result: '成功', ip: '172.16.4.28', details: '将业务状态由正常更新为暂停,原因:账单逾期。' }, - { id: 'AUD-20260723-093602', time: '2026-07-23 09:36:02 CST', actor: 'system-billing', role: '系统任务', action: 'invoice.batch.create', targetType: 'invoice_batch', targetId: 'TASK-260723-001', target: '2026年7月账单', severity: '中', result: '成功', ip: 'internal', details: '生成 48 张账单,跳过 2 条重复候选。' }, - { id: 'AUD-20260723-085844', time: '2026-07-23 08:58:44 CST', actor: '周敏', role: '题库运营', action: 'platform.question_bank.import_executed', targetType: 'question_bank', targetId: 'QB-TJ-MATH', target: '高数公共题库 v2026.7', severity: '中', result: '成功', ip: '172.16.3.16', details: '结构化 JSON 导入完成,新增 8 个内容节点和 126 道题。' }, - { id: 'AUD-20260723-084127', time: '2026-07-23 08:41:27 CST', actor: '刘佳', role: '平台财务', action: 'invoice.payment.confirm', targetType: 'invoice', targetId: 'INV-202607-0016', target: 'INV-202607-0016', severity: '高', result: '成功', ip: '172.16.8.12', details: '人工确认收款 ¥16,800,流水号已脱敏。' }, - { id: 'AUD-20260723-081209', time: '2026-07-23 08:12:09 CST', actor: 'unknown', role: '-', action: 'auth.login.failed', targetType: 'application', targetId: 'platform-console', target: 'platform-console', severity: '严重', result: '失败', ip: '45.62.18.9', details: '5 分钟内连续登录失败 12 次。' }, - { id: 'AUD-20260720-163510', time: '2026-07-20 16:35:10 CST', actor: '周敏', role: '题库运营', action: 'bank.catalog.read', targetType: 'question_bank', targetId: 'QB-SD', target: '山东专升本全科', severity: '中', result: '成功', ip: '172.16.3.16', details: '查看公共题库版本与租户采用状态。' }, - ], - alerts: [ - { id: 'ALT-20260723-008', title: '异常登录尝试', summary: '5 分钟内 12 次平台登录失败', severity: '严重', status: 'open', owner: '安全审计', targetType: 'application', targetId: 'platform-console', evidence: ['来源 IP 45.62.18.9', '账号枚举行为 12 次', '命中规则 LOGIN_FAILURE_BURST'], updatedAt: '2分钟前', note: '' }, - { id: 'ALT-20260723-006', title: '租户账单逾期', summary: '明途教育服务费账单逾期 5 天', severity: '高', status: 'acknowledged', owner: '平台财务', targetType: 'invoice', targetId: 'INV-202607-0017', evidence: ['余额 ¥8,600', '到期日 2026-07-18', '已发送 3 次催缴'], updatedAt: '18分钟前', note: '财务已联系租户。' }, - { id: 'ALT-20260723-004', title: '公共题库导入失败', summary: '结构化 JSON 文件存在 12 个稳定编码冲突', severity: '中', status: 'open', owner: '题库运营', targetType: 'question_bank', targetId: 'QB-EN', evidence: ['文件版本 2.0', '目标题库 公共英语能力库', '冲突 12 条'], updatedAt: '42分钟前', note: '' }, - { id: 'ALT-20260722-019', title: '存储用量告警', summary: '启航专升本存储用量达到套餐 92%', severity: '中', status: 'open', owner: '租户运营', targetType: 'tenant', targetId: 'tenant_qihang_gd', evidence: ['当前 460 GB', '套餐上限 500 GB'], updatedAt: '昨天', note: '' }, - { id: 'ALT-20260722-011', title: 'Provider 密钥即将过期', summary: '优才专转本支付 Provider 密钥 7 天后到期', severity: '高', status: 'resolved', owner: '平台运维', targetType: 'tenant', targetId: 'tenant_youcai_js', evidence: ['密钥只写不可回显', '新密钥已于昨天更新'], updatedAt: '昨天', note: '完成轮换。' }, - ], - alertRules: [ - { id: 'RULE-LOGIN-BURST', code: 'LOGIN_FAILURE_BURST', name: '平台登录失败突增', severity: '严重', enabled: true, window: '5 分钟', threshold: '≥ 10 次', target: '平台账号与来源 IP' }, - { id: 'RULE-INVOICE-OVERDUE', code: 'INVOICE_OVERDUE', name: '服务费账单逾期', severity: '高', enabled: true, window: '每日 09:00', threshold: '逾期 ≥ 1 天', target: '未结清平台账单' }, - { id: 'RULE-BANK-IMPORT', code: 'QUESTION_BANK_IMPORT_FAILED', name: '公共题库导入失败', severity: '中', enabled: true, window: '导入结束时', threshold: '无效记录或冲突 ≥ 10', target: '平台公共题库导入任务' }, - ], - auditChannels: [ - { id: 'CH-SEC-MAIL', code: 'security_email', name: '平台安全邮箱', provider: '邮件', endpoint: 'security@gongxue.cn', minSeverity: '中', statusFilter: 'open,acknowledged', timeout: 8, maxAttempts: 3, enabled: true, lastStatus: '正常' }, - { id: 'CH-SEC-WX', code: 'security_wecom', name: '财务告警群', provider: 'Webhook', endpoint: 'Webhook · 企业微信', minSeverity: '高', statusFilter: 'open', timeout: 5, maxAttempts: 5, enabled: true, lastStatus: '正常' }, - { id: 'CH-DUTY-SMS', code: 'duty_sms', name: '值班手机', provider: '短信', endpoint: '138****6008', minSeverity: '严重', statusFilter: 'open', timeout: 10, maxAttempts: 3, enabled: true, lastStatus: '失败1次' }, - ], - notificationEvents: [ - { id: 'EVT-260723-001', channelId: 'CH-DUTY-SMS', subject: '异常登录尝试', status: '失败', attempts: 2, updatedAt: '2026-07-23 09:44 CST', error: '运营商返回频率限制' }, - { id: 'EVT-260723-002', channelId: 'CH-SEC-MAIL', subject: '异常登录尝试', status: '成功', attempts: 1, updatedAt: '2026-07-23 09:43 CST', error: '' }, - ], - dunningEvents: [], - tasks: [], -}; - -function clone(value) { return JSON.parse(JSON.stringify(value)); } -function normalizeData(saved) { - const normalized = clone(seed); - if (!saved || typeof saved !== 'object') return normalized; - Object.keys(normalized).forEach(key => { - if (key === 'version') return; - if (Array.isArray(normalized[key])) { - if (Array.isArray(saved[key])) normalized[key] = saved[key]; - return; - } - if (normalized[key] && typeof normalized[key] === 'object') { - if (saved[key] && typeof saved[key] === 'object' && !Array.isArray(saved[key])) normalized[key] = { ...normalized[key], ...saved[key] }; - return; - } - if (saved[key] !== undefined) normalized[key] = saved[key]; - }); - normalized.usage = normalized.usage.map(item => ({ overage: [], estimated: 0, source: 'Worker 自动采集', ...item })); - normalized.crmConfigs = normalized.crmConfigs.map(item => ({ enabled: false, status: '未启用', retry: 0, ...item })); - normalized.crmLeads = normalized.crmLeads.map(item => ({ attempts: 0, lastError: '', ...item })); - normalized.smsChannels = normalized.smsChannels.map(item => ({ enabled: false, quota: 0, used: 0, ...item })); - normalized.smsTemplates = normalized.smsTemplates.map(item => ({ lastSend: '-', successRate: '-', ...item })); - normalized.paymentApps = normalized.paymentApps.map(item => ({ mode: 'sandbox', status: '未启用', ...item })); - normalized.paymentEvents = normalized.paymentEvents.map(item => ({ notified: '无', ...item })); - normalized.platformPermissions = Object.fromEntries(Object.entries(normalized.platformPermissions || {}).map(([code, name]) => [ - code, - seed.platformPermissions[code] || name, - ])); - normalized.platformRoles = normalized.platformRoles.map(item => item.code === 'platform_super_admin' - ? { ...item, name: '超级管理员', description: '拥有全部平台管理权限' } - : item); - normalized.staff = normalized.staff.map(item => { - const roleIds = item.roleIds?.length ? item.roleIds : normalized.platformRoles.filter(role => role.name === item.role).map(role => role.id); - const assignedRoles = normalized.platformRoles.filter(role => roleIds.includes(role.id)); - return { - permissions: assignedRoles.flatMap(role => role.permissionCodes), - status: '正常', - lastActive: '尚未登录', - ...item, - userId: item.userId || item.id, - roleIds, - roleCodes: item.roleCodes || assignedRoles.map(role => role.code), - }; - }); - normalized.alerts = normalized.alerts.map(item => ({ evidence: [], note: '', status: 'open', ...item })); - normalized.tasks = normalized.tasks.map(item => ({ status: 'failed', error: '', resultTarget: '任务中心', updatedAt: item.createdAt || todayTime(), ...item })); - normalized.version = seed.version; - return normalized; -} -function loadData() { - try { - const saved = JSON.parse(localStorage.getItem(STORAGE_KEY)); - if (saved?.version === seed.version) { - const normalized = normalizeData(saved); - normalized.tasks.forEach(task => { - if (['pending', 'processing'].includes(task.status)) { - task.status = 'failed'; - task.error = '页面重载中断了本次 Mock 执行,可从任务中心重试。'; - task.updatedAt = todayTime(); - } - }); - return normalized; - } - } catch (error) { - console.warn('Mock state restore failed', error); - } - return clone(seed); -} -let data = loadData(); -if (platformApi?.isEnabled()) { - [ - 'tenants', 'plans', 'subscriptions', 'invoices', 'usage', 'reminders', - 'dunningChannels', 'dunningEvents', 'banks', 'bankNodes', 'bankQuestions', 'staff', - 'auditLogs', 'alerts', 'alertRules', 'auditChannels', 'notificationEvents', 'tasks', - ].forEach(key => { data[key] = []; }); - data.billingProfiles = {}; -} -const state = { - view: 'overview', previousView: '', selectedTenant: data.tenants[0]?.id || '', tenantFilter: 'all', tenantPlan: 'all', tenantSearch: '', globalSearch: '', - billingTab: 'invoices', bankTab: 'structure', selectedBank: data.banks[0]?.id || '', selectedBankNode: '', bankQuestionPage: 1, bankQuestionTotal: 0, - crmTab: 'configs', smsTab: 'channels', paymentTab: 'apps', saasFinanceTab: 'orders', - invoiceSearch: '', invoiceStatus: 'all', bankSearch: '', staffSearch: '', usagePeriod: '2026-07', auditRange: '24h', auditSeverity: 'all', auditSearch: '', alertStatus: 'all', selectedAlert: '', selectedInvoice: '', - role: 'super', scenario: 'normal', response: 'success', modal: '', modalData: {}, submitting: '', reading: '', contractResults: {}, history: [], - apiConnection: platformApi?.isEnabled() ? 'connecting' : 'mock', apiLoadedAt: '', apiLoadedOperations: 0, apiFailedOperations: 0, -}; -let pendingLeave = null; -let historySequence = Number(history.state?.sequence) || 0; -let restoringHistory = false; -let bypassHistoryGuard = false; -const dirtyScopes = new Set(); -const loadedTenantDetails = new Set(); - -let storageWarningShown = false; -function saveData() { - if (platformApi?.isEnabled()) return true; - try { - localStorage.setItem(STORAGE_KEY, JSON.stringify(data)); - return true; - } catch (error) { - console.warn('Mock state persistence failed', error); - if (!storageWarningShown) { - storageWarningShown = true; - showToast('浏览器存储不可用,本次修改仅在当前页面保留', 'error'); - } - return false; - } -} -function backendStatusLabel() { - if (!platformApi?.isEnabled()) return '静态演示数据'; - if (state.apiConnection === 'connecting') return '正在连接后端'; - if (state.apiConnection === 'connected') { - const partial = state.apiFailedOperations ? ` · ${state.apiFailedOperations} 项加载失败` : ''; - return `后端已连接${partial}`; - } - return '后端不可用 · 已保留静态演示'; -} -function backendErrorText(error, fallback = '平台接口请求失败') { - if (!error) return fallback; - const pieces = [error.message || fallback]; - if (error.code) pieces.push(`code=${error.code}`); - if (error.requestId) pieces.push(`requestId=${error.requestId}`); - return pieces.join(' · '); -} -function apiItems(payload) { - if (Array.isArray(payload)) return payload; - if (Array.isArray(payload?.items)) return payload.items; - return []; -} -function apiItem(payload) { - return payload?.item || payload || {}; -} -function updateBackendStatus() { - const status = document.querySelector('.top-status > span'); - if (!status) return; - status.innerHTML = `${escapeHtml(backendStatusLabel())}`; - status.title = platformApi?.isEnabled() - ? `${platformApi.publicConfig().apiBaseUrl || '未配置 API 地址'}${state.apiLoadedAt ? ` · ${state.apiLoadedAt}` : ''}` - : 'runtime-config.js 当前为 mock 模式'; - status.classList.toggle('is-degraded', state.apiConnection === 'degraded'); -} -function applyBackendPatch(patch) { - Object.entries(patch).forEach(([key, value]) => { data[key] = value; }); - if (patch.tenants) { - const tenantIds = new Set(data.tenants.map(tenant => tenant.id)); - if (!tenantIds.has(state.selectedTenant)) state.selectedTenant = data.tenants[0]?.id || ''; - } - if (patch.banks && !data.banks.some(bank => bank.id === state.selectedBank)) state.selectedBank = data.banks[0]?.id || ''; - if (patch.usage) { - const latestUsage = new Map(); - data.usage.forEach(item => { - const current = latestUsage.get(item.tenantId); - if (!current || item.period > current.period) latestUsage.set(item.tenantId, item); - }); - data.tenants.forEach(tenant => { - const usage = latestUsage.get(tenant.id); - if (!usage) return; - tenant.students = usage.students; - tenant.questions = usage.questions; - tenant.storageGB = usage.storageGB; - tenant.trafficTB = usage.trafficTB; - }); - } - if (patch.plans || patch.tenants) { - data.plans.forEach(plan => { - plan.tenantCount = data.tenants.filter(tenant => tenant.planCode === plan.code).length; - }); - } -} -async function hydrateFromBackend({ silent = false } = {}) { - if (!platformApi?.isEnabled()) { - state.apiConnection = 'mock'; - updateBackendStatus(); - return false; - } - state.apiConnection = 'connecting'; - updateBackendStatus(); - try { - const result = await platformApi.bootstrap({ period: state.usagePeriod }); - const successful = Object.keys(result.payloads).length; - if (!successful) throw Object.values(result.errors)[0] || new Error('没有平台接口成功返回'); - applyBackendPatch(platformApi.adaptBootstrap(result.payloads, data)); - state.apiConnection = 'connected'; - state.apiLoadedAt = todayTime(); - state.apiLoadedOperations = successful; - state.apiFailedOperations = Object.keys(result.errors).length; - render(); - if (!silent) showToast(`后端数据已刷新 · ${successful}/${result.requested} 项成功`); - return true; - } catch (error) { - if (error?.status === 401) { - window.GongxuePlatformAuth?.requireReauthentication(); - return false; - } - state.apiConnection = 'degraded'; - state.apiFailedOperations = 1; - render(); - if (!silent) showToast(`${backendErrorText(error, '后端连接失败')} · 已保留静态演示`, 'error'); - return false; - } -} -async function hydrateTenantDetail(tenantId, { force = false } = {}) { - if (!platformApi?.isEnabled() || !tenantId || (!force && loadedTenantDetails.has(tenantId))) return; - try { - const detail = await platformApi.tenantDetail(tenantId); - const tenant = tenantById(tenantId); - if (tenant && detail.tenant) { - tenant.legal = detail.tenant.legalName || tenant.legal; - tenant.brand = detail.tenant.brandName || tenant.brand; - tenant.shortName = detail.tenant.shortName || tenant.shortName; - tenant.createdAt = detail.tenant.createdAt ? String(detail.tenant.createdAt).slice(0, 10) : tenant.createdAt; - tenant.host = detail.domains.find(domain => domain.isPrimary)?.host || detail.domains[0]?.host || tenant.host; - } - data.subscriptions = [ - ...data.subscriptions.filter(item => item.tenantId !== tenantId), - ...detail.subscriptions, - ]; - if (detail.billingProfile) data.billingProfiles[tenantId] = detail.billingProfile; - loadedTenantDetails.add(tenantId); - render(); - } catch (error) { - showToast(backendErrorText(error, '租户详情加载失败'), 'error'); - } -} -function icon(name) { return ``; } -function refreshIcons() { if (window.lucide) window.lucide.createIcons({ attrs: { 'stroke-width': 1.8 } }); } -function formatNumber(value) { return Number(value || 0).toLocaleString('zh-CN'); } -function money(value) { return `¥${Number(value || 0).toLocaleString('zh-CN')}`; } -function todayTime() { return new Intl.DateTimeFormat('zh-CN', { timeZone: 'Asia/Shanghai', dateStyle: 'short', timeStyle: 'medium' }).format(new Date()).replaceAll('/', '-'); } -function requestId() { return `req_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 7)}`; } -function entityId(prefix) { return `${prefix}-${Date.now().toString(36).toUpperCase()}`; } -function tenantById(id) { return data.tenants.find(item => item.id === id); } -function planByCode(code) { return data.plans.find(item => item.code === code); } -function invoiceById(id) { return data.invoices.find(item => item.id === id); } -function paymentForInvoice(invoice) { return data.billingPayments.find(item => item.orderId && item.orderId === invoice?.orderId && item.status === 'pending'); } -function canConfirmInvoicePayment(invoice) { return !platformApi?.isEnabled() || Boolean(paymentForInvoice(invoice)); } -function bankById(id) { return data.banks.find(item => item.id === id); } -function bankNodeById(id) { return data.bankNodes.find(item => item.id === id); } -function questionTypeLabel(value) { return ({ choice: '单选题', multiple_choice: '多选题', true_false: '判断题', fill_blank: '填空题', short_answer: '简答题', reading: '阅读材料题', programming: '编程题' })[String(value || '').toLowerCase()] || value || '-'; } -function bankNodeTypeLabel(value) { return ({ category: '分类', subject: '科目', chapter: '章节', paper: '试卷', custom: '自定义' })[String(value || '').toLowerCase()] || value || '-'; } -function adaptBankNode(item) { return { ...item, questionBankId: item.questionBankId, nodeType: String(item.nodeType || '').replace(/([a-z0-9])([A-Z])/g, '$1_$2').toLowerCase(), questionCount: Number(item.questionCount || 0) }; } -function adaptBankQuestion(item) { return { ...item, statusLabel: businessStatusLabel(item.status), versionNo: Number(item.versionNo || 0) }; } -function parseJsonText(value, fallback) { try { return String(value || '').trim() ? JSON.parse(value) : fallback; } catch { return null; } } -async function loadBankWorkspace({ questions = true } = {}) { - const bank = bankById(state.selectedBank); - if (!bank || !platformApi?.isEnabled()) return; - try { - const nodes = await platformApi.request('PlatformQuestionBanksController_getNodes', { pathParams: { bankId: bank.id } }); - data.bankNodes = apiItems(nodes).map(adaptBankNode); - if (!state.selectedBankNode || !data.bankNodes.some(item => item.id === state.selectedBankNode)) state.selectedBankNode = data.bankNodes.find(item => item.isActive && ['chapter', 'paper'].includes(item.nodeType))?.id || data.bankNodes.find(item => item.isActive)?.id || ''; - if (questions) { - const result = await platformApi.request('PlatformQuestionBanksController_getQuestions', { query: { questionBankId: bank.id, contentNodeId: state.selectedBankNode || undefined, page: state.bankQuestionPage, pageSize: 20 } }); - data.bankQuestions = apiItems(result).map(adaptBankQuestion); - state.bankQuestionTotal = Number(result.total || data.bankQuestions.length); - } - saveData(); render(); - } catch (error) { - showToast(backendErrorText(error, '公共题库加载失败'), 'error'); - } -} -function notificationChannelName(id) { - return [...data.dunningChannels, ...data.auditChannels].find(channel => channel.id === id)?.name || id; -} -function setAccessibleControlName(element, label) { - if (!element || !label) return; - element.setAttribute('aria-label', label); - element.setAttribute('title', label); -} -function recordLabel(name, id) { return [name, id].filter(Boolean).join(' · '); } -function rowActionAccessibleName(control) { - const tenantId = control.dataset.tenantDetail || control.dataset.tenantId; - const tenant = tenantById(tenantId); - if (control.dataset.tenantDetail) return `查看租户 ${recordLabel(tenant?.name, tenantId)} 详情`; - if (control.dataset.invoiceDetail) { - const invoice = invoiceById(control.dataset.invoiceDetail); - return `查看账单 ${recordLabel(invoice?.id, tenantById(invoice?.tenantId)?.name)} 详情`; - } - if (control.dataset.notificationDetail) { - const event = [...(data.notificationEvents || []), ...(data.dunningEvents || [])].find(item => item.id === control.dataset.notificationDetail); - return `查看通知事件 ${recordLabel(event?.subject, event?.id || control.dataset.notificationDetail)} 详情`; - } - if (control.dataset.auditDetail) { - const log = data.auditLogs.find(item => item.id === control.dataset.auditDetail); - return `查看审计日志 ${recordLabel(log?.id || control.dataset.auditDetail, log?.target)} 详情`; - } - const action = control.dataset.action; - if (action === 'prepare-tenant-status') return `${tenant?.status === '暂停' ? '恢复' : '暂停'}租户 ${recordLabel(tenant?.name, tenantId)}`; - if (action === 'tenant-to-billing') return `查看租户 ${recordLabel(tenant?.name, tenantId)} 账务`; - if (action === 'confirm-payment') { - const invoice = invoiceById(control.dataset.invoiceId); - return `确认账单 ${recordLabel(invoice?.id || control.dataset.invoiceId, tenantById(invoice?.tenantId)?.name)} 收款`; - } - if (action === 'edit-dunning-channel') { - const channel = data.dunningChannels.find(item => item.id === control.dataset.channelId); - return `编辑催缴渠道 ${recordLabel(channel?.name, channel?.id || control.dataset.channelId)}`; - } - if (action === 'edit-staff') { - const person = data.staff.find(item => item.id === control.dataset.staffId); - return `编辑员工 ${recordLabel(person?.name, person?.id || control.dataset.staffId)}`; - } - if (action === 'edit-crm-config') { - const config = data.crmConfigs.find(item => item.id === control.dataset.crmId); - return `编辑 CRM 接入 ${recordLabel(tenantById(config?.tenantId)?.name, config?.id || control.dataset.crmId)}`; - } - if (action === 'retry-crm-lead') { - const lead = data.crmLeads.find(item => item.id === control.dataset.leadId); - return `重试 CRM 线索 ${recordLabel(lead?.student, lead?.id || control.dataset.leadId)}`; - } - if (action === 'edit-sms-channel') { - const channel = data.smsChannels.find(item => item.id === control.dataset.smsId); - return `编辑短信渠道 ${recordLabel(channel?.signature, channel?.id || control.dataset.smsId)}`; - } - if (action === 'edit-payment-app') { - const paymentApp = data.paymentApps.find(item => item.id === control.dataset.paymentId); - return `编辑支付应用 ${recordLabel(paymentApp?.appName, paymentApp?.id || control.dataset.paymentId)}`; - } - if (action === 'edit-audit-channel') { - const channel = data.auditChannels.find(item => item.id === control.dataset.channelId); - return `编辑审计通知渠道 ${recordLabel(channel?.name, channel?.id || control.dataset.channelId)}`; - } - return control.title || control.textContent.trim(); -} -function switchAccessibleName(control) { - const enabled = control.classList.contains('is-on'); - const action = control.dataset.action; - if (action === 'toggle-auto-renew') { - const subscription = data.subscriptions.find(item => item.id === control.dataset.subscriptionId); - const tenant = tenantById(subscription?.tenantId); - return `${enabled ? '关闭' : '开启'}${tenant?.name || '该租户'}订阅 ${subscription?.id || control.dataset.subscriptionId} 自动续费`; - } - if (action === 'toggle-dunning-channel') { - const channel = data.dunningChannels.find(item => item.id === control.dataset.channelId); - return `${enabled ? '停用' : '启用'}催缴渠道 ${recordLabel(channel?.name, channel?.id || control.dataset.channelId)}`; - } - if (action === 'toggle-staff') { - const person = data.staff.find(item => item.id === control.dataset.staffId); - return `${enabled ? '停用员工' : '启用员工'} ${recordLabel(person?.name, person?.id || control.dataset.staffId)}${enabled ? '并撤销会话' : ''}`; - } - if (action === 'toggle-crm-config') { - const config = data.crmConfigs.find(item => item.id === control.dataset.crmId); - return `${enabled ? '停用' : '启用'} CRM 接入 ${recordLabel(tenantById(config?.tenantId)?.name, config?.id || control.dataset.crmId)}`; - } - if (action === 'toggle-sms-channel') { - const channel = data.smsChannels.find(item => item.id === control.dataset.smsId); - return `${enabled ? '停用' : '启用'}短信渠道 ${recordLabel(channel?.signature, channel?.id || control.dataset.smsId)}`; - } - if (action === 'toggle-payment-app') { - const paymentApp = data.paymentApps.find(item => item.id === control.dataset.paymentId); - return `${enabled ? '停用' : '启用'}支付应用 ${recordLabel(paymentApp?.appName, paymentApp?.id || control.dataset.paymentId)}`; - } - if (action === 'toggle-audit-channel') { - const channel = data.auditChannels.find(item => item.id === control.dataset.channelId); - return `${enabled ? '停用' : '启用'}审计通知渠道 ${recordLabel(channel?.name, channel?.id || control.dataset.channelId)}`; - } - return enabled ? '关闭此设置' : '开启此设置'; -} -function updateMenuButtonAccessibility() { - const expanded = app.classList.contains('menu-open'); - setAccessibleControlName(menuButton, expanded ? '关闭平台导航菜单' : '打开平台导航菜单'); - menuButton.setAttribute('aria-expanded', String(expanded)); - menuButton.setAttribute('aria-controls', 'sideNav'); -} -function decorateAccessibleControls(root) { - const selectLabels = { - tenantPlanFilter: '租户套餐筛选', - invoiceStatusFilter: '账单状态筛选', - roleSelect: '演示角色', - scenarioSelect: '页面状态演练', - responseSelect: '下一次 Mock 写请求结果', - }; - Object.entries(selectLabels).forEach(([id, label]) => setAccessibleControlName(document.querySelector(`#${id}`), label)); - root.querySelectorAll('.row-action').forEach(control => setAccessibleControlName(control, rowActionAccessibleName(control))); - root.querySelectorAll('.switch').forEach(control => { - setAccessibleControlName(control, switchAccessibleName(control)); - control.setAttribute('role', 'switch'); - control.setAttribute('aria-checked', String(control.classList.contains('is-on'))); - }); - document.querySelectorAll('.icon-button').forEach(control => { - const fallback = control.title || control.getAttribute('aria-label'); - if (fallback) setAccessibleControlName(control, fallback); - }); - updateMenuButtonAccessibility(); -} -function hasPermission(permission) { - if (platformApi?.isEnabled() && data.apiPermissions?.effective && Object.prototype.hasOwnProperty.call(data.apiPermissions.effective, permission)) { - return data.apiPermissions.effective[permission] === true; - } - const grants = roleDefinitions[state.role]?.permissions || []; - if (grants.includes('*') || grants.includes(permission)) return true; - return grants.some(grant => grant.endsWith('*') && permission.startsWith(grant.slice(0, -1))); -} -function tone(text) { - const value = String(text || ''); - if (/正常|活跃|已支付|resolved|已解决|已授权|成功|已完成|启用|已送达/.test(value)) return 'success'; - if (/逾期|暂停|严重|失败|阻断|已停用|同步失败/.test(value)) return 'danger'; - if (/待|试用|警告|即将|acknowledged|已确认|同步中|执行中|开放|open/.test(value)) return 'warning'; - return 'neutral'; -} -function alertStatusLabel(status) { return ({ open: '开放', acknowledged: '已确认', resolved: '已解决', ignored: '已忽略' })[status] || status; } -function taskStatusLabel(status) { return ({ pending: '待处理', processing: '执行中', completed: '已完成', failed: '失败' })[status] || status; } -function escapeHtml(value) { return String(value ?? '').replace(/[&<>'"]/g, char => ({ '&': '&', '<': '<', '>': '>', "'": ''', '"': '"' })[char]); } -function fieldValue(form, name) { return String(new FormData(form).get(name) || '').trim(); } -function parseMoney(value) { return Number(String(value || '').replaceAll(',', '')); } -function addAudit(action, targetType, targetId, target, severity, details, result = '成功') { - data.auditLogs.unshift({ id: entityId('AUD'), time: `${todayTime()} CST`, actor: roleDefinitions[state.role].label, role: roleDefinitions[state.role].label, action, targetType, targetId, target, severity, result, ip: '127.0.0.1', details }); - saveData(); -} -function addTask(label, resultTarget, execute) { - const task = { id: entityId('TASK'), label, resultTarget, status: 'pending', createdAt: todayTime(), updatedAt: todayTime(), error: '' }; - data.tasks.unshift(task); saveData(); updateCounters(); - setTimeout(() => { task.status = 'processing'; task.updatedAt = todayTime(); saveData(); updateCounters(); renderOverlay(); }, 350); - setTimeout(() => { - try { execute?.(task); task.status = 'completed'; } - catch (error) { task.status = 'failed'; task.error = error.message || '任务执行失败'; } - task.updatedAt = todayTime(); saveData(); updateCounters(); render(); renderOverlay(); - }, 1200); - return task; -} -function contractResult(key) { - const result = state.contractResults[key]; - if (!result) return ''; - const toneClass = result.status === 'error' ? 'is-error' : result.status === 'loading' ? 'is-loading' : 'is-success'; - const glyph = result.status === 'error' ? 'triangle-alert' : result.status === 'loading' ? 'loader-circle' : 'circle-check'; - return `
${icon(glyph)}${escapeHtml(result.title)}${escapeHtml(result.detail)} · Request ID:${escapeHtml(result.requestId)}
`; -} -function runContractRead({ key, actionId, operationId, title, apply, suppliedRequestId = '', liveRequest }) { - if (state.reading) return; - const id = suppliedRequestId || requestId(); - state.reading = key; - state.contractResults[key] = { status: 'loading', title: `${title}处理中`, detail: operationId, requestId: id }; - render(); - if (platformApi?.isEnabled()) { - Promise.resolve(typeof liveRequest === 'function' ? liveRequest() : platformApi.request(operationId)) - .then(payload => { - state.reading = ''; - const requestIdValue = payload?.meta?.requestId || payload?.requestId || payload?.traceId || id; - const detail = apply?.(payload) || '查询结果已刷新'; - state.contractResults[key] = { status: 'success', title: `${title}完成`, detail, requestId: requestIdValue }; - if (actionId) window.recordPlatformSpecResult?.(actionId, { result: 'success', operationId, requestId: requestIdValue }); - render(); - }) - .catch(error => { - state.reading = ''; - const requestIdValue = error.requestId || id; - state.contractResults[key] = { status: 'error', title: `${title}失败`, detail: backendErrorText(error), requestId: requestIdValue }; - if (actionId) window.recordPlatformSpecResult?.(actionId, { result: 'failed', operationId, requestId: requestIdValue }); - render(); - }); - return; - } - const response = nextResponse(); - setTimeout(() => { - state.reading = ''; - if (response !== 'success') { - const detail = response === 'validation_error' ? '服务端拒绝查询参数,已保留当前筛选' : 'Mock 查询失败,已保留当前筛选'; - state.contractResults[key] = { status: 'error', title: `${title}失败`, detail, requestId: id }; - addAudit(`${key}.failed`, 'mock_request', id, operationId, response === 'validation_error' ? '中' : '高', `${detail}。Request ID:${id}。`, '失败'); - if (actionId) window.recordPlatformSpecResult?.(actionId, { result: 'failed', operationId, requestId: id }); - render(); - return; - } - const detail = apply?.() || '查询结果已刷新'; - state.contractResults[key] = { status: 'success', title: `${title}完成`, detail, requestId: id }; - if (actionId) window.recordPlatformSpecResult?.(actionId, { result: 'success', operationId, requestId: id }); - render(); - }, 520); -} -function addContractTask({ actionId, operationId, label, resultTarget, execute, suppliedRequestId = '' }) { - const response = nextResponse(); - const id = suppliedRequestId || requestId(); - const task = addTask(label, resultTarget, taskItem => { - if (response !== 'success') { - const message = `${response === 'validation_error' ? '服务端字段校验失败' : 'Mock 异步请求失败'} · Request ID:${id}`; - addAudit(`${actionId}.failed`, 'mock_request', id, operationId, '高', message, '失败'); - window.recordPlatformSpecResult?.(actionId, { result: 'failed', operationId, requestId: id, taskId: taskItem.id }); - throw new Error(message); - } - execute?.(taskItem, id); - window.recordPlatformSpecResult?.(actionId, { result: 'success', operationId, requestId: id, taskId: taskItem.id }); - }); - task.requestId = id; - task.operationId = operationId; - saveData(); - return task; -} -function canWrite(permission) { return hasPermission(permission) && state.role !== 'readonly'; } -function isCompactAdmin() { return window.matchMedia('(max-width: 767px)').matches; } -function requireDesktop(actionLabel) { - if (!isCompactAdmin()) return false; - openModal('mobileBoundary', { actionLabel }); - return true; -} -function closeMobileMenu() { - app.classList.remove('menu-open'); - document.body.classList.remove('menu-locked'); - updateMenuButtonAccessibility(); -} -function toggleMobileMenu() { - const opening = !app.classList.contains('menu-open'); - app.classList.toggle('menu-open', opening); - document.body.classList.toggle('menu-locked', opening); - updateMenuButtonAccessibility(); -} - -function setupPrototypeControls() { - roleSelect.innerHTML = Object.entries(roleDefinitions).map(([value, role]) => ``).join(''); - scenarioSelect.innerHTML = [['normal', '正常'], ['loading', '加载中'], ['empty', '空状态'], ['partial_error', '局部失败'], ['error', '加载失败'], ['forbidden', '403 无权限'], ['session_invalid', '401 会话失效'], ['submitting', '提交中'], ['success', '成功结果']].map(([value, label]) => ``).join(''); - responseSelect.innerHTML = [['success', '下一次成功'], ['server_error', '下一次服务端失败'], ['validation_error', '下一次字段失败']].map(([value, label]) => ``).join(''); - roleSelect.value = state.role; scenarioSelect.value = state.scenario; responseSelect.value = state.response; -} -function renderNav() { - const activeNav = ['tenantDetail', 'billingProfile'].includes(state.view) ? 'tenants' : state.view; - sideNav.innerHTML = navGroups.map(([group, items]) => { - const visible = items.filter(([id]) => - hasPermission(pageMeta[id].permission) && (!platformApi?.isEnabled() || API_CONNECTED_PAGES.has(id))); - if (!visible.length) return ''; - return `

${group}

${visible.map(([id, glyph, label]) => ``).join('')}
`; - }).join(''); - const staffShortcut = document.querySelector('.platform-foot>button'); - if (staffShortcut) staffShortcut.hidden = !hasPermission('platform:staff:read'); - const accountRole = document.querySelector('.platform-foot small'); - if (accountRole) accountRole.textContent = roleDefinitions[state.role]?.label || '平台管理员'; - const authenticatedUser = window.GongxuePlatformAuth?.getUser?.(); - const accountName = document.querySelector('.platform-foot strong'); - const accountAvatar = document.querySelector('.platform-foot>div>span'); - const displayName = authenticatedUser?.name || authenticatedUser?.email; - if (accountName && displayName) accountName.textContent = displayName; - if (accountAvatar && displayName) accountAvatar.textContent = displayName.slice(0, 1).toUpperCase(); -} -function updateCounters() { - const activeTasks = data.tasks.filter(task => ['pending', 'processing'].includes(task.status)).length; - const openAlerts = data.alerts.filter(alert => alert.status === 'open').length; - taskCount.textContent = activeTasks; - taskCount.hidden = activeTasks === 0; - alertCount.textContent = openAlerts; - alertCount.hidden = openAlerts === 0; -} -function pageHead(title, description, actions = '', options = {}) { - const level = options.level || pageMeta[state.view]?.level || 1; - const nav = level > 1 ? `
` : ''; - return `
${nav}${pageMeta[state.view]?.id || ''}${level > 1 ? ` · L${level}` : ''}

${title}

${description}

${actions}
`; -} -function metric(label, value, note, glyph, style = 'blue') { return `
${icon(glyph)}
${label}${value}

${note}

`; } -function statusBadge(value) { return `${escapeHtml(value)}`; } -function emptyBlock(title, description, action = '') { return `
${icon('inbox')}

${title}

${description}

${action}
`; } -function requestErrorBlock(partial = false) { - const id = requestId(); - return `
${icon(partial ? 'cloud-off' : 'triangle-alert')}

${partial ? '部分数据暂时不可用' : '页面加载失败'}

${partial ? '主列表保留成功数据,右侧聚合区加载失败。' : 'Mock 服务返回错误,未泄露内部堆栈。'} Request ID:${id}

`; -} -function renderScenario(content) { - if (state.scenario === 'session_invalid') return `
${pageHead('会话已失效', '平台会话已过期或被管理员撤销。')}
${icon('log-in')}

401 · 请重新登录

当前 Mock 已清理会话上下文,不展示任何平台业务数据。重新登录后返回安全首页。

`; - if (!hasPermission(pageMeta[state.view]?.permission) || state.scenario === 'forbidden') return `
${pageHead('没有访问权限', '当前演示角色无权访问此平台功能。')}
${icon('shield-x')}

403 · 权限不足

需要权限 ${pageMeta[state.view]?.permission}。菜单会按权限隐藏,深链进入则显示此页面。

`; - if (state.scenario === 'loading') return `
${pageHead(pageMeta[state.view].title, '正在从 apps/api Mock 加载数据。')}
${Array.from({ length: 6 }, (_, index) => ``).join('')}

超过 8 秒时可使用重试入口。

`; - if (state.scenario === 'submitting') return `
${pageHead(pageMeta[state.view].title, '正在提交 Mock 写请求。')}
${icon('loader-circle')}

正在提交

按钮已防重复提交,输入内容会保留;完成后将显示结果摘要与唯一结果编号。

`; - if (state.scenario === 'success') return `
${pageHead(pageMeta[state.view].title, '本次 Mock 操作已完成。')}
${icon('circle-check')}

操作成功

结果编号:RESULT-DEMO-20260723 · 已写入审计,可返回当前工作页继续处理。

`; - if (state.scenario === 'error') return `
${pageHead(pageMeta[state.view].title, '数据加载未完成。')}${requestErrorBlock()}
`; - if (state.scenario === 'empty') return `
${pageHead(pageMeta[state.view].title, '当前演示数据集为空。')}${emptyBlock('当前页面没有数据', '这是只存在于 Mock 原型的空状态演练。恢复“正常”即可继续测试真实交互。', '')}
`; - if (state.scenario === 'partial_error') { - const closingIndex = content.lastIndexOf(''); - return closingIndex >= 0 ? `${content.slice(0, closingIndex)}${requestErrorBlock(true)}${content.slice(closingIndex)}` : `${content}${requestErrorBlock(true)}`; - } - return content; -} - -function businessStatusLabel(value) { - const key = String(value || '').replace(/([a-z0-9])([A-Z])/g, '$1_$2').toLowerCase(); - return ({ draft: '草稿', active: '正常', published: '已发布', retired: '已下架', archived: '已归档', pending: '待处理', pending_payment: '待付款', paid: '已支付', succeeded: '已成功', failed: '失败', requested: '已申请', completed: '已完成', verified: '已验证', dns_pending: 'DNS 待验证', tls_pending: 'TLS 待就绪', disabled: '已停用' })[key] || value || '-'; -} - -function renderDomains() { - return `
${pageHead('租户域名与证书', '统一查看租户域名的 DNS 验证、证书和主域名状态,可对未就绪域名重新检查。')} -
${data.domains.map(item => ``).join('')}
租户域名用途主域名DNS 验证TLS 就绪最近检查状态
${escapeHtml(tenantById(item.tenantId)?.name || item.tenantId)}${escapeHtml(item.host)}${escapeHtml(item.domainType || '-')}${item.isPrimary ? '是' : '否'}${item.dnsVerifiedAt ? '已验证' : '待验证'}${item.tlsReadyAt ? '已就绪' : '待就绪'}${escapeHtml(item.lastCheckedAt || '-')}${statusBadge(businessStatusLabel(item.status))}${escapeHtml(item.lastFailureReason || '')}
${data.domains.length ? '' : emptyBlock('暂无租户域名', '租户配置域名后将在这里显示。')}
`; -} - -function renderCatalog() { - const catalog = data.saasCatalog || {}; - const features = catalog.features || []; - const offerings = catalog.offerings || []; - const versions = catalog.versions || []; - const offeringName = id => offerings.find(item => item.id === id)?.name || id; - return `
${pageHead('SaaS 商品与版本', '管理可售套餐、增值服务、功能权益、使用限额和定价版本。', ``)} -
${icon('blocks')}功能${features.length}

其中 ${features.filter(item => String(item.status).toLowerCase() === 'active').length} 项启用

${icon('packages')}商品${offerings.length}

基础套餐与增值包

${icon('git-branch')}版本${versions.length}

草稿、发布与下架生命周期

-

套餐版本

发布后版本不可直接覆写
${versions.map(item => ``).join('')}
商品版本周期原价售价生效时间状态
${escapeHtml(offeringName(item.offeringId))}${escapeHtml(item.offeringId)}V${item.version}${escapeHtml(item.billingCycle || '-')}${money(Number(item.originalAmountCents || 0) / 100)}${money(Number(item.amountCents || 0) / 100)}${escapeHtml(item.effectiveAt || '-')}${statusBadge(businessStatusLabel(item.status))}
${String(item.status).toLowerCase() === 'draft' ? `` : ``}${String(item.status).toLowerCase() === 'published' ? `` : ''}
-

功能目录

配置套餐可包含的业务功能
${features.map(item => ``).join('')}
功能编码分类参考价核心功能状态
${escapeHtml(item.name)}${escapeHtml(item.description || '')}${escapeHtml(item.code)}${escapeHtml(item.category || '-')}${money(Number(item.referencePriceCents || 0) / 100)}${item.isCore ? '是' : '否'}${statusBadge(businessStatusLabel(item.status))}

功能限额

设置席位、题量、存储等使用上限
${(catalog.limitDefinitions || []).map(item => ``).join('')}
限额指标编码所属功能单位计量方式告警阈值硬限额
${escapeHtml(item.name)}${escapeHtml(item.metricCode)}${escapeHtml(features.find(feature => feature.code === item.featureCode)?.name || item.featureCode)}${escapeHtml(item.unit)}${String(item.kind).toLowerCase() === 'period' ? '周期累计' : '当前值'}${item.warningPercent}%${item.isHardLimit ? '是' : '否'}
`; -} - -function renderSaasFinance() { - const tabs = [['orders', '订单'], ['payments', '支付'], ['refunds', '退款'], ['invoices', '发票'], ['subscriptions', '订阅']]; - const rows = state.saasFinanceTab === 'orders' ? data.saasOrders : state.saasFinanceTab === 'payments' ? data.billingPayments : state.saasFinanceTab === 'refunds' ? data.saasRefunds : state.saasFinanceTab === 'invoices' ? data.invoices : data.subscriptions; - const cells = item => state.saasFinanceTab === 'orders' ? [item.orderNo, tenantById(item.tenantId)?.name || item.tenantId, item.purpose, money(Number(item.totalAmountCents || 0) / 100), businessStatusLabel(item.status), item.expiresAt] : state.saasFinanceTab === 'payments' ? [item.paymentNo || item.id, tenantById(item.tenantId)?.name || item.tenantId, item.provider || '-', money(item.amount), businessStatusLabel(item.status), item.paidAt || '-'] : state.saasFinanceTab === 'refunds' ? [item.refundNo || item.id, tenantById(item.tenantId)?.name || item.tenantId, item.reason || '-', money(Number(item.amountCents || 0) / 100), businessStatusLabel(item.status), item.completedAt || '-'] : state.saasFinanceTab === 'invoices' ? [item.id, tenantById(item.tenantId)?.name || item.tenantId, item.type, money(item.total), item.status, item.due] : [item.id, tenantById(item.tenantId)?.name || item.tenantId, item.planCode || '-', money(item.amount), item.status, item.expires]; - return `
${pageHead('SaaS 订单与交易', '集中查看租户订购、收款、退款、开票和订阅情况。')}
${rows.map(item => `${cells(item).map((value, index) => ``).join('')}`).join('')}
编号租户类型 / 说明金额状态时间
${index === 0 ? `${escapeHtml(value)}` : escapeHtml(value)}
${rows.length ? '' : emptyBlock('当前暂无数据', '有新的业务记录后会在这里显示。')}
`; -} - -function renderRoles() { - return `
${pageHead('平台角色与功能', '按岗位配置可访问的菜单和可执行的业务操作。', ``)}

平台角色

${data.platformRoles.length} 个启用角色
${data.platformRoles.map(role => `
${icon('shield-check')}
${escapeHtml(role.name)}${escapeHtml(role.description || '暂无角色说明')}
${role.permissionCodes.length} 项功能
`).join('')}

可分配功能

选择角色可以使用的业务功能
${Object.entries(data.platformPermissions).map(([code, name]) => `
${icon('key-round')}
${escapeHtml(name)}${escapeHtml(code)}
${data.platformRoles.filter(role => role.permissionCodes.includes(code) || role.permissionCodes.includes('*')).length} 个角色
`).join('')}
`; -} - -function renderOverview() { - if (platformApi?.isEnabled()) return renderApiOverview(); - const active = data.tenants.filter(tenant => tenant.status === '正常').length; - const overdue = data.invoices.filter(invoice => invoice.status === '已逾期').reduce((sum, invoice) => sum + invoice.balance, 0); - const openAlerts = data.alerts.filter(alert => alert.status === 'open').slice(0, 4); - const totalStudents = data.tenants.reduce((sum, tenant) => sum + tenant.students, 0); - const totalQuestions = data.banks.reduce((sum, bank) => sum + bank.questions, 0); - return `
${pageHead('平台经营工作台', '查看租户规模、订阅账务、平台用量与安全态势。数据更新时间:2026-07-23 10:10 CST。', ``)} -
${metric('有效租户', active, `共 ${data.tenants.length} 家`, 'building-2')}${metric('活跃订阅', data.subscriptions.filter(item => item.status === '活跃').length, '未来30天到期 2 条', 'badge-dollar-sign', 'green')}${metric('逾期应收', money(overdue), `涉及 ${data.invoices.filter(item => item.status === '已逾期').length} 家租户`, 'receipt-text', 'orange')}${metric('平台学生规模', formatNumber(totalStudents), 'Mock 最近30日活跃 82%', 'users', 'purple')}${metric('公共题库题目', formatNumber(totalQuestions), `${data.banks.length} 个公共来源库`, 'database-zap', 'cyan')}
-

平台收入与租户增长

最近 12 个月 · 不含租户学生端交易流水
MRR有效租户
¥500k¥350k¥200k0
${[42, 48, 52, 58, 64, 71, 78, 82, 88, 94, 101, 108].map((value, index) => `${index + 1}月`).join('')}
-

需要关注

按业务影响排序
${openAlerts.map(alert => ``).join('') || emptyBlock('没有开放告警', '平台当前没有需要处理的开放告警。')}
-

租户状态

可进入租户工作列表处理
${data.tenants.length}全部租户
${[['正常', data.tenants.filter(t => t.status === '正常').length, 68], ['试用', data.tenants.filter(t => t.status === '试用').length, 16], ['待配置', data.tenants.filter(t => t.status === '待配置').length, 16], ['暂停/逾期', data.tenants.filter(t => t.status === '暂停' || t.billing === '逾期').length, 16]].map(([label, count, percent]) => `

${label}${count}

`).join('')}
-

账务结论

先行动,再看明细
待付款${money(data.invoices.filter(i => i.status === '待付款').reduce((s, i) => s + i.balance, 0))}可发送到期提醒
已逾期${money(overdue)}进入催缴处理
预估超额${money(data.usage.reduce((s, u) => s + u.estimated, 0))}需确认生成
-

最近平台事件

跨租户关键变更
${data.auditLogs.slice(0, 3).map(log => `
${escapeHtml(log.actor.slice(0, 1))}

${escapeHtml(log.actor)} ${escapeHtml(log.details)}${escapeHtml(log.time)} · ${escapeHtml(log.ip)}

`).join('')}
`; -} - -function renderApiOverview() { - const overview = data.apiOverview || {}; - const openAlerts = data.alerts.filter(alert => alert.status === 'open').slice(0, 4); - return `
${pageHead('平台经营工作台', `真实 PostgreSQL 数据 · ${state.apiLoadedAt || '正在加载'}`, ``)} -
${metric('全部租户', overview.tenantCount ?? data.tenants.length, `活跃 ${overview.activeTenantCount ?? 0} 家`, 'building-2')}${metric('暂停租户', overview.suspendedTenantCount ?? 0, '来自真实租户状态', 'pause-circle', 'orange')}${metric('已支付订单', overview.paidOrderCount ?? 0, `全部订单 ${overview.orderCount ?? 0}`, 'receipt-text', 'green')}${metric('平台收入', money(Number(overview.revenueCents || 0) / 100), '按已支付订单统计', 'circle-dollar-sign', 'cyan')}${metric('题库 / 题目', `${overview.questionBankCount ?? 0} / ${formatNumber(overview.questionCount ?? 0)}`, `学习活跃用户 ${overview.learningActiveUserCount ?? 0}`, 'database-zap', 'purple')}
-

租户状态

来自 /api/platform-admin/tenants
${data.tenants.length}全部租户
${[['正常', data.tenants.filter(item => item.status === '正常').length, 100], ['待配置', data.tenants.filter(item => item.status === '待配置').length, 100], ['暂停', data.tenants.filter(item => item.status === '暂停').length, 100]].map(([label, count, percent]) => `

${label}${count}

`).join('')}
-

开放告警

真实审计告警
${openAlerts.map(alert => ``).join('') || emptyBlock('没有开放告警', '当前数据库没有需要处理的开放告警。')}
-

最近平台事件

来自真实审计日志
${data.auditLogs.slice(0, 6).map(log => `
${escapeHtml(log.actor.slice(0, 1))}

${escapeHtml(log.actor)} ${escapeHtml(log.details)}${escapeHtml(log.time)} · ${escapeHtml(log.ip)}

`).join('') || '

暂无审计事件

'}
`; -} - -function renderTenants() { - let rows = data.tenants.filter(tenant => state.tenantFilter === 'all' || tenant.status === state.tenantFilter || tenant.billing === state.tenantFilter); - if (state.tenantPlan !== 'all') rows = rows.filter(tenant => tenant.planCode === state.tenantPlan); - const query = state.tenantSearch.trim().toLowerCase(); - if (query) rows = rows.filter(tenant => [tenant.name, tenant.slug, tenant.legal, tenant.host].some(value => value.toLowerCase().includes(query))); - if (state.scenario === 'empty') rows = []; - return `
${pageHead('租户列表与创建', '搜索租户并管理主体、域名、套餐、业务状态与账务状态。', `${platformApi?.isEnabled() ? '' : ``}${canWrite('platform:tenant:write') ? `` : ''}`)} -
${['all', '正常', '试用', '暂停', '待配置', '逾期'].map(value => ``).join('')}
- ${rows.length ? `
${rows.map(tenant => ``).join('')}
租户套餐模式业务状态账务状态学生 / 题目订阅到期待付余额
${escapeHtml(tenant.plan)}${escapeHtml(tenant.mode)}${statusBadge(tenant.status)}${statusBadge(tenant.billing)}${formatNumber(tenant.students)}${formatNumber(tenant.questions)} 题${tenant.expires || '-'}${money(tenant.balance)}
${canWrite('platform:tenant:status') ? `` : ''}
共 ${rows.length} 家匹配租户筛选、搜索和返回上下文会保留
` : emptyBlock(query || state.tenantFilter !== 'all' || state.tenantPlan !== 'all' ? '没有匹配的租户' : '还没有租户', query || state.tenantFilter !== 'all' || state.tenantPlan !== 'all' ? '调整搜索词或筛选条件后重试。' : '创建第一个租户及首期订阅基础。', canWrite('platform:tenant:write') ? `` : '')}
`; -} - -function renderTenantDetail() { - const tenant = tenantById(state.selectedTenant) || data.tenants[0]; - if (!tenant) return `
${pageHead('租户详情与生命周期', '租户不存在或已被移除。', '', { level: 2 })}${emptyBlock('租户不存在', '返回租户列表选择其他租户。', '')}
`; - const subscription = data.subscriptions.find(item => item.tenantId === tenant.id); - const invoices = data.invoices.filter(item => item.tenantId === tenant.id); - const usage = data.usage.find(item => item.tenantId === tenant.id); - return `
${pageHead(tenant.name, `${tenant.slug} · ${tenant.legal}`, `${canWrite('platform:tenant:status') ? `` : ''}`, { level: 2 })} -
业务状态${statusBadge(tenant.status)}
账务状态${statusBadge(tenant.billing)}
当前套餐${escapeHtml(tenant.plan)}
订阅到期${tenant.expires || '-'}
待付余额${money(tenant.balance)}
-

主体、负责人和域名

平台只展示链接,不冒充租户登录
主体名称
${escapeHtml(tenant.legal)}
租户 ID
${tenant.id}
负责人
${escapeHtml(tenant.owner)} · ${escapeHtml(tenant.ownerPhone)}
开通时间
${escapeHtml(tenant.createdAt)} CST
学生端域名
${escapeHtml(tenant.host)} ${statusBadge('已验证')}
租户后台域名
admin.${escapeHtml(tenant.host.replace(/^study\.|^learn\.|^app\.|^tiku\./, ''))} ${statusBadge('已验证')}
-

关联工作区

详情承接上下文,编辑成功回详情
-

生命周期轨迹

状态变更写入平台审计

租户创建${tenant.createdAt} CST · 主体与初始模式已保存

域名验证${tenant.host} · HTTPS 正常

订阅生效${subscription ? `${subscription.start} 至 ${subscription.expires}` : '待创建订阅'}

账务状态${tenant.billing}${tenant.balance ? ` · 待付 ${money(tenant.balance)}` : ''}

`; -} - -function renderBillingProfile() { - const tenant = tenantById(state.selectedTenant) || data.tenants[0]; - const profile = data.billingProfiles[tenant.id] || {}; - const readOnly = !canWrite('platform:tenant:billing_profile'); - return `
${pageHead('租户账务资料', `${tenant.name} · 银行账号仅展示脱敏值,密钥和完整账号不得回显。`, ``, { level: 3 })} -

开票与联系人

${readOnly ? '当前角色仅可查看' : '必填字段离开时校验,提交时再次校验'}
-

发票与银行信息

平台只接受脱敏账户尾号
-
所有时间以 Asia/Shanghai 展示 · 保存将写入审计日志${!readOnly ? `` : ''}
`; -} - -function renderSubscriptions() { - const selectedTenant = state.selectedTenant ? tenantById(state.selectedTenant) : null; - const rows = state.scenario === 'empty' ? [] : data.subscriptions; - return `
${pageHead('SaaS 套餐与订阅', '查看套餐权益,并为租户创建或续订订阅。套餐内容请在“商品与版本”中维护。', `${canWrite('platform:billing:write') ? `` : ''}`)} -
${data.plans.map((plan, index) => `
${plan.name}

${plan.description}

${plan.tenantCount} 家租户
${money(plan.amount)}/年
    ${plan.quotas.map(item => `
  • ${icon('check')}${item}
  • `).join('')}
`).join('')}
- ${rows.length ? `

活跃与试用订阅

${rows.length} 条${selectedTenant ? ` · 已定位 ${selectedTenant.name}` : ''}
${rows.map(subscription => { const tenant = tenantById(subscription.tenantId); return ``; }).join('')}
租户订阅号套餐周期开始时间到期时间自动续费状态
${escapeHtml(tenant?.name || '-')}${escapeHtml(tenant?.slug || '-')}${subscription.id}${planByCode(subscription.planCode)?.name || subscription.planCode}${subscription.cycle}${subscription.start}${subscription.expires}${statusBadge(subscription.status)}
` : emptyBlock('还没有订阅', '创建租户订阅后将在此显示。', canWrite('platform:billing:write') ? '' : '')}
`; -} - -function renderBilling() { - const query = state.invoiceSearch.trim().toLowerCase(); - const rows = state.scenario === 'empty' ? [] : data.invoices.filter(invoice => (!state.selectedTenant || invoice.tenantId === state.selectedTenant) && (state.invoiceStatus === 'all' || invoice.status === state.invoiceStatus) && (!query || [invoice.id, invoice.type, invoice.period, invoice.note, tenantById(invoice.tenantId)?.name].some(value => String(value || '').toLowerCase().includes(query)))); - const unpaid = data.invoices.filter(invoice => invoice.status === '待付款').reduce((sum, invoice) => sum + invoice.balance, 0); - const overdue = data.invoices.filter(invoice => invoice.status === '已逾期').reduce((sum, invoice) => sum + invoice.balance, 0); - return `
${pageHead('服务费账单', '查询、手工创建、预览订阅账单候选并通过 dry-run 确认批量生成。', `${canWrite('platform:billing:write') ? `` : ''}`)} -
${metric('本月应收', money(data.invoices.reduce((s, i) => s + i.total, 0)), `${data.invoices.length} 张账单`, 'receipt-text')}${metric('已收款', money(data.invoices.reduce((s, i) => s + i.paid, 0)), '人工收款需二次确认', 'circle-dollar-sign', 'green')}${metric('待付款', money(unpaid), '可发送到期提醒', 'clock-3', 'orange')}${metric('已逾期', money(overdue), `${data.invoices.filter(i => i.status === '已逾期').length} 家租户`, 'triangle-alert', 'red')}
-
${contractResult('invoice-query')} - - ${rows.length ? `
${rows.map(invoice => { const tenant = tenantById(invoice.tenantId); return ``; }).join('')}
账单号租户类型 / 账期总额已付 / 余额到期日状态
${invoice.type}${invoice.period}${money(invoice.total)}${money(invoice.paid)}余额 ${money(invoice.balance)}${invoice.due}${statusBadge(invoice.status)}
${invoice.balance && canWrite('platform:billing:payment') ? `` : ''}
` : emptyBlock('没有匹配账单', query || state.invoiceStatus !== 'all' ? '调整账单查询条件后重试。' : state.selectedTenant ? '当前租户没有匹配账单,可清除租户上下文查看全部。' : '账单候选生成后会在这里显示。', state.selectedTenant ? '' : '')}
`; -} - -function renderUsage() { - const periodRows = data.usage.filter(item => item.period === state.usagePeriod); - const rows = state.scenario === 'empty' ? [] : periodRows.filter(item => !state.selectedTenant || item.tenantId === state.selectedTenant); - const periodLabel = state.usagePeriod.replace('-', '年') + '月'; - return `
${pageHead('用量与超额计费', '按账期查看学生席位、题目、存储与流量用量;区分 Worker 自动采集和人工补录。', `${canWrite('platform:usage:write') ? `` : ''}`)} -
${periodLabel}学生席位${formatNumber(periodRows.reduce((s, i) => s + i.students, 0))}合同总量 176,000
题目数量${formatNumber(periodRows.reduce((s, i) => s + i.questions, 0))}合同总量 495,000
对象存储${formatNumber(periodRows.reduce((s, i) => s + i.storageGB, 0))} GB合同总量 13.5 TB
预估超额费${money(periodRows.reduce((s, i) => s + i.estimated, 0))}涉及 ${periodRows.filter(i => i.estimated).length} 家租户
- ${rows.length ? `
${rows.map(item => { const tenant = tenantById(item.tenantId); const plan = planByCode(tenant?.planCode); const seatQuota = plan?.code === 'enterprise' ? 20000 : plan?.code === 'pro' ? 8000 : 2000; return ``; }).join('')}
租户来源 / 周期学生席位题目数量存储 / 流量超额项预估费用
${escapeHtml(tenant?.name || '-')}${escapeHtml(tenant?.plan || '-')}${item.source}${item.period}
${formatNumber(item.students)} / ${formatNumber(seatQuota)}
${formatNumber(item.questions)}
${item.storageGB} GB${item.trafficTB} TB 流量${statusBadge(item.overage.length ? item.overage.join(' + ') : '无')}${money(item.estimated)}
` : emptyBlock('本账期没有用量记录', '可以手工补录,或等待 Worker 自动采集。', canWrite('platform:usage:write') ? '' : '')}
`; -} - -function renderDunning() { - const overdueInvoices = data.invoices.filter(invoice => invoice.status === '已逾期' || invoice.status === '待付款'); - return `
${pageHead('收款、逾期与催缴', '人工确认收款、dry-run 预览逾期处理、生成催缴并跟踪通知事件。', `${canWrite('platform:billing:dunning') ? `` : ''}${canWrite('platform:billing:notification') ? `` : ''}`)} - - ${state.billingTab === 'collections' ? `

待收与逾期队列

${overdueInvoices.length} 张账单
${overdueInvoices.map(invoice => { const tenant = tenantById(invoice.tenantId); return `
${icon('building-2')}
${escapeHtml(tenant?.name || '-')}${invoice.id} · 到期 ${invoice.due} · ${invoice.status}
${money(invoice.balance)}
`; }).join('') || emptyBlock('没有待处理账单', '已无待收或逾期服务费账单。')}

全局催缴策略

可由平台任务生成提醒

到期前 7 天邮件 + 租户后台通知

到期当天短信 + 邮件 + 租户后台通知

逾期 3 天升级财务负责人并限制部分写操作

逾期 7 天暂停租户业务,保留只读访问

` : state.billingTab === 'reminders' ? `
${data.reminders.map(item => ``).join('')}
提醒号租户 / 账单级别渠道消息时间状态
${item.id}${escapeHtml(tenantById(item.tenantId)?.name || '-')}${item.invoiceId}L${item.level}${item.channel}${escapeHtml(item.message)}${item.date} CST${statusBadge(item.status)}
` : state.billingTab === 'channels' ? `
${data.dunningChannels.map(channel => ``).join('')}
渠道代码Provider端点重试状态
${escapeHtml(channel.name)}${channel.code}${channel.provider}${escapeHtml(channel.endpoint)}${channel.retry} 次${statusBadge(channel.enabled ? '启用' : '已停用')}
` : `
${(data.dunningEvents || []).map(event => ``).join('')}
事件 ID主题渠道尝试更新时间结果错误
${event.id}${escapeHtml(event.subject)}${escapeHtml(notificationChannelName(event.channelId))}${event.attempts}${event.updatedAt}${statusBadge(event.status)}${escapeHtml(event.error || '-')}
`}
`; -} - -function renderBank() { - const selected = bankById(state.selectedBank) || data.banks[0]; - if (selected && state.selectedBank !== selected.id) state.selectedBank = selected.id; - const query = state.bankSearch.trim().toLowerCase(); - const bankRows = data.banks.filter(bank => !query || [bank.name, bank.status].some(value => String(value || '').toLowerCase().includes(query))); - const nodes = data.bankNodes.filter(node => node.questionBankId === selected?.id); - const nodeOptions = nodes.filter(node => node.isActive).map(node => ``).join(''); - const tabs = [['structure', '内容结构'], ['single', '单题录入'], ['batch', '批量导入'], ['manage', '题目管理'], ['structured', 'JSON 文件导入']]; - const bankSelect = ``; - let content = emptyBlock('尚未创建公共题库', '点击“新建题库”后即可配置分类、科目、章节和试卷。'); - if (selected && state.bankTab === 'structure') content = `
平台公共题库

${escapeHtml(selected.name)}

通过分类、科目、章节和试卷组织题目。

内容节点${selected.nodes || nodes.length}
题目总数${formatNumber(selected.questions || 0)}
启用节点${nodes.filter(item => item.isActive).length}
题库状态${selected.status}
${state.selectedBankNode ? `
${bankNodeTypeLabel(bankNodeById(state.selectedBankNode)?.nodeType)}

${escapeHtml(bankNodeById(state.selectedBankNode)?.name || '')}

当前节点共 ${bankNodeById(state.selectedBankNode)?.questionCount || 0} 道未归档题目。

` : ''}
`; - if (selected && state.bankTab === 'structure' && state.selectedBankNode) content += `

节点排序

调整当前节点在同级内容中的显示顺序
`; - if (selected && state.bankTab === 'single') content = `

单题录入

保存后自动形成新题目版本
`; - if (selected && state.bankTab === 'batch') content = `

普通题目批量导入

先选择章节或试卷,再粘贴题目数组
${renderBankImportResult()}
`; - if (selected && state.bankTab === 'manage') content = `
${data.bankQuestions.map(item => ``).join('')}
题目题型难度节点版本状态
${escapeHtml(String(item.content || '').slice(0, 80) || '未填写题干')}${escapeHtml(item.legacyId || item.id)}${questionTypeLabel(item.type)}${item.difficulty || '-'}${escapeHtml(bankNodeById(item.contentNodeId)?.name || '-')}V${item.versionNo}${statusBadge(item.statusLabel)}${item.statusLabel !== '已归档' ? `` : ''}
${data.bankQuestions.length ? `
共 ${state.bankQuestionTotal} 道题
` : emptyBlock('暂无题目', '选择节点后查询,或先录入、导入题目。')}
`; - if (selected && state.bankTab === 'structured') content = `

JSON 文件导入

支持带分类、科目、章节/试卷和题目的 2.0 结构化文件
${renderBankImportResult()}
`; - return `
${pageHead('公共题库', '配置公共题库内容结构,完成单题录入、题目管理和两种 JSON 导入。', `${selected ? `` : ''}`)}
${bankSelect}
${contractResult('bank-query')}${content}
`; -} - -function renderBankImportResult() { - const result = data.bankImportResult; - if (!result) return ''; - const job = result.detail?.job || result.job || {}; - const issues = result.detail?.issues || result.issues || []; - return `
${job.dryRun ? '预检完成' : '导入完成'}

共 ${job.totalCount || 0} 条,${job.validCount || 0} 条有效

新增题目 ${result.insertedQuestionCount || 0},更新 ${result.updatedQuestionCount || 0},跳过 ${result.skippedQuestionCount || 0},新建节点 ${result.createdNodeCount || 0}。

${issues.length ? `${issues.slice(0, 8).map(item => `第 ${item.rowNo || '-'} 行:${escapeHtml(item.message)}`).join('
')}
` : '没有发现数据问题。'}
`; -} - -function renderCrm() { - const activeConfigs = data.crmConfigs.filter(item => item.enabled).length; - const failedLeads = data.crmLeads.filter(item => item.status === '推送失败').length; - const notice = '集中维护租户线索推送配置、失败队列、分配策略和同步日志。'; - if (state.crmTab === 'logs') return `
${pageHead('CRM 推送日志', notice)}
${data.crmLogs.map(item => ``).join('')}
日志 ID租户队列任务HTTP 状态耗时尝试次数结果 / 错误时间
${escapeHtml(item.id)}${escapeHtml(tenantById(item.tenantId)?.name || item.tenantId)}${escapeHtml(item.queueId || '-')}${escapeHtml(item.statusCode || '-')}${escapeHtml(item.durationMs || 0)} ms${escapeHtml(item.attempt || item.attempts || 1)}${statusBadge(item.success ? '成功' : '失败')}${escapeHtml(item.error || item.responseSummary || '')}${escapeHtml(item.createdAt || '-')}
${data.crmLogs.length ? '' : emptyBlock('暂无 CRM 推送日志', '线索推送后会在这里保留请求结果与错误摘要。')}
`; - return `
${pageHead('CRM 接入与线索流转', notice, `${canWrite('platform:crm:write') ? `` : ''}`)} -
已启用接入${activeConfigs}共 ${data.crmConfigs.length} 家租户配置
待推送线索${data.crmLeads.filter(item => item.status === '待推送').length}来自学生端留资与活动报名
推送失败${failedLeads}进入重试或死信处理
权限${hasPermission('platform:crm:write') ? '可维护' : '只读'}platform:crm:read/write
- - ${state.crmTab === 'configs' ? `
${data.crmConfigs.map(config => ``).join('')}
租户ProviderEndpoint分配方式线索池超时 / 重试状态
${escapeHtml(tenantById(config.tenantId)?.name || '-')}${escapeHtml(config.id)}${escapeHtml(config.provider)}${escapeHtml(config.endpoint)}${escapeHtml(config.assignmentMode)}${escapeHtml(config.pool)}${config.timeout}s / ${config.retry} 次${statusBadge(config.status)}
${canWrite('platform:crm:write') ? `` : ''}
` : state.crmTab === 'leads' ? `
${data.crmLeads.map(lead => ``).join('')}
线索租户来源 / 科目负责人尝试次数状态错误摘要
${escapeHtml(lead.student)}${lead.id} · ${lead.phone}${escapeHtml(tenantById(lead.tenantId)?.name || '-')}${escapeHtml(lead.source)}${escapeHtml(lead.subject)}${escapeHtml(lead.owner)}${lead.attempts}${statusBadge(lead.status)}${escapeHtml(lead.lastError || '-')}${lead.status === '推送失败' && canWrite('platform:crm:write') ? `` : ''}
` : `

平台默认策略

租户可在套餐授权后覆盖
${[['按地区轮转', '地区、校区、课程标签优先,适合多校区机构'], ['按校区容量', '按顾问容量与当日跟进上限分配'], ['手工分配', '只进入队列,由租户管理员手工认领']].map(([name, desc]) => `
${icon('route')}
${name}${desc}
启用
`).join('')}

线索同步边界

平台统一监控推送质量和异常重试

接入配置维护 endpoint、secret 引用、超时和重试策略

线索队列集中查看待推送、失败和重试中的线索

同步日志保留请求结果、错误摘要和审计线索

`}
`; -} - -function renderSms() { - const sent = data.smsChannels.reduce((sum, item) => sum + item.used, 0); - const quota = data.smsChannels.reduce((sum, item) => sum + item.quota, 0); - const notice = '集中管理租户短信渠道、模板审核状态和发送记录。'; - const smsNav = ``; - if (state.smsTab === 'templates') return `
${pageHead('短信模板与审核', notice, ``)}${smsNav}
${data.smsTemplates.map(template => ``).join('')}
租户模板渠道编码类型发送 / 失败审核状态启用状态
${escapeHtml(tenantById(template.tenantId)?.name || template.tenantId)}${escapeHtml(template.name)}${escapeHtml(template.id)}${escapeHtml(template.channelName || data.smsChannels.find(item => item.id === template.channelId)?.signature || '-')}${escapeHtml(template.code)}${escapeHtml(template.type)}${template.sentCount || 0} / ${template.failedCount || 0}${statusBadge(template.status)}${statusBadge(template.templateStatus || '-')}${template.status === '草稿' ? `` : ''}
`; - if (state.smsTab === 'logs') return `
${pageHead('短信发送日志', notice)}${smsNav}
${(data.smsLogs || []).map(item => ``).join('')}
日志 ID租户模板手机号Provider时间状态
${escapeHtml(item.id)}${escapeHtml(tenantById(item.tenantId)?.name || item.tenantId)}${escapeHtml(data.smsTemplates.find(template => template.id === item.templateId)?.name || item.templateId || '-')}${escapeHtml(item.phone)}${escapeHtml(item.provider)}${escapeHtml(item.updatedAt)}${statusBadge(item.status)}
${data.smsLogs?.length ? '' : emptyBlock('暂无短信发送日志', '发送短信后会在这里显示脱敏记录。')}
`; - return `
${pageHead('SMS 短信服务', notice, `${canWrite('platform:sms:write') ? `` : ''}`)} -
启用渠道${data.smsChannels.filter(item => item.enabled).length}租户自有短信服务
本月发送${formatNumber(sent)}总额度 ${formatNumber(quota)}
模板通过${data.smsTemplates.filter(item => item.status === '已通过').length}${data.smsTemplates.length} 个模板
权限${hasPermission('platform:sms:write') ? '可维护' : '只读'}platform:sms:read/write
- - ${state.smsTab === 'channels' ? `
${data.smsChannels.map(channel => ``).join('')}
租户Provider签名场景Secret Ref额度使用状态
${escapeHtml(tenantById(channel.tenantId)?.name || '-')}${channel.id}${escapeHtml(channel.provider)}${escapeHtml(channel.signature)}${escapeHtml(channel.scene)}${escapeHtml(channel.secretRef)}
${formatNumber(channel.used)} / ${formatNumber(channel.quota)}
${statusBadge(channel.status)}
${canWrite('platform:sms:write') ? `` : ''}
` : state.smsTab === 'templates' ? `
${data.smsTemplates.map(template => { const channel = data.smsChannels.find(item => item.id === template.channelId); return ``; }).join('')}
模板渠道代码类型最近发送成功率状态
${escapeHtml(template.name)}${template.id}${escapeHtml(channel?.signature || '-')}${escapeHtml(template.code)}${escapeHtml(template.type)}${escapeHtml(template.lastSend)}${escapeHtml(template.successRate)}${statusBadge(template.status)}
` : `
${data.smsTemplates.slice(0, 3).map((template, index) => { const channel = data.smsChannels.find(item => item.id === template.channelId); return ``; }).join('')}
事件租户模板手机号Provider时间状态
SMSLOG-260723-00${index + 1}${escapeHtml(tenantById(channel?.tenantId)?.name || '-')}${escapeHtml(template.name)}13${index + 6}****${8200 + index}${escapeHtml(channel?.provider || '-')}${escapeHtml(template.lastSend || '-')}${statusBadge(template.status === '已通过' ? '发送成功' : '待发送')}
`}
`; -} - -function renderPaymentSettings() { - const activeApps = data.paymentApps.filter(item => item.status === '正常').length; - const notice = '集中管理平台收款、租户支付代管、支付渠道和回调健康。'; - const paymentNav = ``; - if (state.paymentTab === 'channels') return `
${pageHead('平台支付渠道', '管理平台收款应用的支付服务商、回调地址和密钥引用。', ``)}${paymentNav}
${data.paymentChannels.map(item => ``).join('')}
应用渠道支付服务商模式回调路径密钥引用状态
${escapeHtml(data.paymentApps.find(appItem => appItem.id === item.appId)?.appName || item.appId)}${escapeHtml(item.displayName)}${escapeHtml(item.id)}${escapeHtml(item.provider)}${escapeHtml(item.mode)}${escapeHtml(item.callbackPath || '-')}${escapeHtml(item.secretRef || '-')}${statusBadge(businessStatusLabel(item.status))}
${data.paymentChannels.length ? '' : emptyBlock('暂无平台支付渠道', '请先创建平台收款应用。')}
`; - if (state.paymentTab === 'rebates') { const summary = data.rebateSummary || {}; return `
${pageHead('平台返佣汇总', '查看平台交易的返佣、待结算、已结算与异常数据。')}${paymentNav}
交易总额${money(Number(summary.grossAmountCents || 0) / 100)}
返佣总额${money(Number(summary.commissionAmountCents || 0) / 100)}
待结算${money(Number(summary.pendingSettlementCents || 0) / 100)}
已结算${money(Number(summary.paidSettlementCents || 0) / 100)}
异常数${summary.exceptionCount || 0}
`; } - return `
${pageHead('支付设置', notice, `${canWrite('platform:payment:write') ? `` : ''}`)} -
正常应用${activeApps}共 ${data.paymentApps.length} 个收款应用
本日支付事件${data.paymentEvents.length}含成功、回调失败与人工确认
回调异常${data.paymentEvents.filter(item => item.status === '回调失败').length}需要财务或运维介入
权限${hasPermission('platform:payment:write') ? '可维护' : '只读'}platform:payment:read/write
- ${paymentNav} - ${state.paymentTab === 'apps' ? `
${data.paymentApps.map(appItem => ``).join('')}
租户应用Provider模式结算Secret Ref状态
${escapeHtml(tenantById(appItem.tenantId)?.name || '-')}${appItem.id}${escapeHtml(appItem.appName)}${escapeHtml(appItem.provider)}${escapeHtml(appItem.mode)}${escapeHtml(appItem.settlement)}${escapeHtml(appItem.secretRef)}${statusBadge(appItem.status)}
${canWrite('platform:payment:write') ? `` : ''}
` : state.paymentTab === 'events' ? `
${data.paymentEvents.map(event => { const appItem = data.paymentApps.find(item => item.id === event.appId); return ``; }).join('')}
事件应用订单号金额渠道回调时间状态
${event.id}${escapeHtml(appItem?.appName || '-')}${escapeHtml(tenantById(appItem?.tenantId)?.name || '-')}${escapeHtml(event.orderNo)}${money(event.amount)}${escapeHtml(event.channel)}${escapeHtml(event.notified)}${escapeHtml(event.updatedAt)}${statusBadge(event.status)}
` : `

平台风控规则

配置证书、回调、人工确认等支付安全策略
${[['证书过期提醒', '支付证书 14 天内过期生成高危告警'], ['回调失败重试', '按 1m/5m/30m/2h 退避重试并记录审计'], ['人工确认保护', '线下收款必须二次确认并保留流水号脱敏值']].map(([name, desc]) => `
${icon('shield-check')}
${name}${desc}
启用
`).join('')}

支付能力边界

区分平台收款和租户收款代管

平台收款应用用于套餐、模块和增值服务收款

租户代管应用维护学生端收款渠道和回调地址

支付事件只读跟踪交易、退款、回调和人工确认状态

`}
`; -} - -function renderStaff() { - const query = state.staffSearch.trim().toLowerCase(); - const staffRows = data.staff.filter(person => !query || [person.name, person.username, person.email, person.phone, person.role, person.status].some(value => String(value || '').toLowerCase().includes(query))); - return `
${pageHead('平台员工与权限', '平台权限独立于租户权限;禁用员工可同步撤销会话,且不能禁用最后一名超级管理员。', `${canWrite('platform:staff:write') ? `` : ''}`)} -
-

平台员工

${staffRows.length} 名匹配 · ${data.staff.filter(item => item.status === '正常').length} 名活跃
${staffRows.map(person => `
${escapeHtml(person.name.slice(0, 1))}
${escapeHtml(person.name)}${escapeHtml(person.email)} · ${escapeHtml(person.phone)}
${escapeHtml(person.role)}${person.permissions.includes('*') ? '全部平台功能' : `${person.permissions.length} 项功能`}${person.status}
`).join('') || emptyBlock('没有匹配员工', '调整姓名、邮箱、手机号、角色或状态关键词。')}

平台角色与功能

按岗位分配可使用的业务功能
${data.platformRoles.map(role => { const features = role.permissionCodes.map(code => data.platformPermissions[code] || code); return `
${icon('shield-check')}
${escapeHtml(role.name)}${escapeHtml(role.description || (features.includes('*') ? '全部平台功能' : features.join('、')))}
${data.staff.filter(person => person.roleIds?.includes(role.id)).length}人
`; }).join('') || emptyBlock('暂无可用平台角色', '请先创建平台角色并选择可用功能。')}
`; -} - -function renderAudit() { - let rows = data.auditLogs.filter(log => state.auditSeverity === 'all' || log.severity === state.auditSeverity); - if (state.auditRange === '24h') rows = rows.filter(log => log.time.startsWith('2026-07-23')); - const query = state.auditSearch.toLowerCase(); - if (query) rows = rows.filter(log => [log.id, log.actor, log.action, log.target, log.ip].some(value => value.toLowerCase().includes(query))); - if (state.scenario === 'empty') rows = []; - const relatedAlertCount = data.alerts.filter(alert => rows.some(log => log.targetId === alert.targetId || log.targetId === alert.id)).length; - return `
${pageHead('平台审计日志', '检索跨租户敏感操作、账务变更与权限事件;导出任务提供文件、hash 和行数。', ``)} -
${['all', '严重', '高', '中'].map(value => ``).join('')}
- ${rows.length ? `
${rows.map(log => ``).join('')}
时间操作者动作目标级别结果来源 IP
${escapeHtml(log.time)}${escapeHtml(log.actor)}${escapeHtml(log.role)}${escapeHtml(log.action)}${escapeHtml(log.target)}${log.severity}${statusBadge(log.result)}${escapeHtml(log.ip)}
` : emptyBlock('没有审计日志', '调整时间范围、严重级别或搜索条件。')}
`; -} - -function renderAlerts() { - let alerts = state.alertStatus === 'all' ? data.alerts : data.alerts.filter(alert => alert.status === state.alertStatus); - if (state.scenario === 'empty') alerts = []; - return `
${pageHead('审计告警与通知', '按 open → acknowledged → resolved/ignored 流转;状态接口禁止重新打开。规则当前只读。', `${canWrite('platform:audit:notification') ? `` : ''}`)} -

告警规则

${data.alertRules.length} 条启用规则
${data.alertRules.map(rule => `
${rule.severity}
${escapeHtml(rule.name)}${escapeHtml(rule.code)} · ${escapeHtml(rule.window)} · ${escapeHtml(rule.threshold)}

${escapeHtml(rule.target)}

${statusBadge(rule.enabled ? '启用' : '已停用')}
`).join('')}
-

告警队列

开放 ${data.alerts.filter(a => a.status === 'open').length} · 已确认 ${data.alerts.filter(a => a.status === 'acknowledged').length} · 已结束 ${data.alerts.filter(a => ['resolved', 'ignored'].includes(a.status)).length}
${[['all', '全部'], ['open', '开放'], ['acknowledged', '已确认'], ['resolved', '已解决'], ['ignored', '已忽略']].map(([value, label]) => ``).join('')}
${alerts.length ? alerts.map(alert => `
${alert.severity}
${alert.id} · ${alert.owner}${escapeHtml(alert.title)}

${escapeHtml(alert.summary)}

${alert.updatedAt}
${alertStatusLabel(alert.status)}
${alert.status === 'open' && canWrite('platform:audit:alert') ? `` : ''}${['open', 'acknowledged'].includes(alert.status) && canWrite('platform:audit:alert') ? `` : ''}
`).join('') : emptyBlock('当前筛选没有告警', '告警规则仍保持只读,可切换筛选查看历史状态。')}
-
`; -} - -const templates = { overview: renderOverview, tenants: renderTenants, domains: renderDomains, tenantDetail: renderTenantDetail, billingProfile: renderBillingProfile, catalog: renderCatalog, subscriptions: renderSubscriptions, saasFinance: renderSaasFinance, billing: renderBilling, usage: renderUsage, dunning: renderDunning, bank: renderBank, crm: renderCrm, sms: renderSms, paymentSettings: renderPaymentSettings, staff: renderStaff, roles: renderRoles, audit: renderAudit, alerts: renderAlerts }; - -function render() { - renderNav(); - const meta = pageMeta[state.view] || pageMeta.overview; - pageTitle.textContent = `${meta.id} · ${meta.title}`; - mainView.innerHTML = renderScenario((templates[state.view] || renderOverview)()); - closeMobileMenu(); - roleSelect.value = state.role; scenarioSelect.value = state.scenario; responseSelect.value = state.response; - updateCounters(); refreshIcons(); - window.decoratePlatformSpec?.(mainView, meta.id); - decorateAccessibleControls(mainView); - updateBackendStatus(); -} -function renderOverlay() { - if (!state.modal) { overlayRoot.innerHTML = ''; return; } - const renderer = modalTemplates[state.modal]; - overlayRoot.innerHTML = renderer ? renderer() : ''; - refreshIcons(); - window.decoratePlatformSpec?.(overlayRoot, pageMeta[state.view]?.id || ''); - decorateAccessibleControls(overlayRoot); - requestAnimationFrame(() => { - const modal = overlayRoot.querySelector('.modal'); - modal?.querySelector('input:not([type="hidden"]),select,textarea,button')?.focus(); - }); -} -let toastTimer; -let lastOverlayTrigger = null; -function showToast(message, kind = 'success') { - toast.querySelector('span').textContent = message; - toast.classList.toggle('is-error', kind === 'error'); - toast.classList.add('is-visible'); - clearTimeout(toastTimer); toastTimer = setTimeout(() => toast.classList.remove('is-visible'), 2800); -} -function openModal(name, modalData = {}) { - const activeElement = document.activeElement; - if (!state.modal && activeElement instanceof HTMLElement && activeElement !== document.body && !overlayRoot.contains(activeElement)) lastOverlayTrigger = activeElement; - state.modal = name; - state.modalData = { ...modalData, dirty: false }; - renderOverlay(); -} -function markDirty(scope) { dirtyScopes.add(scope); if (scope === 'modal') state.modalData.dirty = true; } -function clearDirty(scope = '') { if (scope) dirtyScopes.delete(scope); else dirtyScopes.clear(); if (!scope || scope === 'modal') state.modalData.dirty = false; } -function hasUnsavedChanges(scope = '') { return scope ? dirtyScopes.has(scope) || (scope === 'modal' && state.modalData.dirty) : dirtyScopes.size > 0 || Boolean(state.modalData.dirty); } -function renderLeaveGuard() { - if (!pendingLeave) return; - let root = document.querySelector('#unsavedLeaveGuard'); - if (!root) { root = document.createElement('div'); root.id = 'unsavedLeaveGuard'; document.body.append(root); } - root.className = 'unsaved-leave-guard'; - root.innerHTML = ``; - refreshIcons(); requestAnimationFrame(() => root.querySelector('[data-leave-choice="stay"]')?.focus()); -} -function closeLeaveGuard() { document.querySelector('#unsavedLeaveGuard')?.remove(); } -function requestLeave(execute, { scope = '' } = {}) { - if (!hasUnsavedChanges(scope)) { execute(); return true; } - pendingLeave = { execute, scope }; renderLeaveGuard(); return false; -} -function closeModal(options = {}) { - const close = () => { - clearDirty('modal'); - const trigger = lastOverlayTrigger; - state.modal = ''; - state.modalData = {}; - lastOverlayTrigger = null; - renderOverlay(); - if (trigger?.isConnected) requestAnimationFrame(() => trigger.focus()); - }; - if (state.modal && !options.force && hasUnsavedChanges('modal')) return requestLeave(close, { scope: 'modal' }); - close(); - return true; -} -function navigationSnapshot() { - return { view: state.view, selectedTenant: state.selectedTenant, selectedInvoice: state.selectedInvoice, selectedAlert: state.selectedAlert, tenantFilter: state.tenantFilter, tenantPlan: state.tenantPlan, tenantSearch: state.tenantSearch, invoiceSearch: state.invoiceSearch, invoiceStatus: state.invoiceStatus, billingTab: state.billingTab, bankTab: state.bankTab, crmTab: state.crmTab, smsTab: state.smsTab, paymentTab: state.paymentTab, saasFinanceTab: state.saasFinanceTab, bankSearch: state.bankSearch, selectedBank: state.selectedBank, selectedBankNode: state.selectedBankNode, staffSearch: state.staffSearch, usagePeriod: state.usagePeriod, auditRange: state.auditRange, auditSeverity: state.auditSeverity, auditSearch: state.auditSearch, alertStatus: state.alertStatus, scrollY: window.scrollY }; -} -function syncNavigationState() { if (history.state?.[HISTORY_APP_KEY]) history.replaceState({ ...history.state, snapshot: navigationSnapshot() }, '', location.href); } -function navigate(view, options = {}) { - if (!pageMeta[view]) return; - if (platformApi?.isEnabled() && !API_CONNECTED_PAGES.has(view)) { - showToast('该模块当前不可用,请先完成后端配置后再访问', 'error'); - return false; - } - const perform = () => { - clearDirty(); - if (!hasPermission(pageMeta[view].permission)) { state.previousView = state.view; state.view = view; state.scenario = 'forbidden'; render(); return; } - if (options.push !== false) { - const nextEntry = navigationSnapshot(); - const last = state.history[state.history.length - 1]; - if (!last || last.view !== nextEntry.view || last.selectedTenant !== nextEntry.selectedTenant) state.history = [...state.history.slice(-2), nextEntry]; - if (options.browser !== false && history.state?.[HISTORY_APP_KEY]) history.replaceState({ ...history.state, snapshot: nextEntry }, '', location.href); - } - state.previousView = state.view; state.view = view; state.scenario = 'normal'; closeModal({ force: true }); render(); scrollTo(0, 0); - if (options.browser !== false) { historySequence += 1; history.pushState({ [HISTORY_APP_KEY]: true, sequence: historySequence, snapshot: navigationSnapshot() }, '', location.href); } - if (['tenantDetail', 'billingProfile'].includes(view)) hydrateTenantDetail(state.selectedTenant); - if (view === 'bank') loadBankWorkspace(); - }; - if (!options.force && hasUnsavedChanges()) return requestLeave(perform); - perform(); return true; -} -function navigateBack() { - requestLeave(() => { - clearDirty(); - if (history.state?.[HISTORY_APP_KEY] && history.length > 1) { history.back(); return; } - const prior = state.history.pop(); - if (!prior) { state.view = 'overview'; state.previousView = ''; render(); scrollTo(0, 0); return; } - Object.assign(state, prior); render(); requestAnimationFrame(() => scrollTo(0, prior.scrollY || 0)); - }); -} -function closeSubpage() { - requestLeave(() => { clearDirty(); state.history = []; state.view = 'overview'; state.previousView = ''; state.scenario = 'normal'; render(); scrollTo(0, 0); history.replaceState({ [HISTORY_APP_KEY]: true, sequence: historySequence, snapshot: navigationSnapshot() }, '', location.href); }); -} -window.addEventListener('popstate', event => { - const entry = event.state; - if (!entry?.[HISTORY_APP_KEY] || !entry.snapshot) return; - const targetSequence = Number(entry.sequence) || 0; - if (restoringHistory) { restoringHistory = false; return; } - if (hasUnsavedChanges() && !bypassHistoryGuard) { - const delta = targetSequence - historySequence; - restoringHistory = true; history.go(-delta); - requestLeave(() => { bypassHistoryGuard = true; history.go(delta); }); - return; - } - bypassHistoryGuard = false; historySequence = targetSequence; clearDirty(); - const currentView = state.view; - Object.assign(state, entry.snapshot, { previousView: currentView, scenario: 'normal', modal: '', modalData: {} }); - lastOverlayTrigger = null; - if (state.history.length && state.history[state.history.length - 1].view === state.view) state.history.pop(); - render(); - requestAnimationFrame(() => scrollTo(0, entry.snapshot.scrollY || 0)); - if (entry.rootGuard) { historySequence += 1; history.pushState({ [HISTORY_APP_KEY]: true, sequence: historySequence, snapshot: navigationSnapshot() }, '', location.href); } -}); -function nextResponse() { - const response = state.response; - if (response !== 'success') { state.response = 'success'; responseSelect.value = 'success'; } - return response; -} -async function simulateWrite({ key, permission, validate, apply, success, close = true, rerender = true, operationId = '', body, request: executeRequest }) { - if (!canWrite(permission)) { showToast(`缺少写权限:${permission}`, 'error'); return; } - const validation = validate?.(); - if (validation) { showFormErrors(validation); return; } - const mockResponse = platformApi?.isEnabled() ? 'success' : nextResponse(); - state.submitting = key; - const activeForm = overlayRoot.querySelector('form') || mainView.querySelector('form'); - const submitButton = activeForm && (activeForm.querySelector('[type="submit"]') || document.querySelector(`[type="submit"][form="${activeForm.id}"]`)); - const submitMarkup = submitButton?.innerHTML; - if (submitButton) { submitButton.disabled = true; submitButton.innerHTML = `${icon('loader-circle')}提交中`; refreshIcons(); } - const finish = async () => { - if (mockResponse !== 'success') { - state.submitting = ''; - const id = requestId(); - addAudit(`${key}.failed`, 'mock_request', id, key, mockResponse === 'validation_error' ? '中' : '高', `${mockResponse === 'validation_error' ? '服务端字段校验失败' : 'Mock 写请求失败'},Request ID:${id}。`, '失败'); - showToast(`${mockResponse === 'validation_error' ? '服务端字段校验失败' : '提交失败'} · ${id}`, 'error'); - if (mockResponse === 'validation_error') showFormErrors({ server: `服务端拒绝本次输入(${id})` }); - if (submitButton) { submitButton.disabled = false; submitButton.innerHTML = submitMarkup; refreshIcons(); } - return; - } - try { - let payload = null; - if (platformApi?.isEnabled()) { - if (typeof executeRequest === 'function') payload = await executeRequest(); - else if (operationId) { - const input = typeof body === 'function' ? body() : (body || {}); - payload = await platformApi.request(operationId, { body: platformApi.buildBody(operationId, input) }); - } else { - throw new Error(`操作 ${key} 尚未配置后端 operationId`); - } - } else { - await new Promise(resolve => setTimeout(resolve, 650)); - } - state.submitting = ''; - clearDirty(activeForm?.closest('#overlayRoot') ? 'modal' : 'page'); - const result = apply(payload); saveData(); - if (close) closeModal({ force: true }); - if (rerender) render(); - showToast(typeof success === 'function' ? success(result) : success); - if (platformApi?.isEnabled()) hydrateFromBackend({ silent: true }); - } catch (error) { - const id = error.requestId || requestId(); - state.submitting = ''; - showToast(backendErrorText(error, '提交失败'), 'error'); - if (error.status === 400) showFormErrors({ server: backendErrorText(error, '服务端字段校验失败') }); - if (submitButton) { submitButton.disabled = false; submitButton.innerHTML = submitMarkup; refreshIcons(); } - } - }; - finish(); -} -async function executeBackendMutation(operationId, input, apply, { refresh = true, pathParams = {} } = {}) { - if (!platformApi?.isEnabled()) { - apply?.(null); - return true; - } - try { - const payload = await platformApi.request(operationId, { - body: platformApi.buildBody(operationId, typeof input === 'function' ? input() : input), - pathParams, - }); - apply?.(payload); - if (refresh) hydrateFromBackend({ silent: true }); - return true; - } catch (error) { - showToast(backendErrorText(error, '提交失败'), 'error'); - return false; - } -} -function showFormErrors(errors) { - const form = overlayRoot.querySelector('form') || mainView.querySelector('form'); - if (!form) { showToast(Object.values(errors)[0], 'error'); return; } - form.querySelectorAll('.field-error').forEach(node => node.remove()); - form.querySelectorAll('.is-invalid').forEach(node => node.classList.remove('is-invalid')); - const summary = form.querySelector('.form-error-summary'); - if (summary) { summary.hidden = false; summary.innerHTML = `请修正以下问题
    ${Object.values(errors).map(message => `
  • ${escapeHtml(message)}
  • `).join('')}
`; summary.focus(); } - Object.entries(errors).forEach(([name, message]) => { - const input = form.elements[name]; - if (!input) return; - input.classList.add('is-invalid'); - input.insertAdjacentHTML('afterend', `${escapeHtml(message)}`); - }); - const first = form.querySelector('.is-invalid'); first?.focus(); -} - -function modalFrame(title, description, content, actions = '', options = {}) { - return ``; -} -function formField(label, name, value = '', attrs = '') { return ``; } -function tenantOptions(selected = '') { return data.tenants.map(tenant => ``).join(''); } -function planOptions(selected = '') { return data.plans.map(plan => ``).join(''); } -function notificationProviderOptions(selected = '') { - const normalized = ({ Webhook: 'generic', SMTP: 'generic', 邮件: 'generic', 短信: 'generic', 钉钉: 'dingtalk', 飞书: 'feishu', 企微: 'wecom' })[selected] || selected || 'generic'; - return [['generic', '通用 Webhook'], ['dingtalk', '钉钉'], ['feishu', '飞书'], ['wecom', '企微']] - .map(([value, label]) => ``) - .join(''); -} -function channelEndpointFormValue(channel) { - return platformApi?.isEnabled() && channel.endpointRedacted ? '' : channel.endpoint || ''; -} - -const modalTemplates = { - saasFeature() { - return modalFrame('新建 SaaS 功能', '功能将用于套餐版本与租户权益校验。', ``, ``, { id: 'SaaS 商品目录', wide: true }); - }, - saasOffering() { - return modalFrame('新建 SaaS 商品', '商品可为基础套餐或增值包。', ``, ``, { id: 'SaaS 商品目录', wide: true }); - }, - saasLimit() { - const features = data.saasCatalog?.features || []; - return modalFrame('新建 SaaS 功能限额', '限额定义供套餐版本配置和运行时用量校验使用。', ``, ``, { id: 'SaaS 功能限额', wide: true }); - }, - tenantFeatureOverride() { - const features = data.saasCatalog?.features || []; - return modalFrame('租户功能覆盖', '对单个租户强制启用或停用某项 SaaS 功能,必须记录可审计原因。', ``, ``, { id: 'SaaS 租户权益', wide: true }); - }, - saasVersion() { - const offerings = data.saasCatalog?.offerings || []; - return modalFrame('新建套餐版本', '新版本先保存为草稿,确认后再单独发布。', ``, ``, { id: 'SaaS 版本管理', wide: true }); - }, - platformRole() { - const role = data.platformRoles.find(item => item.id === state.modalData.roleId) || {}; - return modalFrame(role.id ? '编辑平台角色' : '新建平台角色', '选择该角色可以使用的业务功能,保存后对所属员工生效。', ``, ``, { id: '平台角色管理', wide: true }); - }, - paymentChannel() { - const channel = data.paymentChannels.find(item => item.id === state.modalData.channelId) || {}; - const apps = data.paymentApps.filter(item => item.appScope === 'platform'); - return modalFrame(channel.id ? '编辑平台支付渠道' : '新建平台支付渠道', '渠道密钥只保存 Secret Ref,不在页面保存明文凭据。', ``, ``, { id: '平台支付设置', wide: true }); - }, - smsTemplate() { - const template = data.smsTemplates.find(item => item.id === state.modalData.templateId) || {}; - const tenantId = template.tenantId || state.selectedTenant || data.smsChannels[0]?.tenantId || ''; - const channels = data.smsChannels.filter(item => !tenantId || item.tenantId === tenantId); - return modalFrame(template.id ? '编辑短信模板' : '新建短信模板', '模板先保存为草稿,再通过独立动作提交审核。', ``, ``, { id: '短信模板管理', wide: true }); - }, - mobileBoundary() { - return modalFrame('请在桌面端继续', `${state.modalData.actionLabel || '此操作'}需要完整工作区。`, `
${icon('monitor-up')}
移动端只支持查看与轻量处理

租户、账务、用量、授权、员工和通知渠道的创建或复杂编辑,请在宽度不少于 768px 的桌面端完成,避免误操作。

`, ``, { id: '全局 · 移动端边界' }); - }, - createTenant() { - return modalFrame('开通租户', '创建租户和首位负责人账号;套餐、域名和账务信息可在开通后继续配置。', ``, ``, { id: 'P-02 · 租户开通', wide: true }); - }, - tenantStatus() { - const tenant = tenantById(state.modalData.tenantId); - const restoring = tenant.status === '暂停'; - return modalFrame(restoring ? '恢复租户' : '暂停租户', `将 ${tenant.name} 的业务状态变更为“${restoring ? '正常' : '暂停'}”。${restoring ? '恢复业务写操作。' : '学生端保留只读访问,新增权益与部分写操作将受限。'}`, ``, ``, { id: 'P-03 · 生命周期' }); - }, - createSubscription() { - const selectedPlan = state.modalData.planCode || tenantById(state.selectedTenant)?.planCode || 'pro'; - return modalFrame('创建租户订阅', '日期与金额必须有效;同一租户的重复活跃订阅会被阻止。', ``, ``, { id: 'P-05 · 订阅表单', wide: true }); - }, - createInvoice() { - return modalFrame('手工创建服务费账单', '金额以元展示,Mock 写入时显式转换;到期日必须晚于今天。', ``, ``, { id: 'P-06 · 手工账单', wide: true }); - }, - invoiceCandidates() { - const candidates = data.subscriptions.filter(subscription => !data.invoices.some(invoice => invoice.note.includes(subscription.id))).map(subscription => ({ subscription, tenant: tenantById(subscription.tenantId) })); - return modalFrame('订阅账单候选 · Dry-run', '预览不会写入账单;已有账单候选将被幂等跳过。', `
${candidates.map(({ subscription, tenant }) => ``).join('') || '

没有可生成候选,全部订阅已存在对应账单。

'}
`, `${candidates.length ? `` : ''}`, { id: 'P-06 · Dry-run', wide: true }); - }, - payment() { - const invoice = invoiceById(state.modalData.invoiceId); - const payment = paymentForInvoice(invoice); - return modalFrame('人工确认收款', `${invoice.id} · 待确认金额 ${money(payment?.amount || invoice.balance)}。本操作确认后端已存在的待支付记录。`, ``, ``, { id: 'P-08 · 资金动作', wide: true }); - }, - overduePreview() { - const candidates = data.invoices.filter(invoice => invoice.status === '已逾期'); - return modalFrame('逾期处理预览 · Dry-run', '本次预览不改变账单或租户状态;确认后异步创建催缴记录。', `
${candidates.map(invoice => ``).join('') || '

当前没有逾期候选。

'}
`, `${candidates.length ? '' : ''}`, { id: 'P-08 · Dry-run' }); - }, - recordUsage() { - return modalFrame('记录平台用量', '人工记录会标记来源;同租户同账期重复记录会被阻止。', ``, ``, { id: 'P-07 · 人工用量', wide: true }); - }, - overagePreview() { - const candidates = data.usage.filter(item => item.period === state.usagePeriod && item.estimated > 0 && !data.invoices.some(invoice => invoice.note === `超额 ${item.period}` && invoice.tenantId === item.tenantId)); - return modalFrame('超额账单候选 · Dry-run', `${state.usagePeriod} 账期预览;确认后通过异步任务生成账单。`, `
${candidates.map(item => ``).join('') || '

当前账期无超额候选。

'}
`, `${candidates.length ? '' : ''}`, { id: 'P-07 · Dry-run' }); - }, - dunningChannel() { - const channel = data.dunningChannels.find(item => item.id === state.modalData.channelId) || {}; - const redactedHint = platformApi?.isEnabled() && channel.endpointRedacted ? ' 后端不会回显完整 URL;编辑时必须重新输入完整 HTTPS Webhook。' : ''; - return modalFrame(channel.id ? '编辑催缴渠道' : '新建催缴渠道', `Webhook secret 为只写字段,保存后不会回显。${redactedHint}`, ``, ``, { id: 'P-08 · 通知渠道', wide: true }); - }, - bank() { - const bank = bankById(state.modalData.bankId) || {}; - return modalFrame(bank.id ? '编辑公共题库' : '新建公共题库', '题库保存后可继续配置分类、科目、章节和试卷。', ``, ``, { id: 'P-09 · 公共题库' }); - }, - bankNode() { - const node = bankNodeById(state.modalData.nodeId) || {}; - const parents = data.bankNodes.filter(item => item.questionBankId === state.selectedBank && item.isActive && item.id !== node.id); - return modalFrame(node.id ? '编辑内容节点' : '新建内容节点', '使用中文业务层级组织题目,章节和试卷可直接录入题目。', ``, ``, { id: 'P-09 · 内容结构' }); - }, - batchBankNodes() { - return modalFrame('批量创建章节或试卷', '每行一个名称,一次最多创建 100 个。', ``, ``, { id: 'P-09 · 批量创建', wide: true }); - }, - crmConfig() { - const config = data.crmConfigs.find(item => item.id === state.modalData.crmId) || {}; - return modalFrame(config.id ? '编辑 CRM 接入' : '新建 CRM 接入', '平台代管租户 CRM webhook 接入;Secret 只保存引用,不提交明文密钥。', ``, ``, { id: 'P-10 · CRM 接入', wide: true }); - }, - smsChannel() { - const channel = data.smsChannels.find(item => item.id === state.modalData.smsId) || {}; - return modalFrame(channel.id ? '编辑短信渠道' : '新建短信渠道', '渠道密钥只保存 Secret Ref;模板和发送日志会保留历史。', ``, ``, { id: 'P-11 · 短信渠道', wide: true }); - }, - paymentApp() { - const appItem = data.paymentApps.find(item => item.id === state.modalData.paymentId) || {}; - const isTenant = appItem.appScope === 'tenant' || appItem.tenantId; - return modalFrame(appItem.id ? '编辑支付应用' : '新建平台支付应用', '平台自有收款用于租户购买套餐/模块;租户代管应用可选择具体租户。', ``, ``, { id: 'P-12 · 支付设置', wide: true }); - }, - staff() { - const person = data.staff.find(item => item.id === state.modalData.staffId) || {}; - const editablePhone = /^1\d{10}$/.test(person.phone || '') ? person.phone : ''; - const selectedRoleIds = person.roleIds?.length ? person.roleIds : (state.modalData.roleId ? [state.modalData.roleId] : []); - const roleOptions = data.platformRoles.map(role => { - const featureNames = role.permissionCodes.map(code => data.platformPermissions[code] || code).join('、') || '暂无功能'; - return ``; - }).join(''); - return modalFrame(person.id ? '编辑平台员工' : '新建平台员工', '员工账号与平台角色由后端统一管理,功能说明来自当前权限目录。', ``, ``, { id: 'P-13 · 员工角色', wide: true }); - }, - auditDetail() { - const log = data.auditLogs.find(item => item.id === state.modalData.auditId); - return modalFrame('审计事件详情', `${log.id} · 敏感字段已脱敏。`, ``, ``, { id: 'P-14 · 只读详情', wide: true }); - }, - alertDetail() { - const alert = data.alerts.find(item => item.id === (state.modalData.alertId || state.selectedAlert)); - return modalFrame('告警证据与处理', `${alert.id} · ${alert.title}`, `
${alert.severity}
${escapeHtml(alert.summary)}${alert.owner} · ${alert.updatedAt}
${statusBadge(alertStatusLabel(alert.status))}
    ${alert.evidence.map(item => `
  • ${icon('file-search')}${escapeHtml(item)}
  • `).join('')}
`, `${['open', 'acknowledged'].includes(alert.status) ? `` : ''}`, { id: 'P-15 · 状态机', wide: true }); - }, - notificationDetail() { - const event = [...(data.notificationEvents || []), ...(data.dunningEvents || [])].find(item => item.id === state.modalData.eventId); - const channel = event ? notificationChannelName(event.channelId) : '-'; - return modalFrame('通知事件详情', `${event?.id || '-'} · 请求与错误摘要已脱敏。`, ``, `${event?.status === '失败' ? `` : ''}`, { id: 'P-15 · 通知事件', wide: true }); - }, - auditChannel() { - const channel = data.auditChannels.find(item => item.id === state.modalData.channelId) || {}; - const redactedHint = platformApi?.isEnabled() && channel.endpointRedacted ? ' 后端不会回显完整 URL;编辑时必须重新输入完整 HTTPS Webhook。' : ''; - return modalFrame(channel.id ? '编辑审计通知渠道' : '新建审计通知渠道', `secret 只写;状态和严重级别过滤由平台后端执行。${redactedHint}`, ``, ``, { id: 'P-15 · 通知渠道', wide: true }); - }, - confirmAction() { - const { title, description, impact, confirmLabel = '确认操作', confirmActionName = 'execute-confirmed', tone: confirmTone = 'danger' } = state.modalData; - return modalFrame(title, description, `
${icon(confirmTone === 'danger' ? 'triangle-alert' : 'circle-help')}

${escapeHtml(impact)}

`, ``, { id: '全局 · 二次确认' }); - }, - tasks() { - return modalFrame('异步任务中心', '批量账单、超额账单和导出均返回 task_id,可跟踪、重试并跳转结果。', `
${data.tasks.length ? data.tasks.map(task => `
${icon(task.status === 'completed' ? 'circle-check' : task.status === 'failed' ? 'circle-x' : 'loader-circle')}
${escapeHtml(task.label)}${task.id} · ${task.updatedAt}

${task.error ? escapeHtml(task.error) : `结果去向:${escapeHtml(task.resultTarget)}`}

${task.status === 'failed' ? `` : statusBadge(taskStatusLabel(task.status))}
`).join('') : emptyBlock('没有异步任务', '批量生成、导出或重试后会出现在这里。')}
`, ``, { id: '全局 · 任务中心', wide: true }); - }, -}; - -function confirmAction(config, execute) { - openModal('confirmAction', config); - state.modalData.execute = execute; -} - -function validateBillingProfile(form) { - const errors = {}; - ['billingName', 'contactName', 'phone', 'email', 'invoiceTitle'].forEach(name => { if (!fieldValue(form, name)) errors[name] = `${form.elements[name].previousElementSibling?.textContent.replace('*', '').trim() || name}不能为空`; }); - const phone = fieldValue(form, 'phone'); if (phone && !/^1\d{10}$/.test(phone)) errors.phone = '请输入 11 位中国大陆手机号'; - const email = fieldValue(form, 'email'); if (email && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) errors.email = '请输入有效邮箱地址'; - const taxId = fieldValue(form, 'taxId'); if (taxId && !/^[0-9A-Z]{15,20}$/.test(taxId)) errors.taxId = '税号应为 15-20 位大写字母或数字'; - const account = fieldValue(form, 'bankAccountMasked'); if (account && !account.includes('*')) errors.bankAccountMasked = '不得提交完整银行账号,请使用脱敏值'; - return Object.keys(errors).length ? errors : null; -} -function validateNotificationChannel(values) { - const errors = {}; - if (!values.code) errors.code = '渠道代码不能为空'; - if (!values.name) errors.name = '渠道名称不能为空'; - if (!values.endpoint) errors.endpoint = 'Webhook URL 不能为空'; - if (platformApi?.isEnabled() && values.endpoint) { - try { - const url = new URL(values.endpoint); - const local = ['localhost', '127.0.0.1', '::1'].includes(url.hostname); - if (url.protocol !== 'https:' && !local) errors.endpoint = '联调/生产 Webhook 必须使用 HTTPS'; - } catch { - errors.endpoint = '请输入完整有效的 Webhook URL'; - } - } - return Object.keys(errors).length ? errors : null; -} - -document.addEventListener('submit', event => { - event.preventDefault(); - const form = event.target; - const desktopOnlyForms = new Set(['createTenantForm', 'tenantStatusForm', 'billingProfileForm', 'subscriptionForm', 'invoiceForm', 'paymentForm', 'usageForm', 'dunningChannelForm', 'bankForm', 'bankNodeForm', 'bankNodeBatchForm', 'crmConfigForm', 'smsChannelForm', 'paymentAppForm', 'staffForm', 'auditChannelForm']); - if (desktopOnlyForms.has(form.id) && requireDesktop('提交复杂配置或资金操作')) return; - if (form.id === 'saasFeatureForm') { - const values = Object.fromEntries(new FormData(form)); - simulateWrite({ key: 'saas-feature', permission: 'platform:plan:write', operationId: 'PlatformSaasController_upsertFeature', body: values, validate: () => !values.code || !values.name || !values.category ? { code: '功能编码、名称和分类不能为空' } : null, apply: payload => { const item = payload || { ...values, id: entityId('FEATURE'), referencePriceCents: Math.round(Number(values.referencePrice || 0) * 100) }; data.saasCatalog.features.unshift(item); return item; }, success: 'SaaS 功能已保存' }); - } - if (form.id === 'saasOfferingForm') { - const values = Object.fromEntries(new FormData(form)); - simulateWrite({ key: 'saas-offering', permission: 'platform:plan:write', operationId: 'PlatformSaasController_upsertOffering', body: values, validate: () => !values.code || !values.name ? { code: '商品编码和名称不能为空' } : null, apply: payload => { const item = payload || { ...values, id: entityId('OFFERING') }; data.saasCatalog.offerings.unshift(item); return item; }, success: 'SaaS 商品已保存' }); - } - if (form.id === 'saasLimitForm') { - const values = Object.fromEntries(new FormData(form)); values.isHardLimit = Boolean(new FormData(form).get('isHardLimit')); - simulateWrite({ key: 'saas-limit', permission: 'platform:plan:write', operationId: 'PlatformSaasController_upsertFeatureLimit', body: values, validate: () => !values.metricCode || !values.featureCode || !values.name ? { metricCode: '指标编码、所属功能和限额名称不能为空' } : null, apply: payload => { const item = payload || { ...values, id: entityId('LIMIT') }; data.saasCatalog.limitDefinitions.unshift(item); return item; }, success: 'SaaS 功能限额已保存' }); - } - if (form.id === 'tenantFeatureOverrideForm') { - const values = Object.fromEntries(new FormData(form)); - simulateWrite({ key: 'tenant-feature-override', permission: 'platform:plan:write', operationId: 'PlatformSaasController_upsertTenantFeatureOverride', body: values, validate: () => !values.tenantId || !values.featureCode || !values.reason ? { reason: '租户、功能和操作原因不能为空' } : null, apply: payload => payload || values, success: '租户功能覆盖规则已保存' }); - } - if (form.id === 'saasVersionForm') { - const values = Object.fromEntries(new FormData(form)); - simulateWrite({ key: 'saas-version', permission: 'platform:plan:write', operationId: 'PlatformSaasController_upsertVersion', body: values, validate: () => !values.offeringId ? { offeringId: '必须选择所属商品' } : Number(values.amount) < 0 ? { amount: '售价不能小于 0' } : null, apply: payload => { const item = payload || { ...values, id: entityId('VERSION'), version: 1, status: 'draft', amountCents: Math.round(Number(values.amount || 0) * 100), originalAmountCents: Math.round(Number(values.originalAmount || 0) * 100) }; data.saasCatalog.versions.unshift(item); return item; }, success: '套餐版本草稿已保存' }); - } - if (form.id === 'platformRoleForm') { - const values = Object.fromEntries(new FormData(form)); const permissionCodes = new FormData(form).getAll('permissionCodes'); - let savedRole = null; - simulateWrite({ key: 'platform-role', permission: 'platform:staff:write', request: async () => { savedRole = await platformApi.request('PlatformBackofficeController_upsertRole', { body: platformApi.buildBody('PlatformBackofficeController_upsertRole', values) }); await platformApi.request('PlatformBackofficeController_replaceRoleBindings', { pathParams: { roleId: savedRole.id }, body: platformApi.buildBody('PlatformBackofficeController_replaceRoleBindings', { permissionCodes, menuCodes: savedRole.menuCodes || [] }) }); return savedRole; }, validate: () => { const errors = {}; if (!values.code) errors.code = '角色编码不能为空'; if (!values.name) errors.name = '角色名称不能为空'; if (!permissionCodes.length) errors.permissionCodes = '至少选择一项平台功能'; return Object.keys(errors).length ? errors : null; }, apply: payload => { const existing = data.platformRoles.find(item => item.id === values.id); const next = { id: payload?.id || values.id || entityId('ROLE'), code: values.code, name: values.name, description: values.description || '', permissionCodes, menuCodes: payload?.menuCodes || existing?.menuCodes || [] }; if (existing) Object.assign(existing, next); else data.platformRoles.unshift(next); return next; }, success: '平台角色与功能绑定已保存' }); - } - if (form.id === 'paymentChannelForm') { - const values = Object.fromEntries(new FormData(form)); - simulateWrite({ key: 'payment-channel', permission: 'platform:payment:write', operationId: 'PlatformAdminPaymentSettingsController_upsertChannel', body: values, validate: () => { const errors = {}; if (!values.appId) errors.appId = '必须选择平台支付应用'; if (!values.displayName) errors.displayName = '渠道名称不能为空'; if (!values.provider) errors.provider = 'Provider 不能为空'; return Object.keys(errors).length ? errors : null; }, apply: payload => { const existing = data.paymentChannels.find(item => item.id === values.id); const next = payload || { ...values, id: values.id || entityId('PAYCH') }; if (existing) Object.assign(existing, next); else data.paymentChannels.unshift(next); return next; }, success: '平台支付渠道已保存' }); - } - if (form.id === 'smsTemplateForm') { - const values = Object.fromEntries(new FormData(form)); - simulateWrite({ key: 'sms-template', permission: 'platform:sms:write', operationId: 'PlatformAdminSmsController_upsertTemplate', body: values, validate: () => { const errors = {}; ['tenantId', 'channelId', 'code', 'name', 'content'].forEach(name => { if (!values[name]) errors[name] = `${name} 不能为空`; }); return Object.keys(errors).length ? errors : null; }, apply: payload => { const existing = data.smsTemplates.find(item => item.id === values.id); const next = payload ? platformApi.adapters.smsTemplate(payload) : { ...values, id: values.id || entityId('SMSTPL'), status: '草稿', templateStatus: '正常', sentCount: 0, failedCount: 0 }; if (existing) Object.assign(existing, next); else data.smsTemplates.unshift(next); return next; }, success: '短信模板草稿已保存' }); - } - if (form.id === 'createTenantForm') { - const values = Object.fromEntries(new FormData(form)); const slug = values.slug; const name = values.name; - simulateWrite({ key: 'create-tenant', permission: 'platform:tenant:write', operationId: 'PlatformAdminTenantsController_create', body: () => values, validate: () => { - const errors = {}; if (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(slug)) errors.slug = 'slug 仅支持小写字母、数字和连字符'; - if (!name) errors.name = '租户名称不能为空'; - if (!values.ownerName) errors.ownerName = '负责人姓名不能为空'; - if (!values.ownerEmail && !values.ownerPhone) errors.ownerEmail = '负责人邮箱和手机号至少填写一项'; - if (values.ownerPhone && !/^1\d{10}$/.test(values.ownerPhone)) errors.ownerPhone = '请输入 11 位中国大陆手机号'; - if (!/^(?=.*[A-Za-z])(?=.*\d).{12,}$/.test(values.temporaryPassword || '')) errors.temporaryPassword = '临时密码至少 12 位且必须同时包含字母和数字'; - if (data.tenants.some(item => item.slug === slug)) errors.slug = 'slug 已存在'; return Object.keys(errors).length ? errors : null; - }, apply: payload => { const fallback = { id: `tenant_${slug.replaceAll('-', '_')}`, slug, name, legal: values.legalName || name, brand: name, shortName: name, host: '-', plan: '未订阅', planCode: '', status: values.status, billing: values.billingStatus, mode: '-', students: 0, questions: 0, storageGB: 0, trafficTB: 0, expires: '', balance: 0, owner: values.ownerName, ownerPhone: values.ownerPhone || '-', createdAt: todayTime() }; const tenantPayload = payload?.tenant || payload?.item; const tenant = tenantPayload ? platformApi.adapters.tenant(tenantPayload, fallback, {}) : fallback; tenant.owner = values.ownerName; tenant.ownerPhone = values.ownerPhone || '-'; data.tenants.unshift(tenant); state.selectedTenant = tenant.id; addAudit('tenant.create', 'tenant', tenant.id, tenant.name, '高', `开通租户 ${tenant.name} 并创建首位负责人账号。`); state.modal = ''; navigate('tenantDetail'); return tenant; }, success: '租户与负责人账号已开通', close: false, rerender: false }); - } - if (form.id === 'tenantStatusForm') { - const tenant = tenantById(state.modalData.tenantId); const reason = fieldValue(form, 'reason'); - simulateWrite({ key: 'tenant-status', permission: 'platform:tenant:status', operationId: 'PlatformAdminTenantsController_status', body: () => ({ tenantId: tenant.id, status: tenant.status === '暂停' ? '正常' : '暂停', billingStatus: fieldValue(form, 'billingStatus'), reason }), validate: () => !reason ? { reason: '必须填写可审计的变更原因' } : !new FormData(form).get('confirm') ? { confirm: '请确认业务影响' } : null, apply: () => { const from = tenant.status; const billingFrom = tenant.billing; tenant.status = from === '暂停' ? '正常' : '暂停'; tenant.billing = fieldValue(form, 'billingStatus') || tenant.billing; addAudit('tenant.status.update', 'tenant', tenant.id, tenant.name, '高', `业务状态 ${from} → ${tenant.status};账务状态 ${billingFrom} → ${tenant.billing}。原因:${reason}`); return tenant.status; }, success: nextStatus => `租户已${nextStatus === '暂停' ? '暂停' : '恢复'},账务状态已同步` }); - } - if (form.id === 'billingProfileForm') { - simulateWrite({ key: 'billing-profile', permission: 'platform:tenant:billing_profile', operationId: 'PlatformAdminTenantsController_billingProfile', body: () => ({ tenantId: state.selectedTenant, ...Object.fromEntries(new FormData(form)) }), validate: () => validateBillingProfile(form), apply: () => { data.billingProfiles[state.selectedTenant] = Object.fromEntries(new FormData(form)); addAudit('tenant.billing_profile.update', 'tenant', state.selectedTenant, tenantById(state.selectedTenant).name, '高', '更新租户账务与开票资料,银行账号保持脱敏。'); navigateBack(); }, success: '账务资料已保存并回到租户详情', close: false, rerender: false }); - } - if (form.id === 'subscriptionForm') { - const values = Object.fromEntries(new FormData(form)); - simulateWrite({ key: 'subscription', permission: 'platform:billing:write', operationId: 'PlatformAdminBillingController_createSubscription', body: () => ({ ...values, autoRenew: Boolean(new FormData(form).get('autoRenew')) }), validate: () => { const errors = {}; if (data.subscriptions.some(item => item.tenantId === values.tenantId && item.status === '活跃')) errors.tenantId = '该租户已有活跃订阅,请先处理原订阅'; if (!values.amount || Number(values.amount) < 0) errors.amount = '金额必须大于等于 0'; if (!values.start) errors.start = '开始日期不能为空'; if (!values.expires || values.expires <= values.start) errors.expires = '到期日期必须晚于开始日期'; return Object.keys(errors).length ? errors : null; }, apply: () => { const subscription = { id: entityId('SUB'), tenantId: values.tenantId, planCode: values.planCode, status: values.status, cycle: values.cycle, amount: Number(values.amount), start: values.start, expires: values.expires, autoRenew: Boolean(new FormData(form).get('autoRenew')) }; data.subscriptions.unshift(subscription); const tenant = tenantById(values.tenantId); tenant.planCode = values.planCode; tenant.plan = planByCode(values.planCode).name; tenant.expires = values.expires; addAudit('subscription.create', 'subscription', subscription.id, tenant.name, '高', `创建 ${subscription.cycle} ${tenant.plan} 订阅,金额 ${money(subscription.amount)}。`); }, success: '订阅已创建并更新租户套餐' }); - } - if (form.id === 'invoiceForm') { - const values = Object.fromEntries(new FormData(form)); - simulateWrite({ key: 'invoice', permission: 'platform:billing:write', operationId: 'PlatformAdminBillingController_createInvoice', body: values, validate: () => { const errors = {}; if (!values.amount || Number(values.amount) <= 0) errors.amount = '金额必须大于 0'; if (!values.due) errors.due = '到期日不能为空'; if (!values.period) errors.period = '账期不能为空'; return Object.keys(errors).length ? errors : null; }, apply: () => { const invoice = { id: entityId('INV'), tenantId: values.tenantId, type: values.type, period: values.period, total: Number(values.amount), paid: 0, balance: Number(values.amount), due: values.due, status: '待付款', note: values.note || values.type }; data.invoices.unshift(invoice); const tenant = tenantById(values.tenantId); tenant.balance += invoice.balance; tenant.billing = '待付款'; addAudit('invoice.create', 'invoice', invoice.id, invoice.id, '高', `手工创建 ${money(invoice.total)} 服务费账单。`); }, success: '账单草稿已创建' }); - } - if (form.id === 'paymentForm') { - const invoice = invoiceById(state.modalData.invoiceId); const values = Object.fromEntries(new FormData(form)); const payment = paymentForInvoice(invoice); const amount = payment?.amount || invoice.balance; - simulateWrite({ key: 'payment', permission: 'platform:billing:payment', operationId: 'PlatformAdminBillingController_confirmPayment', body: () => ({ ...values, paymentId: payment?.id, amount }), validate: () => { const errors = {}; if (platformApi?.isEnabled() && !payment) errors.paymentId = '该账单没有可确认的待支付记录'; if (!amount || amount <= 0) errors.amount = '收款金额必须大于 0'; if (amount > invoice.balance) errors.amount = `收款金额不可超过余额 ${money(invoice.balance)}`; if (!values.tradeNo) errors.tradeNo = '交易流水号不能为空'; if (!new FormData(form).get('confirm')) errors.confirm = '请先确认已核对银行流水'; return Object.keys(errors).length ? errors : null; }, apply: () => { invoice.paid += amount; invoice.balance -= amount; invoice.status = invoice.balance === 0 ? '已支付' : '部分支付'; if (payment) payment.status = 'succeeded'; const tenant = tenantById(invoice.tenantId); tenant.balance = Math.max(0, tenant.balance - amount); tenant.billing = tenant.balance === 0 ? '正常' : '待付款'; if (tenant.status === '暂停' && tenant.balance === 0) tenant.status = '正常'; addAudit('invoice.payment.confirm', 'invoice', invoice.id, invoice.id, '高', `人工确认收款 ${money(amount)},交易流水仅保存脱敏摘要。`); }, success: '收款已确认,账单与租户余额已更新' }); - } - if (form.id === 'usageForm') { - const values = Object.fromEntries(new FormData(form)); - simulateWrite({ key: 'usage', permission: 'platform:usage:write', operationId: 'PlatformAdminBillingController_recordUsage', request: () => Promise.all([['students', values.students], ['questions', values.questions], ['storage_gb', values.storageGB], ['traffic_tb', values.trafficTB]].map(([metricKey, metricValue]) => platformApi.request('PlatformAdminBillingController_recordUsage', { body: platformApi.buildBody('PlatformAdminBillingController_recordUsage', { tenantId: values.tenantId, period: values.period, metricKey, metricValue }) }))), validate: () => data.usage.some(item => item.tenantId === values.tenantId && item.period === values.period) ? { period: '该租户账期已有记录,避免周期重叠或重复' } : null, apply: () => { data.usage.unshift({ tenantId: values.tenantId, period: values.period, source: '人工补录', students: Number(values.students), questions: Number(values.questions), storageGB: Number(values.storageGB), trafficTB: Number(values.trafficTB), overage: [], estimated: 0 }); addAudit('usage.create', 'tenant', values.tenantId, tenantById(values.tenantId).name, '中', `人工补录 ${values.period} 平台用量。`); }, success: '用量记录已保存并标记人工来源' }); - } - if (form.id === 'dunningChannelForm') { - const values = Object.fromEntries(new FormData(form)); - const existing = data.dunningChannels.find(item => item.id === values.id); - simulateWrite({ key: 'dunning-channel', permission: 'platform:billing:notification', operationId: 'PlatformAdminDunningChannelsController_upsertChannel', body: () => ({ ...values, secretRef: existing?.secretRef, reminderTypes: existing?.reminderTypes, reminderChannels: existing?.reminderChannels, minReminderLevel: existing?.minReminderLevel, enabled: Boolean(new FormData(form).get('enabled')) }), validate: () => validateNotificationChannel(values), apply: () => { const next = { id: values.id || entityId('DUN'), code: values.code, name: values.name, provider: values.provider, endpoint: values.endpoint, endpointRedacted: false, secretRef: existing?.secretRef || '', retry: Number(values.retry), enabled: Boolean(new FormData(form).get('enabled')) }; if (existing) Object.assign(existing, next); else data.dunningChannels.unshift(next); addAudit('dunning.channel.upsert', 'notification_channel', next.id, next.name, '高', `保存催缴渠道 ${next.code},secret 保持只写。`); }, success: '催缴通知渠道已保存' }); - } - if (form.id === 'bankForm') { - const values = Object.fromEntries(new FormData(form)); - simulateWrite({ key: 'question-bank', permission: 'platform:question-bank:manage', operationId: 'PlatformQuestionBanksController_upsertBank', body: () => ({ id: values.id || null, name: values.name, metadata: values.version ? { version: values.version } : {} }), validate: () => !values.name?.trim() ? { name: '题库名称不能为空' } : null, apply: payload => { const item = payload ? platformApi.adapters.bank(payload, bankById(payload.id)) : { id: values.id || entityId('QB'), name: values.name, version: values.version || '-', status: '正常', source: '平台自建', catalog: '平台公共题库', nodes: 0, questions: 0 }; const existing = bankById(item.id); if (existing) Object.assign(existing, item); else data.banks.unshift(item); state.selectedBank = item.id; state.selectedBankNode = ''; return item; }, success: '公共题库已保存' }); - } - if (form.id === 'bankNodeForm') { - const values = Object.fromEntries(new FormData(form)); - simulateWrite({ key: 'question-bank-node', permission: 'platform:question-bank:manage', operationId: 'PlatformQuestionBanksController_upsertNode', body: () => ({ id: values.id || null, questionBankId: state.selectedBank, parentId: values.parentId || null, nodeKey: null, name: values.name, nodeType: values.nodeType, sortOrder: Number(values.sortOrder || 0), isSelectable: true, metadata: {} }), validate: () => !values.name?.trim() ? { name: '节点名称不能为空' } : null, apply: payload => { const item = payload ? adaptBankNode(payload) : { id: values.id || entityId('NODE'), questionBankId: state.selectedBank, parentId: values.parentId || null, name: values.name, nodeType: values.nodeType, sortOrder: Number(values.sortOrder || 0), depth: values.parentId ? Number(bankNodeById(values.parentId)?.depth || 0) + 1 : 0, isActive: true, questionCount: 0 }; const existing = bankNodeById(item.id); if (existing) Object.assign(existing, item); else data.bankNodes.push(item); state.selectedBankNode = item.id; return item; }, success: '内容节点已保存' }); - } - if (form.id === 'bankNodeBatchForm') { - const values = Object.fromEntries(new FormData(form)); const names = String(values.names || '').split(/\r?\n/).map(item => item.trim()).filter(Boolean); - simulateWrite({ key: 'question-bank-node-batch', permission: 'platform:question-bank:manage', operationId: 'PlatformQuestionBanksController_batchCreateNodes', body: () => ({ questionBankId: state.selectedBank, parentId: values.parentId || null, nodeType: values.nodeType, names }), validate: () => !names.length ? { names: '至少填写一个章节或试卷名称' } : names.length > 100 ? { names: '一次最多创建 100 个节点' } : null, apply: payload => { const items = apiItems(payload); if (items.length) data.bankNodes.push(...items.map(adaptBankNode)); return items.length || names.length; }, success: count => `已创建 ${count} 个内容节点` }); - } - if (form.id === 'bankQuestionForm') { - const values = Object.fromEntries(new FormData(form)); const options = parseJsonText(values.options, []); const tags = String(values.tags || '').split(/[、,,]/).map(item => item.trim()).filter(Boolean); - simulateWrite({ key: 'question-bank-question', permission: 'platform:question-bank:manage', operationId: 'PlatformQuestionBanksController_upsertQuestion', body: () => ({ id: values.id || null, questionBankId: state.selectedBank, contentNodeId: values.contentNodeId, legacyId: values.legacyId || null, type: values.type, typeLabel: questionTypeLabel(values.type), difficulty: Number(values.difficulty || 3), tags, content: values.content, options, correctOptionIndex: null, correctOptionIndices: [], answerText: values.answerText || null, explanation: values.explanation || null, subQuestions: [], codeLang: null, codeTemplate: null, mediaUrl: values.mediaUrl || null, status: 'published', examMarkers: {}, sourceHash: null }), validate: () => { const errors = {}; if (!values.contentNodeId) errors.contentNodeId = '请选择章节或试卷'; if (!values.content?.trim()) errors.content = '题干不能为空'; if (options === null || !Array.isArray(options)) errors.options = '选项必须是 JSON 数组'; return Object.keys(errors).length ? errors : null; }, apply: payload => { const item = payload ? adaptBankQuestion(payload) : { ...values, id: values.id || entityId('Q'), questionBankId: state.selectedBank, contentNodeId: values.contentNodeId, options, tags, versionNo: 1, status: 'published', statusLabel: '已发布' }; const existing = data.bankQuestions.find(row => row.id === item.id); if (existing) Object.assign(existing, item); else data.bankQuestions.unshift(item); return item; }, success: '题目已保存并生成新版本', close: false }); - } - if (form.id === 'bankBatchImportForm' || form.id === 'bankStructuredImportForm') { - const values = Object.fromEntries(new FormData(form)); const payload = parseJsonText(values.payload, null); const execute = event.submitter?.dataset.importMode === 'execute'; const format = form.id === 'bankStructuredImportForm' ? 'structured-v2' : 'simple'; - simulateWrite({ key: `question-bank-import-${format}`, permission: 'platform:question-bank:manage', operationId: execute ? 'PlatformQuestionBanksController_executeImport' : 'PlatformQuestionBanksController_previewImport', body: () => ({ questionBankId: state.selectedBank, contentNodeId: values.contentNodeId || null, format, sourceName: values.sourceName || (format === 'structured-v2' ? '结构化题库文件' : '普通题目批量导入'), payload }), validate: () => { const errors = {}; if (format === 'simple' && !values.contentNodeId) errors.contentNodeId = '普通批量导入必须选择章节或试卷'; if (payload === null) errors.payload = '请输入有效的 JSON'; return Object.keys(errors).length ? errors : null; }, apply: result => { data.bankImportResult = result || { detail: { job: { dryRun: !execute, totalCount: Array.isArray(payload) ? payload.length : 0, validCount: Array.isArray(payload) ? payload.length : 0, errorCount: 0 }, issues: [] }, insertedQuestionCount: execute && Array.isArray(payload) ? payload.length : 0, updatedQuestionCount: 0, skippedQuestionCount: 0, createdNodeCount: 0 }; return data.bankImportResult; }, success: execute ? '题库导入已执行' : '导入预检已完成', close: false }); - } - if (form.id === 'crmConfigForm') { - const values = Object.fromEntries(new FormData(form)); - values.enabled = Boolean(new FormData(form).get('enabled')); - simulateWrite({ key: 'crm-config', permission: 'platform:crm:write', operationId: 'PlatformAdminCrmController_upsertConfig', body: () => values, validate: () => { const errors = {}; if (!values.tenantId) errors.tenantId = '租户不能为空'; if (!values.endpoint) errors.endpoint = 'Webhook Endpoint 不能为空'; return Object.keys(errors).length ? errors : null; }, apply: payload => { const item = payload ? platformApi.adapters.crmConfig(payload) : { ...values, id: values.id || entityId('CRM'), enabled: values.enabled, status: values.enabled ? '正常' : '未启用' }; const index = data.crmConfigs.findIndex(row => row.id === item.id); if (index >= 0) data.crmConfigs[index] = item; else data.crmConfigs.unshift(item); addAudit('crm.config.upsert', 'crm_config', item.id, tenantById(item.tenantId)?.name || item.id, '中', '保存 CRM 接入配置。'); }, success: 'CRM 接入配置已保存' }); - } - if (form.id === 'smsChannelForm') { - const values = Object.fromEntries(new FormData(form)); - simulateWrite({ key: 'sms-channel', permission: 'platform:sms:write', operationId: 'PlatformAdminSmsController_upsertChannel', body: () => values, validate: () => { const errors = {}; if (!values.tenantId) errors.tenantId = '租户不能为空'; if (!values.provider) errors.provider = 'Provider 不能为空'; if (!values.signature) errors.signature = '短信签名不能为空'; return Object.keys(errors).length ? errors : null; }, apply: payload => { const item = payload ? platformApi.adapters.smsChannel(payload) : { ...values, id: values.id || entityId('SMS'), enabled: values.status === '正常', used: 0 }; const index = data.smsChannels.findIndex(row => row.id === item.id); if (index >= 0) data.smsChannels[index] = item; else data.smsChannels.unshift(item); addAudit('sms.channel.upsert', 'sms_channel', item.id, tenantById(item.tenantId)?.name || item.id, '中', '保存短信渠道配置。'); }, success: '短信渠道已保存' }); - } - if (form.id === 'paymentAppForm') { - const values = Object.fromEntries(new FormData(form)); - const operationId = values.appScope === 'tenant' ? 'PlatformAdminTenantPaymentSettingsController_upsertApp' : 'PlatformAdminPaymentSettingsController_upsertApp'; - simulateWrite({ key: 'payment-app', permission: 'platform:payment:write', operationId, body: () => values, validate: () => { const errors = {}; if (values.appScope === 'tenant' && !values.tenantId) errors.tenantId = '租户代管必须选择租户'; if (!values.appName) errors.appName = '应用名称不能为空'; return Object.keys(errors).length ? errors : null; }, apply: payload => { const item = payload ? (values.appScope === 'tenant' ? platformApi.adapters.tenantPaymentApp(payload) : platformApi.adapters.platformPaymentApp(payload)) : { ...values, id: values.id || entityId('PAYAPP'), status: values.status }; const index = data.paymentApps.findIndex(row => row.id === item.id); if (index >= 0) data.paymentApps[index] = item; else data.paymentApps.unshift(item); addAudit('payment.app.upsert', 'payment_app', item.id, item.appName, '高', '保存支付应用配置。'); }, success: '支付应用已保存' }); - } - if (form.id === 'staffForm') { - const values = Object.fromEntries(new FormData(form)); const roleIds = new FormData(form).getAll('roleIds'); - simulateWrite({ key: 'staff', permission: 'platform:staff:write', operationId: 'PlatformAdminOverviewController_upsertStaff', body: () => ({ ...values, roleIds }), validate: () => { const errors = {}; if (!values.name) errors.name = '姓名不能为空'; if (!values.email) errors.email = '邮箱不能为空'; if (values.phone && !/^1\d{10}$/.test(values.phone)) errors.phone = '请输入 11 位手机号'; if (!roleIds.length) errors.roleIds = '至少选择一个平台角色'; return Object.keys(errors).length ? errors : null; }, apply: payload => { const existing = data.staff.find(item => item.id === values.userId); const assignedRoles = data.platformRoles.filter(role => roleIds.includes(role.id)); const fallback = { id: values.userId || entityId('STAFF'), userId: values.userId || '', name: values.name, email: values.email, phone: values.phone || existing?.phone || '-', roleIds, roleCodes: assignedRoles.map(role => role.code), role: assignedRoles.map(role => role.name).join('、'), permissions: [...new Set(assignedRoles.flatMap(role => role.permissionCodes))], status: existing?.status || '正常', lastActive: existing?.lastActive || '尚未登录' }; const next = payload ? { ...fallback, ...platformApi.adapters.staff(payload), roleIds, roleCodes: fallback.roleCodes, role: fallback.role, permissions: fallback.permissions } : fallback; if (existing) Object.assign(existing, next); else data.staff.unshift(next); addAudit('staff.upsert', 'staff', next.id, next.name, '高', `保存平台员工及 ${assignedRoles.length} 个角色。`); }, success: '平台员工与角色已保存' }); - } - if (form.id === 'auditChannelForm') { - const values = Object.fromEntries(new FormData(form)); - const existing = data.auditChannels.find(item => item.id === values.id); - simulateWrite({ key: 'audit-channel', permission: 'platform:audit:notification', operationId: 'PlatformAdminAuditController_upsertChannel', body: () => ({ ...values, secretRef: existing?.secretRef, enabled: Boolean(new FormData(form).get('enabled')) }), validate: () => validateNotificationChannel(values), apply: () => { const next = { id: values.id || entityId('CH'), code: values.code, name: values.name, provider: values.provider, endpoint: values.endpoint, endpointRedacted: false, secretRef: existing?.secretRef || '', minSeverity: values.minSeverity, statusFilter: values.statusFilter, timeout: Number(values.timeout), maxAttempts: Number(values.maxAttempts), enabled: Boolean(new FormData(form).get('enabled')), lastStatus: existing?.lastStatus || '正常' }; if (existing) Object.assign(existing, next); else data.auditChannels.unshift(next); addAudit('audit.channel.upsert', 'notification_channel', next.id, next.name, '高', `保存审计告警渠道 ${next.code},secret 保持只写。`); }, success: '审计通知渠道已保存' }); - } -}); - -document.addEventListener('click', event => { - if (event.target.classList.contains('modal-backdrop')) { - closeModal(); - return; - } - const copy = event.target.closest('[data-copy]'); if (copy) { navigator.clipboard?.writeText(copy.dataset.copy); showToast('已复制到剪贴板'); return; } - const nav = event.target.closest('[data-nav]'); if (nav) { requestLeave(() => { state.selectedTenant = ''; navigate(nav.dataset.nav, { force: true }); }); return; } - const tenant = event.target.closest('[data-tenant-detail]'); if (tenant) { requestLeave(() => { state.selectedTenant = tenant.dataset.tenantDetail; navigate('tenantDetail', { force: true }); }); return; } - const invoice = event.target.closest('[data-invoice-detail]'); if (invoice) { if (requireDesktop('确认账单收款')) return; state.selectedInvoice = invoice.dataset.invoiceDetail; openModal('payment', { invoiceId: invoice.dataset.invoiceDetail }); return; } - const audit = event.target.closest('[data-audit-detail]'); if (audit) { openModal('auditDetail', { auditId: audit.dataset.auditDetail }); return; } - const alertDetail = event.target.closest('[data-alert-detail]'); if (alertDetail) { openModal('alertDetail', { alertId: alertDetail.dataset.alertDetail }); return; } - const notificationDetail = event.target.closest('[data-notification-detail]'); if (notificationDetail) { openModal('notificationDetail', { eventId: notificationDetail.dataset.notificationDetail }); return; } - const tf = event.target.closest('[data-tenant-filter]'); if (tf) { state.tenantFilter = tf.dataset.tenantFilter; syncNavigationState(); render(); return; } - const billingTab = event.target.closest('[data-billing-tab]'); if (billingTab) { state.billingTab = billingTab.dataset.billingTab; syncNavigationState(); render(); return; } - const bankTab = event.target.closest('[data-bank-tab]'); if (bankTab) { state.bankTab = bankTab.dataset.bankTab; syncNavigationState(); render(); if (['structure', 'manage'].includes(state.bankTab)) loadBankWorkspace(); return; } - const crmTab = event.target.closest('[data-crm-tab]'); if (crmTab) { state.crmTab = crmTab.dataset.crmTab; syncNavigationState(); render(); return; } - const smsTab = event.target.closest('[data-sms-tab]'); if (smsTab) { state.smsTab = smsTab.dataset.smsTab; syncNavigationState(); render(); return; } - const paymentTab = event.target.closest('[data-payment-tab]'); if (paymentTab) { state.paymentTab = paymentTab.dataset.paymentTab; syncNavigationState(); render(); return; } - const saasFinanceTab = event.target.closest('[data-saas-finance-tab]'); if (saasFinanceTab) { state.saasFinanceTab = saasFinanceTab.dataset.saasFinanceTab; syncNavigationState(); render(); return; } - const bankSelect = event.target.closest('[data-bank-select]'); if (bankSelect) { state.selectedBank = bankSelect.dataset.bankSelect; state.selectedBankNode = ''; syncNavigationState(); render(); loadBankWorkspace(); return; } - const bankNodeSelect = event.target.closest('[data-bank-node-select]'); if (bankNodeSelect) { state.selectedBankNode = bankNodeSelect.dataset.bankNodeSelect; syncNavigationState(); render(); return; } - const auditSeverity = event.target.closest('[data-audit-severity]'); if (auditSeverity) { state.auditSeverity = auditSeverity.dataset.auditSeverity; syncNavigationState(); render(); return; } - const alertStatus = event.target.closest('[data-alert-status]'); if (alertStatus) { state.alertStatus = alertStatus.dataset.alertStatus; syncNavigationState(); render(); return; } - const actionElement = event.target.closest('[data-action]'); const action = actionElement?.dataset.action; if (!action) return; - if (action === 'close-modal') { closeModal(); return; } - if (action === 'execute-confirmed' || action === 'execute-staff-disable') { if (requireDesktop('执行高风险确认操作')) return; const execute = state.modalData.execute; closeModal({ force: true }); execute?.(); return; } - if (action === 'subpage-back') { navigateBack(); return; } - if (action === 'subpage-close') { closeSubpage(); return; } - if (action === 'retry-page') { state.scenario = 'normal'; scenarioSelect.value = 'normal'; render(); return; } - if (action === 'restore-session') { state.scenario = 'normal'; state.view = 'overview'; state.previousView = ''; state.history = []; scenarioSelect.value = 'normal'; render(); showToast('Mock 会话已恢复'); return; } - if (action === 'logout' && platformApi?.isEnabled()) { window.GongxuePlatformAuth?.logout(); return; } - if (action === 'logout') { closeModal(); state.scenario = 'session_invalid'; state.view = 'overview'; state.previousView = ''; state.history = []; scenarioSelect.value = 'session_invalid'; addAudit('auth.logout', 'application', 'platform-console', '平台管理控制台', '中', '超级管理员主动退出当前平台端会话。'); saveData(); render(); return; } - if (action === 'refresh') { - if (platformApi?.isEnabled()) { hydrateFromBackend(); return; } - state.scenario = 'loading'; scenarioSelect.value = 'loading'; render(); - setTimeout(() => { state.scenario = 'normal'; scenarioSelect.value = 'normal'; render(); showToast('平台静态演示数据已刷新'); }, 700); - return; - } - if (action === 'reset-mock') { if (requireDesktop('重置平台 Mock 数据')) return; confirmAction({ title: '重置平台 Mock 数据', description: '恢复到 v1.1 初始演示数据。', impact: '所有本地创建的租户、账单、任务、授权、员工修改和告警状态将被清除。', confirmLabel: '确认重置' }, () => { localStorage.removeItem(STORAGE_KEY); data = clone(seed); state.selectedTenant = data.tenants[0].id; saveData(); render(); showToast('平台 Mock 数据已重置'); }); return; } - if (action === 'open-task-center') { openModal('tasks'); return; } - if (action === 'create-tenant') { if (requireDesktop('创建租户')) return; openModal('createTenant'); return; } - if (action === 'new-saas-feature') { openModal('saasFeature'); return; } - if (action === 'new-saas-offering') { openModal('saasOffering'); return; } - if (action === 'new-saas-version') { if (!(data.saasCatalog?.offerings || []).length) { showToast('请先创建 SaaS 商品', 'error'); return; } openModal('saasVersion'); return; } - if (action === 'new-platform-role') { openModal('platformRole'); return; } - if (action === 'edit-platform-role') { openModal('platformRole', { roleId: actionElement.dataset.roleId }); return; } - if (action === 'new-payment-channel') { if (!data.paymentApps.some(item => item.appScope === 'platform')) { showToast('请先创建平台支付应用', 'error'); return; } openModal('paymentChannel'); return; } - if (action === 'edit-payment-channel') { openModal('paymentChannel', { channelId: actionElement.dataset.channelId }); return; } - if (action === 'disable-payment-channel') { const channelId = actionElement.dataset.channelId; if (!platformApi?.isEnabled()) { const channel = data.paymentChannels.find(item => item.id === channelId); if (channel) channel.status = 'disabled'; render(); showToast('支付渠道已停用'); return; } platformApi.request('PlatformAdminPaymentSettingsController_disableChannel', { pathParams: { channelId }, body: {} }).then(payload => { const channel = data.paymentChannels.find(item => item.id === channelId); if (channel) Object.assign(channel, payload); render(); showToast('支付渠道已停用'); }).catch(error => showToast(backendErrorText(error, '停用支付渠道失败'), 'error')); return; } - if (action === 'new-sms-template') { if (!data.smsChannels.length) { showToast('请先创建租户短信渠道', 'error'); return; } openModal('smsTemplate'); return; } - if (action === 'edit-sms-template') { openModal('smsTemplate', { templateId: actionElement.dataset.templateId }); return; } - if (['submit-sms-template', 'disable-sms-template'].includes(action)) { const templateId = actionElement.dataset.templateId; const operationId = action === 'submit-sms-template' ? 'PlatformAdminSmsController_submitTemplateReview' : 'PlatformAdminSmsController_disableTemplate'; if (!platformApi?.isEnabled()) { const template = data.smsTemplates.find(item => item.id === templateId); if (template) { if (action === 'submit-sms-template') template.status = '审核中'; else template.templateStatus = '未启用'; } render(); showToast(action === 'submit-sms-template' ? '短信模板已提交审核' : '短信模板已停用'); return; } platformApi.request(operationId, { pathParams: { templateId }, body: {} }).then(payload => { const template = data.smsTemplates.find(item => item.id === templateId); if (template) Object.assign(template, platformApi.adapters.smsTemplate(payload)); render(); showToast(action === 'submit-sms-template' ? '短信模板已提交审核' : '短信模板已停用'); }).catch(error => showToast(backendErrorText(error, '短信模板操作失败'), 'error')); return; } - if (['publish-saas-version', 'clone-saas-version', 'retire-saas-version'].includes(action)) { const operationId = action === 'publish-saas-version' ? 'PlatformSaasController_publishVersion' : action === 'clone-saas-version' ? 'PlatformSaasController_cloneVersion' : 'PlatformSaasController_retireVersion'; const versionId = actionElement.dataset.versionId; if (!platformApi?.isEnabled()) { const version = data.saasCatalog.versions.find(item => item.id === versionId); if (version) version.status = action === 'retire-saas-version' ? 'retired' : action === 'publish-saas-version' ? 'published' : version.status; render(); showToast('套餐版本状态已更新'); return; } platformApi.request(operationId, { pathParams: { versionId }, body: {} }).then(() => hydrateFromBackend({ silent: true })).then(() => showToast('套餐版本状态已更新')).catch(error => showToast(backendErrorText(error, '套餐版本操作失败'), 'error')); return; } - if (action === 'recheck-domain') { const domain = data.domains.find(item => item.id === actionElement.dataset.domainId); if (!domain) return; if (!platformApi?.isEnabled()) { showToast('真实 API 模式才能重新检查域名', 'error'); return; } platformApi.request('PlatformAdminTenantsController_recheckDomain', { pathParams: { domainId: domain.id }, body: {} }).then(payload => { Object.assign(domain, payload); render(); showToast('域名 DNS/TLS 状态已重新检查'); }).catch(error => showToast(backendErrorText(error, '域名检查失败'), 'error')); return; } - if (action === 'prepare-tenant-status') { if (requireDesktop('变更租户生命周期')) return; openModal('tenantStatus', { tenantId: actionElement.dataset.tenantId || state.selectedTenant }); return; } - if (action === 'open-tenant-portal') { const tenant = tenantById(state.selectedTenant); let portalWindow = null; try { portalWindow = window.open(TENANT_PORTAL_ORIGIN, '_blank'); if (portalWindow) portalWindow.opener = null; } catch {} showToast(portalWindow ? `已在新标签打开独立租户端 · ${tenant?.name || '当前租户'}` : '已请求打开独立租户端;如未出现,请允许本站弹出窗口', portalWindow ? 'success' : 'error'); return; } - if (action === 'edit-billing-profile') { if (requireDesktop('编辑租户账务资料')) return; navigate('billingProfile'); return; } - if (action === 'billing-profile-to-invoices' || action === 'tenant-to-billing') { if (actionElement.dataset.tenantId) state.selectedTenant = actionElement.dataset.tenantId; navigate('billing'); return; } - if (action === 'tenant-to-usage') { state.selectedTenant = actionElement.dataset.tenantId; navigate('usage'); return; } - if (action === 'clear-tenant-context') { state.selectedTenant = ''; render(); return; } - if (action === 'create-subscription-for-tenant') { if (requireDesktop('创建租户订阅')) return; navigate('subscriptions'); openModal('createSubscription'); return; } - if (action === 'create-subscription') { if (requireDesktop('创建租户订阅')) return; openModal('createSubscription'); return; } - if (action === 'select-plan') { if (requireDesktop('选择套餐并创建订阅')) return; openModal('createSubscription', { planCode: actionElement.dataset.planCode }); return; } - if (action === 'subscription-to-billing') { navigate('billing'); return; } - if (action === 'subscriptions-to-usage') { navigate('usage'); return; } - if (action === 'toggle-auto-renew') { if (requireDesktop('变更订阅自动续费')) return; if (platformApi?.isEnabled()) { showToast('后端暂未提供订阅更新接口,真实模式禁止仅改本地状态', 'error'); return; } const item = data.subscriptions.find(subscription => subscription.id === actionElement.dataset.subscriptionId); if (!canWrite('platform:billing:write')) return; item.autoRenew = !item.autoRenew; addAudit('subscription.auto_renew.update', 'subscription', item.id, item.id, '中', `自动续费更新为 ${item.autoRenew ? '开启' : '关闭'}。`); saveData(); render(); showToast('自动续费设置已更新'); return; } - if (action === 'create-invoice') { if (requireDesktop('手工创建账单')) return; openModal('createInvoice'); return; } - if (action === 'apply-invoice-query') { runContractRead({ key: 'invoice-query', actionId: 'act.p-06.01', operationId: 'PlatformAdminBillingController_invoices', title: '账单查询', suppliedRequestId: actionElement.dataset.contractRequestId, liveRequest: () => platformApi.request('PlatformAdminBillingController_invoices', { query: { tenantId: state.selectedTenant || undefined, status: ({ 草稿: 'draft', 待付款: 'issued', 已支付: 'paid', 已作废: 'void', 已逾期: 'overdue' })[state.invoiceStatus], limit: 200 } }), apply: payload => { const items = apiItems(payload); if (items.length) data.invoices = items.map(platformApi.adapters.invoice); return `${data.invoices.filter(invoice => (!state.selectedTenant || invoice.tenantId === state.selectedTenant) && (state.invoiceStatus === 'all' || invoice.status === state.invoiceStatus) && (!state.invoiceSearch.trim() || [invoice.id, invoice.type, invoice.period, invoice.note, tenantById(invoice.tenantId)?.name].some(value => String(value || '').toLowerCase().includes(state.invoiceSearch.trim().toLowerCase())))).length} 张匹配账单`; } }); return; } - if (action === 'preview-invoice-candidates') { if (requireDesktop('批量生成账单')) return; openModal('invoiceCandidates'); return; } - if (action === 'run-invoice-dry-run' && platformApi?.isEnabled()) { const subscriptionIds = Array.from(overlayRoot.querySelectorAll('[name="candidate"]:checked')).map(input => input.value); executeBackendMutation('PlatformAdminBillingController_fromSubscriptionsBatch', { subscriptionIds, dryRun: true }, payload => { const result = apiItem(payload); showToast(`Dry-run 完成 · 可生成 ${result.items?.length || 0} 条,跳过 ${result.skippedCount || 0} 条`); }, { refresh: false }); return; } - if (action === 'run-invoice-dry-run') { const count = overlayRoot.querySelectorAll('[name="candidate"]:checked').length; showToast(`Dry-run 已校验 ${count} 条订阅候选,未写入账单`); return; } - if (action === 'generate-subscription-invoice' && platformApi?.isEnabled()) { if (requireDesktop('为单个订阅生成账单')) return; const subscription = data.subscriptions.find(item => item.id === actionElement.dataset.subscriptionId); if (!subscription) { showToast('订阅不存在或不可用', 'error'); return; } executeBackendMutation('PlatformAdminBillingController_fromSubscription', { tenantId: subscription.tenantId, subscriptionId: subscription.id, status: 'issued' }, payload => { closeModal({ force: true }); window.recordPlatformSpecResult?.('act.p-06.04', { result: 'success', operationId: 'PlatformAdminBillingController_fromSubscription', requestId: payload?.meta?.requestId || payload?.traceId || '' }); showToast('订阅账单已由后端生成'); }); return; } - if (action === 'generate-subscription-invoice') { if (requireDesktop('为单个订阅生成账单')) return; const subscription = data.subscriptions.find(item => item.id === actionElement.dataset.subscriptionId); const suppliedRequestId = actionElement.dataset.contractRequestId || requestId(); if (!subscription || data.invoices.some(invoice => invoice.note.includes(subscription.id))) { state.contractResults['invoice-query'] = { status: 'error', title: '单订阅生成失败', detail: '该订阅已存在账单或订阅不可用', requestId: suppliedRequestId }; addAudit('invoice.from_subscription.failed', 'subscription', subscription?.id || '-', subscription?.id || '-', '中', `幂等冲突。Request ID:${suppliedRequestId}。`, '失败'); window.recordPlatformSpecResult?.('act.p-06.04', { result: 'failed', operationId: 'PlatformAdminBillingController_fromSubscription', requestId: suppliedRequestId }); render(); return; } const task = addContractTask({ actionId: 'act.p-06.04', operationId: 'PlatformAdminBillingController_fromSubscription', label: `为订阅 ${subscription.id} 生成账单`, resultTarget: '服务费账单', suppliedRequestId, execute: taskItem => { const invoice = { id: entityId('INV'), tenantId: subscription.tenantId, type: '订阅服务费', period: '下一订阅账期', total: subscription.amount, paid: 0, balance: subscription.amount, due: subscription.expires, status: '待付款', note: `订阅 ${subscription.id}` }; data.invoices.unshift(invoice); tenantById(subscription.tenantId).balance += invoice.balance; taskItem.invoiceId = invoice.id; addAudit('invoice.from_subscription.create', 'invoice', invoice.id, invoice.id, '高', `通过任务 ${taskItem.id} 为订阅 ${subscription.id} 生成单张账单。`); } }); showToast(`单订阅账单任务 ${task.id} 已创建`); return; } - if (action === 'confirm-generate-candidates' && platformApi?.isEnabled()) { if (requireDesktop('批量生成账单')) return; const subscriptionIds = Array.from(overlayRoot.querySelectorAll('[name="candidate"]:checked')).map(input => input.value); if (!subscriptionIds.length) { showToast('请至少选择一条订阅账单候选', 'error'); return; } executeBackendMutation('PlatformAdminBillingController_fromSubscriptionsBatch', { subscriptionIds, dryRun: false, status: 'issued' }, payload => { closeModal({ force: true }); const result = apiItem(payload); showToast(`后端已生成 ${result.createdCount || 0} 张账单,跳过 ${result.skippedCount || 0} 条`); }); return; } - if (action === 'confirm-generate-candidates') { if (requireDesktop('批量生成账单')) return; const selectedIds = Array.from(overlayRoot.querySelectorAll('[name="candidate"]:checked')).map(input => input.value); if (!selectedIds.length) { showToast('请至少选择一条订阅账单候选', 'error'); return; } const candidates = data.subscriptions.filter(subscription => selectedIds.includes(subscription.id) && !data.invoices.some(invoice => invoice.note.includes(subscription.id))); closeModal(); const task = addTask(`批量生成 ${candidates.length} 张订阅账单`, '服务费账单', () => { candidates.forEach(subscription => { const invoice = { id: entityId('INV'), tenantId: subscription.tenantId, type: '订阅服务费', period: '下一订阅账期', total: subscription.amount, paid: 0, balance: subscription.amount, due: subscription.expires, status: '待付款', note: `订阅 ${subscription.id}` }; data.invoices.unshift(invoice); const tenant = tenantById(subscription.tenantId); tenant.balance += invoice.balance; tenant.billing = '待付款'; }); addAudit('invoice.batch.create', 'invoice_batch', task.id, task.id, '高', `批量生成 ${candidates.length} 张订阅账单。`); }); showToast(`任务 ${task.id} 已创建`); return; } - if (action === 'confirm-payment') { if (requireDesktop('确认账单收款')) return; openModal('payment', { invoiceId: actionElement.dataset.invoiceId }); return; } - if (action === 'preview-overdue' && platformApi?.isEnabled()) { if (requireDesktop('批量处理逾期账单')) return; executeBackendMutation('PlatformAdminBillingController_processOverdue', { dryRun: true, limit: 100, channel: 'internal' }, payload => { const result = apiItem(payload); openModal('overduePreview'); showToast(`后端 Dry-run:${result.processed || result.items?.length || 0} 条候选`); }, { refresh: false }); return; } - if (action === 'preview-overdue') { if (requireDesktop('批量处理逾期账单')) return; openModal('overduePreview'); return; } - if (action === 'confirm-overdue-process' && platformApi?.isEnabled()) { showToast('后端逾期处理接口不支持指定 invoiceIds,真实模式禁止按当前勾选直接执行', 'error'); return; } - if (action === 'confirm-overdue-process') { if (requireDesktop('批量处理逾期账单')) return; const selectedIds = Array.from(overlayRoot.querySelectorAll('[name="candidate"]:checked')).map(input => input.value); if (!selectedIds.length) { showToast('请至少选择一条逾期账单候选', 'error'); return; } const overdue = data.invoices.filter(invoice => invoice.status === '已逾期' && selectedIds.includes(invoice.id)); closeModal(); const task = addTask(`处理 ${overdue.length} 张逾期账单`, '收款与催缴', () => { overdue.forEach(invoice => data.reminders.unshift({ id: entityId('REM'), invoiceId: invoice.id, tenantId: invoice.tenantId, level: 3, channel: '邮件 + 短信', status: '发送中', date: todayTime(), message: `服务费账单 ${invoice.id} 已逾期,请尽快处理。` })); addAudit('invoice.overdue.process', 'invoice_batch', task.id, task.id, '高', `生成 ${overdue.length} 条催缴记录。`); }); showToast(`催缴任务 ${task.id} 已创建`); return; } - if (action === 'generate-reminder' && platformApi?.isEnabled()) { showToast('后端仅提供批量逾期处理,没有单账单催缴创建接口', 'error'); return; } - if (action === 'generate-reminder') { if (requireDesktop('生成账单催缴')) return; const invoice = invoiceById(actionElement.dataset.invoiceId); const reminder = { id: entityId('REM'), invoiceId: invoice.id, tenantId: invoice.tenantId, level: invoice.status === '已逾期' ? 3 : 1, channel: '邮件 + 短信', status: '已加入队列', date: todayTime(), message: invoice.status === '已逾期' ? `账单已逾期,请尽快支付 ${money(invoice.balance)}。` : `账单即将到期,应付 ${money(invoice.balance)}。` }; data.reminders.unshift(reminder); addAudit('invoice.reminder.create', 'reminder', reminder.id, reminder.id, '中', `为 ${invoice.id} 创建 L${reminder.level} 催缴。`); saveData(); render(); showToast('催缴已加入发送队列'); return; } - if (action === 'record-usage') { if (requireDesktop('人工记录平台用量')) return; openModal('recordUsage'); return; } - if (action === 'preview-overage') { if (requireDesktop('批量生成超额账单')) return; openModal('overagePreview'); return; } - if (action === 'run-overage-dry-run' && platformApi?.isEnabled()) { const tenantIds = Array.from(overlayRoot.querySelectorAll('[name="candidate"]:checked')).map(input => input.value.split(':')[0]); executeBackendMutation('PlatformAdminBillingController_fromUsage', { tenantIds, period: state.usagePeriod, dryRun: true }, payload => { const result = apiItem(payload); showToast(`超额 Dry-run 完成 · 可生成 ${result.items?.length || 0} 条`); }, { refresh: false }); return; } - if (action === 'run-overage-dry-run') { const count = overlayRoot.querySelectorAll('[name="candidate"]:checked').length; showToast(`Dry-run 已校验 ${count} 条超额候选,未写入账单`); return; } - if (action === 'confirm-overage-invoices' && platformApi?.isEnabled()) { if (requireDesktop('批量生成超额账单')) return; const tenantIds = Array.from(overlayRoot.querySelectorAll('[name="candidate"]:checked')).map(input => input.value.split(':')[0]); if (!tenantIds.length) { showToast('请至少选择一条超额账单候选', 'error'); return; } executeBackendMutation('PlatformAdminBillingController_fromUsage', { tenantIds, period: state.usagePeriod, dryRun: false, status: 'issued' }, payload => { closeModal({ force: true }); showToast(`后端已生成 ${apiItem(payload).createdCount || 0} 张超额账单`); }); return; } - if (action === 'confirm-overage-invoices') { if (requireDesktop('批量生成超额账单')) return; const selectedKeys = Array.from(overlayRoot.querySelectorAll('[name="candidate"]:checked')).map(input => input.value); if (!selectedKeys.length) { showToast('请至少选择一条超额账单候选', 'error'); return; } const candidates = data.usage.filter(item => item.period === state.usagePeriod && selectedKeys.includes(`${item.tenantId}:${item.period}`) && item.estimated > 0 && !data.invoices.some(invoice => invoice.note === `超额 ${item.period}` && invoice.tenantId === item.tenantId)); closeModal(); const task = addTask(`生成 ${candidates.length} 张超额账单`, '用量与超额计费', () => { candidates.forEach(item => { const invoice = { id: entityId('INV'), tenantId: item.tenantId, type: '用量超额费', period: item.period, total: item.estimated, paid: 0, balance: item.estimated, due: '2026-08-15', status: '待付款', note: `超额 ${item.period}` }; data.invoices.unshift(invoice); const tenant = tenantById(item.tenantId); tenant.balance += invoice.balance; tenant.billing = '待付款'; }); addAudit('usage.invoice.batch.create', 'invoice_batch', task.id, task.id, '高', `生成 ${candidates.length} 张用量超额账单。`); }); showToast(`超额账单任务 ${task.id} 已创建`); return; } - if (action === 'new-dunning-channel') { if (requireDesktop('新建催缴渠道')) return; openModal('dunningChannel'); return; } - if (action === 'edit-dunning-channel') { if (requireDesktop('编辑催缴渠道')) return; openModal('dunningChannel', { channelId: actionElement.dataset.channelId }); return; } - if (action === 'toggle-dunning-channel') { if (requireDesktop('变更催缴渠道状态')) return; if (!canWrite('platform:billing:notification')) return; const channel = data.dunningChannels.find(item => item.id === actionElement.dataset.channelId); if (!channel) return; const nextEnabled = !channel.enabled; const apply = () => { channel.enabled = nextEnabled; addAudit('dunning.channel.status', 'notification_channel', channel.id, channel.name, '高', `催缴渠道${channel.enabled ? '启用' : '停用'}。`); saveData(); render(); showToast('渠道状态已更新'); }; if (!platformApi?.isEnabled()) { apply(); return; } if (!nextEnabled) { executeBackendMutation('PlatformAdminDunningChannelsController_disableChannel', { channelId: channel.id, reason: '平台管理员停用催缴渠道' }, apply); return; } if (channel.endpointRedacted) { openModal('dunningChannel', { channelId: channel.id }); showToast('重新启用前请填写完整的 HTTPS 通知地址', 'error'); return; } executeBackendMutation('PlatformAdminDunningChannelsController_upsertChannel', { ...channel, enabled: true }, apply); return; } - if (action === 'new-bank') { if (requireDesktop('新建公共题库')) return; openModal('bank'); return; } - if (action === 'edit-bank') { if (requireDesktop('编辑公共题库')) return; openModal('bank', { bankId: state.selectedBank }); return; } - if (action === 'archive-bank') { const bank = bankById(state.selectedBank); if (!bank) return; confirmAction({ title: '归档公共题库', description: bank.name, impact: '仅当题库中的题目和内容节点均已归档时才能归档,历史版本不会删除。', confirmLabel: '确认归档' }, () => executeBackendMutation('PlatformQuestionBanksController_archiveBank', {}, payload => { Object.assign(bank, payload ? platformApi.adapters.bank(payload, bank) : { status: '已归档' }); render(); showToast('公共题库已归档'); }, { refresh: false, pathParams: { bankId: bank.id } })); return; } - if (action === 'new-bank-node') { if (requireDesktop('新建内容节点')) return; openModal('bankNode'); return; } - if (action === 'edit-bank-node') { if (requireDesktop('编辑内容节点')) return; openModal('bankNode', { nodeId: state.selectedBankNode }); return; } - if (action === 'batch-bank-nodes') { if (requireDesktop('批量创建章节或试卷')) return; openModal('batchBankNodes'); return; } - if (action === 'shift-bank-node') { const node = bankNodeById(state.selectedBankNode); if (!node) return; const sortOrder = Number(node.sortOrder || 0) + Number(actionElement.dataset.sortDelta || 0); executeBackendMutation('PlatformQuestionBanksController_upsertNode', { id: node.id, questionBankId: node.questionBankId, parentId: node.parentId || null, nodeKey: node.nodeKey || null, name: node.name, nodeType: node.nodeType, sortOrder, isSelectable: node.isSelectable !== false, metadata: node.metadata || {} }, payload => { Object.assign(node, payload ? adaptBankNode(payload) : { sortOrder }); data.bankNodes.sort((left, right) => Number(left.sortOrder || 0) - Number(right.sortOrder || 0)); render(); showToast('内容节点顺序已保存'); }, { refresh: false }); return; } - if (action === 'apply-bank-search') { runContractRead({ key: 'bank-query', actionId: 'act.p-09.01', operationId: 'PlatformQuestionBanksController_getBanks', title: '公共题库查询', suppliedRequestId: actionElement.dataset.contractRequestId, liveRequest: () => platformApi.request('PlatformQuestionBanksController_getBanks', { query: { keyword: state.bankSearch || undefined, status: 'all' } }), apply: payload => { const items = apiItems(payload); data.banks = items.map(item => platformApi.adapters.bank(item, bankById(item.id))); if (!bankById(state.selectedBank)) state.selectedBank = data.banks[0]?.id || ''; return `${data.banks.length} 个匹配题库`; } }); return; } - if (action === 'load-bank-questions' || action === 'bank-question-page') { if (action === 'bank-question-page') state.bankQuestionPage = Number(actionElement.dataset.page || 1); const query = { questionBankId: state.selectedBank, contentNodeId: state.selectedBankNode || undefined, keyword: document.querySelector('#bankQuestionSearch')?.value || undefined, type: document.querySelector('#bankQuestionType')?.value || undefined, status: document.querySelector('#bankQuestionStatus')?.value || undefined, page: state.bankQuestionPage, pageSize: 20 }; if (!platformApi?.isEnabled()) { render(); return; } platformApi.request('PlatformQuestionBanksController_getQuestions', { query }).then(payload => { data.bankQuestions = apiItems(payload).map(adaptBankQuestion); state.bankQuestionTotal = Number(payload.total || data.bankQuestions.length); render(); }).catch(error => showToast(backendErrorText(error, '题目查询失败'), 'error')); return; } - if (action === 'edit-bank-question') { const question = data.bankQuestions.find(item => item.id === actionElement.dataset.questionId); if (!question) return; state.bankTab = 'single'; state.selectedBankNode = question.contentNodeId; render(); requestAnimationFrame(() => { const form = document.querySelector('#bankQuestionForm'); if (!form) return; form.elements.id.value = question.id; form.elements.contentNodeId.value = question.contentNodeId; form.elements.type.value = question.type; form.elements.difficulty.value = question.difficulty || 3; form.elements.legacyId.value = question.legacyId || ''; form.elements.content.value = question.content || ''; form.elements.options.value = JSON.stringify(question.options || [], null, 2); form.elements.answerText.value = question.answerText || ''; form.elements.explanation.value = question.explanation || ''; form.elements.mediaUrl.value = question.mediaUrl || ''; form.elements.tags.value = Array.isArray(question.tags) ? question.tags.join('、') : ''; }); return; } - if (action === 'archive-bank-question') { const questionId = actionElement.dataset.questionId; const apply = () => { const question = data.bankQuestions.find(item => item.id === questionId); if (question) { question.status = 'archived'; question.statusLabel = '已归档'; } render(); showToast('题目已归档'); }; confirmAction({ title: '归档题目', description: '归档后题目历史版本仍会保留。', impact: '该题目不会再进入公共题库正常查询结果。', confirmLabel: '确认归档' }, () => executeBackendMutation('PlatformQuestionBanksController_archiveQuestions', { questionIds: [questionId] }, apply, { refresh: false })); return; } - if (action === 'archive-bank-node') { const node = bankNodeById(state.selectedBankNode); if (!node) return; confirmAction({ title: '归档内容节点', description: node.name, impact: '仅当节点没有启用的下级节点和未归档题目时才能归档。', confirmLabel: '确认归档' }, () => executeBackendMutation('PlatformQuestionBanksController_archiveNode', {}, () => { node.isActive = false; render(); showToast('内容节点已归档'); }, { refresh: false, pathParams: { nodeId: node.id } })); return; } - if (action === 'upload-question-image') { const input = document.querySelector('#bankQuestionImage'); const file = input?.files?.[0]; if (!file) { showToast('请先选择题目图片', 'error'); return; } if (!platformApi?.isEnabled()) { document.querySelector('#bankQuestionForm').elements.mediaUrl.value = `https://static.example.test/questions/${encodeURIComponent(file.name)}`; showToast('图片地址已填入'); return; } actionElement.disabled = true; platformApi.request('PlatformQuestionBanksController_signAssetUpload', { body: { contentNodeId: state.selectedBankNode || null, fileName: file.name, mimeType: file.type || 'application/octet-stream', fileSizeBytes: file.size, title: file.name, metadata: { usage: 'question' } } }).then(async signed => { await fetch(signed.upload.url, { method: signed.upload.method || 'PUT', headers: signed.upload.headers || {}, body: file }); const confirmed = await platformApi.request('PlatformQuestionBanksController_confirmAssetUpload', { body: { assetId: signed.item.id, mimeType: file.type, fileSizeBytes: file.size } }); document.querySelector('#bankQuestionForm').elements.mediaUrl.value = confirmed.item.cdnUrl || String(signed.upload.url).split('?')[0]; markDirty('page'); showToast('题目图片已上传并填入地址'); }).catch(error => showToast(backendErrorText(error, '题目图片上传失败'), 'error')).finally(() => { actionElement.disabled = false; }); return; } - if (action === 'preview-question') { const form = document.querySelector('#bankQuestionForm'); showToast(form?.elements.content.value?.trim() ? `题目预览:${form.elements.content.value.trim().slice(0, 80)}` : '请先填写题干', form?.elements.content.value?.trim() ? 'success' : 'error'); return; } - if (action === 'new-crm-config' || action === 'edit-crm-config') { if (!canWrite('platform:crm:write')) return; openModal('crmConfig', { crmId: actionElement.dataset.crmId || '' }); return; } - if (action === 'crm-rule-detail') { showToast('CRM 分配策略保存在接入配置的 assignmentConfig 中'); return; } - if (action === 'toggle-crm-config') { if (!canWrite('platform:crm:write')) return; const config = data.crmConfigs.find(item => item.id === actionElement.dataset.crmId); if (!config) return; const nextEnabled = !config.enabled; const apply = payload => { const next = payload ? platformApi.adapters.crmConfig(payload) : { ...config, enabled: nextEnabled, status: nextEnabled ? '正常' : '未启用' }; Object.assign(config, next); addAudit('crm.config.status', 'crm_config', config.id, tenantById(config.tenantId)?.name || config.id, '中', `CRM 接入${config.enabled ? '启用' : '停用'}。`); saveData(); render(); showToast('CRM 接入状态已更新'); }; if (platformApi?.isEnabled()) executeBackendMutation('PlatformAdminCrmController_upsertConfig', { ...config, enabled: nextEnabled }, apply); else apply(); return; } - if (action === 'retry-crm-lead') { if (!canWrite('platform:crm:write')) return; const lead = data.crmLeads.find(item => item.id === actionElement.dataset.leadId); if (!lead) return; const apply = payload => { const next = payload ? platformApi.adapters.crmLead(payload) : { ...lead, status: '重试中', attempts: lead.attempts + 1, lastError: '' }; Object.assign(lead, next); addAudit('crm.lead.retry', 'crm_lead', lead.id, lead.student, '中', `CRM 线索 ${lead.id} 已重试推送。`); saveData(); render(); showToast('线索已进入重试队列'); }; if (platformApi?.isEnabled()) executeBackendMutation('PlatformAdminCrmController_retryLead', lead, apply); else apply(); return; } - if (action === 'new-sms-channel' || action === 'edit-sms-channel') { if (!canWrite('platform:sms:write')) return; openModal('smsChannel', { smsId: actionElement.dataset.smsId || '' }); return; } - if (action === 'toggle-sms-channel') { if (!canWrite('platform:sms:write')) return; const channel = data.smsChannels.find(item => item.id === actionElement.dataset.smsId); if (!channel) return; const nextStatus = channel.enabled ? '未启用' : '正常'; const apply = payload => { const next = payload ? platformApi.adapters.smsChannel(payload) : { ...channel, enabled: nextStatus === '正常', status: nextStatus }; Object.assign(channel, next); addAudit('sms.channel.status', 'sms_channel', channel.id, tenantById(channel.tenantId)?.name || channel.id, '中', `短信渠道${channel.enabled ? '启用' : '停用'}。`); saveData(); render(); showToast('短信渠道状态已更新'); }; if (!platformApi?.isEnabled()) { apply(); return; } if (channel.enabled) { executeBackendMutation('PlatformAdminSmsController_disableChannel', {}, apply, { refresh: false, pathParams: { channelId: channel.id } }); return; } executeBackendMutation('PlatformAdminSmsController_upsertChannel', { ...channel, status: nextStatus }, apply); return; } - if (action === 'new-payment-app' || action === 'edit-payment-app') { if (!canWrite('platform:payment:write')) return; openModal('paymentApp', { paymentId: actionElement.dataset.paymentId || '' }); return; } - if (action === 'payment-rule-detail') { showToast('支付风控规则用于证书提醒、回调重试和人工确认保护'); return; } - if (action === 'toggle-payment-app') { if (!canWrite('platform:payment:write')) return; const paymentApp = data.paymentApps.find(item => item.id === actionElement.dataset.paymentId); if (!paymentApp) return; const disabling = paymentApp.status !== '未启用'; const nextStatus = disabling ? '未启用' : '正常'; const operationId = paymentApp.appScope === 'tenant' ? 'PlatformAdminTenantPaymentSettingsController_upsertApp' : 'PlatformAdminPaymentSettingsController_upsertApp'; const apply = payload => { const next = payload ? (paymentApp.appScope === 'tenant' ? platformApi.adapters.tenantPaymentApp(payload) : platformApi.adapters.platformPaymentApp(payload)) : { ...paymentApp, status: nextStatus }; Object.assign(paymentApp, next); addAudit('payment.app.status', 'payment_app', paymentApp.id, paymentApp.appName, '高', `支付应用${disabling ? '停用' : '启用'}。`); saveData(); render(); showToast('支付应用状态已更新'); }; if (platformApi?.isEnabled()) executeBackendMutation(operationId, { ...paymentApp, status: nextStatus }, apply); else apply(); return; } - if (action === 'new-staff') { if (requireDesktop('新建平台员工与授权')) return; openModal('staff', { roleId: actionElement.dataset.roleId || '' }); return; } - if (action === 'edit-staff') { if (requireDesktop('编辑平台员工与授权')) return; openModal('staff', { staffId: actionElement.dataset.staffId }); return; } - if (action === 'toggle-staff') { if (requireDesktop('变更平台员工状态')) return; if (!canWrite('platform:staff:status')) return; const person = data.staff.find(item => item.id === actionElement.dataset.staffId); if (!person) return; const disabling = person.status === '正常'; const isSuperAdmin = person.roleCodes?.includes('platform_super_admin'); if (disabling && isSuperAdmin && data.staff.filter(item => item.roleCodes?.includes('platform_super_admin') && item.status === '正常').length === 1) { showToast('不能禁用最后一名超级管理员', 'error'); return; } const apply = () => { person.status = disabling ? '已停用' : '正常'; addAudit('staff.status.update', 'staff', person.id, person.name, '高', `${disabling ? '停用并撤销会话' : '启用'}平台员工。`); saveData(); render(); showToast(`员工已${disabling ? '停用并撤销会话' : '启用'}`); }; const execute = () => platformApi?.isEnabled() ? executeBackendMutation('PlatformAdminOverviewController_updateStaffStatus', { userId: person.userId || person.id, status: disabling ? 'disabled' : 'active', reason: disabling ? '平台控制台停用员工' : '平台控制台启用员工' }, apply) : apply(); if (disabling) confirmAction({ title: '停用平台员工', description: `${person.name} · ${person.role}`, impact: '该员工的全部平台会话将立即撤销,后续无法登录平台端;租户端权限不在本域名内处理。', confirmLabel: '停用并撤销会话', confirmActionName: 'execute-staff-disable' }, execute); else execute(); return; } - if (action === 'select-permission-group') { const form = overlayRoot.querySelector('#staffForm'); const role = fieldValue(form, 'role'); const recommended = role === '平台财务' ? ['platform:billing:read', 'platform:billing:write', 'platform:billing:payment', 'platform:billing:dunning', 'platform:billing:notification', 'platform:usage:read', 'platform:usage:write', 'platform:payment:read', 'platform:payment:write'] : role === '安全审计' ? ['platform:audit:read', 'platform:audit:export', 'platform:audit:alert', 'platform:audit:notification'] : role === '题库运营' ? ['platform:dashboard:view', 'platform:question-bank:manage'] : role === '租户运营' ? ['platform:tenant:read', 'platform:tenant:write', 'platform:tenant:status', 'platform:tenant:billing_profile', 'platform:crm:read', 'platform:crm:write', 'platform:sms:read', 'platform:sms:write'] : Array.from(form.querySelectorAll('[name="permissions"]')).map(input => input.value); form.querySelectorAll('[name="permissions"]').forEach(input => { input.checked = recommended.includes(input.value); }); return; } - if (action === 'clear-staff-form') { const form = overlayRoot.querySelector('#staffForm'); if (!form) return; form.querySelectorAll('input:not([type="hidden"]):not([type="checkbox"])').forEach(input => { input.value = ''; }); form.querySelectorAll('input[type="checkbox"]').forEach(input => { input.checked = false; }); state.modalData.dirty = true; form.querySelector('[name="name"]')?.focus(); return; } - if (action === 'apply-staff-search') { render(); return; } - if (action === 'export-audit') { if (!hasPermission('platform:audit:export')) { showToast('缺少导出权限:platform:audit:export', 'error'); return; } const format = actionElement.dataset.format || 'csv'; if (platformApi?.isEnabled()) { platformApi.request('PlatformAdminAuditController_exportLogs', { query: { format, q: state.auditSearch || undefined, limit: 500 } }).then(payload => { const item = platformApi.downloadExport(payload); showToast(`审计文件已下载 · ${item.rowCount ?? item.rows ?? 0} 行 · ${item.sha256 || item.hash || 'hash 见响应'}`); }).catch(error => showToast(backendErrorText(error, '审计导出失败'), 'error')); return; } const task = addTask(`导出平台审计日志 ${format.toUpperCase()}`, '任务中心下载文件', taskItem => { taskItem.file = `platform-audit-${Date.now()}.${format}`; taskItem.hash = `sha256:${Math.random().toString(36).slice(2).padEnd(32, '0')}`; taskItem.rows = data.auditLogs.length; }); showToast(`导出任务 ${task.id} 已创建`); return; } - if (action === 'jump-related-alert') { state.alertStatus = 'all'; state.selectedAlert = data.alerts.find(alert => data.auditLogs.some(log => log.targetId === alert.targetId || log.targetId === alert.id))?.id || ''; navigate('alerts'); if (state.selectedAlert) openModal('alertDetail', { alertId: state.selectedAlert }); return; } - if (action === 'jump-audit-target') { const log = data.auditLogs.find(item => item.id === actionElement.dataset.auditId); closeModal(); if (log.targetType === 'tenant') { state.selectedTenant = log.targetId; navigate('tenantDetail'); } else if (log.targetType === 'invoice') { state.selectedInvoice = log.targetId; navigate('billing'); } else if (log.targetType === 'question_bank') navigate('bank'); else navigate('alerts'); return; } - if (action === 'transition-alert') { if (!canWrite('platform:audit:alert')) return; const alert = data.alerts.find(item => item.id === actionElement.dataset.alertId); const next = actionElement.dataset.nextStatus; if (!alert) return; if (!['open', 'acknowledged'].includes(alert.status)) { showToast('已结束告警禁止重新打开或再次处理', 'error'); return; } if (alert.status === 'open' && !['acknowledged', 'resolved', 'ignored'].includes(next)) return; if (alert.status === 'acknowledged' && !['resolved', 'ignored'].includes(next)) return; const note = document.querySelector('#alertNote')?.value.trim() || ''; const apply = () => { alert.status = next; alert.note = note; alert.updatedAt = '刚刚'; addAudit('audit.alert.status.update', 'audit_alert', alert.id, alert.title, '高', `告警状态更新为 ${alertStatusLabel(next)}${note ? `,备注:${note}` : ''}。`); clearDirty('modal'); saveData(); closeModal({ force: true }); render(); showToast(`告警已${alertStatusLabel(next)}`); }; if (platformApi?.isEnabled()) executeBackendMutation('PlatformAdminAuditController_updateAlert', { alertId: alert.id, status: next, note }, apply); else apply(); return; } - if (action === 'new-audit-channel') { if (requireDesktop('新建审计通知渠道')) return; openModal('auditChannel'); return; } - if (action === 'edit-audit-channel') { if (requireDesktop('编辑审计通知渠道')) return; openModal('auditChannel', { channelId: actionElement.dataset.channelId }); return; } - if (action === 'toggle-audit-channel') { if (requireDesktop('变更审计通知渠道状态')) return; if (!canWrite('platform:audit:notification')) return; const channel = data.auditChannels.find(item => item.id === actionElement.dataset.channelId); if (!channel) return; if (platformApi?.isEnabled() && channel.endpointRedacted) { openModal('auditChannel', { channelId: channel.id }); showToast('后端不回显完整 Webhook;请重新输入完整 HTTPS URL 后保存状态', 'error'); return; } const nextEnabled = !channel.enabled; const apply = () => { channel.enabled = nextEnabled; addAudit('audit.channel.status', 'notification_channel', channel.id, channel.name, '高', `审计告警渠道${channel.enabled ? '启用' : '停用'}。`); saveData(); render(); showToast('审计通知渠道状态已更新'); }; if (platformApi?.isEnabled()) executeBackendMutation('PlatformAdminAuditController_upsertChannel', { ...channel, enabled: nextEnabled }, apply); else apply(); return; } - if (action === 'retry-notification') { const eventId = actionElement.dataset.eventId; const dunningEvent = (data.dunningEvents || []).find(item => item.id === eventId); const notification = dunningEvent || (data.notificationEvents || []).find(item => item.id === eventId); if (!notification) return; if (platformApi?.isEnabled()) { if (!dunningEvent) { showToast('审计通知暂无后端重试接口', 'error'); return; } platformApi.request('PlatformAdminDunningEventsController_retryEvent', { body: { eventId, reason: '平台管理员手工重试' } }).then(payload => { Object.assign(dunningEvent, platformApi.adapters.event(payload, 'dunning')); closeModal({ force: true }); render(); showToast('催缴通知事件已重新标记待发送'); }).catch(error => showToast(backendErrorText(error, '催缴通知重试失败'), 'error')); return; } notification.status = '重试中'; notification.attempts += 1; notification.updatedAt = `${todayTime()} CST`; saveData(); render(); setTimeout(() => { notification.status = '成功'; notification.error = ''; saveData(); render(); showToast('通知重试成功'); }, 800); return; } - if (action === 'retry-task') { const task = data.tasks.find(item => item.id === actionElement.dataset.taskId); task.status = 'processing'; task.error = ''; task.updatedAt = todayTime(); saveData(); renderOverlay(); setTimeout(() => { task.status = 'completed'; task.updatedAt = todayTime(); saveData(); renderOverlay(); updateCounters(); showToast('任务重试完成'); }, 900); return; } -}); - -document.addEventListener('input', event => { - if (state.modal && event.target.closest('#overlayRoot') && event.target.matches('input,select,textarea')) markDirty('modal'); - if (event.target.closest('#mainView form')) markDirty('page'); - if (event.target.id === 'tenantSearch') { state.tenantSearch = event.target.value; clearTimeout(state.searchTimer); state.searchTimer = setTimeout(render, 180); } - if (event.target.id === 'invoiceSearch') state.invoiceSearch = event.target.value; - if (event.target.id === 'bankSearch') state.bankSearch = event.target.value; - if (event.target.id === 'staffSearch') { state.staffSearch = event.target.value; clearTimeout(state.staffTimer); state.staffTimer = setTimeout(render, 180); } - if (event.target.id === 'auditSearch') { state.auditSearch = event.target.value; clearTimeout(state.auditTimer); state.auditTimer = setTimeout(render, 180); } - if (event.target.id === 'globalSearch') state.globalSearch = event.target.value; - if (['tenantSearch', 'invoiceSearch', 'bankSearch', 'staffSearch', 'auditSearch'].includes(event.target.id)) syncNavigationState(); -}); -document.addEventListener('change', event => { - if (state.modal && event.target.closest('#overlayRoot') && event.target.matches('input,select,textarea')) markDirty('modal'); - if (event.target.closest('#mainView form')) markDirty('page'); - if (event.target === roleSelect) { state.role = event.target.value; state.scenario = 'normal'; if (!hasPermission(pageMeta[state.view].permission)) state.view = 'overview'; render(); showToast(`已切换为${roleDefinitions[state.role].label}`); } - if (event.target === scenarioSelect) { state.scenario = event.target.value; render(); } - if (event.target === responseSelect) { state.response = event.target.value; showToast('下一次 Mock 写请求结果已设置'); } - if (event.target.id === 'tenantPlanFilter') { state.tenantPlan = event.target.value; syncNavigationState(); render(); } - if (event.target.id === 'invoiceStatusFilter') { state.invoiceStatus = event.target.value; syncNavigationState(); } - if (event.target.id === 'usagePeriodFilter') { state.usagePeriod = event.target.value; syncNavigationState(); render(); } - if (event.target.id === 'auditRangeFilter') { state.auditRange = event.target.value; syncNavigationState(); render(); } - if (event.target.id === 'bankSelector') { state.selectedBank = event.target.value; state.selectedBankNode = ''; state.bankQuestionPage = 1; syncNavigationState(); render(); loadBankWorkspace(); } - if (event.target.id === 'bankStructuredFile') { const file = event.target.files?.[0]; if (!file) return; file.text().then(text => { const target = document.querySelector('#bankStructuredPayload'); if (target) { target.value = text; markDirty('page'); } }).catch(() => showToast('无法读取所选 JSON 文件', 'error')); } -}); -menuButton.addEventListener('click', toggleMobileMenu); -document.querySelector('#sidebarBackdrop').addEventListener('click', closeMobileMenu); -document.addEventListener('keydown', event => { - if ((event.metaKey || event.ctrlKey) && event.key.toLowerCase() === 'k') { event.preventDefault(); document.querySelector('#globalSearch').focus(); } - if (event.key === 'Enter' && event.target.id === 'globalSearch') { - event.preventDefault(); - const query = event.target.value.trim().toLowerCase(); - if (!query) { showToast('请输入租户、账单、告警或审计关键词', 'error'); return; } - const tenant = data.tenants.find(item => [item.name, item.slug, item.legal, item.host].some(value => value.toLowerCase().includes(query))); - if (tenant) { state.selectedTenant = tenant.id; navigate('tenantDetail'); showToast(`已定位租户:${tenant.name}`); return; } - const invoice = data.invoices.find(item => [item.id, item.type, item.period, item.note].some(value => String(value).toLowerCase().includes(query))); - if (invoice) { state.selectedTenant = invoice.tenantId; state.selectedInvoice = invoice.id; navigate('billing'); showToast(`已定位账单:${invoice.id}`); return; } - const alert = data.alerts.find(item => [item.id, item.title, item.summary].some(value => value.toLowerCase().includes(query))); - if (alert) { state.selectedAlert = alert.id; navigate('alerts'); openModal('alertDetail', { alertId: alert.id }); return; } - const audit = data.auditLogs.find(item => [item.id, item.actor, item.action, item.target, item.details].some(value => value.toLowerCase().includes(query))); - if (audit) { navigate('audit'); openModal('auditDetail', { auditId: audit.id }); return; } - showToast('没有找到匹配的租户、账单、告警或审计事件', 'error'); - } - if (event.key === 'Tab' && state.modal) { - const modal = overlayRoot.querySelector('.modal'); - const focusable = modal ? Array.from(modal.querySelectorAll('button:not([disabled]),input:not([disabled]):not([type="hidden"]),select:not([disabled]),textarea:not([disabled]),[tabindex]:not([tabindex="-1"])')).filter(element => element.offsetParent !== null) : []; - if (focusable.length) { - const first = focusable[0]; const last = focusable[focusable.length - 1]; - if (event.shiftKey && document.activeElement === first) { event.preventDefault(); last.focus(); } - else if (!event.shiftKey && document.activeElement === last) { event.preventDefault(); first.focus(); } - } - } - if (event.key === 'Escape') { if (state.modal) closeModal(); else if (app.classList.contains('menu-open')) closeMobileMenu(); else if (pageMeta[state.view]?.level > 1) navigateBack(); } -}); -document.addEventListener('click', event => { - const choice = event.target.closest('[data-leave-choice]')?.dataset.leaveChoice; - if (!choice) return; - event.preventDefault(); event.stopImmediatePropagation(); - if (choice === 'stay') { pendingLeave = null; closeLeaveGuard(); return; } - const leave = pendingLeave; pendingLeave = null; clearDirty(leave?.scope || ''); closeLeaveGuard(); leave?.execute?.(); -}, true); -window.addEventListener('beforeunload', event => { if (!hasUnsavedChanges()) return; event.preventDefault(); event.returnValue = ''; }); -window.addEventListener('DOMContentLoaded', async () => { - if (platformApi?.isEnabled()) { - const authenticated = await window.GongxuePlatformAuth?.requireSession(); - if (!authenticated) return; - document.documentElement.dataset.platformMode = 'api'; - } - setupPrototypeControls(); - if (platformApi?.isEnabled()) document.querySelector('.prototype-controls')?.setAttribute('hidden', ''); - render(); - const rootSnapshot = navigationSnapshot(); - history.replaceState({ [HISTORY_APP_KEY]: true, rootGuard: true, sequence: historySequence, snapshot: rootSnapshot }, '', location.href); - historySequence += 1; - history.pushState({ [HISTORY_APP_KEY]: true, sequence: historySequence, snapshot: rootSnapshot }, '', location.href); - if (platformApi?.isEnabled()) hydrateFromBackend({ silent: true }); -}); diff --git a/Tiku.Api/wwwroot/platform-admin/index.html b/Tiku.Api/wwwroot/platform-admin/index.html deleted file mode 100644 index 497d823..0000000 --- a/Tiku.Api/wwwroot/platform-admin/index.html +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - 恭学题库 SaaS · 平台管理 - - - - - - - - - - - -
- -
-
PLATFORM / PROD平台经营工作台
所有系统正常
-
-
-
- -
-
- - diff --git a/Tiku.Api/wwwroot/platform-admin/platform-api.js b/Tiku.Api/wwwroot/platform-admin/platform-api.js deleted file mode 100644 index 991bdf3..0000000 --- a/Tiku.Api/wwwroot/platform-admin/platform-api.js +++ /dev/null @@ -1,1318 +0,0 @@ -(() => { - const defaults = { - mode: 'mock', - apiBaseUrl: '', - fallbackToMock: true, - timeoutMs: 10000, - getAccessToken: null, - }; - const runtime = { ...defaults, ...(window.GONGXUE_PLATFORM_RUNTIME_CONFIG || {}) }; - const operationCatalog = Object.fromEntries( - (window.GONGXUE_PLATFORM_SPEC?.operations || []).map(operation => [operation.operationId, operation]), - ); - const trace = []; - - class PlatformApiError extends Error { - constructor(message, options = {}) { - super(message); - this.name = 'PlatformApiError'; - this.status = Number(options.status || 0); - this.code = options.code || 'PLATFORM_API_ERROR'; - this.requestId = options.requestId || ''; - this.operationId = options.operationId || ''; - this.details = options.details; - } - } - - function normalizeBaseUrl(value) { - return String(value || '').trim().replace(/\/+$/, ''); - } - - function isEnabled() { - return runtime.mode === 'api' || (runtime.mode === 'auto' && Boolean(normalizeBaseUrl(runtime.apiBaseUrl))); - } - - function publicConfig() { - return { - mode: runtime.mode, - apiBaseUrl: normalizeBaseUrl(runtime.apiBaseUrl), - fallbackToMock: runtime.fallbackToMock !== false, - timeoutMs: Number(runtime.timeoutMs) || defaults.timeoutMs, - configured: isEnabled(), - }; - } - - async function accessToken() { - const provider = typeof runtime.getAccessToken === 'function' - ? runtime.getAccessToken - : typeof window.GONGXUE_PLATFORM_ACCESS_TOKEN_PROVIDER === 'function' - ? window.GONGXUE_PLATFORM_ACCESS_TOKEN_PROVIDER - : null; - const token = provider ? await provider() : ''; - return String(token || '').trim(); - } - - function buildUrl(path, query = {}, pathParams = {}) { - const baseUrl = normalizeBaseUrl(runtime.apiBaseUrl); - const resolvedPath = Object.entries(pathParams).reduce((value, [key, replacement]) => value.replace(`{${key}}`, encodeURIComponent(String(replacement))), path); - const url = new URL(`${baseUrl}${resolvedPath.startsWith('/') ? resolvedPath : `/${resolvedPath}`}`, window.location.href); - Object.entries(query).forEach(([key, value]) => { - if (value === undefined || value === null || value === '') return; - url.searchParams.set(key, Array.isArray(value) ? value.join(',') : String(value)); - }); - return url.toString(); - } - - function responseRequestId(payload, response) { - return String( - payload?.meta?.requestId - || payload?.requestId - || payload?.traceId - || payload?.extensions?.traceId - || response?.headers?.get?.('x-request-id') - || '', - ); - } - - function responseErrorCode(payload) { - return String(payload?.code || payload?.extensions?.code || payload?.errorCode || 'PLATFORM_API_REQUEST_FAILED'); - } - - function responseErrorMessage(payload, status) { - return String(payload?.message || payload?.title || payload?.error || `请求失败(HTTP ${status})`); - } - - async function request(operationId, options = {}) { - const operation = operationCatalog[operationId]; - if (!operation) { - throw new PlatformApiError(`未知平台接口:${operationId}`, { - code: 'PLATFORM_OPERATION_UNKNOWN', - operationId, - }); - } - if (!isEnabled()) { - throw new PlatformApiError('平台 API 未启用', { - code: 'PLATFORM_API_DISABLED', - operationId, - }); - } - const token = await accessToken(); - if (!token) { - throw new PlatformApiError('缺少平台管理员 access token', { - status: 401, - code: 'PLATFORM_ACCESS_TOKEN_MISSING', - operationId, - }); - } - const extraHeaders = Object.fromEntries(Object.entries(options.headers || {}).map(([key, value]) => [key, String(value)])); - const forbiddenHeader = Object.keys(extraHeaders).find((key) => { - const normalized = key.toLowerCase(); - return ['authorization', 'x-user-id', 'x-platform-admin-key'].includes(normalized) - || normalized.startsWith('x-tenant-'); - }); - if (forbiddenHeader) { - throw new PlatformApiError(`禁止页面覆盖身份头:${forbiddenHeader}`, { - code: 'PLATFORM_IDENTITY_HEADER_FORBIDDEN', - operationId, - }); - } - - const controller = new AbortController(); - const timeout = setTimeout(() => controller.abort(), Number(runtime.timeoutMs) || defaults.timeoutMs); - const startedAt = Date.now(); - if (options.signal) { - if (options.signal.aborted) controller.abort(); - else options.signal.addEventListener('abort', () => controller.abort(), { once: true }); - } - try { - const response = await fetch(buildUrl(operation.path, options.query, options.pathParams), { - method: operation.method, - headers: { - ...extraHeaders, - Accept: 'application/json', - Authorization: `Bearer ${token}`, - ...(operation.method === 'GET' ? {} : { 'Content-Type': 'application/json' }), - }, - body: operation.method === 'GET' || options.body === undefined - ? undefined - : JSON.stringify(options.body), - credentials: 'omit', - signal: controller.signal, - }); - const text = await response.text(); - let payload = {}; - if (text) { - try { - payload = JSON.parse(text); - } catch { - payload = { error: text.slice(0, 500) }; - } - } - const requestId = responseRequestId(payload, response); - trace.push({ - operationId, - method: operation.method, - path: operation.path, - status: response.status, - requestId, - durationMs: Date.now() - startedAt, - at: new Date().toISOString(), - }); - if (trace.length > 120) trace.splice(0, trace.length - 120); - if (!response.ok) { - throw new PlatformApiError( - responseErrorMessage(payload, response.status), - { - status: response.status, - code: responseErrorCode(payload), - requestId, - operationId, - details: payload, - }, - ); - } - return payload; - } catch (error) { - if (error instanceof PlatformApiError) throw error; - const aborted = error?.name === 'AbortError'; - throw new PlatformApiError(aborted ? '平台接口请求超时' : (error?.message || '平台接口请求失败'), { - code: aborted ? 'PLATFORM_API_TIMEOUT' : 'PLATFORM_API_NETWORK_ERROR', - operationId, - details: error, - }); - } finally { - clearTimeout(timeout); - } - } - - const dictionaries = { - tenantStatusToApi: { 待配置: 'draft', 试用: 'active', 正常: 'active', 暂停: 'suspended', 已归档: 'archived' }, - tenantStatusFromApi: { draft: '待配置', active: '正常', suspended: '暂停', archived: '已归档' }, - billingStatusToApi: { 试用: 'trial', 正常: 'active', 待付款: 'active', 逾期: 'past_due', 暂停: 'suspended', 已取消: 'cancelled' }, - billingStatusFromApi: { trial: '试用', active: '正常', past_due: '逾期', suspended: '暂停', cancelled: '已取消' }, - subscriptionStatusToApi: { 试用中: 'trial', 活跃: 'active', 暂停: 'suspended', 已取消: 'cancelled', 已到期: 'expired' }, - subscriptionStatusFromApi: { trial: '试用中', active: '活跃', suspended: '暂停', cancelled: '已取消', expired: '已到期' }, - invoiceStatusFromApi: { draft: '草稿', issued: '待付款', paid: '已支付', void: '已作废', overdue: '已逾期' }, - invoiceTypeToApi: { 订阅服务费: 'subscription', 用量超额费: 'usage', 人工调整: 'adjustment', 首期服务费: 'manual' }, - invoiceTypeFromApi: { subscription: '订阅服务费', usage: '用量超额费', usage_overage: '用量超额费', manual: '人工账单', adjustment: '人工调整' }, - severityToApi: { 低: 'low', 中: 'medium', 高: 'high', 严重: 'critical' }, - severityFromApi: { low: '低', medium: '中', high: '高', critical: '严重' }, - providerToApi: { Webhook: 'generic', SMTP: 'generic', 邮件: 'generic', 短信: 'generic', 钉钉: 'dingtalk', 飞书: 'feishu', 企微: 'wecom' }, - providerFromApi: { generic: 'Webhook', dingtalk: '钉钉', feishu: '飞书', wecom: '企微' }, - eventStatusFromApi: { pending: '待处理', processing: '发送中', sent: '成功', retrying: '重试中', failed: '失败', discarded: '已丢弃' }, - crmStatusFromApi: { pending: '待推送', processing: '推送中', retrying: '重试中', sent: '已推送', failed: '推送失败', discarded: '已忽略' }, - providerStatusFromApi: { active: '正常', disabled: '未启用', testing: '测试中' }, - providerStatusToApi: { 正常: 'active', 未启用: 'disabled', 测试中: 'testing' }, - smsTemplateStatusFromApi: { active: '正常', disabled: '未启用' }, - smsAuditStatusFromApi: { draft: '草稿', pending_review: '审核中', approved: '已通过', rejected: '已拒绝' }, - paymentStatusFromApi: { active: '正常', disabled: '未启用', testing: '测试中' }, - paymentStatusToApi: { 正常: 'active', 未启用: 'disabled', 测试中: 'testing' }, - }; - - const platformPermissionLabels = { - 'platform:dashboard:view': '查看平台经营概览', - 'platform:tenant:manage': '管理平台租户', - 'platform:staff:manage': '管理平台员工', - 'platform:role:manage': '管理平台角色与权限', - 'platform:question-bank:manage': '运营平台公共题库', - 'platform:audit:view': '查看平台审计与告警', - 'platform:billing:notification': '管理账务催缴通知', - 'platform:saas-catalog:manage': '管理 SaaS 商品与版本', - 'platform:saas-billing:manage': '管理 SaaS 订单与账务', - 'platform:crm:read': '查看租户 CRM 配置', - 'platform:crm:write': '管理租户 CRM 配置', - 'platform:sms:read': '查看租户短信服务', - 'platform:sms:write': '管理租户短信服务', - 'platform:payment:read': '查看平台支付设置', - 'platform:payment:write': '管理平台支付设置', - }; - - const platformRoleLabels = { - platform_super_admin: { name: '超级管理员', description: '拥有全部平台管理权限' }, - }; - - function mapValue(map, value, fallback = value) { - return Object.prototype.hasOwnProperty.call(map, value) ? map[value] : fallback; - } - - function centsToYuan(value) { - const number = Number(value || 0); - return Number.isFinite(number) ? number / 100 : 0; - } - - function yuanToCents(value) { - const number = Number(value || 0); - return Number.isFinite(number) ? Math.round(number * 100) : 0; - } - - function dateOnly(value) { - return value ? String(value).slice(0, 10) : ''; - } - - function monthOnly(value) { - return value ? String(value).slice(0, 7) : ''; - } - - function dateTime(value) { - if (!value) return '-'; - const parsed = new Date(value); - if (Number.isNaN(parsed.getTime())) return String(value); - return new Intl.DateTimeFormat('zh-CN', { - timeZone: 'Asia/Shanghai', - year: 'numeric', - month: '2-digit', - day: '2-digit', - hour: '2-digit', - minute: '2-digit', - second: '2-digit', - hour12: false, - }).format(parsed).replaceAll('/', '-'); - } - - function isoStartOfDay(value) { - if (!value) return undefined; - return `${String(value).slice(0, 10)}T00:00:00+08:00`; - } - - function splitList(value) { - if (Array.isArray(value)) return value.map(String).map(item => item.trim()).filter(Boolean); - return String(value || '').split(/[、,,]/).map(item => item.trim()).filter(Boolean); - } - - function periodBounds(period) { - const match = String(period || '').match(/^(\d{4})-(\d{2})$/); - if (!match) return { periodStart: '', periodEnd: '' }; - const year = Number(match[1]); - const month = Number(match[2]); - const lastDay = new Date(Date.UTC(year, month, 0)).getUTCDate(); - return { - periodStart: `${match[1]}-${match[2]}-01`, - periodEnd: `${match[1]}-${match[2]}-${String(lastDay).padStart(2, '0')}`, - }; - } - - function invoicePeriodBounds(label) { - const match = String(label || '').match(/^(\d{4})年(\d{1,2})月$/); - return match ? periodBounds(`${match[1]}-${String(match[2]).padStart(2, '0')}`) : {}; - } - - const bodyBuilders = { - PlatformSaasController_upsertFeature(input) { - return { id: input.id || undefined, code: input.code, name: input.name, category: input.category, description: input.description || undefined, referencePriceCents: yuanToCents(input.referencePrice), currency: 'CNY', status: input.status || 'active', sortOrder: Number(input.sortOrder || 100) }; - }, - PlatformSaasController_upsertOffering(input) { - return { id: input.id || undefined, code: input.code, name: input.name, type: input.type || 'base_plan', status: input.status || 'active', description: input.description || undefined, sortOrder: Number(input.sortOrder || 100) }; - }, - PlatformSaasController_upsertFeatureLimit(input) { - return { id: input.id || undefined, metricCode: input.metricCode, featureCode: input.featureCode, name: input.name, unit: input.unit || 'count', kind: input.kind || 'current', warningPercent: Number(input.warningPercent || 80), isHardLimit: input.isHardLimit !== false }; - }, - PlatformSaasController_upsertVersion(input) { - return { id: input.id || undefined, offeringId: input.offeringId, billingCycle: input.billingCycle || 'yearly', originalAmountCents: yuanToCents(input.originalAmount), amountCents: yuanToCents(input.amount), currency: 'CNY', effectiveAt: input.effectiveAt ? new Date(input.effectiveAt).toISOString() : undefined, featureCodes: splitList(input.featureCodes), limits: {}, metadata: {} }; - }, - PlatformBackofficeController_upsertRole(input) { - return { id: input.id || undefined, code: input.code, name: input.name, status: input.status || 'active', description: input.description || undefined }; - }, - PlatformBackofficeController_replaceRoleBindings(input) { - return { permissionCodes: input.permissionCodes || [], menuCodes: input.menuCodes || [] }; - }, - PlatformSaasController_upsertTenantFeatureOverride(input) { - return { tenantId: input.tenantId, featureCode: input.featureCode, mode: input.mode, expiresAt: input.expiresAt ? new Date(input.expiresAt).toISOString() : undefined, reason: input.reason }; - }, - PlatformAdminTenantsController_create(input) { - return { - slug: input.slug, - name: input.name, - legalName: input.legalName || undefined, - status: mapValue(dictionaries.tenantStatusToApi, input.status, input.status), - billingStatus: mapValue(dictionaries.billingStatusToApi, input.billingStatus, input.billingStatus), - metadata: input.metadata || {}, - ownerEmail: input.ownerEmail || undefined, - ownerPhone: input.ownerPhone || undefined, - ownerName: input.ownerName, - temporaryPassword: input.temporaryPassword, - }; - }, - PlatformAdminTenantsController_status(input) { - return { - tenantId: input.tenantId, - status: mapValue(dictionaries.tenantStatusToApi, input.status, input.status), - billingStatus: mapValue(dictionaries.billingStatusToApi, input.billingStatus, input.billingStatus), - reason: input.reason, - }; - }, - PlatformAdminTenantsController_billingProfile(input) { - return { - tenantId: input.tenantId, - billingName: input.billingName || undefined, - taxId: input.taxId || undefined, - contactName: input.contactName || undefined, - contactPhone: input.phone || input.contactPhone || undefined, - contactEmail: input.email || input.contactEmail || undefined, - billingAddress: input.billingAddress || undefined, - invoiceTitle: input.invoiceTitle || undefined, - invoiceType: ({ 增值税专用发票: 'special_vat', 增值税普通发票: 'normal_vat', 不开票: 'none' })[input.type || input.invoiceType] || input.invoiceType || 'none', - bankName: input.bankName || undefined, - bankAccountMasked: input.bankAccountMasked || undefined, - }; - }, - PlatformAdminBillingController_createSubscription(input) { - return { - tenantId: input.tenantId, - planCode: input.planCode, - status: mapValue(dictionaries.subscriptionStatusToApi, input.status, input.status || 'active'), - billingCycle: ({ 年度: 'yearly', 月度: 'monthly', 试用: 'trial' })[input.cycle] || input.billingCycle, - amountCents: yuanToCents(input.amount), - startsAt: isoStartOfDay(input.start || input.startsAt), - expiresAt: isoStartOfDay(input.expires || input.expiresAt), - metadata: { autoRenew: Boolean(input.autoRenew), source: 'static-platform-console' }, - }; - }, - PlatformAdminBillingController_createInvoice(input) { - const bounds = invoicePeriodBounds(input.period); - return { - tenantId: input.tenantId, - invoiceType: mapValue(dictionaries.invoiceTypeToApi, input.type, input.invoiceType || 'manual'), - status: input.status || 'draft', - dueDate: input.due || input.dueDate, - billingPeriodStart: input.billingPeriodStart || bounds.periodStart, - billingPeriodEnd: input.billingPeriodEnd || bounds.periodEnd, - items: input.items || [{ - itemType: mapValue(dictionaries.invoiceTypeToApi, input.type, 'manual'), - description: input.note || input.type || '平台手工账单', - quantity: 1, - unitAmountCents: yuanToCents(input.amount), - metadata: { periodLabel: input.period || '' }, - }], - note: input.note || undefined, - }; - }, - PlatformAdminBillingController_fromSubscription(input) { - return { - tenantId: input.tenantId, - subscriptionId: input.subscriptionId || undefined, - status: input.status || 'issued', - dueDate: input.dueDate || undefined, - note: input.note || undefined, - }; - }, - PlatformAdminBillingController_fromSubscriptionsBatch(input) { - return { - tenantIds: input.tenantIds || undefined, - subscriptionIds: input.subscriptionIds || undefined, - daysAhead: input.daysAhead ?? 45, - status: input.status || 'issued', - dueDate: input.dueDate || undefined, - note: input.note || undefined, - dryRun: Boolean(input.dryRun), - }; - }, - PlatformAdminBillingController_fromUsage(input) { - const bounds = input.periodStart && input.periodEnd ? input : { ...input, ...periodBounds(input.period) }; - return { - tenantIds: bounds.tenantIds || undefined, - periodStart: bounds.periodStart, - periodEnd: bounds.periodEnd, - dueDate: bounds.dueDate || undefined, - note: bounds.note || undefined, - status: bounds.status || 'issued', - dryRun: Boolean(bounds.dryRun), - }; - }, - PlatformAdminBillingController_processOverdue(input) { - return { dryRun: Boolean(input.dryRun), channel: input.channel || 'internal', limit: Number(input.limit || 100) }; - }, - PlatformAdminBillingController_confirmPayment(input) { - return { - paymentId: input.paymentId || input.backendPaymentId || input.invoiceId, - providerTradeNo: input.tradeNo || input.providerTradeNo || undefined, - paidAt: input.paidAt ? new Date(input.paidAt).toISOString() : undefined, - reason: input.reason || input.paymentNo || 'platform_manual_payment_confirm', - }; - }, - PlatformAdminBillingController_recordUsage(input) { - const bounds = input.periodStart && input.periodEnd ? input : { ...input, ...periodBounds(input.period) }; - return { - tenantId: bounds.tenantId, - metricKey: bounds.metricKey, - metricValue: Number(bounds.metricValue || 0), - periodStart: bounds.periodStart, - periodEnd: bounds.periodEnd, - metadata: { source: 'platform_console_manual' }, - }; - }, - PlatformAdminOverviewController_upsertStaff(input) { - return { - userId: input.userId || undefined, - email: input.email || undefined, - phone: input.phone || undefined, - name: input.name, - status: input.status === '已停用' ? 'disabled' : 'active', - roleIds: input.roleIds || [], - }; - }, - PlatformAdminOverviewController_updateStaffStatus(input) { - return { - userId: input.userId || input.staffId, - status: input.status === '正常' || input.status === 'active' ? 'active' : 'disabled', - reason: input.reason || undefined, - }; - }, - PlatformAdminAuditController_updateAlert(input) { - return { - alertId: input.alertId, - status: input.status, - resolutionNote: input.resolutionNote || input.note || undefined, - }; - }, - PlatformAdminCrmController_upsertConfig(input) { - return { - id: input.backendId || input.id || undefined, - tenantId: input.tenantId, - enabled: input.enabled !== false && input.status !== '未启用', - url: input.endpoint || input.url || undefined, - secretRef: input.secretRef || undefined, - formName: input.formName || input.pool || undefined, - examType: input.examType || input.subject || undefined, - timeoutSeconds: Number(input.timeout || input.timeoutSeconds || 10), - delaySeconds: Number(input.delaySeconds || 0), - assignmentMode: input.assignmentMode || 'round_robin', - assignmentPool: splitList(input.pool), - assignmentConfig: { retry: Number(input.retry || 3), source: 'platform_console' }, - }; - }, - PlatformAdminCrmController_retryLead(input) { - return { queueId: input.backendId || input.queueId || input.id, note: input.note || 'platform_console_retry' }; - }, - PlatformAdminSmsController_upsertChannel(input) { - return { - id: input.backendId || input.id || undefined, - tenantId: input.tenantId, - provider: input.provider || 'generic', - name: input.name || `${input.provider || 'generic'} 短信渠道`, - signature: input.signature || '', - scene: input.scene || 'login', - status: mapValue(dictionaries.providerStatusToApi, input.status, input.status || 'active'), - secretRef: input.secretRef || undefined, - priority: Number(input.priority || 100), - monthlyQuota: Number(input.quota || input.monthlyQuota || 0), - configPublic: input.configPublic || { redacted: true }, - metadata: { source: 'platform_console' }, - }; - }, - PlatformAdminSmsController_upsertTemplate(input) { - return { - id: input.backendId || input.id || undefined, - tenantId: input.tenantId, - channelId: input.channelId, - code: input.code, - name: input.name, - type: input.type || 'notification', - auditStatus: input.auditStatus || 'draft', - status: input.status || 'active', - providerTemplateCode: input.providerTemplateCode || undefined, - content: input.content || '', - remark: input.remark || undefined, - metadata: { source: 'platform_console' }, - }; - }, - PlatformAdminPaymentSettingsController_upsertApp(input) { - return { - id: input.backendId || input.id || undefined, - appCode: input.appCode || input.code || String(input.appName || '').toLowerCase().replaceAll(' ', '_'), - appName: input.appName, - status: mapValue(dictionaries.paymentStatusToApi, input.status, input.status || 'active'), - settlementMode: input.settlement || input.settlementMode || 'PlatformCollect', - description: input.description || undefined, - metadata: { source: 'platform_console' }, - }; - }, - PlatformAdminPaymentSettingsController_upsertChannel(input) { - return { - id: input.backendId || input.id || undefined, - appId: input.appId, - provider: input.provider || 'manual', - mode: input.mode || 'PlatformCollect', - status: mapValue(dictionaries.paymentStatusToApi, input.status, input.status || 'active'), - displayName: input.displayName || input.appName || input.provider || '支付渠道', - secretRef: input.secretRef || undefined, - callbackPath: input.callbackPath || undefined, - priority: Number(input.priority || 100), - configPublic: input.configPublic || { redacted: true }, - metadata: { source: 'platform_console' }, - }; - }, - PlatformAdminTenantPaymentSettingsController_upsertApp(input) { - return { - tenantId: input.tenantId, - provider: input.provider || 'manual', - status: mapValue(dictionaries.providerStatusToApi, input.status, input.status || 'active'), - displayName: input.appName || input.displayName || undefined, - secretRef: input.secretRef || undefined, - priority: Number(input.priority || 100), - configPublic: input.configPublic || { mode: input.mode || 'TenantCollect', redacted: true }, - metadata: { source: 'platform_console' }, - }; - }, - PlatformQuestionBanksController_upsertBank(input) { - return { - id: input.id || undefined, - name: input.name, - metadata: input.metadata || {}, - }; - }, - PlatformQuestionBanksController_upsertNode(input) { - return { - id: input.id || undefined, - questionBankId: input.questionBankId, - parentId: input.parentId || undefined, - nodeKey: input.nodeKey || undefined, - name: input.name, - nodeType: input.nodeType, - sortOrder: Number(input.sortOrder || 0), - isSelectable: input.isSelectable !== false, - metadata: input.metadata || {}, - }; - }, - PlatformQuestionBanksController_batchCreateNodes(input) { - return { - questionBankId: input.questionBankId, - parentId: input.parentId || undefined, - nodeType: input.nodeType, - names: Array.isArray(input.names) ? input.names : splitList(input.names), - }; - }, - PlatformQuestionBanksController_upsertQuestion(input) { - return { - id: input.id || undefined, - questionBankId: input.questionBankId, - contentNodeId: input.contentNodeId, - legacyId: input.legacyId || undefined, - type: input.type, - typeLabel: input.typeLabel || undefined, - difficulty: input.difficulty == null ? undefined : Number(input.difficulty), - tags: input.tags || [], - content: input.content, - options: input.options || [], - correctOptionIndex: input.correctOptionIndex ?? undefined, - correctOptionIndices: input.correctOptionIndices || [], - answerText: input.answerText || undefined, - explanation: input.explanation || undefined, - subQuestions: input.subQuestions || [], - codeLang: input.codeLang || undefined, - codeTemplate: input.codeTemplate || undefined, - mediaUrl: input.mediaUrl || undefined, - status: input.status || 'published', - examMarkers: input.examMarkers || {}, - sourceHash: input.sourceHash || undefined, - }; - }, - PlatformQuestionBanksController_archiveQuestions(input) { - return { questionIds: input.questionIds || [] }; - }, - PlatformQuestionBanksController_previewImport(input) { - return { - questionBankId: input.questionBankId, - contentNodeId: input.contentNodeId || undefined, - format: input.format, - sourceName: input.sourceName || undefined, - payload: input.payload, - }; - }, - PlatformQuestionBanksController_executeImport(input) { - return bodyBuilders.PlatformQuestionBanksController_previewImport(input); - }, - }; - - function notificationBody(input) { - const maxAttempts = Number(input.maxAttempts || input.retry || 3); - return { - id: input.id || undefined, - channelCode: input.code || input.channelCode, - name: input.name, - enabled: input.enabled !== false, - provider: mapValue(dictionaries.providerToApi, input.provider, input.provider || 'generic'), - webhookUrl: input.endpoint || input.webhookUrl, - secret: input.secret || undefined, - secretRef: input.secretRef || undefined, - minSeverity: mapValue(dictionaries.severityToApi, input.minSeverity, input.minSeverity || 'medium'), - statusFilter: splitList(input.statusFilter || 'open,acknowledged'), - timeoutSec: Number(input.timeout || input.timeoutSec || 10), - maxAttempts, - metadata: { ...(input.metadata || {}), maxAttempts }, - }; - } - bodyBuilders.PlatformAdminAuditController_upsertChannel = notificationBody; - bodyBuilders.PlatformAdminDunningChannelsController_upsertChannel = input => ({ - channelId: input.id || input.channelId || undefined, - channelCode: input.code || input.channelCode, - name: input.name, - description: input.description || undefined, - enabled: input.enabled !== false, - provider: mapValue(dictionaries.providerToApi, input.provider, input.provider || 'generic'), - webhookUrl: input.endpoint || input.webhookUrl, - secretRef: input.secretRef || undefined, - minReminderLevel: Number(input.minReminderLevel || 1), - reminderTypes: input.reminderTypes || ['overdue', 'final_notice'], - reminderChannels: input.reminderChannels || ['internal'], - tenantIds: input.tenantIds || [], - timeoutSeconds: Number(input.timeout || input.timeoutSeconds || 10), - metadata: { ...(input.metadata || {}), secretRedacted: Boolean(input.secretRef) }, - }); - - function buildBody(operationId, input = {}) { - const builder = bodyBuilders[operationId]; - return builder ? builder(input) : input; - } - - function jsonSummary(value) { - if (!value) return ''; - if (typeof value === 'string') return value; - try { - return JSON.stringify(value); - } catch { - return String(value); - } - } - - function safeEndpoint(item) { - if (!item?.webhook) return ''; - const protocol = item.webhook.protocol ? `${item.webhook.protocol}://` : ''; - return `${protocol}${item.webhook.host || ''}${item.webhook.pathname || ''}`; - } - - function currentById(items, id) { - return (items || []).find(item => item.id === id) || {}; - } - - function itemOf(payload) { - return payload?.item || payload || {}; - } - - function itemsOf(payload, key = '') { - if (Array.isArray(payload)) return payload; - if (Array.isArray(payload?.items)) return payload.items; - if (key && Array.isArray(payload?.[key])) return payload[key]; - return []; - } - - function lowerEnum(value) { - return String(value || '').replace(/([a-z0-9])([A-Z])/g, '$1_$2').toLowerCase(); - } - - function catalogPlans(payload) { - const offerings = itemsOf(payload, 'offerings'); - const offeringsById = new Map(offerings.map(item => [item.id, item])); - return itemsOf(payload, 'versions') - .map(version => { - const offering = offeringsById.get(version.offeringId) || {}; - return { - ...version, - code: offering.code || version.offeringCode, - name: offering.name || version.offeringName, - description: offering.description || version.description, - status: lowerEnum(version.status), - billingCycle: lowerEnum(version.billingCycle), - baseAmountCents: version.amountCents ?? version.baseAmountCents, - includedQuotas: version.limits, - offeringType: lowerEnum(offering.type || version.offeringType), - }; - }) - .filter(item => item.offeringType !== 'add_on' && item.status !== 'retired'); - } - - const adapters = { - plan(item, current = {}) { - const quotas = item.includedQuotas && typeof item.includedQuotas === 'object' - ? Object.entries(item.includedQuotas).map(([key, value]) => `${key}: ${value}`) - : current.quotas || []; - return { - ...current, - code: item.code, - name: item.name, - description: item.description || '', - cycle: ({ yearly: '年度', monthly: '月度' })[item.billingCycle] || item.billingCycle || '-', - amount: centsToYuan(item.baseAmountCents), - quotas, - tenantCount: Number(current.tenantCount || 0), - status: item.status, - }; - }, - tenant(item, current = {}, planMap = {}) { - const plan = planMap[item.planCode]; - return { - students: 0, - questions: 0, - storageGB: 0, - trafficTB: 0, - balance: 0, - host: '-', - owner: '待配置', - ownerPhone: '-', - ...current, - id: item.id, - slug: item.slug, - name: item.name, - legal: item.legalName || current.legal || item.name, - brand: item.brandName || current.brand || item.name, - planCode: item.planCode || '', - plan: plan?.name || current.plan || item.planCode || '未订阅', - status: mapValue(dictionaries.tenantStatusFromApi, item.status, item.status || '-'), - billing: mapValue(dictionaries.billingStatusFromApi, item.billingStatus, item.billingStatus || '-'), - mode: item.mode === 'saas' ? '正式' : item.mode || current.mode || '-', - expires: dateOnly(item.subscriptionExpiresAt), - balance: centsToYuan(item.openBalanceCents), - createdAt: dateTime(item.createdAt), - }; - }, - subscription(item) { - return { - id: item.subscriptionId || item.id, - tenantId: item.tenantId, - planCode: item.planCode || item.baseOfferingVersionId || '', - status: mapValue(dictionaries.subscriptionStatusFromApi, lowerEnum(item.status), item.status || '-'), - cycle: ({ yearly: '年度', monthly: '月度', quarterly: '季度', trial: '试用' })[lowerEnum(item.billingCycle)] || item.billingCycle || '-', - amount: centsToYuan(item.amountCents ?? item.totalAmountCents), - start: dateOnly(item.startsAt), - expires: dateOnly(item.expiresAt || item.currentPeriodEnd), - autoRenew: Boolean(item.metadata?.autoRenew), - }; - }, - invoice(item) { - const status = lowerEnum(item.status); - const totalCents = item.totalCents ?? item.totalAmountCents; - const paidCents = item.paidCents ?? (status === 'paid' ? totalCents : 0); - return { - id: item.invoiceNo || item.id, - backendId: item.id, - orderId: item.orderId || '', - tenantId: item.tenantId, - type: mapValue(dictionaries.invoiceTypeFromApi, item.invoiceType, item.invoiceType || '-'), - period: item.billingPeriodStart ? monthOnly(item.billingPeriodStart) : monthOnly(item.issuedAt || item.dueDate), - total: centsToYuan(totalCents), - paid: centsToYuan(paidCents), - balance: centsToYuan(item.balanceCents ?? Math.max(0, Number(totalCents || 0) - Number(paidCents || 0))), - due: dateOnly(item.dueDate), - status: mapValue(dictionaries.invoiceStatusFromApi, status, item.status || '-'), - note: item.note || '', - }; - }, - billingPayment(item) { - return { - id: item.id, - orderId: item.orderId, - tenantId: item.tenantId, - paymentNo: item.paymentNo || '', - status: lowerEnum(item.status), - amount: centsToYuan(item.amountCents), - providerTradeNo: item.providerTradeNo || '', - paidAt: item.paidAt || '', - }; - }, - reminder(item) { - return { - id: item.id, - invoiceId: item.invoiceNo || item.invoiceId, - backendInvoiceId: item.invoiceId, - tenantId: item.tenantId, - level: Number(item.reminderLevel || 1), - channel: item.channel || '-', - status: mapValue(dictionaries.eventStatusFromApi, item.status, item.status || '-'), - date: dateTime(item.reminderDate || item.createdAt), - message: item.message || '', - }; - }, - bank(item, current = {}) { - return { - ...current, - id: item.id, - name: item.name, - contentEntryId: item.contentEntryId || '', - catalog: '平台公共题库', - source: '平台自建', - nodes: Number(item.nodeCount || 0), - questions: Number(item.questionCount || 0), - version: item.metadata?.version || item.metadata?.contentVersion || '-', - status: lowerEnum(item.status) === 'active' ? '正常' : lowerEnum(item.status) === 'archived' ? '已归档' : item.status || '-', - }; - }, - staff(item) { - const roleCodes = item.roleCodes || []; - const permissions = roleCodes.includes('platform_super_admin') ? ['*'] : []; - return { - id: item.userId || item.id, - userId: item.userId || item.id, - name: item.name || item.email || '平台员工', - email: item.email || '', - phone: item.phoneMasked || item.phone || '-', - roleCodes, - role: permissions.includes('*') ? '超级管理员' : roleCodes.join('、') || '未分配角色', - permissions, - status: item.status === 'active' ? '正常' : '已停用', - lastActive: dateTime(item.updatedAt), - }; - }, - audit(item) { - const details = jsonSummary(item.details); - return { - id: item.id, - time: `${dateTime(item.createdAt)} CST`, - actor: item.actorName || item.actorUsername || item.actorUserId || 'system', - role: item.actorUserId ? '平台管理员' : '系统任务', - action: item.action || '-', - targetType: item.targetType || '-', - targetId: item.targetId || '', - target: item.tenantName || item.targetId || item.targetType || '-', - severity: mapValue(dictionaries.severityFromApi, item.details?.severity, item.details?.severity || '中'), - result: item.details?.result === 'failed' ? '失败' : '成功', - ip: item.ipAddress || '-', - details, - }; - }, - alert(item) { - const evidence = Array.isArray(item.details?.evidence) - ? item.details.evidence.map(String) - : Object.entries(item.details || {}).slice(0, 8).map(([key, value]) => `${key}: ${jsonSummary(value)}`); - return { - id: item.id, - title: item.title || item.ruleName || '平台审计告警', - summary: item.summary || item.action || '', - severity: mapValue(dictionaries.severityFromApi, item.severity, item.severity || '-'), - status: item.status || 'open', - owner: item.acknowledgedByName || item.resolvedByName || item.tenantName || item.ruleName || '待认领', - targetType: item.targetType || '-', - targetId: item.targetId || '', - evidence, - updatedAt: dateTime(item.updatedAt || item.createdAt), - note: item.resolutionNote || '', - }; - }, - rule(item) { - return { - id: item.id, - code: item.code, - name: item.name, - severity: mapValue(dictionaries.severityFromApi, item.severity, item.severity || '-'), - enabled: item.enabled !== false, - window: item.conditions?.window || item.metadata?.window || '-', - threshold: item.conditions?.threshold || item.metadata?.threshold || '-', - target: item.description || (item.targetTypes || []).join('、') || '-', - }; - }, - channel(item) { - return { - id: item.id, - code: item.channelCode, - name: item.name, - provider: mapValue(dictionaries.providerFromApi, item.provider, item.provider || 'Webhook'), - endpoint: safeEndpoint(item), - enabled: item.enabled !== false, - retry: Number(item.maxAttempts || item.metadata?.maxAttempts || 3), - minSeverity: mapValue(dictionaries.severityFromApi, item.minSeverity, item.minSeverity || '中'), - statusFilter: (item.statusFilter || []).join(','), - timeout: Number(item.timeoutSec || 10), - maxAttempts: Number(item.maxAttempts || item.metadata?.maxAttempts || 3), - lastStatus: '正常', - secretRef: item.secretRef || '', - endpointRedacted: true, - reminderTypes: item.reminderTypes || [], - reminderChannels: item.reminderChannels || [], - minReminderLevel: Number(item.minReminderLevel || 1), - }; - }, - event(item, type = 'audit') { - return { - id: item.id, - channelId: item.channelId, - subject: type === 'dunning' - ? item.reminderMessage || item.invoiceNo || '催缴通知' - : item.alertTitle || item.alertAction || '审计告警通知', - status: mapValue(dictionaries.eventStatusFromApi, item.status, item.status || '-'), - attempts: Number(item.attempts || 0), - updatedAt: dateTime(item.updatedAt || item.sentAt || item.createdAt), - error: item.lastError || '', - }; - }, - crmConfig(item) { - const assignmentPool = Array.isArray(item.assignmentPool) ? item.assignmentPool.join('、') : jsonSummary(item.assignmentPool); - return { - id: item.id, - backendId: item.id, - tenantId: item.tenantId, - provider: item.url ? 'Webhook' : 'generic', - endpoint: item.url || '', - assignmentMode: ({ round_robin: '按地区轮转', direct: '手工分配', referrer: '来源归属', none: '不分配' })[lowerEnum(item.assignmentMode)] || item.assignmentMode || '-', - pool: assignmentPool || item.formName || '-', - timeout: Number(item.timeoutSeconds || 0), - retry: Number(item.assignmentConfig?.retry || 0), - enabled: item.enabled !== false, - status: item.enabled === false ? '未启用' : '正常', - secretRef: item.secretRef || '', - formName: item.formName || '', - examType: item.examType || '', - }; - }, - crmLead(item) { - return { - id: item.id, - backendId: item.id, - tenantId: item.tenantId, - student: item.payload?.student || item.leadId || item.recordId || 'CRM 线索', - phone: item.payload?.phoneMasked || '-', - source: item.source || '-', - subject: item.payload?.subject || item.provider || '-', - owner: item.payload?.owner || '-', - attempts: Number(item.attempts || 0), - status: mapValue(dictionaries.crmStatusFromApi, lowerEnum(item.status), item.status || '-'), - lastError: item.lastError || '', - }; - }, - smsChannel(item) { - const status = mapValue(dictionaries.providerStatusFromApi, lowerEnum(item.status), item.status || '-'); - return { - id: item.id, - backendId: item.id, - tenantId: item.tenantId, - provider: item.provider || '-', - name: item.name || item.displayName || '', - signature: item.signature || item.name || '-', - scene: item.scene || '-', - secretRef: item.secretRef || '', - quota: Number(item.monthlyQuota || 0), - used: Number(item.sentThisMonth || 0), - status, - enabled: status === '正常', - priority: Number(item.priority || 100), - }; - }, - smsTemplate(item) { - const sent = Number(item.sentCount || 0); - const failed = Number(item.failedCount || 0); - return { - id: item.id, - backendId: item.id, - tenantId: item.tenantId, - channelId: item.channelId, - name: item.name || '-', - code: item.code || '-', - type: lowerEnum(item.type), - status: mapValue(dictionaries.smsAuditStatusFromApi, lowerEnum(item.auditStatus), item.auditStatus || '-'), - templateStatus: mapValue(dictionaries.smsTemplateStatusFromApi, lowerEnum(item.status), item.status || '-'), - lastSend: dateTime(item.updatedAt), - successRate: sent + failed ? `${Math.round(sent / (sent + failed) * 100)}%` : '-', - content: item.content || '', - }; - }, - smsLog(item) { - return { - id: item.id, - tenantId: item.tenantId, - templateId: item.templateId, - channelId: item.channelId, - phone: item.phoneMasked || '-', - provider: item.provider || '-', - updatedAt: dateTime(item.sentAt || item.createdAt), - status: lowerEnum(item.status) === 'sent' ? '发送成功' : lowerEnum(item.status) === 'failed' ? '发送失败' : '待发送', - }; - }, - platformPaymentApp(item) { - const status = mapValue(dictionaries.paymentStatusFromApi, lowerEnum(item.status), item.status || '-'); - return { - id: item.id, - backendId: item.id, - tenantId: '', - appCode: item.appCode || '', - appName: item.appName || '-', - provider: 'platform', - mode: '平台收款', - settlement: item.settlementMode || 'PlatformCollect', - secretRef: '', - status, - appScope: 'platform', - }; - }, - tenantPaymentApp(item) { - const status = mapValue(dictionaries.providerStatusFromApi, lowerEnum(item.status), item.status || '-'); - return { - id: item.id, - backendId: item.id, - tenantId: item.tenantId || '', - appName: item.displayName || item.provider || '-', - provider: item.provider || '-', - mode: item.configPublic?.mode || 'TenantCollect', - settlement: '租户收款', - secretRef: item.secretRef || '', - status, - appScope: 'tenant', - }; - }, - platformPaymentEvent(item) { - return { - id: item.id, - appId: item.appId || '', - orderNo: item.providerEventId || item.eventId || item.paymentId || '-', - amount: centsToYuan(item.payload?.amountCents || item.amountCents || 0), - channel: item.provider || '-', - notified: item.eventType || '-', - updatedAt: dateTime(item.createdAt || item.processedAt), - status: item.error ? '回调失败' : '成功', - }; - }, - }; - - function aggregateUsage(items) { - const records = new Map(); - items.forEach(item => { - const period = monthOnly(item.periodStart || item.periodEnd); - const key = `${item.tenantId}:${period}`; - const record = records.get(key) || { - tenantId: item.tenantId, - period, - source: item.metadata?.source === 'platform_usage_worker' ? 'Worker 自动采集' : '人工补录', - students: 0, - questions: 0, - storageGB: 0, - trafficTB: 0, - overage: [], - estimated: 0, - }; - const metricMap = { - students: 'students', - questions: 'questions', - storage_gb: 'storageGB', - traffic_tb: 'trafficTB', - }; - const field = metricMap[item.metricKey || item.metricCode]; - if (field) record[field] = Number(item.metricValue ?? item.usedValue ?? 0); - records.set(key, record); - }); - return Array.from(records.values()); - } - - function currentPeriod() { - const parts = new Intl.DateTimeFormat('en-US', { - timeZone: 'Asia/Shanghai', - year: 'numeric', - month: '2-digit', - }).formatToParts(new Date()); - const values = Object.fromEntries(parts.map(part => [part.type, part.value])); - return `${values.year}-${values.month}`; - } - - const bootstrapDescriptors = [ - ['backofficeBootstrap', 'PlatformBackofficeController_bootstrap', {}], - ['overview', 'PlatformAdminOverviewController_overview', {}], - ['domains', 'PlatformAdminTenantsController_domains', { query: { limit: 200 } }], - ['plans', 'PlatformAdminOverviewController_plans', {}], - ['tenants', 'PlatformAdminTenantsController_list', { query: { limit: 200 } }], - ['subscriptions', 'PlatformAdminBillingController_subscriptions', { query: { limit: 200 } }], - ['saasOrders', 'PlatformAdminBillingController_orders', { query: { limit: 200 } }], - ['saasRefunds', 'PlatformAdminBillingController_refunds', { query: { limit: 200 } }], - ['invoices', 'PlatformAdminBillingController_invoices', { query: { limit: 200 } }], - ['billingPayments', 'PlatformAdminBillingController_payments', { query: { limit: 200 } }], - ['usage', 'PlatformAdminBillingController_usage', { query: { limit: 200 } }], - ['reminders', 'PlatformAdminBillingController_reminders', { query: { limit: 100 } }], - ['banks', 'PlatformQuestionBanksController_getBanks', { query: { status: 'all' } }], - ['staff', 'PlatformAdminOverviewController_staff', { query: { limit: 200 } }], - ['dunningChannels', 'PlatformAdminDunningChannelsController_channels', { query: { limit: 100 } }], - ['dunningEvents', 'PlatformAdminDunningEventsController_events', { query: { limit: 100 } }], - ['auditLogs', 'PlatformAdminAuditController_logs', { query: { limit: 200 } }], - ['alerts', 'PlatformAdminAuditController_alerts', { query: { limit: 100 } }], - ['crmConfigs', 'PlatformAdminCrmController_configs', { query: { limit: 200 } }], - ['crmLeads', 'PlatformAdminCrmController_leads', { query: { limit: 200 } }], - ['crmLogs', 'PlatformAdminCrmController_logs', { query: { limit: 200 } }], - ['smsChannels', 'PlatformAdminSmsController_channels', { query: { limit: 200 } }], - ['smsTemplates', 'PlatformAdminSmsController_templates', { query: { limit: 200 } }], - ['smsLogs', 'PlatformAdminSmsController_logs', { query: { limit: 200 } }], - ['platformPaymentApps', 'PlatformAdminPaymentSettingsController_apps', { query: { limit: 200 } }], - ['paymentChannels', 'PlatformAdminPaymentSettingsController_channels', { query: { limit: 200 } }], - ['rebateSummary', 'PlatformAdminPaymentSettingsController_rebateSummary', {}], - ['tenantPaymentApps', 'PlatformAdminTenantPaymentSettingsController_apps', { query: { limit: 200 } }], - ['platformPaymentEvents', 'PlatformAdminPaymentSettingsController_events', { query: { limit: 100 } }], - ['tenantPaymentEvents', 'PlatformAdminTenantPaymentSettingsController_events', { query: { limit: 100 } }], - ]; - - async function bootstrap(options = {}) { - const descriptors = bootstrapDescriptors.map(([key, operationId, requestOptions]) => { - const nextOptions = { ...requestOptions, query: { ...(requestOptions.query || {}) } }; - return [key, operationId, nextOptions]; - }); - const results = await Promise.allSettled( - descriptors.map(([, operationId, requestOptions]) => request(operationId, requestOptions)), - ); - const payloads = {}; - const errors = {}; - results.forEach((result, index) => { - const [key] = descriptors[index]; - if (result.status === 'fulfilled') payloads[key] = result.value; - else errors[key] = result.reason; - }); - return { payloads, errors, requested: descriptors.length }; - } - - function adaptBootstrap(payloads, currentData = {}) { - const patch = {}; - const backoffice = payloads.backofficeBootstrap || {}; - const permissionItems = Array.isArray(backoffice.permissions) ? backoffice.permissions : []; - const roleItems = Array.isArray(backoffice.roles) ? backoffice.roles : []; - if (permissionItems.length) { - patch.platformPermissions = Object.fromEntries(permissionItems.map(item => [ - item.code, - platformPermissionLabels[item.code] || item.name || item.code, - ])); - } - if (roleItems.length) { - patch.platformRoles = roleItems - .filter(item => String(item.status || '').toLowerCase() === 'active') - .map(item => { - const localized = platformRoleLabels[item.code] || {}; - return { id: item.id, code: item.code, name: localized.name || item.name || item.code, description: localized.description || item.description || '', permissionCodes: item.permissionCodes || [], menuCodes: item.menuCodes || [] }; - }); - } - if (payloads.overview) patch.apiOverview = itemOf(payloads.overview); - if (payloads.domains) patch.domains = itemsOf(payloads.domains); - if (payloads.plans) patch.saasCatalog = payloads.plans; - if (payloads.permissions) patch.apiPermissions = itemOf(payloads.permissions); - const planPayload = itemsOf(payloads.plans, 'versions').length ? catalogPlans(payloads.plans) : itemsOf(payloads.plans); - if (planPayload.length) { - patch.plans = planPayload.map(item => adapters.plan(item, currentById(currentData.plans, item.code))); - } - const planItems = patch.plans || currentData.plans || []; - const planMap = Object.fromEntries(planItems.map(item => [item.code, item])); - const tenants = itemsOf(payloads.tenants); - if (tenants.length) { - patch.tenants = tenants.map(item => adapters.tenant(item, currentById(currentData.tenants, item.id), planMap)); - } - const staff = itemsOf(payloads.staff); - if (staff.length) { - const roles = patch.platformRoles || currentData.platformRoles || []; - patch.staff = staff.map(item => { - const adapted = adapters.staff(item); - const assignedRoles = roles.filter(role => adapted.roleCodes.includes(role.code)); - adapted.roleIds = assignedRoles.map(role => role.id); - adapted.role = assignedRoles.map(role => role.name).join('、') || adapted.role; - adapted.permissions = adapted.permissions.includes('*') ? adapted.permissions : [...new Set(assignedRoles.flatMap(role => role.permissionCodes))]; - return adapted; - }); - } - const invoices = itemsOf(payloads.invoices); - if (invoices.length) patch.invoices = invoices.map(adapters.invoice); - const billingPayments = itemsOf(payloads.billingPayments); - if (billingPayments.length) patch.billingPayments = billingPayments.map(adapters.billingPayment); - const subscriptions = itemsOf(payloads.subscriptions); - if (subscriptions.length) patch.subscriptions = subscriptions.map(adapters.subscription); - if (payloads.saasOrders) patch.saasOrders = itemsOf(payloads.saasOrders); - if (payloads.saasRefunds) patch.saasRefunds = itemsOf(payloads.saasRefunds); - const usage = itemsOf(payloads.usage); - if (usage.length) patch.usage = aggregateUsage(usage); - if (Array.isArray(payloads.usageCandidates?.items) && patch.usage) { - const usageByKey = new Map(patch.usage.map(item => [`${item.tenantId}:${item.period}`, item])); - payloads.usageCandidates.items.forEach(candidate => { - const record = usageByKey.get(`${candidate.tenantId}:${monthOnly(candidate.periodStart)}`); - if (!record) return; - record.estimated = centsToYuan(candidate.totalCents); - record.overage = (candidate.items || []).map(item => item.description || item.itemType).filter(Boolean); - }); - } - const reminders = itemsOf(payloads.reminders); - if (reminders.length) patch.reminders = reminders.map(adapters.reminder); - const dunningChannels = itemsOf(payloads.dunningChannels); - if (dunningChannels.length) patch.dunningChannels = dunningChannels.map(adapters.channel); - const dunningEvents = itemsOf(payloads.dunningEvents); - if (dunningEvents.length) patch.dunningEvents = dunningEvents.map(item => adapters.event(item, 'dunning')); - const banks = itemsOf(payloads.banks); - if (banks.length) { - patch.banks = banks.map(item => adapters.bank(item, currentById(currentData.banks, item.id))); - } - const auditLogs = itemsOf(payloads.auditLogs); - if (auditLogs.length) patch.auditLogs = auditLogs.map(adapters.audit); - const alertRules = itemsOf(payloads.alertRules); - if (alertRules.length) patch.alertRules = alertRules.map(adapters.rule); - const alerts = itemsOf(payloads.alerts); - if (alerts.length) patch.alerts = alerts.map(adapters.alert); - const crmConfigs = itemsOf(payloads.crmConfigs); - if (crmConfigs.length) patch.crmConfigs = crmConfigs.map(adapters.crmConfig); - const crmLeads = itemsOf(payloads.crmLeads); - if (crmLeads.length) patch.crmLeads = crmLeads.map(adapters.crmLead); - if (payloads.crmLogs) patch.crmLogs = itemsOf(payloads.crmLogs); - const smsChannels = itemsOf(payloads.smsChannels); - if (smsChannels.length) patch.smsChannels = smsChannels.map(adapters.smsChannel); - const smsTemplates = itemsOf(payloads.smsTemplates); - if (smsTemplates.length) patch.smsTemplates = smsTemplates.map(adapters.smsTemplate); - const smsLogs = itemsOf(payloads.smsLogs); - if (smsLogs.length) patch.smsLogs = smsLogs.map(adapters.smsLog); - const platformPaymentApps = itemsOf(payloads.platformPaymentApps).map(adapters.platformPaymentApp); - const tenantPaymentApps = itemsOf(payloads.tenantPaymentApps).map(adapters.tenantPaymentApp); - if (platformPaymentApps.length || tenantPaymentApps.length) patch.paymentApps = [...platformPaymentApps, ...tenantPaymentApps]; - if (payloads.paymentChannels) patch.paymentChannels = itemsOf(payloads.paymentChannels); - if (payloads.rebateSummary) patch.rebateSummary = itemOf(payloads.rebateSummary); - const paymentEvents = [ - ...itemsOf(payloads.platformPaymentEvents).map(adapters.platformPaymentEvent), - ...itemsOf(payloads.tenantPaymentEvents).map(adapters.platformPaymentEvent), - ]; - if (paymentEvents.length) patch.paymentEvents = paymentEvents; - const auditChannels = itemsOf(payloads.auditChannels); - if (auditChannels.length) patch.auditChannels = auditChannels.map(adapters.channel); - const notificationEvents = itemsOf(payloads.notificationEvents); - if (notificationEvents.length) { - patch.notificationEvents = notificationEvents.map(item => adapters.event(item, 'audit')); - } - return patch; - } - - async function tenantDetail(tenantId) { - const payload = await request('PlatformAdminTenantsController_detail', { query: { tenantId } }); - const item = payload.item || {}; - return { - tenant: item.tenant || null, - domains: item.domains || [], - subscriptions: (item.subscriptions || []).map(adapters.subscription), - invoices: (item.invoices || []).map(adapters.invoice), - usage: aggregateUsage(item.usage || []), - billingProfile: item.tenant ? { - billingName: item.tenant.billingName || '', - taxId: item.tenant.taxId || '', - contactName: item.tenant.contactName || '', - phone: item.tenant.contactPhone || '', - email: item.tenant.contactEmail || '', - billingAddress: item.tenant.billingAddress || '', - invoiceTitle: item.tenant.invoiceTitle || '', - type: ({ special_vat: '增值税专用发票', normal_vat: '增值税普通发票', none: '不开票' })[item.tenant.invoiceType] || item.tenant.invoiceType || '', - bankName: item.tenant.bankName || '', - bankAccountMasked: item.tenant.bankAccountMasked || '', - } : null, - }; - } - - function downloadExport(payload) { - const item = payload?.item; - if (!item?.contentBase64) { - throw new PlatformApiError('审计导出响应缺少文件内容', { code: 'AUDIT_EXPORT_INVALID' }); - } - const bytes = Uint8Array.from(atob(item.contentBase64), character => character.charCodeAt(0)); - const blob = new Blob([bytes], { type: item.mimeType || 'application/octet-stream' }); - const url = URL.createObjectURL(blob); - const anchor = document.createElement('a'); - anchor.href = url; - anchor.download = item.filename || `platform-audit.${item.format || 'csv'}`; - anchor.click(); - setTimeout(() => URL.revokeObjectURL(url), 1000); - return item; - } - - window.GongxuePlatformApi = Object.freeze({ - PlatformApiError, - adapters, - adaptBootstrap, - bootstrap, - buildBody, - dictionaries, - downloadExport, - isEnabled, - operationCatalog, - periodBounds, - publicConfig, - request, - tenantDetail, - trace, - }); -})(); diff --git a/Tiku.Api/wwwroot/platform-admin/platform-auth.js b/Tiku.Api/wwwroot/platform-admin/platform-auth.js deleted file mode 100644 index 6697a43..0000000 --- a/Tiku.Api/wwwroot/platform-admin/platform-auth.js +++ /dev/null @@ -1,141 +0,0 @@ -(() => { - const ACCESS_TOKEN_KEY = 'tiku_platform_access_token'; - const REFRESH_TOKEN_KEY = 'tiku_platform_refresh_token'; - const ACCESS_EXPIRES_KEY = 'tiku_platform_access_expires_at'; - const USER_KEY = 'tiku_platform_user'; - const runtime = window.GONGXUE_PLATFORM_RUNTIME_CONFIG || {}; - let challengeToken = ''; - let pendingResolve; - - function apiUrl(path) { - return `${String(runtime.apiBaseUrl || '').replace(/\/+$/, '')}${path}`; - } - - async function post(path, body) { - const response = await fetch(apiUrl(path), { - method: 'POST', - headers: { Accept: 'application/json', 'Content-Type': 'application/json' }, - credentials: 'omit', - body: JSON.stringify(body), - }); - const text = await response.text(); - let payload = {}; - if (text) { - try { payload = JSON.parse(text); } catch { payload = { detail: text.slice(0, 500) }; } - } - if (!response.ok) throw new Error(payload.detail || payload.title || payload.message || `请求失败(HTTP ${response.status})`); - return payload; - } - - function gate() { return document.querySelector('#platformAuthGate'); } - - function shell(title, description, content) { - gate().innerHTML = ``; - gate().hidden = false; - document.querySelector('.platform-app')?.setAttribute('inert', ''); - } - - function showError(error) { - const target = document.querySelector('#platformAuthError'); - if (target) target.textContent = error?.message || '操作失败,请重试'; - } - - function setBusy(form, busy) { - form.querySelectorAll('button,input').forEach(control => { control.disabled = busy; }); - } - - function storeAuthenticated(result) { - const user = result?.user; - const tokens = user?.tokens; - if (!tokens?.accessToken || !tokens?.refreshToken) throw new Error('登录响应缺少令牌'); - sessionStorage.setItem(ACCESS_TOKEN_KEY, tokens.accessToken); - sessionStorage.setItem(REFRESH_TOKEN_KEY, tokens.refreshToken); - sessionStorage.setItem(ACCESS_EXPIRES_KEY, tokens.accessTokenExpiresAt || ''); - sessionStorage.setItem(USER_KEY, JSON.stringify({ userId: user.userId, email: user.email, name: user.name })); - } - - function completeGate() { - gate().hidden = true; - gate().innerHTML = ''; - document.querySelector('.platform-app')?.removeAttribute('inert'); - pendingResolve?.(true); - pendingResolve = null; - } - - function finishAuthentication(result) { - storeAuthenticated(result); - completeGate(); - } - - async function handleAuthenticationResult(result) { - challengeToken = result.challengeToken || ''; - if (result.status === 'authenticated') { finishAuthentication(result); return; } - if (result.status === 'password_change_required') { renderPasswordChange(); return; } - throw new Error(`不支持的认证状态:${result.status || 'unknown'}`); - } - - function renderLogin() { - shell('平台管理员登录', '连接真实 PostgreSQL 与 ASP.NET Core API。', `
`); - document.querySelector('#platformLoginForm').addEventListener('submit', async event => { - event.preventDefault(); - const form = event.currentTarget; - setBusy(form, true); - try { - const result = await post('/api/auth/login/password', { realm: 'platform', identifier: form.elements.identifier.value.trim(), password: form.elements.password.value }); - await handleAuthenticationResult(result); - } catch (error) { showError(error); setBusy(form, false); } - }); - } - - function renderPasswordChange() { - shell('设置正式密码', '至少 8 位,且必须同时包含字母和数字。', `
`); - document.querySelector('#platformPasswordForm').addEventListener('submit', async event => { - event.preventDefault(); - const form = event.currentTarget; - if (form.elements.newPassword.value !== form.elements.confirmPassword.value) { showError(new Error('两次输入的密码不一致')); return; } - setBusy(form, true); - try { await handleAuthenticationResult(await post('/api/auth/password/change-required', { challengeToken, newPassword: form.elements.newPassword.value })); } - catch (error) { showError(error); setBusy(form, false); } - }); - } - - function clearSession() { - [ACCESS_TOKEN_KEY, REFRESH_TOKEN_KEY, ACCESS_EXPIRES_KEY, USER_KEY].forEach(key => sessionStorage.removeItem(key)); - } - - function hasSession() { - const token = sessionStorage.getItem(ACCESS_TOKEN_KEY); - const expiresAt = Date.parse(sessionStorage.getItem(ACCESS_EXPIRES_KEY) || ''); - return Boolean(token) && Number.isFinite(expiresAt) && expiresAt > Date.now() + 15_000; - } - - async function requireSession() { - if (hasSession()) return true; - clearSession(); - renderLogin(); - return new Promise(resolve => { pendingResolve = resolve; }); - } - - function requireReauthentication() { - clearSession(); - renderLogin(); - pendingResolve = () => location.reload(); - } - - async function logout() { - const refreshToken = sessionStorage.getItem(REFRESH_TOKEN_KEY); - try { if (refreshToken) await post('/api/auth/logout', { refreshToken }); } catch { /* Clear the browser session even when revocation cannot be reached. */ } - clearSession(); - location.reload(); - } - - window.GongxuePlatformAuth = Object.freeze({ - getAccessToken: () => sessionStorage.getItem(ACCESS_TOKEN_KEY) || '', - getUser: () => { - try { return JSON.parse(sessionStorage.getItem(USER_KEY) || 'null'); } catch { return null; } - }, - logout, - requireReauthentication, - requireSession, - }); -})(); diff --git a/Tiku.Api/wwwroot/platform-admin/runtime-config.js b/Tiku.Api/wwwroot/platform-admin/runtime-config.js deleted file mode 100644 index cc4d436..0000000 --- a/Tiku.Api/wwwroot/platform-admin/runtime-config.js +++ /dev/null @@ -1,24 +0,0 @@ -/* - * 平台端公开运行时配置。 - * - * 默认连接同源后端。其他部署环境可在本文件之前注入同名对象, - * 或在部署时替换本文件。不要把 access token、service role key 或任何服务端密钥 - * 写入静态文件;getAccessToken 应从当前平台登录会话中按需读取短期 JWT。 - * - * window.GONGXUE_PLATFORM_RUNTIME_CONFIG = { - * mode: 'api', - * apiBaseUrl: 'https://api.example.com', - * fallbackToMock: true, - * timeoutMs: 10000, - * getAccessToken: async () => { - * return sessionStorage.getItem('tiku_platform_access_token') || ''; - * }, - * }; - */ -window.GONGXUE_PLATFORM_RUNTIME_CONFIG = window.GONGXUE_PLATFORM_RUNTIME_CONFIG || { - mode: 'api', - apiBaseUrl: '', - fallbackToMock: false, - timeoutMs: 10000, - getAccessToken: async () => window.GongxuePlatformAuth?.getAccessToken() || '', -}; diff --git a/Tiku.Api/wwwroot/platform-admin/spec-contract.js b/Tiku.Api/wwwroot/platform-admin/spec-contract.js deleted file mode 100644 index b0500d3..0000000 --- a/Tiku.Api/wwwroot/platform-admin/spec-contract.js +++ /dev/null @@ -1,313 +0,0 @@ -(() => { - const actions = [ - ['P-01', 'act.p-01.01', '进入租户/账务/题库/审计', 'command', 'native', 'nav', '[data-nav="tenants"],[data-nav="billing"],[data-nav="bank"],[data-nav="audit"]', 'PlatformAdminOverviewController_overview', 'allow'], - ['P-01', 'act.p-01.02', '确认/解决告警', 'command', 'native', 'mutation', '[data-alert-detail],[data-action="transition-alert"]', 'PlatformAdminAuditController_alerts', 'allow'], - ['P-01', 'act.p-01.03', '导出审计', 'async', 'native', 'task', '[data-action="export-audit"]', 'PlatformAdminAuditController_logs', 'allow'], - ['P-01', 'act.p-01.04', '刷新', 'command', 'native', 'read', '[data-action="refresh"]', 'PlatformAdminOverviewController_overview', 'allow'], - ['P-02', 'act.p-02.01', '搜索', 'command', 'native', 'read', '#tenantSearch,[data-action="apply-tenant-query"]', 'PlatformAdminTenantsController_list', 'allow'], - ['P-02', 'act.p-02.02', '创建租户', 'command', 'native', 'mutation', '[data-action="create-tenant"],[form="createTenantForm"]', 'PlatformAdminTenantsController_create', 'block'], - ['P-02', 'act.p-02.03', '打开详情', 'command', 'native', 'nav', '[data-tenant-detail]', 'PlatformAdminTenantsController_list', 'allow'], - ['P-02', 'act.p-02.04', '准备暂停/恢复', 'destructive', 'native', 'mutation', '[data-action="prepare-tenant-status"],[form="tenantStatusForm"]', 'PlatformAdminTenantsController_status', 'block'], - ['P-02', 'act.p-02.05', '去账务', 'command', 'native', 'nav', '[data-action="tenant-to-billing"]', 'PlatformAdminBillingController_invoices', 'allow'], - ['P-03', 'act.p-03.01', '修改状态', 'command', 'native', 'mutation', '[data-action="prepare-tenant-status"],[form="tenantStatusForm"]', 'PlatformAdminTenantsController_status', 'block'], - ['P-03', 'act.p-03.02', '编辑账务资料', 'command', 'native', 'nav', '[data-action="edit-billing-profile"]', 'PlatformAdminTenantsController_billingProfile', 'block'], - ['P-03', 'act.p-03.03', '创建订阅', 'command', 'native', 'mutation', '[data-action="create-subscription-for-tenant"],[form="subscriptionForm"]', 'PlatformAdminBillingController_createSubscription', 'block'], - ['P-03', 'act.p-03.04', '查看账单/用量', 'command', 'native', 'nav', '[data-action="tenant-to-billing"],[data-action="tenant-to-usage"]', 'PlatformAdminTenantsController_detail', 'allow'], - ['P-03', 'act.p-03.05', '打开租户门户入口', 'command', 'native', 'nav', '[data-action="open-tenant-portal"]', 'PlatformAdminTenantsController_detail', 'allow'], - ['P-04', 'act.p-04.01', '编辑', 'command', 'native', 'mutation', '#billingProfileForm', 'PlatformAdminTenantsController_billingProfile', 'block'], - ['P-04', 'act.p-04.02', '保存', 'command', 'native', 'mutation', '[form="billingProfileForm"]', 'PlatformAdminTenantsController_billingProfile', 'block'], - ['P-04', 'act.p-04.03', '查看关联账单', 'command', 'native', 'nav', '[data-action="billing-profile-to-invoices"]', 'PlatformAdminTenantsController_billingProfile', 'allow'], - ['P-05', 'act.p-05.01', '选择套餐', 'command', 'native', 'mutation', '[data-action="select-plan"]', 'PlatformAdminOverviewController_plans', 'block'], - ['P-05', 'act.p-05.02', '创建订阅', 'command', 'native', 'mutation', '[data-action="create-subscription"],[form="subscriptionForm"]', 'PlatformAdminBillingController_createSubscription', 'block'], - ['P-05', 'act.p-05.03', '进入账单候选', 'command', 'native', 'nav', '[data-action="subscription-to-billing"]', 'PlatformAdminBillingController_createSubscription', 'allow'], - ['P-05', 'act.p-05.04', '查看租户详情', 'command', 'native', 'nav', '[data-tenant-detail]', 'PlatformAdminBillingController_createSubscription', 'allow'], - ['P-06', 'act.p-06.01', '查询', 'command', 'contract', 'read', '[data-action="apply-invoice-query"]', 'PlatformAdminBillingController_invoices', 'allow'], - ['P-06', 'act.p-06.02', '手工创建', 'command', 'native', 'mutation', '[data-action="create-invoice"],[form="invoiceForm"]', 'PlatformAdminBillingController_createInvoice', 'block'], - ['P-06', 'act.p-06.03', '预览候选', 'command', 'native', 'read', '[data-action="preview-invoice-candidates"]', 'PlatformAdminBillingController_subscriptionCandidates', 'block'], - ['P-06', 'act.p-06.04', '单个生成', 'async', 'contract', 'task', '[data-action="generate-subscription-invoice"]', 'PlatformAdminBillingController_fromSubscription', 'block'], - ['P-06', 'act.p-06.05', '批量 dry-run', 'command', 'native', 'read', '[data-action="run-invoice-dry-run"]', 'PlatformAdminBillingController_fromSubscriptionsBatch', 'block'], - ['P-06', 'act.p-06.06', '确认生成', 'async', 'native', 'task', '[data-action="confirm-generate-candidates"]', 'PlatformAdminBillingController_fromSubscriptionsBatch', 'block'], - ['P-06', 'act.p-06.07', '打开租户', 'command', 'native', 'nav', '[data-tenant-detail]', 'PlatformAdminBillingController_invoices', 'allow'], - ['P-07', 'act.p-07.01', '记录用量', 'command', 'native', 'mutation', '[data-action="record-usage"],[form="usageForm"]', 'PlatformAdminBillingController_recordUsage', 'block'], - ['P-07', 'act.p-07.02', '查询', 'command', 'native', 'read', '#usagePeriodFilter', 'PlatformAdminBillingController_usage', 'allow'], - ['P-07', 'act.p-07.03', '预览超额候选', 'command', 'native', 'read', '[data-action="preview-overage"]', 'PlatformAdminBillingController_usageCandidates', 'block'], - ['P-07', 'act.p-07.04', 'dry-run', 'command', 'native', 'read', '[data-action="run-overage-dry-run"]', 'PlatformAdminBillingController_fromUsage', 'block'], - ['P-07', 'act.p-07.05', '生成超额账单', 'async', 'native', 'task', '[data-action="confirm-overage-invoices"]', 'PlatformAdminBillingController_fromUsage', 'block'], - ['P-07', 'act.p-07.06', '跳租户详情', 'command', 'native', 'nav', '[data-tenant-detail]', 'PlatformAdminBillingController_usage', 'allow'], - ['P-08', 'act.p-08.01', '确认收款', 'command', 'native', 'mutation', '[data-action="confirm-payment"],[form="paymentForm"]', 'PlatformAdminBillingController_confirmPayment', 'block'], - ['P-08', 'act.p-08.02', '预览逾期', 'command', 'native', 'read', '[data-action="preview-overdue"]', 'PlatformAdminBillingController_processOverdue', 'block'], - ['P-08', 'act.p-08.03', '生成催缴', 'async', 'native', 'task', '[data-action="confirm-overdue-process"],[data-action="generate-reminder"]', 'PlatformAdminBillingController_processOverdue', 'block'], - ['P-08', 'act.p-08.04', '查询提醒', 'command', 'native', 'read', '[data-billing-tab="reminders"]', 'PlatformAdminBillingController_reminders', 'allow'], - ['P-08', 'act.p-08.05', '新增/编辑/启停渠道', 'command', 'native', 'mutation', '[data-action="new-dunning-channel"],[data-action="edit-dunning-channel"],[data-action="toggle-dunning-channel"]', 'PlatformAdminDunningChannelsController_upsertChannel', 'block'], - ['P-08', 'act.p-08.06', '查看通知事件', 'command', 'contract', 'read', '[data-notification-detail]', 'PlatformAdminDunningEventsController_events', 'allow'], - ['P-09', 'act.p-09.01', '查询与选择题库', 'command', 'native', 'read', '[data-action="apply-bank-search"],[data-bank-select]', 'PlatformQuestionBanksController_getBanks', 'allow'], - ['P-09', 'act.p-09.02', '维护题库与内容结构', 'command', 'native', 'mutation', '[data-action="new-bank"],[data-action="edit-bank"],[data-action="new-bank-node"],[data-action="batch-bank-nodes"]', 'PlatformQuestionBanksController_upsertNode', 'block'], - ['P-09', 'act.p-09.03', '单题录入与题目管理', 'command', 'native', 'mutation', '#bankQuestionForm,[data-action="edit-bank-question"],[data-action="archive-bank-question"]', 'PlatformQuestionBanksController_upsertQuestion', 'block'], - ['P-09', 'act.p-09.04', '普通题目批量导入', 'async', 'native', 'task', '#bankBatchImportForm', 'PlatformQuestionBanksController_executeImport', 'block'], - ['P-09', 'act.p-09.05', '结构化题库文件导入', 'async', 'native', 'task', '#bankStructuredImportForm', 'PlatformQuestionBanksController_executeImport', 'block'], - ['P-10', 'act.p-10.01', '切换 CRM 视图', 'command', 'native', 'read', '[data-crm-tab]', 'PlatformAdminCrmController_configs', 'allow'], - ['P-10', 'act.p-10.02', '新建/编辑 CRM 接入', 'command', 'native', 'mutation', '[data-action="new-crm-config"],[data-action="edit-crm-config"]', 'PlatformAdminCrmController_upsertConfig', 'block'], - ['P-10', 'act.p-10.03', '启停 CRM 接入', 'destructive', 'native', 'mutation', '[data-action="toggle-crm-config"]', 'PlatformAdminCrmController_upsertConfig', 'block'], - ['P-10', 'act.p-10.04', '重试线索推送', 'command', 'native', 'mutation', '[data-action="retry-crm-lead"]', 'PlatformAdminCrmController_retryLead', 'block'], - ['P-11', 'act.p-11.01', '切换短信视图', 'command', 'native', 'read', '[data-sms-tab]', 'PlatformAdminSmsController_channels', 'allow'], - ['P-11', 'act.p-11.02', '新建/编辑短信渠道', 'command', 'native', 'mutation', '[data-action="new-sms-channel"],[data-action="edit-sms-channel"]', 'PlatformAdminSmsController_upsertChannel', 'block'], - ['P-11', 'act.p-11.03', '启停短信渠道', 'destructive', 'native', 'mutation', '[data-action="toggle-sms-channel"]', 'PlatformAdminSmsController_upsertChannel', 'block'], - ['P-12', 'act.p-12.01', '切换支付设置视图', 'command', 'native', 'read', '[data-payment-tab]', 'PlatformAdminPaymentSettingsController_apps', 'allow'], - ['P-12', 'act.p-12.02', '新建/编辑支付应用', 'command', 'native', 'mutation', '[data-action="new-payment-app"],[data-action="edit-payment-app"]', 'PlatformAdminPaymentSettingsController_upsertApp', 'block'], - ['P-12', 'act.p-12.03', '启停支付应用', 'destructive', 'native', 'mutation', '[data-action="toggle-payment-app"]', 'PlatformAdminPaymentSettingsController_upsertApp', 'block'], - ['P-12', 'act.p-12.04', '查看风控规则', 'command', 'native', 'read', '[data-action="payment-rule-detail"]', 'PlatformAdminPaymentSettingsController_events', 'allow'], - ['P-13', 'act.p-13.01', '新建/编辑', 'command', 'native', 'mutation', '[data-action="new-staff"],[data-action="edit-staff"]', 'PlatformAdminOverviewController_upsertStaff', 'block'], - ['P-13', 'act.p-13.02', '全选/分组授权', 'command', 'native', 'mutation', '[data-action="select-permission-group"]', 'PlatformAdminOverviewController_permissions', 'block'], - ['P-13', 'act.p-13.03', '启用/禁用', 'destructive', 'native', 'mutation', '[data-action="toggle-staff"]', 'PlatformAdminOverviewController_updateStaffStatus', 'block'], - ['P-13', 'act.p-13.04', '禁用时撤销会话', 'destructive', 'native', 'audit', '[data-action="execute-staff-disable"]', 'PlatformAdminOverviewController_updateStaffStatus', 'block'], - ['P-13', 'act.p-13.05', '清空表单', 'command', 'contract', 'mutation', '[data-action="clear-staff-form"]', 'PlatformAdminOverviewController_upsertStaff', 'block'], - ['P-14', 'act.p-14.01', '筛选', 'command', 'native', 'read', '#auditSearch,#auditRangeFilter,[data-audit-severity]', 'PlatformAdminAuditController_logs', 'allow'], - ['P-14', 'act.p-14.02', '查看详情', 'command', 'native', 'read', '[data-audit-detail]', 'PlatformAdminAuditController_logs', 'allow'], - ['P-14', 'act.p-14.03', '导出 CSV/JSON', 'async', 'native', 'task', '[data-action="export-audit"]', 'PlatformAdminAuditController_exportLogs', 'allow'], - ['P-14', 'act.p-14.04', '复制 ID', 'command', 'native', 'read', '[data-copy]', 'PlatformAdminAuditController_logs', 'allow'], - ['P-14', 'act.p-14.05', '跳目标对象', 'command', 'native', 'nav', '[data-action="jump-audit-target"],[data-action="jump-related-alert"]', 'PlatformAdminAuditController_logs', 'allow'], - ['P-15', 'act.p-15.01', '确认/解决告警', 'command', 'native', 'mutation', '[data-action="transition-alert"]', 'PlatformAdminAuditController_updateAlert', 'allow'], - ['P-15', 'act.p-15.02', '查看证据', 'command', 'native', 'read', '[data-alert-detail]', 'PlatformAdminAuditController_alerts', 'allow'], - ['P-15', 'act.p-15.03', '新建/编辑/启停通知渠道', 'command', 'native', 'mutation', '[data-action="new-audit-channel"],[data-action="edit-audit-channel"],[data-action="toggle-audit-channel"]', 'PlatformAdminAuditController_upsertChannel', 'block'], - ['P-15', 'act.p-15.04', '查看失败事件', 'command', 'contract', 'read', '[data-notification-detail]', 'PlatformAdminAuditController_events', 'allow'], - ].map(([pageId, id, label, kind, mode, effect, selector, operationId, mobile]) => ({ pageId, id, label, kind, mode, effect, selector, operationIds: [operationId], mobile, destructive: kind === 'destructive', implemented: true })); - - const operationRows = [ - ['P-13', 'PlatformBackofficeController_bootstrap', 'GET', '/api/backoffice/platform/bootstrap'], - ['P-01', 'PlatformAdminOverviewController_overview', 'GET', '/api/platform-admin/overview'], - ['P-01', 'PlatformAdminAuditController_alerts', 'GET', '/api/platform-admin/audit-alerts'], - ['P-01', 'PlatformAdminAuditController_logs', 'GET', '/api/platform-admin/audit-logs'], - ['P-02', 'PlatformAdminTenantsController_list', 'GET', '/api/platform-admin/tenants'], - ['P-02', 'PlatformAdminTenantsController_create', 'POST', '/api/platform-admin/tenants'], - ['P-02A', 'PlatformAdminTenantsController_domains', 'GET', '/api/platform-admin/domains'], - ['P-02A', 'PlatformAdminTenantsController_recheckDomain', 'POST', '/api/platform-admin/domains/{domainId}/recheck'], - ['P-03', 'PlatformAdminTenantsController_detail', 'GET', '/api/platform-admin/tenants/detail'], - ['P-03', 'PlatformAdminTenantsController_status', 'PATCH', '/api/platform-admin/tenants/status'], - ['P-03', 'PlatformAdminTenantsController_billingProfile', 'PUT', '/api/platform-admin/tenants/billing-profile'], - ['P-03', 'PlatformAdminBillingController_createSubscription', 'POST', '/api/platform-admin/saas/subscriptions'], - ['P-04', 'PlatformAdminTenantsController_billingProfile', 'PUT', '/api/platform-admin/tenants/billing-profile'], - ['P-05', 'PlatformAdminOverviewController_plans', 'GET', '/api/platform-admin/saas/catalog'], - ['P-05A', 'PlatformSaasController_upsertFeature', 'PUT', '/api/platform-admin/saas/features'], - ['P-05A', 'PlatformSaasController_upsertFeatureLimit', 'PUT', '/api/platform-admin/saas/feature-limits'], - ['P-05A', 'PlatformSaasController_upsertOffering', 'PUT', '/api/platform-admin/saas/offerings'], - ['P-05A', 'PlatformSaasController_upsertVersion', 'PUT', '/api/platform-admin/saas/offering-versions'], - ['P-05A', 'PlatformSaasController_publishVersion', 'POST', '/api/platform-admin/saas/offering-versions/{versionId}/publish'], - ['P-05A', 'PlatformSaasController_cloneVersion', 'POST', '/api/platform-admin/saas/offering-versions/{versionId}/clone'], - ['P-05A', 'PlatformSaasController_retireVersion', 'POST', '/api/platform-admin/saas/offering-versions/{versionId}/retire'], - ['P-05B', 'PlatformAdminBillingController_orders', 'GET', '/api/platform-admin/saas/orders'], - ['P-05B', 'PlatformAdminBillingController_refunds', 'GET', '/api/platform-admin/saas/refunds'], - ['P-05A', 'PlatformSaasController_upsertTenantFeatureOverride', 'PUT', '/api/platform-admin/saas/tenant-feature-overrides'], - ['P-05', 'PlatformAdminBillingController_subscriptions', 'GET', '/api/platform-admin/saas/subscriptions'], - ['P-05', 'PlatformAdminBillingController_createSubscription', 'POST', '/api/platform-admin/saas/subscriptions'], - ['P-06', 'PlatformAdminBillingController_invoices', 'GET', '/api/platform-admin/saas/invoices'], - ['P-06', 'PlatformAdminBillingController_createInvoice', 'POST', '/api/platform-admin/saas/invoices'], - ['P-06', 'PlatformAdminBillingController_subscriptionCandidates', 'GET', '/api/platform-admin/saas/invoices/subscription-candidates'], - ['P-06', 'PlatformAdminBillingController_fromSubscription', 'POST', '/api/platform-admin/saas/invoices/from-subscription'], - ['P-06', 'PlatformAdminBillingController_fromSubscriptionsBatch', 'POST', '/api/platform-admin/saas/invoices/from-subscriptions-batch'], - ['P-07', 'PlatformAdminBillingController_usage', 'GET', '/api/platform-admin/saas/usage'], - ['P-07', 'PlatformAdminBillingController_recordUsage', 'POST', '/api/platform-admin/saas/usage'], - ['P-07', 'PlatformAdminBillingController_usageCandidates', 'GET', '/api/platform-admin/saas/invoices/usage-overage-candidates'], - ['P-07', 'PlatformAdminBillingController_fromUsage', 'POST', '/api/platform-admin/saas/invoices/from-usage-overage'], - ['P-08', 'PlatformAdminBillingController_confirmPayment', 'POST', '/api/platform-admin/saas/payments/manual/confirm'], - ['P-08', 'PlatformAdminBillingController_payments', 'GET', '/api/platform-admin/saas/payments'], - ['P-08', 'PlatformAdminBillingController_processOverdue', 'POST', '/api/platform-admin/saas/invoices/process-overdue'], - ['P-08', 'PlatformAdminBillingController_reminders', 'GET', '/api/platform-admin/saas/invoices/reminders'], - ['P-08', 'PlatformAdminDunningChannelsController_channels', 'GET', '/api/platform-admin/saas/dunning/channels'], - ['P-08', 'PlatformAdminDunningChannelsController_upsertChannel', 'PUT', '/api/platform-admin/saas/dunning/channels'], - ['P-08', 'PlatformAdminDunningChannelsController_disableChannel', 'POST', '/api/platform-admin/saas/dunning/channels/disable'], - ['P-08', 'PlatformAdminDunningEventsController_events', 'GET', '/api/platform-admin/saas/dunning/events'], - ['P-08', 'PlatformAdminDunningEventsController_eventDetail', 'GET', '/api/platform-admin/saas/dunning/events/detail'], - ['P-08', 'PlatformAdminDunningEventsController_retryEvent', 'POST', '/api/platform-admin/saas/dunning/events/retry'], - ['P-09', 'PlatformQuestionBanksController_getBanks', 'GET', '/api/platform-admin/question-banks'], - ['P-09', 'PlatformQuestionBanksController_upsertBank', 'PUT', '/api/platform-admin/question-banks'], - ['P-09', 'PlatformQuestionBanksController_archiveBank', 'POST', '/api/platform-admin/question-banks/{bankId}/archive'], - ['P-09', 'PlatformQuestionBanksController_getNodes', 'GET', '/api/platform-admin/question-banks/{bankId}/nodes'], - ['P-09', 'PlatformQuestionBanksController_upsertNode', 'PUT', '/api/platform-admin/question-banks/nodes'], - ['P-09', 'PlatformQuestionBanksController_batchCreateNodes', 'POST', '/api/platform-admin/question-banks/nodes/batch'], - ['P-09', 'PlatformQuestionBanksController_archiveNode', 'POST', '/api/platform-admin/question-banks/nodes/{nodeId}/archive'], - ['P-09', 'PlatformQuestionBanksController_getQuestions', 'GET', '/api/platform-admin/question-banks/questions'], - ['P-09', 'PlatformQuestionBanksController_upsertQuestion', 'PUT', '/api/platform-admin/question-banks/questions'], - ['P-09', 'PlatformQuestionBanksController_archiveQuestions', 'POST', '/api/platform-admin/question-banks/questions/archive'], - ['P-09', 'PlatformQuestionBanksController_previewImport', 'POST', '/api/platform-admin/question-banks/imports/preview'], - ['P-09', 'PlatformQuestionBanksController_executeImport', 'POST', '/api/platform-admin/question-banks/imports'], - ['P-09', 'PlatformQuestionBanksController_getImport', 'GET', '/api/platform-admin/question-banks/imports/{jobId}'], - ['P-09', 'PlatformQuestionBanksController_signAssetUpload', 'POST', '/api/platform-admin/question-banks/assets/upload-sign'], - ['P-09', 'PlatformQuestionBanksController_confirmAssetUpload', 'POST', '/api/platform-admin/question-banks/assets/upload-confirm'], - ['P-10', 'PlatformAdminCrmController_configs', 'GET', '/api/platform-admin/tenant-capabilities/crm/configs'], - ['P-10', 'PlatformAdminCrmController_upsertConfig', 'PUT', '/api/platform-admin/tenant-capabilities/crm/configs'], - ['P-10', 'PlatformAdminCrmController_leads', 'GET', '/api/platform-admin/tenant-capabilities/crm/leads'], - ['P-10', 'PlatformAdminCrmController_retryLead', 'POST', '/api/platform-admin/tenant-capabilities/crm/leads/retry'], - ['P-10', 'PlatformAdminCrmController_logs', 'GET', '/api/platform-admin/tenant-capabilities/crm/logs'], - ['P-11', 'PlatformAdminSmsController_channels', 'GET', '/api/platform-admin/tenant-capabilities/sms/channels'], - ['P-11', 'PlatformAdminSmsController_disableChannel', 'POST', '/api/platform-admin/tenant-capabilities/sms/channels/{channelId}/disable'], - ['P-11', 'PlatformAdminSmsController_templates', 'GET', '/api/platform-admin/tenant-capabilities/sms/templates'], - ['P-11', 'PlatformAdminSmsController_submitTemplateReview', 'POST', '/api/platform-admin/tenant-capabilities/sms/templates/{templateId}/submit-review'], - ['P-11', 'PlatformAdminSmsController_disableTemplate', 'POST', '/api/platform-admin/tenant-capabilities/sms/templates/{templateId}/disable'], - ['P-11', 'PlatformAdminSmsController_logs', 'GET', '/api/platform-admin/tenant-capabilities/sms/logs'], - ['P-11', 'PlatformAdminSmsController_upsertChannel', 'PUT', '/api/platform-admin/tenant-capabilities/sms/channels'], - ['P-11', 'PlatformAdminSmsController_upsertTemplate', 'PUT', '/api/platform-admin/tenant-capabilities/sms/templates'], - ['P-12', 'PlatformAdminPaymentSettingsController_apps', 'GET', '/api/platform-admin/payment-settings/apps'], - ['P-12', 'PlatformAdminPaymentSettingsController_channels', 'GET', '/api/platform-admin/payment-settings/channels'], - ['P-12', 'PlatformAdminPaymentSettingsController_upsertChannel', 'PUT', '/api/platform-admin/payment-settings/channels'], - ['P-12', 'PlatformAdminPaymentSettingsController_disableChannel', 'POST', '/api/platform-admin/payment-settings/channels/{channelId}/disable'], - ['P-12', 'PlatformAdminPaymentSettingsController_rebateSummary', 'GET', '/api/platform-admin/payment-settings/rebates/summary'], - ['P-12', 'PlatformAdminPaymentSettingsController_events', 'GET', '/api/platform-admin/payment-settings/events'], - ['P-12', 'PlatformAdminPaymentSettingsController_rebates', 'GET', '/api/platform-admin/payment-settings/rebates/summary'], - ['P-12', 'PlatformAdminPaymentSettingsController_upsertApp', 'PUT', '/api/platform-admin/payment-settings/apps'], - ['P-12', 'PlatformAdminTenantPaymentSettingsController_apps', 'GET', '/api/platform-admin/tenant-capabilities/payments/apps'], - ['P-12', 'PlatformAdminTenantPaymentSettingsController_events', 'GET', '/api/platform-admin/tenant-capabilities/payments/events'], - ['P-12', 'PlatformAdminTenantPaymentSettingsController_upsertApp', 'PUT', '/api/platform-admin/tenant-capabilities/payments/apps'], - ['P-13', 'PlatformAdminOverviewController_permissions', 'GET', '/api/platform-admin/permissions'], - ['P-13', 'PlatformAdminOverviewController_staff', 'GET', '/api/platform-admin/staff'], - ['P-13', 'PlatformAdminOverviewController_upsertStaff', 'PUT', '/api/platform-admin/staff'], - ['P-13', 'PlatformAdminOverviewController_updateStaffStatus', 'PATCH', '/api/platform-admin/staff/status'], - ['P-13A', 'PlatformBackofficeController_upsertRole', 'POST', '/api/backoffice/platform/roles'], - ['P-13A', 'PlatformBackofficeController_replaceRoleBindings', 'PUT', '/api/backoffice/platform/roles/{roleId}/bindings'], - ['P-14', 'PlatformAdminAuditController_logs', 'GET', '/api/platform-admin/audit-logs'], - ['P-14', 'PlatformAdminAuditController_exportLogs', 'GET', '/api/platform-admin/audit-logs/export'], - ['P-15', 'PlatformAdminAuditController_rules', 'GET', '/api/platform-admin/audit-alert-rules'], - ['P-15', 'PlatformAdminAuditController_alerts', 'GET', '/api/platform-admin/audit-alerts'], - ['P-15', 'PlatformAdminAuditController_updateAlert', 'POST', '/api/platform-admin/audit-alerts/status'], - ['P-15', 'PlatformAdminAuditController_channels', 'GET', '/api/platform-admin/audit-notification-channels'], - ['P-15', 'PlatformAdminAuditController_upsertChannel', 'PUT', '/api/platform-admin/audit-notification-channels'], - ['P-15', 'PlatformAdminAuditController_events', 'GET', '/api/platform-admin/audit-notification-events'], - ]; - const operations = operationRows.map(([pageId, operationId, method, path]) => ({ pageId, operationId, method, path })); - const operationById = Object.fromEntries(operations.map(operation => [operation.operationId, operation])); - - const navEdges = [ - ['nav.p-01.p-02', 'P-01', 'P-02', '[data-nav="tenants"]'], - ['nav.p-01.p-06', 'P-01', 'P-06', '[data-nav="billing"]'], - ['nav.p-01.p-10', 'P-01', 'P-10', '[data-nav="crm"]'], - ['nav.p-01.p-11', 'P-01', 'P-11', '[data-nav="sms"]'], - ['nav.p-01.p-12', 'P-01', 'P-12', '[data-nav="paymentSettings"]'], - ['nav.p-01.p-15', 'P-01', 'P-15', '[data-nav="alerts"],[data-alert-detail]'], - ['nav.p-02.p-03', 'P-02', 'P-03', '[data-tenant-detail]'], - ['nav.p-03.p-04', 'P-03', 'P-04', '[data-action="edit-billing-profile"]'], - ['nav.p-03.p-05', 'P-03', 'P-05', '[data-action="create-subscription-for-tenant"]'], - ['nav.p-03.p-06', 'P-03', 'P-06', '[data-action="tenant-to-billing"]'], - ['nav.p-05.p-06', 'P-05', 'P-06', '[data-action="subscription-to-billing"]'], - ['nav.p-05.p-07', 'P-05', 'P-07', '[data-action="subscriptions-to-usage"]'], - ['nav.p-06.p-08', 'P-06', 'P-08', '[data-nav="dunning"]'], - ['nav.p-14.p-15', 'P-14', 'P-15', '[data-action="jump-related-alert"]'], - ].map(([id, fromPageId, toPageId, selector]) => ({ id, fromPageId, toPageId, selector, implemented: true })); - - const supportingReads = []; - - const trace = []; - const decoratedActionIds = new Set(); - const selectorCollisions = new Set(); - const explicitResultActionIds = new Set(['act.p-06.01', 'act.p-06.04', 'act.p-09.01', 'act.p-09.05']); - function pushTrace(entry) { - trace.push({ at: new Date().toISOString(), ...entry }); - if (trace.length > 120) trace.splice(0, trace.length - 120); - document.documentElement.dataset.platformContractEvents = String(trace.length); - } - - function decorate(root = document, pageId = '') { - const shell = root.querySelector?.('.page-shell'); - if (shell && pageId) { - const pageOperations = operations.filter(operation => operation.pageId === pageId); - shell.dataset.specPageId = pageId; - shell.dataset.operationIds = pageOperations.map(operation => operation.operationId).join(' '); - shell.dataset.operationContracts = pageOperations.map(operation => `${operation.method} ${operation.path}`).join(' | '); - } - actions.filter(action => action.pageId === pageId).forEach(action => { - root.querySelectorAll?.(action.selector).forEach(element => { - const existingActionId = element.dataset.specActionId; - if (existingActionId && existingActionId !== action.id) selectorCollisions.add(`${existingActionId} -> ${action.id}`); - element.dataset.specActionId = action.id; - element.dataset.specActionMode = action.mode; - element.dataset.specEffect = action.effect; - element.dataset.mobileBoundary = action.mobile; - const operation = operationById[action.operationIds[0]]; - if (operation) { - element.dataset.operationId = operation.operationId; - element.dataset.operationMethod = operation.method; - element.dataset.operationPath = operation.path; - } - decoratedActionIds.add(action.id); - }); - }); - supportingReads.filter(read => read.pageId === pageId).forEach(read => { - const operation = operationById[read.operationId]; - root.querySelectorAll?.(read.selector).forEach(element => { - element.dataset.specSupportingRead = 'true'; - element.dataset.specEffect = 'read'; - if (operation) { - element.dataset.operationId = operation.operationId; - element.dataset.operationMethod = operation.method; - element.dataset.operationPath = operation.path; - } - }); - }); - navEdges.filter(edge => edge.fromPageId === pageId).forEach(edge => { - root.querySelectorAll?.(edge.selector).forEach(element => { - element.dataset.navEdgeId = edge.id; - element.dataset.navTargetPage = edge.toPageId; - }); - }); - window.__PLATFORM_SPEC_COVERAGE__ = coverage(); - } - - function eventContract(target) { - const element = target?.closest?.('[data-spec-action-id]'); - if (!element) return null; - return { element, actionId: element.dataset.specActionId, operationId: element.dataset.operationId || '', requestId: `req_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 7)}` }; - } - - document.addEventListener('click', event => { - const contract = eventContract(event.target); - if (!contract) return; - contract.element.dataset.contractRequestId = contract.requestId; - pushTrace({ phase: 'before', actionId: contract.actionId, operationId: contract.operationId, requestId: contract.requestId }); - setTimeout(() => pushTrace({ phase: 'after', actionId: contract.actionId, operationId: contract.operationId, requestId: contract.requestId, result: 'handled', pageId: document.querySelector('.page-shell')?.dataset.specPageId || '' }), 0); - }, true); - - document.addEventListener('change', event => { - const contract = eventContract(event.target); - if (!contract) return; - pushTrace({ phase: 'after', actionId: contract.actionId, operationId: contract.operationId, requestId: contract.requestId, result: 'changed' }); - }, true); - - const coverage = () => ({ - expected: 70, - total: actions.length, - unique: new Set(actions.map(action => action.id)).size, - catalogued: actions.filter(action => action.label && action.kind).length, - selectorDeclared: actions.filter(action => action.selector).length, - nativeMetadata: actions.filter(action => action.mode === 'native').length, - contractMetadata: actions.filter(action => action.mode === 'contract').length, - nativeMapped: actions.filter(action => action.mode === 'native' && decoratedActionIds.has(action.id)).length, - dedicatedExecutor: explicitResultActionIds.size, - dedicatedExecutorDefinition: 'actions with explicit success/failure result recording', - reachable: actions.filter(action => action.implemented && action.selector).length, - mountedThisSession: decoratedActionIds.size, - decoratedInSession: decoratedActionIds.size, - notYetDecorated: actions.filter(action => !decoratedActionIds.has(action.id)).map(action => action.id), - implemented: actions.filter(action => action.implemented && action.selector).length, - unimplemented: actions.filter(action => !action.implemented || !action.selector).map(action => action.id), - selectorCollisions: Array.from(selectorCollisions), - apiExact: operations.filter(operation => operation.operationId && operation.method && operation.path).length, - uiOnlyExplained: actions.filter(action => action.operationIds.length === 0).length, - effectDeclared: actions.filter(action => action.effect).length, - mobileDeclared: actions.filter(action => action.mobile).length, - actuallyExecuted: new Set(trace.filter(entry => entry.phase === 'result' && entry.result === 'success').map(entry => entry.actionId)).size, - executionNote: 'catalogue and selector metadata are not counted as successful business execution', - navigation: { expected: 14, total: navEdges.length, unique: new Set(navEdges.map(edge => edge.id)).size }, - pageBindings: { expected: 63, total: operations.length, unique: new Set(operations.map(operation => `${operation.pageId}:${operation.operationId}`)).size }, - }); - const assertions = { - pages: new Set(actions.map(action => action.pageId)).size === 15, - actionIds: actions.every(action => action.id.startsWith(`act.${action.pageId.toLowerCase()}.`)), - duplicateActions: new Set(actions.map(action => action.id)).size === actions.length, - operationContracts: operations.every(operation => /^(GET|POST|PUT|PATCH|DELETE)$/.test(operation.method) && operation.path.startsWith('/api/')), - navTargets: navEdges.every(edge => actions.some(action => action.pageId === edge.fromPageId) && actions.some(action => action.pageId === edge.toPageId)), - }; - window.GONGXUE_PLATFORM_SPEC = { actions, operations, navEdges, supportingReads }; - window.__GONGXUE_ACTION_CONTRACT__ = { coverage, assertions, trace }; - window.decoratePlatformSpec = decorate; - window.recordPlatformSpecResult = (actionId, result = {}) => pushTrace({ phase: 'result', actionId, ...result }); - window.__PLATFORM_CONTRACT_EVENTS__ = trace; - window.__PLATFORM_SPEC_COVERAGE__ = coverage(); -})(); diff --git a/Tiku.Api/wwwroot/platform-admin/styles.css b/Tiku.Api/wwwroot/platform-admin/styles.css deleted file mode 100644 index 90379ca..0000000 --- a/Tiku.Api/wwwroot/platform-admin/styles.css +++ /dev/null @@ -1,49 +0,0 @@ -:root{--navy:#111827;--navy-2:#1d2939;--blue:#1455ff;--blue-50:#f3f6ff;--blue-100:#e7edff;--ink:#101828;--ink-2:#344054;--muted:#667085;--line:#e4e7ec;--canvas:#f5f6f8;--green:#159455;--orange:#ed8b00;--red:#d92d20;--purple:#6941c6;--cyan:#088ab2;--sidebar:230px;font-family:Inter,"PingFang SC","Microsoft YaHei",system-ui,sans-serif;color:var(--ink);background:var(--canvas);font-synthesis:none}*{box-sizing:border-box}html,body{margin:0;min-height:100%;background:var(--canvas)}body{min-width:320px;letter-spacing:0}button,input,select,textarea{font:inherit;letter-spacing:0}button{cursor:pointer;color:inherit}button:focus-visible,input:focus-visible,select:focus-visible{outline:3px solid rgba(20,85,255,.2);outline-offset:2px}svg{width:19px;height:19px}.platform-app{min-height:100vh;display:grid;grid-template-columns:var(--sidebar) minmax(0,1fr)}.platform-sidebar{position:fixed;inset:0 auto 0 0;z-index:30;width:var(--sidebar);display:flex;flex-direction:column;padding:17px 14px;background:var(--navy);color:#d0d5dd;overflow:auto}.platform-brand{height:53px;display:flex;align-items:center;gap:10px;padding:4px 7px;border:0;background:transparent;color:#fff;text-align:left}.platform-brand img{width:37px;height:37px;border-radius:7px}.platform-brand span{display:grid;gap:2px}.platform-brand strong{font-size:15px}.platform-brand small{color:#98a2b3;font-size:8px}.environment{height:34px;display:grid;grid-template-columns:8px 1fr auto;align-items:center;gap:7px;margin:13px 6px 21px;padding:0 9px;border:1px solid #344054;background:#182230;font-size:8px}.environment i{width:7px;height:7px;border-radius:50%;background:#32d583;box-shadow:0 0 0 3px rgba(50,213,131,.1)}.environment b{color:#98a2b3;font-size:7px}#sideNav{display:grid;gap:19px}#sideNav section{display:grid;gap:3px}#sideNav h2{margin:0 10px 5px;color:#667085;font-size:7.5px;text-transform:uppercase}#sideNav button,.platform-foot>button{position:relative;width:100%;height:40px;display:grid;grid-template-columns:20px 1fr auto;align-items:center;gap:8px;padding:0 10px;border:0;border-radius:5px;background:transparent;color:#98a2b3;text-align:left;font-size:10px;font-weight:650}#sideNav button:hover,.platform-foot>button:hover{background:#1d2939;color:#fff}#sideNav button.is-active{background:#23335d;color:#fff}#sideNav button.is-active:before{content:"";position:absolute;left:-14px;width:3px;height:25px;background:#6b8cff}#sideNav svg,.platform-foot svg{width:16px}#sideNav b{min-width:18px;height:18px;display:grid;place-items:center;border-radius:9px;background:#d92d20;color:#fff;font-size:7px}.platform-foot{margin-top:auto;padding-top:14px;border-top:1px solid #344054}.platform-foot>div{height:54px;display:grid;grid-template-columns:31px 1fr 24px;align-items:center;gap:8px;margin:8px 4px 0}.platform-foot>div>span{width:30px;height:30px;display:grid;place-items:center;border-radius:50%;background:#344054;color:#fff;font-size:9px}.platform-foot p{display:grid;gap:3px;margin:0}.platform-foot strong{color:#fff;font-size:9px}.platform-foot small{color:#667085;font-size:7.5px}.platform-foot>div button{border:0;background:transparent;color:#667085}.platform-foot>div svg{width:14px}.platform-workspace{grid-column:2;min-width:0}.platform-topbar{position:sticky;top:0;z-index:20;height:66px;display:flex;align-items:center;gap:22px;padding:0 30px;border-bottom:1px solid var(--line);background:rgba(255,255,255,.96);backdrop-filter:blur(12px)}.page-context{display:grid;gap:3px;min-width:190px}.page-context small{color:#98a2b3;font-size:7px}.page-context strong{font-size:11px}.platform-search{width:min(470px,37vw);height:37px;display:flex;align-items:center;gap:8px;padding:0 10px;border:1px solid transparent;background:#f3f5f7}.platform-search:focus-within{border-color:#a9c0ff;background:#fff}.platform-search svg{width:15px;color:var(--muted)}.platform-search input{min-width:0;width:100%;border:0;outline:0;background:transparent;font-size:9px}.platform-search kbd{padding:2px 5px;border:1px solid var(--line);background:#fff;color:var(--muted);font-size:7px}.top-status{margin-left:auto;display:flex;align-items:center;gap:13px}.top-status>span{display:flex;align-items:center;gap:6px;color:var(--green);font-size:8px}.top-status>span i{width:7px;height:7px;border-radius:50%;background:#32d583}.icon-button{position:relative;width:36px;height:36px;display:grid;place-items:center;border:1px solid var(--line);background:#fff}.icon-button svg{width:16px}.icon-button b{position:absolute;right:-3px;top:-4px;min-width:17px;height:17px;display:grid;place-items:center;border:2px solid #fff;border-radius:9px;background:var(--red);color:#fff;font-size:7px}.mobile-menu{display:none}#mainView{min-height:calc(100vh - 66px);padding:26px 30px 48px}.page-shell{width:min(1540px,100%);margin:0 auto}.page-head{min-height:52px;display:flex;align-items:flex-start;justify-content:space-between;gap:20px;margin-bottom:18px}.page-head h1{margin:0;font-size:21px}.page-head p{margin:5px 0 0;color:var(--muted);font-size:9.5px}.page-head>div:last-child{display:flex;gap:8px}.button{min-height:36px;display:inline-flex;align-items:center;justify-content:center;gap:7px;padding:0 12px;border:1px solid #d0d5dd;background:#fff;font-size:9px;font-weight:650}.button:hover{border-color:#9db9ff;color:var(--blue)}.button.primary{border-color:var(--blue);background:var(--blue);color:#fff}.button.danger{border-color:#ffb4ae;color:var(--red)}.button svg{width:14px}.control{height:36px;border:1px solid var(--line);background:#fff;padding:0 9px;font-size:8px}.link{padding:0;border:0;background:transparent;color:var(--blue);font-size:8px;font-weight:700}.metric-grid{display:grid;grid-template-columns:repeat(5,1fr);gap:11px}.metric{min-height:112px;display:grid;grid-template-columns:40px 1fr;align-items:center;gap:12px;padding:17px;border:1px solid var(--line);background:#fff}.metric-icon{width:38px;height:38px;display:grid;place-items:center;border-radius:6px;background:var(--blue-100);color:var(--blue)}.metric-icon.green{background:#edf9f2;color:var(--green)}.metric-icon.orange{background:#fff5e8;color:var(--orange)}.metric-icon.red{background:#fff0ef;color:var(--red)}.metric-icon.purple{background:#f3f0ff;color:var(--purple)}.metric-icon.cyan{background:#edfafd;color:var(--cyan)}.metric-icon svg{width:17px}.metric div{display:grid;gap:5px}.metric small,.metric p{margin:0;color:var(--muted);font-size:7.5px}.metric strong{font-size:20px}.panel,.table-panel{border:1px solid var(--line);background:#fff}.panel-head{min-height:60px;display:flex;align-items:center;justify-content:space-between;gap:12px;padding:0 17px;border-bottom:1px solid var(--line)}.panel-head h2{margin:0;font-size:11px}.panel-head span{display:block;margin-top:4px;color:var(--muted);font-size:7.5px}.overview-grid{display:grid;grid-template-columns:minmax(0,1.7fr) minmax(310px,.72fr);gap:11px;margin-top:11px}.revenue-panel{min-width:0}.legend{display:flex;gap:12px;color:var(--muted);font-size:7.5px}.legend span{display:flex!important;align-items:center;gap:5px}.legend i{width:7px;height:7px;border-radius:50%}.legend .blue{background:var(--blue)}.legend .green{background:var(--green)}.revenue-chart{height:278px;display:grid;grid-template-columns:38px 1fr;padding:24px 18px 18px}.chart-axis{display:flex;flex-direction:column;justify-content:space-between;color:#98a2b3;font-size:7px}.chart-plot{position:relative}.chart-plot .grid{position:absolute;inset:0 0 20px;background:repeating-linear-gradient(to bottom,var(--line) 0,var(--line) 1px,transparent 1px,transparent 33.333%)}.bars{position:absolute;inset:0;display:flex;align-items:end;gap:8px}.bars>span{height:100%;flex:1;display:flex;align-items:end;justify-content:center;gap:3px;position:relative;padding-bottom:20px}.bars i{width:45%;background:var(--blue);opacity:.78}.bars b{width:18%;background:var(--green)}.bars em{position:absolute;bottom:0;color:#98a2b3;font-size:6.5px;font-style:normal}.alert-row{width:100%;min-height:62px;display:grid;grid-template-columns:34px minmax(0,1fr) 14px;align-items:center;gap:9px;padding:9px 14px;border:0;border-bottom:1px solid var(--line);background:#fff;text-align:left}.alert-row:last-child{border-bottom:0}.alert-row:hover{background:#fafbfc}.alert-row>span{width:32px;height:32px;display:grid;place-items:center;border-radius:6px;background:#fff5e8;color:var(--orange)}.alert-row svg{width:15px}.alert-row div{display:grid;gap:4px}.alert-row strong{font-size:8.5px}.alert-row small{color:var(--muted);font-size:7px}.alert-row>svg{color:#98a2b3}.overview-lower{display:grid;grid-template-columns:.8fr 1fr 1fr;gap:11px;margin-top:11px}.tenant-health{min-height:192px;display:grid;grid-template-columns:140px 1fr;align-items:center;gap:10px;padding:17px}.health-donut{width:118px;height:118px;display:grid;place-items:center;align-content:center;gap:2px;border-radius:50%;background:conic-gradient(var(--blue) 79%,#6b8cff 0 89%,#a9bbff 0 95%,#e4e7ec 0);position:relative}.health-donut:before{content:"";position:absolute;width:82px;height:82px;border-radius:50%;background:#fff}.health-donut strong,.health-donut span{position:relative}.health-donut strong{font-size:19px}.health-donut span{color:var(--muted);font-size:7px}.tenant-health>div:last-child{display:grid;gap:10px}.tenant-health p{display:grid;grid-template-columns:55px 1fr 20px;align-items:center;gap:7px;margin:0;font-size:7.5px}.tenant-health p i{height:4px;background:#edf0f4}.tenant-health p i b{display:block;height:100%;background:var(--blue)}.usage-summary{display:grid;grid-template-columns:repeat(3,1fr);padding:18px}.usage-summary>div{display:grid;gap:6px;padding:0 13px;border-right:1px solid var(--line)}.usage-summary>div:first-child{padding-left:0}.usage-summary>div:last-child{border-right:0}.usage-summary span,.usage-summary small{color:var(--muted);font-size:7px}.usage-summary strong{font-size:15px}.usage-summary i,.usage-kpis i,.usage-cell i,.drawer-usage i{height:4px;background:#edf0f4}.usage-summary i b,.usage-kpis i b,.usage-cell i b,.drawer-usage i b{display:block;height:100%;background:var(--blue)}.platform-activity{display:grid;padding:7px 14px}.platform-activity>div{min-height:51px;display:grid;grid-template-columns:27px 1fr;align-items:center;gap:8px;border-bottom:1px solid var(--line)}.platform-activity>div:last-child{border-bottom:0}.platform-activity>div>span{width:26px;height:26px;display:grid;place-items:center;border-radius:50%;background:#f2f4f7;font-size:7px}.platform-activity p{display:grid;gap:4px;margin:0;font-size:7.5px}.platform-activity small{color:var(--muted);font-size:6.5px}.filter-bar{min-height:59px;display:flex;align-items:center;gap:8px;padding:10px 12px;border:1px solid var(--line);background:#fff}.filter-bar label{min-width:300px;height:36px;display:flex;align-items:center;gap:7px;padding:0 9px;border:1px solid var(--line);background:#f8fafc}.filter-bar label svg{width:14px;color:var(--muted)}.filter-bar input{min-width:0;width:100%;border:0;outline:0;background:transparent;font-size:8px}.filter-bar select{height:36px;border:1px solid var(--line);background:#fff;padding:0 28px 0 9px;font-size:8px}.filter-segment{display:flex;gap:3px;margin-left:auto;padding:3px;background:#f2f4f7}.filter-segment button{height:28px;padding:0 9px;border:0;background:transparent;color:var(--muted);font-size:7px;white-space:nowrap}.filter-segment button.is-active{background:#fff;color:var(--blue);box-shadow:0 1px 4px rgba(16,24,40,.08);font-weight:700}.table-panel{overflow:auto;border-top:0}.platform-table{width:100%;min-width:1040px;border-collapse:collapse}.platform-table th{height:42px;padding:0 12px;background:#f8fafc;color:var(--muted);font-size:7px;font-weight:650;text-align:left}.platform-table td{height:65px;padding:8px 12px;border-top:1px solid var(--line);font-size:8px;vertical-align:middle}.platform-table tr:hover td{background:#fcfcfd}.platform-table td>strong,.platform-table td>small{display:block}.platform-table td>small{margin-top:4px;color:var(--muted);font-size:6.5px}.tenant-cell{display:flex;align-items:center;gap:9px}.tenant-cell>span{width:31px;height:31px;display:grid;place-items:center;border-radius:6px;background:var(--blue-100);color:var(--blue);font-size:8px;font-weight:800}.tenant-cell>div{display:grid;gap:4px}.tenant-cell strong{font-size:8.5px}.tenant-cell small{color:var(--muted);font-size:6.5px}.status{display:inline-flex;align-items:center;justify-content:center;min-height:21px;padding:0 7px;border-radius:4px;font-size:6.5px!important;font-style:normal;font-weight:700;white-space:nowrap}.status.success{background:#edf9f2;color:var(--green)}.status.warning{background:#fff5e8;color:#b96700}.status.danger{background:#fff0ef;color:var(--red)}.status.neutral{background:#f2f4f7;color:var(--muted)}.money-due{color:var(--red)}.row-action{width:28px;height:28px;display:grid;place-items:center;border:0;background:transparent;color:var(--muted)}.row-action:hover{background:var(--blue-100);color:var(--blue)}.row-action svg{width:13px}.table-panel>footer{height:48px;display:flex;align-items:center;justify-content:space-between;padding:0 13px;border-top:1px solid var(--line);color:var(--muted);font-size:7px}.table-panel>footer button{display:flex;align-items:center;gap:5px;border:0;background:transparent;color:var(--blue);font-size:7px}.table-panel>footer svg{width:12px}.drawer-backdrop{position:fixed;z-index:60;inset:0;background:rgba(16,24,40,.28)}.tenant-drawer{position:absolute;right:0;top:0;bottom:0;width:min(620px,100%);display:flex;flex-direction:column;background:#fff;box-shadow:-18px 0 50px rgba(16,24,40,.18);overflow:auto}.tenant-drawer>header{min-height:92px;display:flex;align-items:center;justify-content:space-between;padding:16px 21px;border-bottom:1px solid var(--line)}.tenant-drawer>header>div{display:flex;align-items:center;gap:12px}.tenant-drawer>header>div>span{width:45px;height:45px;display:grid;place-items:center;border-radius:8px;background:var(--blue-100);color:var(--blue);font-size:12px;font-weight:800}.tenant-drawer header small{color:var(--blue);font-size:7px}.tenant-drawer h2{margin:4px 0;font-size:15px}.tenant-drawer header p{margin:0;color:var(--muted);font-size:7px}.tenant-drawer header>button{border:0;background:transparent}.tenant-drawer header svg{width:17px}.drawer-status{display:grid!important;grid-template-columns:repeat(4,1fr);padding:0!important;border-bottom:1px solid var(--line)}.drawer-status>div{min-height:73px;display:grid;align-content:center;gap:6px;padding:13px;border-right:1px solid var(--line)}.drawer-status>div:last-child{border-right:0}.drawer-status span{color:var(--muted);font-size:7px}.drawer-status strong{font-size:8px}.drawer-tabs{height:43px;display:flex;gap:16px;padding:0 20px;border-bottom:1px solid var(--line)}.drawer-tabs button{border:0;background:transparent;color:var(--muted);font-size:7.5px}.drawer-tabs button.is-active{color:var(--blue);border-bottom:2px solid var(--blue);font-weight:700}.tenant-drawer>section{padding:19px 21px;border-bottom:1px solid var(--line)}.tenant-drawer>section h3{margin:0 0 12px;font-size:10px}.tenant-drawer dl{display:grid;grid-template-columns:1fr 1fr;gap:13px;margin:0}.tenant-drawer dl div{display:grid;gap:4px}.tenant-drawer dt{color:var(--muted);font-size:7px}.tenant-drawer dd{margin:0;font-size:8px}.domain-item{min-height:49px;display:grid;grid-template-columns:24px 1fr auto;align-items:center;gap:8px;border-bottom:1px solid var(--line)}.domain-item>svg{width:15px;color:var(--blue)}.domain-item span{display:grid;gap:4px}.domain-item strong{font-size:8px}.domain-item small{color:var(--muted);font-size:6.5px}.drawer-usage{display:grid;gap:13px}.drawer-usage>div{display:grid;grid-template-columns:80px 1fr;align-items:center;gap:6px 12px}.drawer-usage span{color:var(--muted);font-size:7px}.drawer-usage strong{font-size:8px}.drawer-usage i{grid-column:2}.tenant-drawer>footer{position:sticky;bottom:0;display:flex;justify-content:flex-end;gap:7px;margin-top:auto;padding:12px 20px;border-top:1px solid var(--line);background:#fff}.lifecycle-summary{display:grid;grid-template-columns:repeat(4,1fr);gap:10px}.lifecycle-summary article{min-height:92px;display:grid;grid-template-columns:42px 1fr 20px;align-items:center;gap:10px;padding:15px;border:1px solid var(--line);background:#fff}.stage-number{width:40px;height:40px;display:grid;place-items:center;border-radius:50%;background:var(--blue-100);color:var(--blue);font-size:15px;font-weight:800}.stage-number.risk{background:#fff0ef;color:var(--red)}.lifecycle-summary article>div{display:grid;gap:5px}.lifecycle-summary strong{font-size:9px}.lifecycle-summary small{color:var(--muted);font-size:7px}.lifecycle-summary button{border:0;background:transparent;color:#98a2b3}.lifecycle-summary svg{width:13px}.lifecycle-grid{display:grid;grid-template-columns:1.2fr .8fr;gap:11px;margin-top:11px}.lifecycle-row{min-height:64px;display:grid;grid-template-columns:31px minmax(0,1fr) 42px auto;align-items:center;gap:9px;padding:8px 15px;border-bottom:1px solid var(--line)}.lifecycle-row>span{width:29px;height:29px;display:grid;place-items:center;border-radius:6px;background:var(--blue-100);color:var(--blue);font-size:8px}.lifecycle-row>div{display:grid;gap:4px}.lifecycle-row strong{font-size:8px}.lifecycle-row small{color:var(--muted);font-size:6.5px}.lifecycle-row>b{color:var(--orange);font-size:8px}.setup-card{padding:17px}.setup-card header{display:flex;justify-content:space-between;margin-bottom:12px}.setup-card header span{font-size:9px;font-weight:700}.setup-card header b{color:var(--blue);font-size:8px}.setup-card p{display:flex;align-items:center;gap:7px;margin:0;min-height:35px;color:var(--muted);font-size:7.5px}.setup-card p.done{color:var(--green)}.setup-card p svg{width:14px}.setup-card .button{width:100%;margin-top:12px}.plan-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:11px}.plan-card{min-height:330px;padding:20px;border:1px solid var(--line);background:#fff}.plan-card.is-featured{border:2px solid var(--blue);padding:19px}.plan-card header{display:flex;justify-content:space-between;gap:10px}.plan-card header span{font-size:13px;font-weight:800}.plan-card header p{margin:5px 0 0;color:var(--muted);font-size:7.5px}.plan-card header b{height:21px;padding:0 7px;display:flex;align-items:center;background:var(--blue-100);color:var(--blue);font-size:6.5px;white-space:nowrap}.plan-card>strong{display:block;margin:26px 0 22px;color:var(--blue);font-size:31px}.plan-card>strong small{color:var(--muted);font-size:8px}.plan-card ul{display:grid;gap:12px;margin:0 0 25px;padding:18px 0;border-block:1px solid var(--line);list-style:none}.plan-card li{display:flex;align-items:center;gap:7px;font-size:8px}.plan-card li svg{width:13px;color:var(--green)}.plan-card>.button{width:100%}.subscription-table{margin-top:11px;border-top:1px solid var(--line)}.table-head{height:58px;display:flex;align-items:center;justify-content:space-between;padding:0 15px;border-bottom:1px solid var(--line)}.table-head h2{margin:0;font-size:10px}.table-head span{color:var(--muted);font-size:7px}.table-head label{width:220px;height:32px;display:flex;align-items:center;gap:6px;padding:0 8px;border:1px solid var(--line);background:#f8fafc}.table-head svg{width:13px;color:var(--muted)}.table-head input{min-width:0;width:100%;border:0;outline:0;background:transparent;font-size:7.5px}.switch{width:32px;height:18px;padding:2px;border:0;border-radius:9px;background:#d0d5dd}.switch i{display:block;width:14px;height:14px;border-radius:50%;background:#fff}.switch.is-on{background:var(--blue)}.switch.is-on i{transform:translateX(14px)}.billing-metrics{grid-template-columns:repeat(4,1fr)}.billing-tabs{height:47px;display:flex;gap:22px;margin-top:11px;padding:0 15px;border:1px solid var(--line);border-bottom:0;background:#fff}.billing-tabs button{border:0;background:transparent;color:var(--muted);font-size:8px}.billing-tabs button.is-active{color:var(--blue);border-bottom:2px solid var(--blue);font-weight:700}.collection-console{display:grid;grid-template-columns:1.2fr .8fr;gap:11px}.collection-console>.panel{border-top:0}.collection-console article{min-height:70px;display:grid;grid-template-columns:34px minmax(0,1fr) auto auto;align-items:center;gap:9px;padding:9px 15px;border-bottom:1px solid var(--line)}.collection-console article>span{width:32px;height:32px;display:grid;place-items:center;background:#fff0ef;color:var(--red)}.collection-console article svg{width:15px}.collection-console article>div{display:grid;gap:4px}.collection-console article strong{font-size:8.5px}.collection-console article small{color:var(--muted);font-size:7px}.collection-console article>b{color:var(--red);font-size:8px}.policy-timeline{padding:15px}.policy-timeline p{position:relative;display:grid;gap:4px;margin:0;padding:0 0 20px 20px;border-left:1px solid var(--line)}.policy-timeline p:last-child{padding-bottom:0}.policy-timeline p:before{content:"";position:absolute;left:-4px;top:2px;width:7px;height:7px;border-radius:50%;background:var(--blue)}.policy-timeline b{font-size:8px}.policy-timeline span{color:var(--muted);font-size:7px}.usage-kpis{display:grid;grid-template-columns:repeat(4,1fr);margin-bottom:11px;border:1px solid var(--line);background:#fff}.usage-kpis>div{min-height:110px;display:grid;gap:6px;align-content:center;padding:16px 18px;border-right:1px solid var(--line)}.usage-kpis>div:last-child{border-right:0}.usage-kpis span,.usage-kpis small{color:var(--muted);font-size:7px}.usage-kpis strong{font-size:20px}.usage-kpis i.orange b{background:var(--orange)}.usage-cell{min-width:110px;display:grid;gap:6px}.usage-cell span{font-size:7px}.bank-layout{min-height:600px;display:grid;grid-template-columns:280px minmax(0,1fr);border:1px solid var(--line);background:#fff}.bank-tree{border-right:1px solid var(--line)}.bank-tree header{height:51px;display:flex;align-items:center;justify-content:space-between;padding:0 13px;border-bottom:1px solid var(--line)}.bank-tree header strong{font-size:9px}.bank-tree header button{border:0;background:transparent;color:var(--blue)}.bank-tree header svg{width:14px}.bank-tree>button{width:100%;min-height:57px;display:grid;grid-template-columns:28px 1fr 14px;align-items:center;gap:8px;padding:8px 12px;border:0;border-bottom:1px solid var(--line);background:#fff;text-align:left}.bank-tree>button.is-active{background:var(--blue-50);box-shadow:inset 3px 0 var(--blue)}.bank-tree>button>svg:first-child{width:16px;color:var(--blue)}.bank-tree>button>svg:last-child{width:13px;color:#98a2b3}.bank-tree>button span{display:grid;gap:4px}.bank-tree strong{font-size:8px}.bank-tree small{color:var(--muted);font-size:6.5px}.bank-content{min-width:0;padding:22px}.bank-content>header{display:flex;align-items:flex-start;justify-content:space-between}.bank-content header span{color:var(--blue);font-size:7px}.bank-content h2{margin:7px 0 5px;font-size:16px}.bank-content header p{margin:0;color:var(--muted);font-size:7.5px}.bank-stats{display:grid;grid-template-columns:repeat(4,1fr);margin:20px 0;border:1px solid var(--line)}.bank-stats>div{min-height:75px;display:grid;align-content:center;gap:5px;padding:13px;border-right:1px solid var(--line)}.bank-stats>div:last-child{border-right:0}.bank-stats span{color:var(--muted);font-size:7px}.bank-stats strong{font-size:17px}.version-card{min-height:115px;display:flex;align-items:center;justify-content:space-between;gap:15px;padding:17px;border:1px solid var(--line);margin-top:10px}.version-card h3{margin:8px 0 6px;font-size:12px}.version-card p{margin:0;color:var(--ink-2);font-size:8px}.version-card small{display:block;margin-top:8px;color:var(--muted);font-size:6.5px}.version-card>div:last-child{display:flex;gap:7px}.audit-filter label{min-width:320px}.audit-table code{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:6.5px}.severity{display:inline-flex;align-items:center;justify-content:center;min-width:34px;height:20px;border-radius:4px;font-size:6.5px;font-weight:800}.severity.success{background:#edf9f2;color:var(--green)}.severity.warning{background:#fff5e8;color:#b96700}.severity.danger{background:#fff0ef;color:var(--red)}.severity.neutral{background:#f2f4f7;color:var(--muted)}.alert-layout{display:grid;grid-template-columns:minmax(0,1.35fr) minmax(320px,.65fr);gap:11px}.security-alert{min-height:94px;display:grid;grid-template-columns:40px minmax(0,1fr) auto auto;align-items:center;gap:11px;padding:12px 15px;border-bottom:1px solid var(--line)}.alert-level{width:38px;height:38px;display:grid;place-items:center;border-radius:50%;font-size:7px;font-weight:800}.alert-level.danger{background:#fff0ef;color:var(--red)}.alert-level.warning{background:#fff5e8;color:#b96700}.security-alert>div{display:grid;gap:4px}.security-alert small,.security-alert em{color:var(--muted);font-size:6.5px;font-style:normal}.security-alert strong{font-size:8.5px}.security-alert p{margin:0;color:var(--ink-2);font-size:7px}.channel-panel{display:grid;align-content:start;gap:11px}.channel-row{min-height:65px;display:grid;grid-template-columns:32px minmax(0,1fr) auto 22px;align-items:center;gap:8px;padding:9px 13px;border-bottom:1px solid var(--line)}.channel-row>span{width:30px;height:30px;display:grid;place-items:center;background:var(--blue-100);color:var(--blue)}.channel-row svg{width:14px}.channel-row>div{display:grid;gap:4px}.channel-row strong{font-size:8px}.channel-row small{color:var(--muted);font-size:6.5px}.channel-row>button{border:0;background:transparent}.failure-panel>div:last-child{padding:15px}.failure-panel strong{font-size:8px}.failure-panel p{color:var(--muted);font-size:7px;line-height:1.6}.staff-layout{display:grid;grid-template-columns:1.1fr .9fr;gap:11px}.staff-row{min-height:67px;display:grid;grid-template-columns:32px minmax(0,1fr) 82px 90px auto 22px;align-items:center;gap:9px;padding:9px 14px;border-bottom:1px solid var(--line)}.staff-row>span{width:30px;height:30px;display:grid;place-items:center;border-radius:50%;background:var(--blue-100);color:var(--blue);font-size:8px}.staff-row>div{display:grid;gap:4px}.staff-row strong{font-size:8px}.staff-row small{color:var(--muted);font-size:6.5px}.staff-row>b,.staff-row>em{font-size:7px;font-style:normal;font-weight:500}.staff-row>button{border:0;background:transparent}.role-row{min-height:68px;display:grid;grid-template-columns:32px minmax(0,1fr) 30px auto;align-items:center;gap:9px;padding:9px 14px;border-bottom:1px solid var(--line)}.role-row>span{width:30px;height:30px;display:grid;place-items:center;background:#edf9f2;color:var(--green)}.role-row svg{width:14px}.role-row>div{display:grid;gap:4px}.role-row strong{font-size:8px}.role-row small{color:var(--muted);font-size:6.5px}.role-row>b{font-size:7px}.toast{position:fixed;z-index:100;left:50%;bottom:24px;min-height:40px;display:flex;align-items:center;gap:8px;padding:0 13px;background:#101828;color:#fff;box-shadow:0 12px 30px rgba(16,24,40,.24);transform:translate(-50%,16px);opacity:0;pointer-events:none;transition:.2s;font-size:8px}.toast.is-visible{transform:translate(-50%,0);opacity:1}.toast svg{width:14px;color:#78e2a8} -@media(max-width:1240px){:root{--sidebar:210px}.metric-grid{grid-template-columns:repeat(3,1fr)}.overview-grid{grid-template-columns:1fr}.overview-lower{grid-template-columns:1fr 1fr}.activity-panel{grid-column:1/-1}.lifecycle-grid,.collection-console,.alert-layout{grid-template-columns:1fr}.staff-layout{grid-template-columns:1fr}} -@media(max-width:900px){.platform-app{display:block}.platform-sidebar{transform:translateX(-100%);transition:.2s;box-shadow:18px 0 48px rgba(16,24,40,.28)}.platform-app.menu-open .platform-sidebar{transform:translateX(0)}.platform-workspace{min-width:0}.platform-topbar{height:58px;padding:0 12px;gap:9px}.mobile-menu{display:grid}.page-context small,.platform-search kbd,.top-status>span{display:none}.page-context{min-width:120px}.platform-search{width:auto;flex:1}#mainView{padding:18px 12px 32px}.page-head{align-items:flex-start;flex-direction:column}.page-head>div:last-child{width:100%;overflow:auto}.metric-grid{grid-template-columns:1fr 1fr}.overview-lower{grid-template-columns:1fr}.activity-panel{grid-column:auto}.filter-bar{align-items:stretch;flex-wrap:wrap}.filter-bar label{min-width:100%}.filter-bar select{flex:1}.filter-segment{width:100%;margin-left:0;overflow:auto}.filter-segment button{flex:1}.table-panel{border-top:1px solid var(--line)}.lifecycle-summary{grid-template-columns:1fr 1fr}.plan-grid{grid-template-columns:1fr}.collection-console{grid-template-columns:1fr}.usage-kpis{grid-template-columns:1fr 1fr}.bank-layout{display:block}.bank-tree{border-right:0;border-bottom:1px solid var(--line)}.bank-tree>button{display:inline-grid;width:260px;border-right:1px solid var(--line)}.bank-tree{overflow:auto;white-space:nowrap}.bank-tree header{position:sticky;left:0;background:#fff}.bank-content{padding:16px}.staff-layout{grid-template-columns:1fr}} -@media(max-width:560px){.page-context{display:none}.top-status .icon-button{display:none}.metric-grid{grid-template-columns:1fr}.metric{min-height:94px}.revenue-chart{height:230px;padding-inline:8px}.overview-lower{grid-template-columns:1fr}.tenant-health{grid-template-columns:1fr;justify-items:center}.usage-summary{grid-template-columns:1fr}.usage-summary>div{padding:12px 0;border-right:0;border-bottom:1px solid var(--line)}.usage-summary>div:last-child{border-bottom:0}.lifecycle-summary{grid-template-columns:1fr}.drawer-status{grid-template-columns:1fr 1fr}.drawer-status>div:nth-child(2){border-right:0}.drawer-status>div:nth-child(-n+2){border-bottom:1px solid var(--line)}.drawer-tabs{overflow:auto}.drawer-tabs button{min-width:max-content}.tenant-drawer dl{grid-template-columns:1fr}.billing-metrics{grid-template-columns:1fr}.billing-tabs{overflow:auto}.billing-tabs button{min-width:max-content}.usage-kpis{grid-template-columns:1fr}.usage-kpis>div{border-right:0;border-bottom:1px solid var(--line)}.bank-stats{grid-template-columns:1fr 1fr}.bank-stats>div:nth-child(2){border-right:0}.bank-stats>div:nth-child(-n+2){border-bottom:1px solid var(--line)}.version-card{align-items:flex-start;flex-direction:column}.security-alert{grid-template-columns:38px minmax(0,1fr)}.security-alert>b,.security-alert>.button{grid-column:2;width:max-content}.staff-row{grid-template-columns:31px minmax(0,1fr) auto}.staff-row>em,.staff-row>i{display:none}.role-row{grid-template-columns:30px minmax(0,1fr) auto}.role-row>.button{grid-column:2/-1}.tenant-drawer{width:100%}} -@media(prefers-reduced-motion:reduce){*,*:before,*:after{transition:none!important}} - -/* Global productive typography floor: dense, but never miniature. */ -:root{--text-caption:12px;--text-label:13px;--text-body:14px;--text-heading:18px;--text-title:24px;--line-caption:18px;--line-body:22px} -.platform-brand small,.environment,.environment b,.environment-switch,.environment-switch small,#sideNav section h2,.platform-foot small,.platform-foot>div>span,.platform-foot strong,.page-context small,.platform-search input,.platform-search kbd,.top-status,.top-status>span,.icon-button b,.page-head p,.metric small,.metric p,.panel-head span,.legend,.chart-axis,.bars em,.alert-row small,.health-donut span,.tenant-health p,.usage-summary span,.usage-summary small,.platform-activity>span,.platform-activity small,.filter-bar input,.filter-bar select,.platform-table th,.platform-table td>small,.tenant-cell small,.table-panel>footer,.tenant-drawer header small,.tenant-drawer header p,.drawer-status span,.drawer-tabs button,.tenant-drawer dt,.domain-item small,.drawer-usage span,.setup-card p,.plan-card header p,.plan-card header b,.plan-card>strong small,.table-head span,.table-head input,.billing-tabs button,.collection-console article small,.policy-timeline span,.usage-kpis span,.usage-kpis small,.usage-cell span,.bank-tree small,.bank-content header span,.bank-content header p,.bank-stats span,.version-card small,.audit-table code,.severity,.security-alert small,.security-alert em,.security-alert p,.alert-level,.channel-row small,.failure-panel p,.staff-row small,.staff-row>b,.staff-row>em,.role-row small,.role-row>b{font-size:var(--text-caption)!important;line-height:var(--line-caption)} -#sideNav button,.platform-foot>button,.page-context strong,.button,.control,.link,.filter-segment button,.platform-table td,.platform-table footer button,.tenant-drawer h3,.tenant-drawer dd,.domain-item strong,.drawer-usage strong,.setup-card header span,.setup-card header b,.plan-card li,.table-head h2,.collection-console article strong,.collection-console article>b,.policy-timeline b,.bank-tree header strong,.bank-tree strong,.version-card p,.security-alert strong,.channel-row strong,.failure-panel strong,.staff-row strong,.role-row strong,.status,.toast{font-size:var(--text-label)!important;line-height:20px} -.page-head h1{font-size:var(--text-title);line-height:32px}.panel-head h2,.tenant-drawer h2,.bank-content h2{font-size:var(--text-heading);line-height:26px}.metric strong{font-size:28px;line-height:36px}.usage-kpis strong{font-size:24px;line-height:32px}.plan-card>strong{font-size:36px;line-height:44px}.platform-table th{height:46px}.platform-table td{height:68px}.button,.control,.platform-search,.filter-bar label,.filter-bar select{min-height:40px}.icon-button{width:40px;height:40px}.status,.severity{min-height:24px;padding-inline:8px}.tenant-drawer{width:min(640px,100%)}.tenant-drawer>header>button{width:40px;height:40px;display:grid;place-items:center}.drawer-tabs{height:48px}.drawer-tabs button{padding-inline:12px}.tenant-drawer>footer{gap:8px} -@media(max-width:900px){:root{--text-body:15px;--text-label:14px}.button,.control,.icon-button{min-height:44px}.platform-table td{font-size:14px!important}.platform-table th{font-size:12px!important}} - -/* v1.1 specification interaction layer */ -.prototype-controls{display:flex;align-items:center;gap:7px}.prototype-controls label{height:40px;display:flex;align-items:center;gap:6px;padding:0 8px;border:1px solid var(--line);background:#fff}.prototype-controls span{color:var(--muted);font-size:12px;white-space:nowrap}.prototype-controls select{max-width:118px;border:0;outline:0;background:transparent;font-size:12px;color:var(--ink)} -.page-id{display:block;margin:0 0 5px;color:var(--blue);font-size:12px;font-weight:750}.page-head.is-subpage{padding-bottom:14px;border-bottom:1px solid var(--line)}.subpage-nav{display:flex!important;align-items:center;gap:8px!important;margin-bottom:14px}.subpage-nav .icon-button{min-height:40px}.cell-link{padding:0;border:0;background:transparent;color:inherit;text-align:left;font:inherit}.tenant-cell.cell-link{display:flex}.row-actions,.inline-actions{display:flex;align-items:center;gap:6px}.platform-table tr.is-highlighted td{background:var(--blue-50)} -.state-panel{min-height:300px;display:grid;place-items:center;align-content:center;gap:12px;padding:36px;border:1px solid var(--line);background:#fff;text-align:center}.state-panel>span{width:52px;height:52px;display:grid;place-items:center;border-radius:50%;background:var(--blue-100);color:var(--blue)}.state-panel>span svg{width:24px}.state-panel h2,.state-panel p{margin:0}.state-panel h2{font-size:20px}.state-panel p{max-width:650px;color:var(--muted);font-size:14px;line-height:22px}.state-panel>div{display:flex;gap:8px}.state-panel.is-error>span{background:#fff0ef;color:var(--red)}.state-panel.is-forbidden>span{background:#fff5e8;color:var(--orange)}.state-panel.is-partial{min-height:180px;margin-top:12px;background:#fffdf7}.skeleton-stack{display:grid;gap:13px;padding:28px;border:1px solid var(--line);background:#fff}.skeleton-stack i{width:var(--w);height:42px;background:linear-gradient(90deg,#f2f4f7,#fafafa,#f2f4f7);background-size:200% 100%;animation:skeleton 1.2s linear infinite}.state-hint{color:var(--muted);font-size:13px}@keyframes skeleton{to{background-position:-200% 0}} -.detail-summary{display:grid;grid-template-columns:repeat(5,1fr);margin-bottom:12px;border:1px solid var(--line);background:#fff}.detail-summary>div{min-height:84px;display:grid;align-content:center;gap:7px;padding:14px 17px;border-right:1px solid var(--line)}.detail-summary>div:last-child{border-right:0}.detail-summary span{color:var(--muted);font-size:12px}.detail-summary strong{font-size:16px}.detail-grid{display:grid;grid-template-columns:minmax(0,1.25fr) minmax(340px,.75fr);gap:12px}.detail-list{display:grid;grid-template-columns:1fr 1fr;gap:20px;margin:0;padding:22px}.detail-list div{display:grid;gap:6px}.detail-list dt{color:var(--muted);font-size:12px}.detail-list dd{margin:0;font-size:14px;line-height:22px}.action-panel>button{width:100%;min-height:72px;display:grid;grid-template-columns:32px 1fr 20px;align-items:center;gap:10px;padding:12px 16px;border:0;border-bottom:1px solid var(--line);background:#fff;text-align:left}.action-panel>button:hover{background:var(--blue-50)}.action-panel>button>svg:first-child{color:var(--blue)}.action-panel>button>span{display:grid;gap:5px}.action-panel>button strong{font-size:14px}.action-panel>button small{color:var(--muted);font-size:12px}.timeline-panel{margin-top:12px}.timeline{display:grid;grid-template-columns:repeat(4,1fr);padding:22px}.timeline p{position:relative;display:grid;gap:6px;margin:0;padding:0 20px 0 25px;border-top:2px solid var(--line)}.timeline p:before{content:"";position:absolute;left:0;top:-7px;width:12px;height:12px;border-radius:50%;background:#d0d5dd}.timeline p.done{border-color:#98b1ff}.timeline p.done:before{background:var(--blue)}.timeline p.risk{border-color:#ffb4ae}.timeline p.risk:before{background:var(--red)}.timeline b{padding-top:16px;font-size:14px}.timeline span{color:var(--muted);font-size:12px;line-height:18px} -.form-workspace{display:grid;gap:12px}.form-section{overflow:hidden}.form-grid{display:grid;grid-template-columns:1fr 1fr;gap:18px;padding:22px}.form-grid label,.modal-form>label,.alert-evidence>label{display:grid;align-content:start;gap:7px}.form-grid label.wide,.modal-detail .wide{grid-column:1/-1}.form-grid label>span,.modal-form label>span,.alert-evidence label>span{font-size:13px;font-weight:700}.form-grid input,.form-grid select,.form-grid textarea,.modal-form input,.modal-form select,.modal-form textarea,.alert-evidence textarea{width:100%;min-height:42px;padding:9px 11px;border:1px solid #d0d5dd;background:#fff;color:var(--ink);font-size:14px}.form-grid textarea,.modal-form textarea{resize:vertical}.form-grid input:disabled,.form-grid select:disabled{background:#f2f4f7;color:var(--muted)}.form-actions{position:sticky;bottom:0;z-index:4;display:flex;justify-content:flex-end;align-items:center;gap:8px;padding:14px 18px;border:1px solid var(--line);background:#fff}.form-actions>span{margin-right:auto;color:var(--muted);font-size:12px}.form-error-summary{margin:0;padding:14px 17px;border:1px solid #ffb4ae;background:#fff0ef;color:#b42318;font-size:13px}.form-error-summary strong{font-size:14px}.form-error-summary ul{margin:8px 0 0;padding-left:20px}.field-error{color:#b42318;font-size:12px;line-height:18px}.is-invalid{border-color:var(--red)!important;box-shadow:0 0 0 3px rgba(217,45,32,.08)} -.toggle-label{display:flex;align-items:center;gap:7px;padding:0 10px;border:1px solid var(--line);background:#fff;font-size:13px}.modal-backdrop{position:fixed;z-index:80;inset:0;display:grid;place-items:center;padding:24px;background:rgba(16,24,40,.42)}.modal{width:min(620px,100%);max-height:min(820px,calc(100vh - 48px));display:flex;flex-direction:column;border:1px solid var(--line);background:#fff;box-shadow:0 24px 80px rgba(16,24,40,.25)}.modal.is-wide{width:min(880px,100%)}.modal>header{display:flex;align-items:flex-start;justify-content:space-between;gap:16px;padding:20px 22px;border-bottom:1px solid var(--line)}.modal>header small{color:var(--blue);font-size:12px;font-weight:750}.modal>header h2{margin:5px 0;font-size:20px}.modal>header p{margin:0;color:var(--muted);font-size:13px;line-height:20px}.modal>header .icon-button{flex:0 0 auto}.modal>footer{display:flex;justify-content:flex-end;gap:8px;padding:14px 20px;border-top:1px solid var(--line);background:#fff}.modal-form{min-height:0;display:grid;gap:16px;padding:20px 22px;overflow:auto}.modal-form .form-grid{padding:0}.check-row{display:flex!important;align-items:center!important;grid-template-columns:20px 1fr;gap:8px!important;min-height:42px}.check-row input{width:18px!important;min-height:18px!important}.danger-notice{display:flex;gap:8px;padding:12px;border:1px solid #ffb4ae;background:#fff0ef;color:#b42318;font-size:13px;line-height:20px}.modal-form fieldset{margin:0;padding:16px;border:1px solid var(--line)}.modal-form legend{padding:0 6px;font-size:14px;font-weight:700}.permission-grid{display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-bottom:12px}.permission-grid label{display:flex;align-items:center;gap:7px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px}.permission-grid input{width:16px;min-height:16px}.modal-detail{display:grid;grid-template-columns:1fr 1fr;gap:18px;margin:0;padding:22px;overflow:auto}.modal-detail div{display:grid;gap:6px}.modal-detail dt{color:var(--muted);font-size:12px}.modal-detail dd{margin:0;font-size:14px;line-height:22px}.candidate-list,.task-list{display:grid;gap:0;min-height:0;overflow:auto}.candidate-list label{min-height:68px;display:grid;grid-template-columns:20px 1fr;align-items:center;gap:10px;padding:12px 22px;border-bottom:1px solid var(--line)}.candidate-list label>span{display:grid;gap:5px}.candidate-list strong{font-size:14px}.candidate-list small{color:var(--muted);font-size:12px}.candidate-list>p{padding:30px;text-align:center;color:var(--muted)}.alert-evidence{display:grid;gap:18px;padding:22px;overflow:auto}.evidence-head{display:grid;grid-template-columns:42px 1fr auto;align-items:center;gap:12px}.evidence-head>div{display:grid;gap:5px}.evidence-head strong{font-size:15px}.evidence-head small{color:var(--muted);font-size:12px}.alert-evidence ul{display:grid;gap:8px;margin:0;padding:0;list-style:none}.alert-evidence li{display:flex;align-items:center;gap:8px;padding:10px 12px;background:#f8fafc;font-size:13px}.alert-evidence li svg{width:15px;color:var(--blue)}.task-list article{min-height:80px;display:grid;grid-template-columns:38px 1fr auto;align-items:center;gap:12px;padding:12px 20px;border-bottom:1px solid var(--line)}.task-state{width:36px;height:36px;display:grid;place-items:center;border-radius:50%;background:#f2f4f7;color:var(--muted)}.task-state.success{background:#edf9f2;color:var(--green)}.task-state.danger{background:#fff0ef;color:var(--red)}.task-state.warning svg{animation:spin 1s linear infinite}.task-list article>div{display:grid;gap:4px}.task-list strong{font-size:14px}.task-list small,.task-list p{margin:0;color:var(--muted);font-size:12px;line-height:18px}@keyframes spin{to{transform:rotate(360deg)}} -.toast.is-error svg{color:#ffb4ae}.failure-panel article{padding:0}.channel-row .row-actions{justify-content:flex-end}.collection-console article .inline-actions{justify-content:flex-end}.collection-console article .inline-actions .button{white-space:nowrap} -.confirm-impact{display:grid;grid-template-columns:42px 1fr;align-items:center;gap:12px;padding:22px}.confirm-impact>span{width:40px;height:40px;display:grid;place-items:center;border-radius:50%;background:#fff0ef;color:var(--red)}.confirm-impact p{margin:0;font-size:14px;line-height:22px}.icons-unavailable [data-lucide]{display:none}.icons-unavailable .button:empty,.icons-unavailable .icon-button:empty{display:none} -.unsaved-leave-guard{position:fixed;z-index:140;inset:0;display:grid;place-items:center;padding:24px;background:rgba(16,24,40,.5)}.leave-guard-card{width:min(520px,100%);box-shadow:0 28px 90px rgba(16,24,40,.28)} -.alert-row strong,.platform-activity p{font-size:13px;line-height:20px}.platform-activity p strong{font-size:13px}.tenant-health p strong{font-size:13px}.failure-panel article strong{font-size:13px}.failure-panel article p{font-size:12px;line-height:18px} -.platform-activity>div>span,#sideNav b{font-size:12px!important}.platform-foot>div>span{font-size:13px!important}.mobile-boundary{display:grid;grid-template-columns:48px 1fr;align-items:start;gap:14px;padding:22px}.mobile-boundary>span{width:46px;height:46px;display:grid;place-items:center;background:var(--blue-100);color:var(--blue)}.mobile-boundary strong{font-size:15px}.mobile-boundary p{margin:6px 0 0;color:var(--muted);font-size:13px;line-height:20px} -.tenant-cell>span,.staff-row>span{font-size:12px!important}.tenant-cell strong{font-size:13px!important;line-height:20px} -.sidebar-backdrop{display:none;position:fixed;z-index:29;inset:0;border:0;background:rgba(16,24,40,.42)} -@media(max-width:1320px){.prototype-controls label span{display:none}.prototype-controls select{max-width:105px}.detail-summary{grid-template-columns:repeat(3,1fr)}.detail-summary>div:nth-child(3){border-right:0}.detail-summary>div:nth-child(-n+3){border-bottom:1px solid var(--line)}} -@media(max-width:1050px){.prototype-controls{display:none}.detail-grid{grid-template-columns:1fr}.timeline{grid-template-columns:1fr}.timeline p{padding-bottom:16px;border-top:0;border-left:2px solid var(--line)}.timeline p:before{top:0;left:-7px}.timeline b{padding-top:0}.detail-summary{grid-template-columns:1fr 1fr}.detail-summary>div:nth-child(3){border-right:1px solid var(--line)}.detail-summary>div:nth-child(even){border-right:0}.detail-summary>div{border-bottom:1px solid var(--line)}} -@media(max-width:900px){body.menu-locked{overflow:hidden}.platform-app.menu-open+.sidebar-backdrop{display:block}.modal-backdrop{padding:0}.modal,.modal.is-wide{width:100%;height:100%;max-height:none}.modal>header{padding:16px}.modal>footer{padding:12px 14px}.form-grid,.modal-form .form-grid,.modal-detail,.permission-grid{grid-template-columns:1fr}.form-grid label.wide,.modal-detail .wide{grid-column:auto}.form-actions{position:static;bottom:auto;z-index:auto;flex-wrap:wrap}.form-actions>span{width:100%;margin:0}.row-action,.switch{position:relative;width:44px;height:44px;flex:0 0 44px}.row-action{background:transparent}.row-action:before{content:"";position:absolute;inset:8px;background:transparent}.row-action:hover{background:transparent}.row-action:hover:before{background:var(--blue-100)}.row-action svg{position:relative;z-index:1}.switch{display:grid;place-items:center;padding:0;border-radius:0;background:transparent}.switch:before{content:"";position:absolute;left:6px;top:13px;width:32px;height:18px;border-radius:9px;background:#d0d5dd}.switch i{position:relative;z-index:1;transform:translateX(-7px)}.switch.is-on{background:transparent}.switch.is-on:before{background:var(--blue)}.switch.is-on i{transform:translateX(7px)}.detail-summary{grid-template-columns:1fr 1fr}.collection-console article{grid-template-columns:34px minmax(0,1fr)}.collection-console article>b,.collection-console article>.inline-actions{grid-column:2}.platform-topbar{overflow:hidden}.platform-search{min-width:0}} -@media(max-width:900px){.unsaved-leave-guard{padding:0;align-items:end}.unsaved-leave-guard .modal{width:100%;height:auto;max-height:100vh}.leave-guard-card footer{flex-wrap:wrap}.leave-guard-card footer .button{min-height:44px;flex:1}} -@media(max-width:560px){.detail-summary{grid-template-columns:1fr}.detail-summary>div{border-right:0!important}.page-head.is-subpage>div:last-child{display:none}.modal>footer{overflow:auto;justify-content:flex-start}.modal>footer .button{white-space:nowrap}.form-actions .button{flex:1;min-width:0;white-space:nowrap}.alert-layout,.channel-panel,.panel{min-width:0}.panel-head{align-items:flex-start;flex-wrap:wrap;padding-block:12px}.panel-head>.filter-segment{max-width:100%;overflow:auto}.security-alert{grid-template-columns:38px minmax(0,1fr)}.security-alert .inline-actions{grid-column:2;flex-wrap:wrap;min-width:0}.security-alert .inline-actions .button{min-width:0;white-space:normal}.task-list article{grid-template-columns:34px 1fr}.task-list article>.button,.task-list article>.status{grid-column:2;width:max-content}.evidence-head{grid-template-columns:40px 1fr}.evidence-head>.status{grid-column:2;width:max-content}.top-status .icon-button:first-of-type{display:grid}.staff-row{grid-template-columns:32px minmax(0,1fr) auto}.staff-row>b,.staff-row>em,.staff-row>i{display:none}.mobile-boundary{grid-template-columns:1fr}.mobile-boundary>span{width:44px;height:44px}} -.contract-result{display:grid;grid-template-columns:24px minmax(0,1fr);align-items:center;gap:10px;margin:0 0 12px;padding:10px 12px;border:1px solid #b7e4c7;background:#f2fbf5;color:#17663a}.contract-result>svg{width:18px}.contract-result>span{display:grid;gap:3px}.contract-result strong{font-size:13px}.contract-result small{color:#52705f;font-size:12px;line-height:18px}.contract-result.is-loading{border-color:#bfd0ff;background:var(--blue-50);color:var(--blue)}.contract-result.is-loading>svg{animation:spin 1s linear infinite}.contract-result.is-error{border-color:#ffb4ae;background:#fff0ef;color:#b42318}.contract-result.is-error small{color:#8f2d25}.candidate-list label:has(>.button){grid-template-columns:20px minmax(0,1fr) auto}.alert-rules{margin-bottom:12px}.alert-rules .panel-head code{max-width:46%;overflow:hidden;color:var(--muted);font-size:12px;text-overflow:ellipsis;white-space:nowrap}.rule-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr))}.rule-grid article{min-height:106px;display:grid;grid-template-columns:42px minmax(0,1fr) auto;align-items:start;gap:10px;padding:16px;border-right:1px solid var(--line);border-top:1px solid var(--line)}.rule-grid article:last-child{border-right:0}.rule-grid article>div{display:grid;gap:5px}.rule-grid strong{font-size:13px}.rule-grid small,.rule-grid p{margin:0;color:var(--muted);font-size:12px;line-height:18px}.tree-empty{padding:18px;color:var(--muted);font-size:13px;text-align:center} -@media(max-width:1050px){.rule-grid{grid-template-columns:1fr}.rule-grid article{border-right:0}.candidate-list label:has(>.button){grid-template-columns:20px minmax(0,1fr)}.candidate-list label>.button{grid-column:2;width:max-content}} -/* Real API authentication gate. Tokens are held in sessionStorage by platform-auth.js. */ -.platform-auth-gate { position: fixed; inset: 0; z-index: 10000; display: grid; place-items: center; padding: 24px; background: radial-gradient(circle at 20% 10%, #17345f 0, #0b1220 42%, #060a12 100%); color: #e5e7eb; } -.platform-auth-gate[hidden] { display: none; } -.platform-auth-card { width: min(460px, 100%); padding: 32px; border: 1px solid rgba(148,163,184,.22); border-radius: 18px; background: rgba(15,23,42,.96); box-shadow: 0 24px 80px rgba(0,0,0,.45); } -.platform-auth-card header { display: flex; gap: 14px; align-items: center; margin-bottom: 26px; } -.platform-auth-card header img { width: 44px; height: 44px; border-radius: 12px; } -.platform-auth-card h1 { margin: 0; font-size: 22px; } -.platform-auth-card header p, .platform-auth-card .auth-help { margin: 5px 0 0; color: #94a3b8; font-size: 13px; line-height: 1.6; } -.platform-auth-card form { display: grid; gap: 16px; } -.platform-auth-card label { display: grid; gap: 7px; color: #cbd5e1; font-size: 13px; } -.platform-auth-card input { width: 100%; box-sizing: border-box; padding: 11px 12px; border: 1px solid #334155; border-radius: 9px; background: #0b1220; color: #f8fafc; font: inherit; } -.platform-auth-card input:focus { outline: 2px solid #3b82f6; outline-offset: 1px; } -.platform-auth-card button { width: 100%; min-height: 42px; margin-top: 14px; border: 0; border-radius: 9px; background: #2563eb; color: white; font: inherit; font-weight: 700; cursor: pointer; } -.platform-auth-card button:disabled { opacity: .55; cursor: wait; } -.platform-auth-error { min-height: 20px; margin: 14px 0 0; color: #fca5a5; font-size: 13px; } diff --git a/Tiku.IntegrationTests/Api/PlatformAdminFrontendSeparationTests.cs b/Tiku.IntegrationTests/Api/PlatformAdminFrontendSeparationTests.cs new file mode 100644 index 0000000..0900e8d --- /dev/null +++ b/Tiku.IntegrationTests/Api/PlatformAdminFrontendSeparationTests.cs @@ -0,0 +1,23 @@ +using System.Net; + +namespace Tiku.IntegrationTests.Api; + +public sealed class PlatformAdminFrontendSeparationTests +{ + [Theory] + [InlineData("/platform-admin")] + [InlineData("/platform-admin/")] + [InlineData("/platform-admin/app.js")] + public async Task WebApi_does_not_host_platform_admin_frontend(string path) + { + await using var factory = new ApiTestFactory(); + using var client = factory.CreateClient(new() + { + AllowAutoRedirect = false + }); + + using var response = await client.GetAsync(path); + + Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); + } +} diff --git a/Tiku.IntegrationTests/Api/PlatformAdminStaticEndpointTests.cs b/Tiku.IntegrationTests/Api/PlatformAdminStaticEndpointTests.cs deleted file mode 100644 index 0579a4a..0000000 --- a/Tiku.IntegrationTests/Api/PlatformAdminStaticEndpointTests.cs +++ /dev/null @@ -1,117 +0,0 @@ -using System.Net; - -namespace Tiku.IntegrationTests.Api; - -public sealed class PlatformAdminStaticEndpointTests -{ - [Fact] - public async Task Platform_admin_static_shell_is_served_without_api_authentication() - { - await using var factory = new ApiTestFactory(); - using var client = factory.CreateClient(); - - var response = await client.GetAsync("/platform-admin/"); - var body = await response.Content.ReadAsStringAsync(); - - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - Assert.Contains("恭学题库 SaaS · 平台管理", body, StringComparison.Ordinal); - Assert.Contains("./platform-api.js", body, StringComparison.Ordinal); - Assert.Contains("./platform-auth.js", body, StringComparison.Ordinal); - Assert.Contains("platformAuthGate", body, StringComparison.Ordinal); - } - - [Fact] - public async Task Platform_admin_short_path_redirects_to_static_shell_directory() - { - await using var factory = new ApiTestFactory(); - using var client = factory.CreateClient(new() - { - AllowAutoRedirect = false - }); - - var response = await client.GetAsync("/platform-admin"); - - Assert.Equal(HttpStatusCode.MovedPermanently, response.StatusCode); - Assert.Equal("/platform-admin/", response.Headers.Location?.AbsolutePath); - } - - [Fact] - public async Task Platform_admin_runtime_uses_real_api_without_mock_fallback() - { - await using var factory = new ApiTestFactory(); - using var client = factory.CreateClient(); - - var runtime = await client.GetStringAsync("/platform-admin/runtime-config.js"); - var authentication = await client.GetStringAsync("/platform-admin/platform-auth.js"); - - Assert.Contains("mode: 'api'", runtime, StringComparison.Ordinal); - Assert.Contains("fallbackToMock: false", runtime, StringComparison.Ordinal); - Assert.Contains("/api/auth/login/password", authentication, StringComparison.Ordinal); - Assert.Contains("/api/auth/password/change-required", authentication, StringComparison.Ordinal); - Assert.DoesNotContain("/api/auth/mfa", authentication, StringComparison.Ordinal); - } - - [Fact] - public async Task Platform_admin_shell_covers_current_platform_capabilities_and_dto_fields() - { - await using var factory = new ApiTestFactory(); - using var client = factory.CreateClient(); - - var application = await client.GetStringAsync("/platform-admin/app.js"); - var api = await client.GetStringAsync("/platform-admin/platform-api.js"); - var contract = await client.GetStringAsync("/platform-admin/spec-contract.js"); - - Assert.Contains("租户域名与证书", application, StringComparison.Ordinal); - Assert.Contains("SaaS 商品与版本", application, StringComparison.Ordinal); - Assert.Contains("SaaS 订单与交易", application, StringComparison.Ordinal); - Assert.Contains("平台角色与功能", application, StringComparison.Ordinal); - Assert.Contains("function businessStatusLabel(value)", application, StringComparison.Ordinal); - Assert.Contains("function backendStatusLabel()", application, StringComparison.Ordinal); - Assert.DoesNotContain("业务功能名称和中文说明", application, StringComparison.Ordinal); - Assert.DoesNotContain("中文说明", application, StringComparison.Ordinal); - Assert.DoesNotContain("API 契约", application, StringComparison.Ordinal); - Assert.Contains("/api/backoffice/platform/bootstrap", contract, StringComparison.Ordinal); - Assert.Contains("/api/platform-admin/payment-settings/channels", contract, StringComparison.Ordinal); - Assert.Contains("/api/platform-admin/tenant-capabilities/crm/logs", contract, StringComparison.Ordinal); - Assert.Contains("userId: input.userId", api, StringComparison.Ordinal); - Assert.Contains("roleIds: input.roleIds", api, StringComparison.Ordinal); - Assert.Contains("resolutionNote: input.resolutionNote", api, StringComparison.Ordinal); - Assert.Contains("platformPermissionLabels[item.code]", api, StringComparison.Ordinal); - Assert.Contains("'platform:role:manage': '管理平台角色与权限'", api, StringComparison.Ordinal); - Assert.DoesNotContain("authUserId: input.authUserId", api, StringComparison.Ordinal); - Assert.DoesNotContain("platformPermissions:", api, StringComparison.Ordinal); - Assert.DoesNotContain("staffId: input.staffId", api, StringComparison.Ordinal); - } - - [Fact] - public async Task Platform_question_bank_workspace_loads_cache_busted_scripts_and_real_api_bindings() - { - await using var factory = new ApiTestFactory(); - using var client = factory.CreateClient(); - - var shell = await client.GetStringAsync("/platform-admin/"); - var application = await client.GetStringAsync("/platform-admin/app.js"); - var api = await client.GetStringAsync("/platform-admin/platform-api.js"); - var contract = await client.GetStringAsync("/platform-admin/spec-contract.js"); - - Assert.Contains("app.js?v=20260730-question-bank1", shell, StringComparison.Ordinal); - Assert.Contains("platform-api.js?v=20260730-question-bank1", shell, StringComparison.Ordinal); - Assert.Contains("spec-contract.js?v=20260730-question-bank1", shell, StringComparison.Ordinal); - Assert.Contains("operationId: 'PlatformQuestionBanksController_upsertBank'", application, StringComparison.Ordinal); - Assert.Contains("operationId: 'PlatformQuestionBanksController_upsertNode'", application, StringComparison.Ordinal); - Assert.Contains("operationId: 'PlatformQuestionBanksController_upsertQuestion'", application, StringComparison.Ordinal); - Assert.Contains("PlatformQuestionBanksController_archiveQuestions", application, StringComparison.Ordinal); - Assert.Contains("PlatformQuestionBanksController_archiveNode", application, StringComparison.Ordinal); - Assert.Contains("PlatformQuestionBanksController_archiveBank", application, StringComparison.Ordinal); - Assert.Contains("data-action=\"shift-bank-node\"", application, StringComparison.Ordinal); - Assert.Contains("PlatformQuestionBanksController_signAssetUpload", application, StringComparison.Ordinal); - Assert.Contains("PlatformQuestionBanksController_confirmAssetUpload", application, StringComparison.Ordinal); - Assert.Contains("PlatformQuestionBanksController_upsertBank(input)", api, StringComparison.Ordinal); - Assert.Contains("PlatformQuestionBanksController_upsertQuestion(input)", api, StringComparison.Ordinal); - Assert.Contains("PlatformQuestionBanksController_executeImport(input)", api, StringComparison.Ordinal); - Assert.Contains("['P-09', 'PlatformQuestionBanksController_upsertBank', 'PUT', '/api/platform-admin/question-banks']", contract, StringComparison.Ordinal); - Assert.Contains("['P-09', 'PlatformQuestionBanksController_executeImport', 'POST', '/api/platform-admin/question-banks/imports']", contract, StringComparison.Ordinal); - Assert.DoesNotContain("question_bank:grant", application, StringComparison.Ordinal); - Assert.DoesNotContain("question_bank:ops", application, StringComparison.Ordinal); - } -} diff --git a/Tiku.PlatformAdmin.Web/.env.example b/Tiku.PlatformAdmin.Web/.env.example new file mode 100644 index 0000000..0458ce6 --- /dev/null +++ b/Tiku.PlatformAdmin.Web/.env.example @@ -0,0 +1,2 @@ +VITE_API_BASE_URL=http://localhost:5090 +OPENAPI_URL=http://localhost:5090/openapi/v1.json diff --git a/Tiku.PlatformAdmin.Web/.gitignore b/Tiku.PlatformAdmin.Web/.gitignore new file mode 100644 index 0000000..b813019 --- /dev/null +++ b/Tiku.PlatformAdmin.Web/.gitignore @@ -0,0 +1,5 @@ +node_modules/ +dist/ +.generated/ +.env.local +*.log diff --git a/Tiku.PlatformAdmin.Web/README.md b/Tiku.PlatformAdmin.Web/README.md new file mode 100644 index 0000000..5c93c53 --- /dev/null +++ b/Tiku.PlatformAdmin.Web/README.md @@ -0,0 +1,25 @@ +# Tiku 平台管理前端 + +独立部署的 React + TypeScript 平台管理端。业务接口契约只从 `Tiku.Api` 实时 OpenAPI 文档生成,不依赖旧静态前端的接口适配代码。 + +## 本地开发 + +首次使用先安装前端依赖: + +```bash +npm install +``` + +之后从仓库根目录运行 `dotnet run --project Tiku.Api`,ASP.NET Core 的开发代理会自动启动本工程的 Vite 服务。访问 。开发服务器默认代理 `/api` 到 `http://localhost:5090`;需要修改目标时设置 `VITE_DEV_API_TARGET`。 + +也可以在本目录单独执行 `npm run dev`,便于只调试前端。Production 环境不会由 API 启动 Node 进程,前端仍应独立构建和部署。 + +## 接口契约 + +```bash +OPENAPI_URL=http://localhost:5090/openapi/v1.json npm run generate:api +``` + +生成结果包括完整 OpenAPI TypeScript 类型,以及全部 `/api/platform-admin/**`、`/api/backoffice/platform/**` 接口的页面操作元数据。`npm test` 会验证每个后端平台接口都已归入且只归入一个页面组。 + +生产部署通过 `VITE_API_BASE_URL` 指定 API 地址;同域反向代理时可以留空。 diff --git a/Tiku.PlatformAdmin.Web/index.html b/Tiku.PlatformAdmin.Web/index.html new file mode 100644 index 0000000..c2eed97 --- /dev/null +++ b/Tiku.PlatformAdmin.Web/index.html @@ -0,0 +1,13 @@ + + + + + + + 恭学题库 SaaS · 平台管理 + + +
+ + + diff --git a/Tiku.PlatformAdmin.Web/package-lock.json b/Tiku.PlatformAdmin.Web/package-lock.json new file mode 100644 index 0000000..3d0644f --- /dev/null +++ b/Tiku.PlatformAdmin.Web/package-lock.json @@ -0,0 +1,3534 @@ +{ + "name": "@tiku/platform-admin", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "@tiku/platform-admin", + "version": "0.1.0", + "dependencies": { + "@ant-design/icons": "^6.0.1", + "antd": "6.5.0", + "react": "^19.2.0", + "react-dom": "^19.2.0", + "react-router": "^8.3.0" + }, + "devDependencies": { + "@types/node": "^24.10.0", + "@types/react": "^19.2.2", + "@types/react-dom": "^19.2.2", + "@vitejs/plugin-react": "^5.1.1", + "openapi-typescript": "^7.10.1", + "typescript": "^5.9.3", + "vite": "^7.2.2", + "vitest": "^4.0.8" + } + }, + "node_modules/@ant-design/colors": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@ant-design/colors/-/colors-8.0.1.tgz", + "integrity": "sha512-foPVl0+SWIslGUtD/xBr1p9U4AKzPhNYEseXYRRo5QSzGACYZrQbe11AYJbYfAWnWSpGBx6JjBmSeugUsD9vqQ==", + "license": "MIT", + "dependencies": { + "@ant-design/fast-color": "^3.0.0" + } + }, + "node_modules/@ant-design/cssinjs": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@ant-design/cssinjs/-/cssinjs-2.1.2.tgz", + "integrity": "sha512-2Hy8BnCEH31xPeSLbhhB2ctCPXE2ZnASdi+KbSeS79BNbUhL9hAEe20SkUk+BR8aKTmqb6+FKFruk7w8z0VoRQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.11.1", + "@emotion/hash": "^0.8.0", + "@emotion/unitless": "^0.7.5", + "@rc-component/util": "^1.4.0", + "clsx": "^2.1.1", + "csstype": "^3.1.3", + "stylis": "^4.3.4" + }, + "peerDependencies": { + "react": ">=16.0.0", + "react-dom": ">=16.0.0" + } + }, + "node_modules/@ant-design/cssinjs-utils": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@ant-design/cssinjs-utils/-/cssinjs-utils-2.1.2.tgz", + "integrity": "sha512-5fTHQ158jJJ5dC/ECeyIdZUzKxE/mpEMRZxthyG1sw/AKRHKgJBg00Yi6ACVXgycdje7KahRNvNET/uBccwCnA==", + "license": "MIT", + "dependencies": { + "@ant-design/cssinjs": "^2.1.2", + "@babel/runtime": "^7.23.2", + "@rc-component/util": "^1.4.0" + }, + "peerDependencies": { + "react": ">=18", + "react-dom": ">=18" + } + }, + "node_modules/@ant-design/fast-color": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@ant-design/fast-color/-/fast-color-3.0.1.tgz", + "integrity": "sha512-esKJegpW4nckh0o6kV3Tkb7NPIZYbPnnFxmQDUmL08ukXZAvV85TZBr70eGuke/CIArLaP6aw8lt9KILjnWuOw==", + "license": "MIT", + "engines": { + "node": ">=8.x" + } + }, + "node_modules/@ant-design/icons": { + "version": "6.3.2", + "resolved": "https://registry.npmjs.org/@ant-design/icons/-/icons-6.3.2.tgz", + "integrity": "sha512-B6O5a5XJ4wjtNOfZejXYwHW5zvKV5gYkjGf11dHGLEbKn0ABDGndo41+gfIiXyTFhvESj4XTotuud33mUFid0g==", + "license": "MIT", + "dependencies": { + "@ant-design/colors": "^8.0.1", + "@ant-design/icons-svg": "^4.5.0", + "@rc-component/util": "^1.11.0", + "clsx": "^2.1.1" + }, + "engines": { + "node": ">=8" + }, + "peerDependencies": { + "react": ">=16.0.0", + "react-dom": ">=16.0.0" + } + }, + "node_modules/@ant-design/icons-svg": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@ant-design/icons-svg/-/icons-svg-4.5.0.tgz", + "integrity": "sha512-1BTUFyKPTBZ53MuTP8s0k5SFEXL7o3VHEOwLgzaoWKwnBeqIcqUtVshc4SKzhI6uACfqhJqBwBUE9FsWR3uULA==", + "license": "MIT" + }, + "node_modules/@ant-design/react-slick": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@ant-design/react-slick/-/react-slick-2.0.0.tgz", + "integrity": "sha512-HMS9sRoEmZey8LsE/Yo6+klhlzU12PisjrVcydW3So7RdklyEd2qehyU6a7Yp+OYN72mgsYs3NFCyP2lCPFVqg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.28.4", + "clsx": "^2.1.1", + "json2mq": "^0.2.0", + "throttle-debounce": "^5.0.0" + }, + "peerDependencies": { + "react": "^0.14.0 || ^15.0.1 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^0.14.0 || ^15.0.1 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz", + "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.29.7", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.7.tgz", + "integrity": "sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.7.tgz", + "integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.7", + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helpers": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/template": "^7.29.7", + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7", + "@jridgewell/remapping": "^2.3.5", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/generator": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.7.tgz", + "integrity": "sha512-DkXD5OJQaAQIdZ1bt3UZdEnHAn9Imd3IVBdX03UFe+ony9Ojw5pzr9YVKGDY1jt+Gcn/FnGkNf8r+Vj5NOJWtQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.7", + "@babel/types": "^7.29.7", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.29.7.tgz", + "integrity": "sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.29.7", + "@babel/helper-validator-option": "^7.29.7", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-globals": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.29.7.tgz", + "integrity": "sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.29.7.tgz", + "integrity": "sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.29.7.tgz", + "integrity": "sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7", + "@babel/traverse": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.29.7.tgz", + "integrity": "sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", + "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", + "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.29.7.tgz", + "integrity": "sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.7.tgz", + "integrity": "sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.7.tgz", + "integrity": "sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.7" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-self": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.29.7.tgz", + "integrity": "sha512-TL0hMc9xzy86VD31nUiwzd5otRAcyEPcsegCxolO0PvcXuH1v0kECe/UIznYFihpkvU5wg/jk4v0TTEFfm53fw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-source": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.29.7.tgz", + "integrity": "sha512-06IyK09H3wi4cGbhDBwp5gUGo0IKtnYa8tyTiephirPCK6fbobVGiXMMI5zLQ4aKEYP3wZ3ArU44o+8KMrSG/Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.7.tgz", + "integrity": "sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.29.7.tgz", + "integrity": "sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.7.tgz", + "integrity": "sha512-EhlfNQtZ+NK22w5BM61ciuiq1m58ed33Wr1Xan//ZRTy6hgjnwyCffRYwzsGXdASJSUJ1guZILsErh1eQcl+zw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.7", + "@babel/helper-globals": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.7", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.7.tgz", + "integrity": "sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@emotion/hash": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz", + "integrity": "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==", + "license": "MIT" + }, + "node_modules/@emotion/unitless": { + "version": "0.7.5", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz", + "integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==", + "license": "MIT" + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.1.tgz", + "integrity": "sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.1.tgz", + "integrity": "sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.1.tgz", + "integrity": "sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.1.tgz", + "integrity": "sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.1.tgz", + "integrity": "sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.1.tgz", + "integrity": "sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.1.tgz", + "integrity": "sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.1.tgz", + "integrity": "sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.1.tgz", + "integrity": "sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.1.tgz", + "integrity": "sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.1.tgz", + "integrity": "sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.1.tgz", + "integrity": "sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.1.tgz", + "integrity": "sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.1.tgz", + "integrity": "sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.1.tgz", + "integrity": "sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.1.tgz", + "integrity": "sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.1.tgz", + "integrity": "sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.1.tgz", + "integrity": "sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.1.tgz", + "integrity": "sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.1.tgz", + "integrity": "sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.1.tgz", + "integrity": "sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.1.tgz", + "integrity": "sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.1.tgz", + "integrity": "sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.1.tgz", + "integrity": "sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.1.tgz", + "integrity": "sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.1.tgz", + "integrity": "sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@rc-component/async-validator": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@rc-component/async-validator/-/async-validator-6.0.0.tgz", + "integrity": "sha512-D3AGQwdyE58gmvx6waVSXJ80JGO+IY5L2O8HDnSOex7JNlzB3GuN/4hyHNTdhy2qtOhkpbIjmeAN3tL993wKbA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.24.4" + }, + "engines": { + "node": ">=14.x" + } + }, + "node_modules/@rc-component/cascader": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/@rc-component/cascader/-/cascader-1.17.0.tgz", + "integrity": "sha512-3cVNG0zrQF1PoXq262L3wGCU+/YLEC1mGSVHDl577dQmA0ZKkXFbY6nwyXo+beCcM7buo49t24jkr+QZdL7O8w==", + "license": "MIT", + "dependencies": { + "@rc-component/select": "~1.8.0", + "@rc-component/tree": "~1.3.2", + "@rc-component/util": "^1.11.1", + "clsx": "^2.1.1" + }, + "peerDependencies": { + "react": ">=18.0.0", + "react-dom": ">=18.0.0" + } + }, + "node_modules/@rc-component/checkbox": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@rc-component/checkbox/-/checkbox-2.0.0.tgz", + "integrity": "sha512-3CXGPpAR9gsPKeO2N78HAPOzU30UdemD6HGJoWVJOpa6WleaGB5kzZj3v6bdTZab31YuWgY/RxV3VKPctn0DwQ==", + "license": "MIT", + "dependencies": { + "@rc-component/util": "^1.3.0", + "clsx": "^2.1.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/collapse": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@rc-component/collapse/-/collapse-1.2.0.tgz", + "integrity": "sha512-ZRYSKSS39qsFx93p26bde7JUZJshsUBEQRlRXPuJYlAiNX0vyYlF5TsAm8JZN3LcF8XvKikdzPbgAtXSbkLUkw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "@rc-component/motion": "^1.1.4", + "@rc-component/util": "^1.3.0", + "clsx": "^2.1.1" + }, + "peerDependencies": { + "react": ">=18.0.0", + "react-dom": ">=18.0.0" + } + }, + "node_modules/@rc-component/color-picker": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@rc-component/color-picker/-/color-picker-3.1.1.tgz", + "integrity": "sha512-OHaCHLHszCegdXmIq2ZRIZBN/EtpT6Wm8SG/gpzLATHbVKc/avvuKi+zlOuk05FTWvgaMmpxAko44uRJ3M+2pg==", + "license": "MIT", + "dependencies": { + "@ant-design/fast-color": "^3.0.1", + "@rc-component/util": "^1.3.0", + "clsx": "^2.1.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/context": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@rc-component/context/-/context-2.0.2.tgz", + "integrity": "sha512-uiGpAlblCNlziHPwj4S4Iy/oemeuz/hR03mbiEjTCXwsqOIN3BOzsRMyDwpyO5Fm0vIEEJRUf9ZtbRLbhksuTA==", + "license": "MIT", + "dependencies": { + "@rc-component/util": "^1.11.0" + }, + "peerDependencies": { + "react": ">=18.0.0", + "react-dom": ">=18.0.0" + } + }, + "node_modules/@rc-component/dialog": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@rc-component/dialog/-/dialog-1.10.0.tgz", + "integrity": "sha512-eDukNlz9vNszAGv7i3zKXdxEd3wgVmNxuJijYt8zvTh17QwTu8KK/bdURRd/lU4qaMzhO1HKKmMrwOnkaw0BvQ==", + "license": "MIT", + "dependencies": { + "@rc-component/motion": "^1.3.3", + "@rc-component/portal": "^2.1.0", + "@rc-component/util": "^1.9.0", + "clsx": "^2.1.1" + }, + "peerDependencies": { + "react": ">=18.0.0", + "react-dom": ">=18.0.0" + } + }, + "node_modules/@rc-component/drawer": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@rc-component/drawer/-/drawer-1.4.2.tgz", + "integrity": "sha512-1ib+fZEp6FBu+YvcIktm+nCQ+Q+qIpwpoaJH6opGr4ofh2QMq+qdr5DLC4oCf5qf3pcWX9lUWPYX652k4ini8Q==", + "license": "MIT", + "dependencies": { + "@rc-component/motion": "^1.1.4", + "@rc-component/portal": "^2.1.3", + "@rc-component/util": "^1.9.0", + "clsx": "^2.1.1" + }, + "peerDependencies": { + "react": ">=18.0.0", + "react-dom": ">=18.0.0" + } + }, + "node_modules/@rc-component/dropdown": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rc-component/dropdown/-/dropdown-1.0.3.tgz", + "integrity": "sha512-YTST/N6kpqpDz3IMuM/PSSZnrDpSOA6dgHv12gPA90ZTSLv2CoqkZ0+9NtwTY6BeO7dstPblSic2QJg7dSFy/g==", + "license": "MIT", + "dependencies": { + "@rc-component/trigger": "^3.0.0", + "@rc-component/util": "^1.11.1", + "clsx": "^2.1.1" + }, + "peerDependencies": { + "react": ">=16.11.0", + "react-dom": ">=16.11.0" + } + }, + "node_modules/@rc-component/form": { + "version": "1.8.6", + "resolved": "https://registry.npmjs.org/@rc-component/form/-/form-1.8.6.tgz", + "integrity": "sha512-1EXVsSKPZC6kGrIqxVck7kAWM6T65b6et/n5wIcyiaIa41VrDshD0nVLHoBDEIZr2ATQsOP6icb4XQkNFMLBAw==", + "license": "MIT", + "dependencies": { + "@rc-component/async-validator": "^6.0.0", + "@rc-component/util": "^1.11.1", + "clsx": "^2.1.1" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/image": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@rc-component/image/-/image-1.9.0.tgz", + "integrity": "sha512-khF7w7xkBH5B1bsBcI1FSUZdkyd1aqpl2eYyILCqCzzQH3XdfehGUaZTnptyaJJfs09/R5hv9jXWyazOMFIClQ==", + "license": "MIT", + "dependencies": { + "@rc-component/motion": "^1.0.0", + "@rc-component/portal": "^2.1.2", + "@rc-component/util": "^1.10.1", + "clsx": "^2.1.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/input": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@rc-component/input/-/input-1.3.1.tgz", + "integrity": "sha512-iFvTUT9W+JC/MSin2aGAk8NqsVlTzcExNC9DZariON1IWirju9NoNeEk47an4Q8iHazkoVI/y1LnDi88+CPcig==", + "license": "MIT", + "dependencies": { + "@rc-component/resize-observer": "^1.1.1", + "@rc-component/util": "^1.11.1", + "clsx": "^2.1.1" + }, + "peerDependencies": { + "react": ">=16.0.0", + "react-dom": ">=16.0.0" + } + }, + "node_modules/@rc-component/input-number": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/@rc-component/input-number/-/input-number-1.6.2.tgz", + "integrity": "sha512-Gjcq7meZlCOiWN1t1xCC+7/s85humHVokTBI7PJgTfoyw5OWF74y3e6P8PHX104g9+b54jsodFIzyaj6p8LI9w==", + "license": "MIT", + "dependencies": { + "@rc-component/mini-decimal": "^1.0.1", + "@rc-component/util": "^1.4.0", + "clsx": "^2.1.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/mentions": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@rc-component/mentions/-/mentions-1.10.0.tgz", + "integrity": "sha512-CI1njYUVY0NjHtLhNoVmXlJyy568Sfep9Wsak6vmGjtT6uazx98djGYlCXz2xkHhEm73g91Y3MTvzUyE5avI7w==", + "license": "MIT", + "dependencies": { + "@rc-component/input": "~1.3.0", + "@rc-component/menu": "~1.4.0", + "@rc-component/trigger": "^3.0.0", + "@rc-component/util": "^1.3.0", + "clsx": "^2.1.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/menu": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@rc-component/menu/-/menu-1.4.1.tgz", + "integrity": "sha512-3GsVRoQ4cnF/AoIQ4P+Z1haBfgfBPQfLT1RJY3Nu4DzOnheTslfCiGSPj7bv/cLj5sW5pHqN25dDXGP3JELAlQ==", + "license": "MIT", + "dependencies": { + "@rc-component/motion": "^1.1.4", + "@rc-component/overflow": "^1.0.0", + "@rc-component/trigger": "^3.0.0", + "@rc-component/util": "^1.11.1", + "clsx": "^2.1.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/mini-decimal": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@rc-component/mini-decimal/-/mini-decimal-1.1.4.tgz", + "integrity": "sha512-xiuXcaCwyOWpD8a8scdExFl+bntNphAW8XeenL1ig2en0AAZY0Pcp4pC0dI22qJ+NvxKn9RoNIoRdqYU3BLH4w==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.0" + }, + "engines": { + "node": ">=8.x" + } + }, + "node_modules/@rc-component/motion": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@rc-component/motion/-/motion-1.3.3.tgz", + "integrity": "sha512-Xh3IszxvlSv3/PLYFyC2UZi9LNB83yOnkB/LNmRzaypZLvkhqUIPS7MQpGZcCMWrNsXV2p6YTSWbSGvFpEle9A==", + "license": "MIT", + "dependencies": { + "@rc-component/util": "^1.11.0", + "clsx": "^2.1.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/mutate-observer": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@rc-component/mutate-observer/-/mutate-observer-2.0.1.tgz", + "integrity": "sha512-AyarjoLU5YlxuValRi+w8JRH2Z84TBbFO2RoGWz9d8bSu0FqT8DtugH3xC3BV7mUwlmROFauyWuXFuq4IFbH+w==", + "license": "MIT", + "dependencies": { + "@rc-component/util": "^1.2.0" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/notification": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@rc-component/notification/-/notification-2.0.7.tgz", + "integrity": "sha512-nqZzpf6BPdaj+3ILx7si79LLmqPKyUmQoXa+/9gg0SkH0v1DbD66oJgRMSBEVnd/zUT3D4gwxWIHUKebYf2ZXQ==", + "license": "MIT", + "dependencies": { + "@rc-component/motion": "^1.1.4", + "@rc-component/util": "^1.11.0", + "clsx": "^2.1.1" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=18.0.0", + "react-dom": ">=18.0.0" + } + }, + "node_modules/@rc-component/overflow": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@rc-component/overflow/-/overflow-1.0.1.tgz", + "integrity": "sha512-syfmgAABaHCnCDzPwHZ/2tuvIcpOO3jefYZMmfkN+pmo8HKTzsfhS57vxo4ksPdN0By+uWVJhJWNFozNBxi2eA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.11.1", + "@rc-component/resize-observer": "^1.0.1", + "@rc-component/util": "^1.4.0", + "clsx": "^2.1.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/pagination": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@rc-component/pagination/-/pagination-1.4.0.tgz", + "integrity": "sha512-CW1g7P9V8u+e8JQdUsl2RWg+GCsoee0mtJjZUCCxn/vb3jzOwDKm6hAdwddHCVBfWJ58eGUBZz3IvnU8rRktjw==", + "license": "MIT", + "dependencies": { + "@rc-component/util": "^1.11.1", + "clsx": "^2.1.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/picker": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@rc-component/picker/-/picker-1.11.0.tgz", + "integrity": "sha512-6qXGKtoJvO8sUd17m5cyNEbEJub0zflCHnaZTBBmj63DPRZYc0WEHN8rp6hFSl+yMCJS/dJY5G+1fQ8bLCuD7A==", + "license": "MIT", + "dependencies": { + "@rc-component/overflow": "^1.0.0", + "@rc-component/resize-observer": "^1.0.0", + "@rc-component/trigger": "^3.6.15", + "@rc-component/util": "^1.11.1", + "clsx": "^2.1.1" + }, + "engines": { + "node": ">=12.x" + }, + "peerDependencies": { + "date-fns": ">= 2.x", + "dayjs": ">= 1.x", + "luxon": ">= 3.x", + "moment": ">= 2.x", + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + }, + "peerDependenciesMeta": { + "date-fns": { + "optional": true + }, + "dayjs": { + "optional": true + }, + "luxon": { + "optional": true + }, + "moment": { + "optional": true + } + } + }, + "node_modules/@rc-component/portal": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@rc-component/portal/-/portal-2.2.1.tgz", + "integrity": "sha512-ck+r1kW/JSv0wxPji3KN2ss9K6Z0qqwusw/mf/0JobXhZ8hC2ejZwCJObW/SvDi0uhA0VzmCnx0CaCci95tcmA==", + "license": "MIT", + "dependencies": { + "@rc-component/util": "^1.11.0", + "clsx": "^2.1.1" + }, + "engines": { + "node": ">=12.x" + }, + "peerDependencies": { + "react": ">=18.0.0", + "react-dom": ">=18.0.0" + } + }, + "node_modules/@rc-component/progress": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@rc-component/progress/-/progress-1.0.2.tgz", + "integrity": "sha512-WZUnH9eGxH1+xodZKqdrHke59uyGZSWgj5HBM5Kwk5BrTMuAORO7VJ2IP5Qbm9aH3n9x3IcesqHHR0NWPBC7fQ==", + "license": "MIT", + "dependencies": { + "@rc-component/util": "^1.2.1", + "clsx": "^2.1.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/qrcode": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@rc-component/qrcode/-/qrcode-2.0.0.tgz", + "integrity": "sha512-aAv3QhPP1xyafuTZOxub6a54pCeBnN3IwQkpETrBtthq4BL5IgxnCbuoBWPDpdLw1y1j6BgBUCAKV92+yX06Dw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.24.7" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/rate": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@rc-component/rate/-/rate-1.0.1.tgz", + "integrity": "sha512-bkXxeBqDpl5IOC7yL7GcSYjQx9G8H+6kLYQnNZWeBYq2OYIv1MONd6mqKTjnnJYpV0cQIU2z3atdW0j1kttpTw==", + "license": "MIT", + "dependencies": { + "@rc-component/util": "^1.3.0", + "clsx": "^2.1.1" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/resize-observer": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@rc-component/resize-observer/-/resize-observer-1.1.2.tgz", + "integrity": "sha512-t/Bb0W8uvL4PYKAB3YcChC+DlHh0Wt5kM7q/J+0qpVEUMLe7Hk5zuvc9km0hMnTFPSx5Z7Wu/fzCLN6erVLE8Q==", + "license": "MIT", + "dependencies": { + "@rc-component/util": "^1.2.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/segmented": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@rc-component/segmented/-/segmented-1.3.0.tgz", + "integrity": "sha512-5J/bJ01mbDnoA6P/FW8SxUvKn+OgUSTZJPzCNnTBntG50tzoP7DydGhqxp7ggZXZls7me3mc2EQDXakU3iTVFg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.11.1", + "@rc-component/motion": "^1.1.4", + "@rc-component/util": "^1.3.0", + "clsx": "^2.1.1" + }, + "peerDependencies": { + "react": ">=16.0.0", + "react-dom": ">=16.0.0" + } + }, + "node_modules/@rc-component/select": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/@rc-component/select/-/select-1.8.2.tgz", + "integrity": "sha512-HQ9zuYqjfZTlcEMWlU1GAPBajd2OHIMVHyjZSGVTCVARwkfCgvXZMTEn0cduy3L+ejAKkaZluOQvxovZoaJaQw==", + "license": "MIT", + "dependencies": { + "@rc-component/overflow": "^1.0.0", + "@rc-component/trigger": "^3.0.0", + "@rc-component/util": "^1.11.1", + "@rc-component/virtual-list": "^1.2.0", + "clsx": "^2.1.1" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": "*", + "react-dom": "*" + } + }, + "node_modules/@rc-component/slider": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@rc-component/slider/-/slider-1.1.1.tgz", + "integrity": "sha512-LSzgWGYDgeCDgR4r1XlU29gbYws6HpLnvJd/uMhLeW/vQgxldeR+Wb4uzHDCHiYEbr1bnEHWdjkPxjJRHxuiig==", + "license": "MIT", + "dependencies": { + "@rc-component/util": "^1.3.0", + "clsx": "^2.1.1" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/steps": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@rc-component/steps/-/steps-1.2.2.tgz", + "integrity": "sha512-/yVIZ00gDYYPHSY0JP+M+s3ZvuXLu2f9rEjQqiUDs7EcYsUYrpJ/1bLj9aI9R7MBR3fu/NGh6RM9u2qGfqp+Nw==", + "license": "MIT", + "dependencies": { + "@rc-component/util": "^1.2.1", + "clsx": "^2.1.1" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/switch": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rc-component/switch/-/switch-1.0.3.tgz", + "integrity": "sha512-Jgi+EbOBquje/XNdofr7xbJQZPYJP+BlPfR0h+WN4zFkdtB2EWqEfvkXJWeipflwjWip0/17rNbxEAqs8hVHfw==", + "license": "MIT", + "dependencies": { + "@rc-component/util": "^1.3.0", + "clsx": "^2.1.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/table": { + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/@rc-component/table/-/table-1.10.4.tgz", + "integrity": "sha512-HwoTnrwc29zeoXkXGhWqzJh8FIibGUxi1jM4LtoSzmR9d5Vv5osUQpZxnXKBP8iOCvyD6BQzZm1nXJRcnrxpAg==", + "license": "MIT", + "dependencies": { + "@rc-component/context": "^2.0.1", + "@rc-component/resize-observer": "^1.0.0", + "@rc-component/util": "^1.11.1", + "@rc-component/virtual-list": "^1.0.1", + "clsx": "^2.1.1" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=18.0.0", + "react-dom": ">=18.0.0" + } + }, + "node_modules/@rc-component/tabs": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@rc-component/tabs/-/tabs-1.11.0.tgz", + "integrity": "sha512-hA/drZYOVa/MMIb4M2fWf3yaTyTG4qVuIABmghvEhyfw2nBob5VTH69lMCDjSVKmgODjO6nWlCV+gVn3xBrj5Q==", + "license": "MIT", + "dependencies": { + "@rc-component/dropdown": "~1.0.0", + "@rc-component/menu": "~1.4.0", + "@rc-component/motion": "^1.1.3", + "@rc-component/resize-observer": "^1.0.0", + "@rc-component/util": "^1.11.1", + "clsx": "^2.1.1" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/tooltip": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@rc-component/tooltip/-/tooltip-1.4.0.tgz", + "integrity": "sha512-8Rx5DCctIlLI4raR0I0xHjVTf1aF48+gKCNeAAo5bmF5VoR5YED+A/XEqzXv9KKqrJDRcd3Wndpxh2hyzrTtSg==", + "license": "MIT", + "dependencies": { + "@rc-component/trigger": "^3.7.1", + "@rc-component/util": "^1.3.0", + "clsx": "^2.1.1" + }, + "peerDependencies": { + "react": ">=18.0.0", + "react-dom": ">=18.0.0" + } + }, + "node_modules/@rc-component/tour": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@rc-component/tour/-/tour-2.4.0.tgz", + "integrity": "sha512-aui4r4TqmTzwaBgcQxHYep8kM8PTjZFufjokObpy35KfFeZ0k9ArquWFZqegQlH24P14t+F0qO0mGTgzlav1yg==", + "license": "MIT", + "dependencies": { + "@rc-component/portal": "^2.2.0", + "@rc-component/trigger": "^3.0.0", + "@rc-component/util": "^1.7.0", + "clsx": "^2.1.1" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/tree": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@rc-component/tree/-/tree-1.3.2.tgz", + "integrity": "sha512-bJFj46wEkpBPnWyTm18XmgAgNQ/4YvprxMOPPY2a6rmhGJYxLuNKEFiL5Qej4Qctu9wHJm8WW+v2SYskafE0kA==", + "license": "MIT", + "dependencies": { + "@rc-component/motion": "^1.0.0", + "@rc-component/util": "^1.11.1", + "@rc-component/virtual-list": "^1.2.0", + "clsx": "^2.1.1" + }, + "engines": { + "node": ">=10.x" + }, + "peerDependencies": { + "react": "*", + "react-dom": "*" + } + }, + "node_modules/@rc-component/tree-select": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@rc-component/tree-select/-/tree-select-1.11.0.tgz", + "integrity": "sha512-EhS0X0wtUhBfK4S5TlpSY3MR9ndPMGgujtt1PJW3Ej+ToAlnS/6ohYURtCoXBYGqazUwHmgQGVUDsfpVwhWPkg==", + "license": "MIT", + "dependencies": { + "@rc-component/select": "~1.8.0", + "@rc-component/tree": "~1.3.2", + "@rc-component/util": "^1.11.1", + "clsx": "^2.1.1" + }, + "peerDependencies": { + "react": "*", + "react-dom": "*" + } + }, + "node_modules/@rc-component/trigger": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@rc-component/trigger/-/trigger-3.10.1.tgz", + "integrity": "sha512-mXlDN0IXdtV8Yqqm8195ECCyrbmfvvfKvwVvSlH0+qvKD6BUF8gRhEjSy0FOcD1+CcDRHgTiX99LoxfQrmh3Cw==", + "license": "MIT", + "dependencies": { + "@rc-component/motion": "^1.3.3", + "@rc-component/portal": "^2.2.1", + "@rc-component/resize-observer": "^1.1.2", + "@rc-component/util": "^1.11.1", + "clsx": "^2.1.1" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=18.0.0", + "react-dom": ">=18.0.0" + } + }, + "node_modules/@rc-component/upload": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@rc-component/upload/-/upload-1.1.1.tgz", + "integrity": "sha512-GvYWSKeaJTOxxC5p6+nOSadzfvXA1h8C/iHFPFZX+szH3JUXrvs+DLiW8YUTBgvMh8m63mJeHrlYlJzAlg+pDA==", + "license": "MIT", + "dependencies": { + "@rc-component/util": "^1.11.1", + "clsx": "^2.1.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/util": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/@rc-component/util/-/util-1.12.0.tgz", + "integrity": "sha512-AEjPL8JVdohIITaiXokyjL9WQ6tKWWjAYK9QU16tGNE9JaQABBQy+hA4H2Lup5MgXy9yY3iLrbZJheuU13hTdQ==", + "license": "MIT", + "dependencies": { + "is-mobile": "^5.0.0", + "react-is": "^19.2.7" + }, + "peerDependencies": { + "react": ">=18.0.0", + "react-dom": ">=18.0.0" + } + }, + "node_modules/@rc-component/virtual-list": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@rc-component/virtual-list/-/virtual-list-1.4.0.tgz", + "integrity": "sha512-qoyNStkTJQDezPjBibGA5HNxS9NiKJvemD1bLp7qfyxDlwy7ofPLUP0ZqJ47hR8AKcFaizd0AP/7QWLTLpudKQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^8.0.0", + "@rc-component/resize-observer": "^1.0.1", + "@rc-component/util": "^1.4.0", + "clsx": "^2.1.1" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=18.0.0", + "react-dom": ">=18.0.0" + } + }, + "node_modules/@rc-component/virtual-list/node_modules/@babel/runtime": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-8.0.0.tgz", + "integrity": "sha512-sL6cvO2IfkSu/iU+zs2S/w01B7A8V7suXSIKEN4hPFFdZoiPGxrj5pAG0lCaqLWiEIrjKzdznIWuaLcxPR53qw==", + "license": "MIT" + }, + "node_modules/@redocly/ajv": { + "version": "8.11.2", + "resolved": "https://registry.npmjs.org/@redocly/ajv/-/ajv-8.11.2.tgz", + "integrity": "sha512-io1JpnwtIcvojV7QKDUSIuMN/ikdOUd1ReEnUnMKGfDVridQZ31J0MmIuqwuRjWDZfmvr+Q0MqCcfHM2gTivOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js-replace": "^1.0.1" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@redocly/config": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/@redocly/config/-/config-0.22.0.tgz", + "integrity": "sha512-gAy93Ddo01Z3bHuVdPWfCwzgfaYgMdaZPcfL7JZ7hWJoK9V0lXDbigTWkhiPFAaLWzbOJ+kbUQG1+XwIm0KRGQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@redocly/openapi-core": { + "version": "1.34.18", + "resolved": "https://registry.npmjs.org/@redocly/openapi-core/-/openapi-core-1.34.18.tgz", + "integrity": "sha512-UyKIm0wTPw5BcY7Z2PkbK1Ma260um96LSBWXHrdSMe+ZV0EPMyDfAcUcjjm3qEiGST9OK/1TriekdPCZkn4Q3A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@redocly/ajv": "8.11.2", + "@redocly/config": "0.22.0", + "colorette": "1.4.0", + "https-proxy-agent": "7.0.6", + "js-levenshtein": "1.1.6", + "js-yaml": "4.3.0", + "minimatch": "5.1.9", + "pluralize": "8.0.0", + "yaml-ast-parser": "0.0.43" + }, + "engines": { + "node": ">=18.17.0", + "npm": ">=9.5.0" + } + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.0-rc.3", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.3.tgz", + "integrity": "sha512-eybk3TjzzzV97Dlj5c+XrBFW57eTNhzod66y9HrBlzJ6NsCrWCp/2kaPS3K9wJmurBC0Tdw4yPjXKZqlznim3Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.62.3.tgz", + "integrity": "sha512-c0wdcekXtQvvn5Tsrk/+op/gUArrbWaFduBnTLP2l1cKLSQs4diMWjJw3m6A0DdzT8dAAX95KpkJ3qynCePbmw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.62.3.tgz", + "integrity": "sha512-3YjElDdWN+qXAFbJ/CzPV+0wspLqh54k/I6GfdYtEJRqg7buSgc1yPM3B+93j1M4neobtkATHZTmxK2AMVGfnA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.62.3.tgz", + "integrity": "sha512-Pch2pFNOxxz1hTjypIdPyRTR6riiwRl84+VcN9djS680fw+Co1nAJINrdpqp7KV0NvyuU8ilZXZCjd7ykJl1GQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.62.3.tgz", + "integrity": "sha512-LEuncFUHFiF8t4yZVZvvZA1wk0pjAscRnsrn1EfTEmN4HXotBi2YtcnLRyaK6UbuczW7xZS5ES+81Rdz8Z0T6g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.62.3.tgz", + "integrity": "sha512-zvBUvsQUpOWALdDsk6qbS8bXf2VxmPisuudNDrY7x0p0jBdsoZl8HsHczIOgkQiZldmcacMKtBzpoGVNeIe2bQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.62.3.tgz", + "integrity": "sha512-C2KmNrcSem/AMg984H/dev+si0lieQGdXdR/lYGJnuumXnFb9Y7QdiI62obFdLlxRYLBv4P0eUVIDbD4c1vVvw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.62.3.tgz", + "integrity": "sha512-ggXnsTAEzNQx74XpunRsiZ9aBZDsI7XIa0hm2nzR9f4WzH5/f/d73ZSDaC5ejJ8YLY4NW+V3wr0tjOaeCq8hqA==", + "cpu": [ + "arm" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.62.3.tgz", + "integrity": "sha512-2vng+FlzNUhKZxtej3IUqJgbZoQk2M/dwQM20+ULV0R/E/8tr9/P6uEf2iiGIk4HL0zMKh5Jry7mUHdUOvyGgA==", + "cpu": [ + "arm" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.62.3.tgz", + "integrity": "sha512-LLLFZKt4/Nraf9rxDkhiU8QVgLF4WmCkfr0L4fj0fPfIZFBib0DeiFk1hhaYKd03LFAFJcxHslhDFlNJLylf5Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.62.3.tgz", + "integrity": "sha512-WJkdQCvS9sWNOUBJZfQRKpZGFBztRzcowI+nndmflKgU4XY+3a420FgTOSKTsVqJbnzSxeT4vaJalpOaPo2YCQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.62.3.tgz", + "integrity": "sha512-PwHXCCS2n64/1Ot6rP1YEYA02MGYBcQlr8CSZZyrUG2O7NH6NklYmvr9v3Jy+5e/eDeNchc/ukmKJi9LuflMIQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.62.3.tgz", + "integrity": "sha512-vUjxINQu3RC8NZS3ykk1gN65gIz8pAopOq2HXuZhiIxHdx7TFvDG+jgrdSgInu1Eza4/Rfi2VzZgyIgEH4WOaw==", + "cpu": [ + "loong64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.62.3.tgz", + "integrity": "sha512-wzko4aJ13+0G3kGnviCg5gnXFKd40izKsrf2uOw12US4XqprkDrmwOpeW14aSNa37V8bfPcz5Fkob6LZ3BAPmA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.62.3.tgz", + "integrity": "sha512-8120ue0JUMSwy11stlwnfdX3pPd+WZYGCDBwEHWtIHi6pOpZmsEF5QKB7a/UN+XFdqvobxz98kv8RTqikyCEBw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.62.3.tgz", + "integrity": "sha512-XLFHnR3tXMjbOCh2vtVJHmxt+995uJsTERQyseFDRA0xxMxyTZPLa3OIUlyFaO4mF/Lu0FjmWHCuPXJT1n/IOg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.62.3.tgz", + "integrity": "sha512-se6yXvNGMIl0f+RQzyh7XAmia8/9kplQx424wnG2w0C1oi6XgO6Y8otKhdXFHbHs88Ihavzmvh1NWjuovE76BQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.62.3.tgz", + "integrity": "sha512-gNoxRefktVIiGflpONuxWWXZAzIQG++z9qHO3xKwk4WdDMuQja3JHGfE1u0i3PfPDyvhypdk+WrgIJqLhGG7sg==", + "cpu": [ + "s390x" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.62.3.tgz", + "integrity": "sha512-V4KtWtQfAFMU7+9/A/VDps/VI8CHd3cYz0L8sgJzz8qK7eY7wI4ruFD82UYIYvW9Z4DtlTfhQcsl4XyPHW5uSg==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.62.3.tgz", + "integrity": "sha512-LBx9LYXvj2CBkMkjLdNAWLwH0MLMin7do2VcVo9kVPibGLkY0BQQut2fv7NVqkXqZ/CrAu9LqDHVV1xHCMpCPw==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.62.3.tgz", + "integrity": "sha512-ABVf3Q0RCu7NcyCCOZQI0pJ3GuSdfSl8EXcy88QtdceIMIoCUdfhsJChZ64L9zVM2aJHjde1Bhn5uqSRcX9ySA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.62.3.tgz", + "integrity": "sha512-+2Cy/ldweGBLlPIKsQLF8U5N44a0KDdbrk1rAjHOM9M2K+kGdIVjHLmmrZIcx+9Ny3ke/1JomCsDI1ocb11+sg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.62.3.tgz", + "integrity": "sha512-dtZvzc8BedpSaFNy75x6uiWwAGTH+aZHDtdrqP6qk+WcLJrfti6sGje1ZJ9UxyzDLF23d/mV+PaMwuC0hL7UVA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.62.3.tgz", + "integrity": "sha512-Rj8Ra4noo+aYy7sKBggCx0407mws34kAb1ySyWuq5DAtFBQdkSwnsjCgPrhPe9cvgBKZIukpE+CVHvORCS93kQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.62.3.tgz", + "integrity": "sha512-vp7N084ew/odXn2gi/mzm9mUkQu9l6AiN6dt4IeUM2Uvm9o+cVmP+YkqbMOteLbiGgqBBlJZjIMYVCfOOIVbVQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.62.3.tgz", + "integrity": "sha512-MOG/3gTOn4Fwf574RVOaY61I5o6P90legkFADiTyn1hyjNydT+cerU2rLUwPdZkKKyJ+iT+K9p7WXK4LM1Ka6g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@standard-schema/spec": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", + "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", + "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz", + "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.2" + } + }, + "node_modules/@types/chai": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz", + "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/deep-eql": "*", + "assertion-error": "^2.0.1" + } + }, + "node_modules/@types/deep-eql": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", + "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/estree": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "24.13.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.13.3.tgz", + "integrity": "sha512-Dh8vAsV36ig5wa9OX4pXvMc9D3Veibfw2wix0CUwYODLD8nkj9UsLjASr49nPg+2eKzxhBV+v7L8pXvT4e639Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~7.18.0" + } + }, + "node_modules/@types/react": { + "version": "19.2.17", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.17.tgz", + "integrity": "sha512-MXfmqaVPEVgkBT/aY0aGCkRWWtByiYQXo3xdQ8r5RzuFrPiRn8Gar2tQdXSUQ2GKV3bkXckek89V8wQBY2Q/Aw==", + "dev": true, + "license": "MIT", + "dependencies": { + "csstype": "^3.2.2" + } + }, + "node_modules/@types/react-dom": { + "version": "19.2.3", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz", + "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/react": "^19.2.0" + } + }, + "node_modules/@vitejs/plugin-react": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-5.2.0.tgz", + "integrity": "sha512-YmKkfhOAi3wsB1PhJq5Scj3GXMn3WvtQ/JC0xoopuHoXSdmtdStOpFrYaT1kie2YgFBcIe64ROzMYRjCrYOdYw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.29.0", + "@babel/plugin-transform-react-jsx-self": "^7.27.1", + "@babel/plugin-transform-react-jsx-source": "^7.27.1", + "@rolldown/pluginutils": "1.0.0-rc.3", + "@types/babel__core": "^7.20.5", + "react-refresh": "^0.18.0" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "peerDependencies": { + "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/@vitest/expect": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.10.tgz", + "integrity": "sha512-YsCn+qAk1GWjQOWFEsEcL2gNQ0zmVmQu3T03qP6UyjhtmdtwtbuI+DASn/7iQB3HGTXkdBwGddzxPlmiql5vlA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@standard-schema/spec": "^1.1.0", + "@types/chai": "^5.2.2", + "@vitest/spy": "4.1.10", + "@vitest/utils": "4.1.10", + "chai": "^6.2.2", + "tinyrainbow": "^3.1.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/mocker": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.10.tgz", + "integrity": "sha512-v0xaezt+DKEmKfaxg133ldzADrwLGd7Ze1MfQQTYfvs8OqZIwbxyxaYURivwV7sWy5fqn3rH5uOrSp07bp44Ow==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/spy": "4.1.10", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.21" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "msw": "^2.4.9", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } + } + }, + "node_modules/@vitest/pretty-format": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.10.tgz", + "integrity": "sha512-W1HsjSH4MXQ9YfmmhLAoIYf1HRfekQCGngeIgcei6MP5QQGWUe0gkopdZQaVCFO+JDJMrAJGwa5pRpNpvy4P8Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyrainbow": "^3.1.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.1.10.tgz", + "integrity": "sha512-IKI6kpIH+LmpROplyLwBBaCfMgOZOMsygVa6BARD6ahA04VRuJSa6OaVG7kRvSEMD870Vd91rSSw0eegtWyLGg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/utils": "4.1.10", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/snapshot": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.1.10.tgz", + "integrity": "sha512-xRkfOT1qpTAi/Ti4Y1LtfRc3kEuqxGw59eN2jN9pRWMtS/XDevekhcFSqvQqjUNGksfjMJu3Y+oJ+4Ypn2OaJw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "4.1.10", + "@vitest/utils": "4.1.10", + "magic-string": "^0.30.21", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/spy": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.1.10.tgz", + "integrity": "sha512-PLf/Ugvoq5wO/b4rwYCR1h2PSIdXz7wnkQFMiUpLdtM7l6pqVFcQIBEHyT1+l+cj7mNwAfZHzqXqDyjvOuwbDw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.1.10.tgz", + "integrity": "sha512-fy9am/HWxbaGt/Sawrp90vt6Y6jQwf1RX77cz3uwoJwJVMli/e1IEwRPnMNJ7vKfPTwo0diXifkpPvwH9v7nGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "4.1.10", + "convert-source-map": "^2.0.0", + "tinyrainbow": "^3.1.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/agent-base": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/ansi-colors": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/antd": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/antd/-/antd-6.5.0.tgz", + "integrity": "sha512-9zbVc9UukfGuqCvIAov01nlpDQWfARNmZQyt21ZhqLX7ilXmi4cdkp12xA48WEmXRXwZvno8A03qQuGE9JG8fg==", + "license": "MIT", + "dependencies": { + "@ant-design/colors": "^8.0.1", + "@ant-design/cssinjs": "^2.1.2", + "@ant-design/cssinjs-utils": "^2.1.2", + "@ant-design/fast-color": "^3.0.1", + "@ant-design/icons": "^6.3.1", + "@ant-design/react-slick": "~2.0.0", + "@babel/runtime": "^7.29.2", + "@rc-component/cascader": "~1.17.0", + "@rc-component/checkbox": "~2.0.0", + "@rc-component/collapse": "~1.2.0", + "@rc-component/color-picker": "~3.1.1", + "@rc-component/dialog": "~1.10.0", + "@rc-component/drawer": "~1.4.2", + "@rc-component/dropdown": "~1.0.2", + "@rc-component/form": "~1.8.5", + "@rc-component/image": "~1.9.0", + "@rc-component/input": "~1.3.1", + "@rc-component/input-number": "~1.6.2", + "@rc-component/mentions": "~1.10.0", + "@rc-component/menu": "~1.4.1", + "@rc-component/motion": "^1.3.3", + "@rc-component/mutate-observer": "^2.0.1", + "@rc-component/notification": "~2.0.7", + "@rc-component/pagination": "~1.4.0", + "@rc-component/picker": "~1.11.0", + "@rc-component/progress": "~1.0.2", + "@rc-component/qrcode": "~2.0.0", + "@rc-component/rate": "~1.0.1", + "@rc-component/resize-observer": "^1.1.2", + "@rc-component/segmented": "~1.3.0", + "@rc-component/select": "~1.8.2", + "@rc-component/slider": "~1.1.1", + "@rc-component/steps": "~1.2.2", + "@rc-component/switch": "~1.0.3", + "@rc-component/table": "~1.10.2", + "@rc-component/tabs": "~1.11.0", + "@rc-component/tooltip": "~1.4.0", + "@rc-component/tour": "~2.4.0", + "@rc-component/tree": "~1.3.2", + "@rc-component/tree-select": "~1.11.0", + "@rc-component/trigger": "^3.9.1", + "@rc-component/upload": "~1.1.1", + "@rc-component/util": "^1.11.1", + "clsx": "^2.1.1", + "dayjs": "^1.11.11", + "scroll-into-view-if-needed": "^3.1.0", + "throttle-debounce": "^5.0.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/ant-design" + }, + "peerDependencies": { + "react": ">=18.0.0", + "react-dom": ">=18.0.0" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/assertion-error": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/baseline-browser-mapping": { + "version": "2.11.7", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.11.7.tgz", + "integrity": "sha512-APw5YuIQAg6L9w4sHDI6j26DGFJI6RpYOhnkMPdC9lWbkKvsyPHzDsve1yd73lk21yz7Y09Kci8B2Pp9FonzWA==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/brace-expansion": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.3.tgz", + "integrity": "sha512-DRdx5neNsG/QXbniLFWi2YmC/68oeOOmKz6zOjVk6ZS1ZLXgLIKqVEc6hWsmkjBbgii0SwaBTcJ5XKj5gzY/4A==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/browserslist": { + "version": "4.28.7", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.7.tgz", + "integrity": "sha512-JxV13hNrFxqjOc8alRbq9dK1MM79NEXYpma2B2J4wAtpWS5zIEIKqWPGCl7N4o7Uc7B7itylh7SuDujATRyyTw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "baseline-browser-mapping": "^2.10.44", + "caniuse-lite": "^1.0.30001806", + "electron-to-chromium": "^1.5.393", + "node-releases": "^2.0.51", + "update-browserslist-db": "^1.2.3" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001806", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001806.tgz", + "integrity": "sha512-72Cuvd95zbSYPKq6Fhg8eDJRlzgWDf7/mtoZv6Qe/DYNCEBdNxoA3+rZAU2ZhGCpZlns3EssFavaZomckT5Uuw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/chai": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.2.tgz", + "integrity": "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/change-case": { + "version": "5.4.4", + "resolved": "https://registry.npmjs.org/change-case/-/change-case-5.4.4.tgz", + "integrity": "sha512-HRQyTk2/YPEkt9TnUPbOpr64Uw3KOicFWPVBb+xiHvd6eBx/qPr9xqfBFDT8P2vWsvvz4jbEkfDe71W3VyNu2w==", + "dev": true, + "license": "MIT" + }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/colorette": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz", + "integrity": "sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==", + "dev": true, + "license": "MIT" + }, + "node_modules/compute-scroll-into-view": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-3.1.1.tgz", + "integrity": "sha512-VRhuHOLoKYOy4UbilLbUzbYg93XLjv2PncJC50EuTWPA3gaja1UjBsUP/D/9/juV3vQFr6XBEzn9KCAHdUvOHw==", + "license": "MIT" + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/cookie-es": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/cookie-es/-/cookie-es-3.1.1.tgz", + "integrity": "sha512-UaXxwISYJPTr9hwQxMFYZ7kNhSXboMXP+Z3TRX6f1/NyaGPfuNUZOWP1pUEb75B2HjfklIYLVRfWiFZJyC6Npg==", + "license": "MIT" + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "license": "MIT" + }, + "node_modules/dayjs": { + "version": "1.11.21", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.21.tgz", + "integrity": "sha512-98IT+HOahAisibz/yjKbzuOBwYcjJ7BCLPzARyHiyEBmRz4fatF+KPJszEHXsGYjUG234aH/cOjW1wwTbKUZlA==", + "license": "MIT" + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/electron-to-chromium": { + "version": "1.5.398", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.398.tgz", + "integrity": "sha512-AsvhAxopJGh6museTDMIjn6JpDYOfgu4RLlygomt87MUwBUqTfd/1EiPtx10/LZE8xpTvkP2E9Gafq7lkLtodQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/es-module-lexer": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.3.1.tgz", + "integrity": "sha512-shc1dbU90Yl/xq1QrC7QRtfcwURZuVRfPhZbDoldJ1cn1gzDvBaBWlv0eFolj5+0znnPJz5TXLxsN77X/12KTA==", + "dev": true, + "license": "MIT" + }, + "node_modules/esbuild": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.1.tgz", + "integrity": "sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.28.1", + "@esbuild/android-arm": "0.28.1", + "@esbuild/android-arm64": "0.28.1", + "@esbuild/android-x64": "0.28.1", + "@esbuild/darwin-arm64": "0.28.1", + "@esbuild/darwin-x64": "0.28.1", + "@esbuild/freebsd-arm64": "0.28.1", + "@esbuild/freebsd-x64": "0.28.1", + "@esbuild/linux-arm": "0.28.1", + "@esbuild/linux-arm64": "0.28.1", + "@esbuild/linux-ia32": "0.28.1", + "@esbuild/linux-loong64": "0.28.1", + "@esbuild/linux-mips64el": "0.28.1", + "@esbuild/linux-ppc64": "0.28.1", + "@esbuild/linux-riscv64": "0.28.1", + "@esbuild/linux-s390x": "0.28.1", + "@esbuild/linux-x64": "0.28.1", + "@esbuild/netbsd-arm64": "0.28.1", + "@esbuild/netbsd-x64": "0.28.1", + "@esbuild/openbsd-arm64": "0.28.1", + "@esbuild/openbsd-x64": "0.28.1", + "@esbuild/openharmony-arm64": "0.28.1", + "@esbuild/sunos-x64": "0.28.1", + "@esbuild/win32-arm64": "0.28.1", + "@esbuild/win32-ia32": "0.28.1", + "@esbuild/win32-x64": "0.28.1" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, + "node_modules/expect-type": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.4.0.tgz", + "integrity": "sha512-KfYbmpRm0VbLjEvVa9yGwCi9GI34xvi7A/HXYWQO65CSD2u3MczUJSuwXKFIxlGsgBQizV9q5J9NHj4VG0n+pA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/index-to-position": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/index-to-position/-/index-to-position-1.2.0.tgz", + "integrity": "sha512-Yg7+ztRkqslMAS2iFaU+Oa4KTSidr63OsFGlOrJoW981kIYO3CGCS3wA95P1mUi/IVSJkn0D479KTJpVpvFNuw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-mobile": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-mobile/-/is-mobile-5.0.0.tgz", + "integrity": "sha512-Tz/yndySvLAEXh+Uk8liFCxOwVH6YutuR74utvOcu7I9Di+DwM0mtdPVZNaVvvBUM2OXxne/NhOs1zAO7riusQ==", + "license": "MIT" + }, + "node_modules/js-levenshtein": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/js-levenshtein/-/js-levenshtein-1.1.6.tgz", + "integrity": "sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.0.tgz", + "integrity": "sha512-1td788aAnnZ5qs7V2QIRl1owjtYpbKt749Y3xauqQgwIIGF/xXWz1wMTEBx5O3LK3lXLVuqXPdPxj2BoFHaW9Q==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true, + "license": "MIT" + }, + "node_modules/json2mq": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/json2mq/-/json2mq-0.2.0.tgz", + "integrity": "sha512-SzoRg7ux5DWTII9J2qkrZrqV1gt+rTaoufMxEzXbS26Uid0NwaJd123HcoB80TgubEppxxIGdNxCx50fEoEWQA==", + "license": "MIT", + "dependencies": { + "string-convert": "^0.2.0" + } + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/minimatch": { + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz", + "integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.16", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.16.tgz", + "integrity": "sha512-bzlKTyNJ7+LdGIIwy8ijFpIqEQIvafahV7eYykJ8Cvh42EdJeODoJ6gUJXpQJvej1BddH8OqTXZNE/KfbWAu8Q==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/node-releases": { + "version": "2.0.51", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.51.tgz", + "integrity": "sha512-wRNIrw4DmVLKQlbgOMdkMx27Wrpzes2hh5Jtbi2bjPd+4wJstWIqP5A+lscnqbm0xxmT5Bpg8Lec5ItEBwx6BQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/obug": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.4.tgz", + "integrity": "sha512-4a+OsYv9UktOJKE+l1A4OufDgdRF9PifWj+tJnHURo/P+WOxpG4GzUFL9qCalmWauao6ogiG+QvnCovwPoyAWA==", + "dev": true, + "funding": [ + "https://github.com/sponsors/sxzz", + "https://opencollective.com/debug" + ], + "license": "MIT", + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/openapi-typescript": { + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/openapi-typescript/-/openapi-typescript-7.13.0.tgz", + "integrity": "sha512-EFP392gcqXS7ntPvbhBzbF8TyBA+baIYEm791Hy5YkjDYKTnk/Tn5OQeKm5BIZvJihpp8Zzr4hzx0Irde1LNGQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@redocly/openapi-core": "^1.34.6", + "ansi-colors": "^4.1.3", + "change-case": "^5.4.4", + "parse-json": "^8.3.0", + "supports-color": "^10.2.2", + "yargs-parser": "^21.1.1" + }, + "bin": { + "openapi-typescript": "bin/cli.js" + }, + "peerDependencies": { + "typescript": "^5.x" + } + }, + "node_modules/parse-json": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-8.3.0.tgz", + "integrity": "sha512-ybiGyvspI+fAoRQbIPRddCcSTV9/LsJbf0e/S85VLowVGzRmokfneg2kwVW/KU5rOXrPSbF1qAKPMgNTqqROQQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.26.2", + "index-to-position": "^1.1.0", + "type-fest": "^4.39.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "dev": true, + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz", + "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pluralize": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", + "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss": { + "version": "8.5.25", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.25.tgz", + "integrity": "sha512-DTPx3RWSSnWyzLxQnlH0rJP+EW5ekl16ZU4/psbIhA0e53kJfdgaN5vKM+xP7yJtXVu+nfdVFmlgFDEKAe4Pyw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.16", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/react": { + "version": "19.2.8", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.8.tgz", + "integrity": "sha512-PWaYA1L/q9u2u7xYQi+Y3L3Yfnie7XyLeaJICV1MGD6LprsBxcAqGjYyr0eY3p+QdsA+x/Irkt4Qif8D63+Sbw==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "19.2.8", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.8.tgz", + "integrity": "sha512-rVprimfGBG3DR+Tq0IQG2DT5PxKth1WIGDmj5yPmlzr4YBe7uyE+Du4oVqTDXZSHGGGXRtTJEGSSePyQCMBglQ==", + "license": "MIT", + "dependencies": { + "scheduler": "^0.27.0" + }, + "peerDependencies": { + "react": "^19.2.8" + } + }, + "node_modules/react-is": { + "version": "19.2.8", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.2.8.tgz", + "integrity": "sha512-s5un28nYxKJw5gvUHyW5PCC28CvBqLu9r3cWgzHT4Vo/5fqqkFcdRYsGcKf50WMPpjjFZS5d76fn3YCo2njKwQ==", + "license": "MIT" + }, + "node_modules/react-refresh": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.18.0.tgz", + "integrity": "sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-router": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-8.3.0.tgz", + "integrity": "sha512-qyPMvW83jGIct3yiieisxdk9M745anqhpIMKN5m1t6yBMfgVPpt77aHOqs5fUlEJRMCGffg9BaQLH9oPVOL7xQ==", + "license": "MIT", + "dependencies": { + "cookie-es": "^3.1.1" + }, + "engines": { + "node": ">=22.22.0" + }, + "peerDependencies": { + "react": ">=19.2.7", + "react-dom": ">=19.2.7" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + } + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/rollup": { + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.62.3.tgz", + "integrity": "sha512-Gu0c0iH9FzgX1L1t7ByIbbS3Vmdz+6KHm/EsqmmC71gUQ82yvZRkTK6XzrFObSka91WUVdynqp6nsfilzr5k6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.9" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.62.3", + "@rollup/rollup-android-arm64": "4.62.3", + "@rollup/rollup-darwin-arm64": "4.62.3", + "@rollup/rollup-darwin-x64": "4.62.3", + "@rollup/rollup-freebsd-arm64": "4.62.3", + "@rollup/rollup-freebsd-x64": "4.62.3", + "@rollup/rollup-linux-arm-gnueabihf": "4.62.3", + "@rollup/rollup-linux-arm-musleabihf": "4.62.3", + "@rollup/rollup-linux-arm64-gnu": "4.62.3", + "@rollup/rollup-linux-arm64-musl": "4.62.3", + "@rollup/rollup-linux-loong64-gnu": "4.62.3", + "@rollup/rollup-linux-loong64-musl": "4.62.3", + "@rollup/rollup-linux-ppc64-gnu": "4.62.3", + "@rollup/rollup-linux-ppc64-musl": "4.62.3", + "@rollup/rollup-linux-riscv64-gnu": "4.62.3", + "@rollup/rollup-linux-riscv64-musl": "4.62.3", + "@rollup/rollup-linux-s390x-gnu": "4.62.3", + "@rollup/rollup-linux-x64-gnu": "4.62.3", + "@rollup/rollup-linux-x64-musl": "4.62.3", + "@rollup/rollup-openbsd-x64": "4.62.3", + "@rollup/rollup-openharmony-arm64": "4.62.3", + "@rollup/rollup-win32-arm64-msvc": "4.62.3", + "@rollup/rollup-win32-ia32-msvc": "4.62.3", + "@rollup/rollup-win32-x64-gnu": "4.62.3", + "@rollup/rollup-win32-x64-msvc": "4.62.3", + "fsevents": "~2.3.2" + } + }, + "node_modules/scheduler": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", + "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", + "license": "MIT" + }, + "node_modules/scroll-into-view-if-needed": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/scroll-into-view-if-needed/-/scroll-into-view-if-needed-3.1.0.tgz", + "integrity": "sha512-49oNpRjWRvnU8NyGVmUaYG4jtTkNonFZI86MmGRDqBphEK2EXT9gdEUoQPZhuBM8yWHxCWbobltqYO5M4XrUvQ==", + "license": "MIT", + "dependencies": { + "compute-scroll-into-view": "^3.0.2" + } + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", + "dev": true, + "license": "ISC" + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "dev": true, + "license": "MIT" + }, + "node_modules/std-env": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-4.2.0.tgz", + "integrity": "sha512-oCUKSupKTHX53EyjDtuZQ64pjLJ6yYCtpmEw0goYxtjG9KpbRe8KAsl2tBUGU9DyMcJ0RwJ8GqJAFzMXcXW1Rw==", + "dev": true, + "license": "MIT" + }, + "node_modules/string-convert": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/string-convert/-/string-convert-0.2.1.tgz", + "integrity": "sha512-u/1tdPl4yQnPBjnVrmdLo9gtuLvELKsAoRapekWggdiQNvvvum+jYF329d84NAa660KQw7pB2n36KrIKVoXa3A==", + "license": "MIT" + }, + "node_modules/stylis": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.4.0.tgz", + "integrity": "sha512-5Z9ZpRzfuH6l/UAvCPAPUo3665Nk2wLaZU3x+TLHKVzIz33+sbJqbtrYoC3KD4/uVOr2Zp+L0LySezP9OHV9yA==", + "license": "MIT" + }, + "node_modules/supports-color": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-10.2.2.tgz", + "integrity": "sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/throttle-debounce": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-5.0.2.tgz", + "integrity": "sha512-B71/4oyj61iNH0KeCamLuE2rmKuTO5byTOSVwECM5FA7TiAiAW+UqTKZ9ERueC4qvgSttUhdmq1mXC3kJqGX7A==", + "license": "MIT", + "engines": { + "node": ">=12.22" + } + }, + "node_modules/tinybench": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyexec": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.2.4.tgz", + "integrity": "sha512-SHf/r48b7vOrjve9PxJo3MN5v5yuyjHvdUcrQffT3WXMUfnGmHDVbC4k3sHJaJTgZCwpUplIaAo5ANtMyp3YHg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyrainbow": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.1.1.tgz", + "integrity": "sha512-yau8yJdTt989Mm0Bd/236QnzEiPf2xLLTqUZRUJOo/3CB078LSwzei343DgtJVmfJKJE3TMINY1u42SQsP6mXw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/type-fest": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz", + "integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==", + "dev": true, + "license": "MIT" + }, + "node_modules/update-browserslist-db": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js-replace": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/uri-js-replace/-/uri-js-replace-1.0.1.tgz", + "integrity": "sha512-W+C9NWNLFOoBI2QWDp4UT9pv65r2w5Cx+3sTYFvtMdDBxkKt1syCqsUdSFAChbEe1uK5TfS04wt/nGwmaeIQ0g==", + "dev": true, + "license": "MIT" + }, + "node_modules/vite": { + "version": "7.3.6", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.6.tgz", + "integrity": "sha512-4XP60spRGjSZFf1qYH+dJIkK2znL3zQfl9KkOV9MkkRR/3Dls0dxaBsQPTloEc5BLXWPL9vsOxopxyKoMmDueg==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.27.0 || ^0.28.0", + "fdir": "^6.5.0", + "picomatch": "^4.0.3", + "postcss": "^8.5.6", + "rollup": "^4.43.0", + "tinyglobby": "^0.2.15" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "lightningcss": "^1.21.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/vitest": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.10.tgz", + "integrity": "sha512-R9jUTe5S4Qb0HCd4TNqpC7oGcrMssMRGXLW80ubjWsW9VH5GF8y1Y0SFLY9AbqSk6nt0PnOx4H4WNJYZ13GUPw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/expect": "4.1.10", + "@vitest/mocker": "4.1.10", + "@vitest/pretty-format": "4.1.10", + "@vitest/runner": "4.1.10", + "@vitest/snapshot": "4.1.10", + "@vitest/spy": "4.1.10", + "@vitest/utils": "4.1.10", + "es-module-lexer": "^2.0.0", + "expect-type": "^1.3.0", + "magic-string": "^0.30.21", + "obug": "^2.1.1", + "pathe": "^2.0.3", + "picomatch": "^4.0.3", + "std-env": "^4.0.0-rc.1", + "tinybench": "^2.9.0", + "tinyexec": "^1.0.2", + "tinyglobby": "^0.2.15", + "tinyrainbow": "^3.1.0", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0", + "why-is-node-running": "^2.3.0" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": "^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@opentelemetry/api": "^1.9.0", + "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", + "@vitest/browser-playwright": "4.1.10", + "@vitest/browser-preview": "4.1.10", + "@vitest/browser-webdriverio": "4.1.10", + "@vitest/coverage-istanbul": "4.1.10", + "@vitest/coverage-v8": "4.1.10", + "@vitest/ui": "4.1.10", + "happy-dom": "*", + "jsdom": "*", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@opentelemetry/api": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser-playwright": { + "optional": true + }, + "@vitest/browser-preview": { + "optional": true + }, + "@vitest/browser-webdriverio": { + "optional": true + }, + "@vitest/coverage-istanbul": { + "optional": true + }, + "@vitest/coverage-v8": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + }, + "vite": { + "optional": false + } + } + }, + "node_modules/why-is-node-running": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC" + }, + "node_modules/yaml-ast-parser": { + "version": "0.0.43", + "resolved": "https://registry.npmjs.org/yaml-ast-parser/-/yaml-ast-parser-0.0.43.tgz", + "integrity": "sha512-2PTINUwsRqSd+s8XxKaJWQlUuEMHJQyEuh2edBbW8KNJz0SJPwUSD2zRWqezFEdN7IzAgeuYHFUCF7o8zRdZ0A==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + } + } +} diff --git a/Tiku.PlatformAdmin.Web/package.json b/Tiku.PlatformAdmin.Web/package.json new file mode 100644 index 0000000..74ef37e --- /dev/null +++ b/Tiku.PlatformAdmin.Web/package.json @@ -0,0 +1,31 @@ +{ + "name": "@tiku/platform-admin", + "private": true, + "version": "0.1.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "tsc -b && vite build", + "preview": "vite preview", + "generate:api": "node scripts/generate-platform-operations.mjs", + "test": "vitest run", + "check": "npm run build && npm run test" + }, + "dependencies": { + "@ant-design/icons": "^6.0.1", + "antd": "6.5.0", + "react": "^19.2.0", + "react-dom": "^19.2.0", + "react-router": "^8.3.0" + }, + "devDependencies": { + "@types/node": "^24.10.0", + "@types/react": "^19.2.2", + "@types/react-dom": "^19.2.2", + "@vitejs/plugin-react": "^5.1.1", + "openapi-typescript": "^7.10.1", + "typescript": "^5.9.3", + "vite": "^7.2.2", + "vitest": "^4.0.8" + } +} diff --git a/Tiku.Api/wwwroot/platform-admin/assets/logo.png b/Tiku.PlatformAdmin.Web/public/logo.png similarity index 100% rename from Tiku.Api/wwwroot/platform-admin/assets/logo.png rename to Tiku.PlatformAdmin.Web/public/logo.png diff --git a/Tiku.PlatformAdmin.Web/scripts/generate-platform-operations.mjs b/Tiku.PlatformAdmin.Web/scripts/generate-platform-operations.mjs new file mode 100644 index 0000000..4134a2d --- /dev/null +++ b/Tiku.PlatformAdmin.Web/scripts/generate-platform-operations.mjs @@ -0,0 +1,51 @@ +import { execFileSync } from 'node:child_process'; +import { mkdirSync, writeFileSync } from 'node:fs'; +import { fileURLToPath } from 'node:url'; +import path from 'node:path'; + +const projectRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..'); +const openApiUrl = process.env.OPENAPI_URL || 'http://localhost:5090/openapi/v1.json'; +const response = await fetch(openApiUrl); +if (!response.ok) throw new Error(`OpenAPI 下载失败:${response.status} ${response.statusText}`); +const document = await response.json(); + +const generatedDir = path.join(projectRoot, '.generated'); +const apiDir = path.join(projectRoot, 'src', 'api'); +mkdirSync(generatedDir, { recursive: true }); +mkdirSync(apiDir, { recursive: true }); +const snapshotPath = path.join(generatedDir, 'openapi.json'); +writeFileSync(snapshotPath, `${JSON.stringify(document)}\n`); + +const cli = path.join(projectRoot, 'node_modules', '.bin', process.platform === 'win32' ? 'openapi-typescript.cmd' : 'openapi-typescript'); +execFileSync(cli, [snapshotPath, '-o', path.join(apiDir, 'schema.generated.d.ts')], { stdio: 'inherit' }); + +const methods = new Set(['get', 'post', 'put', 'patch', 'delete']); +const operations = []; +for (const [route, pathItem] of Object.entries(document.paths || {})) { + for (const [method, operation] of Object.entries(pathItem || {})) { + if (!methods.has(method)) continue; + const tags = operation.tags || []; + const isPlatform = route.startsWith('/api/platform-admin/') || route === '/api/platform-admin' || route.startsWith('/api/backoffice/platform/'); + if (!isPlatform) continue; + const requestSchema = operation.requestBody?.content?.['application/json']?.schema || null; + const responseEntry = Object.entries(operation.responses || {}).find(([status]) => /^2/.test(status)); + const responseSchema = responseEntry?.[1]?.content?.['application/json']?.schema || null; + operations.push({ + id: `${method.toUpperCase()} ${route}`, + method: method.toUpperCase(), + path: route, + tag: tags[0] || '平台端', + summary: operation.summary || `${method.toUpperCase()} ${route}`, + description: operation.description || '', + parameters: [...(pathItem.parameters || []), ...(operation.parameters || [])], + requestSchema, + responseSchema, + }); + } +} + +operations.sort((a, b) => a.path.localeCompare(b.path) || a.method.localeCompare(b.method)); +const schemas = document.components?.schemas || {}; +const source = `/* eslint-disable */\n// 由 scripts/generate-platform-operations.mjs 根据后端 OpenAPI 自动生成,请勿手改。\nimport type { PlatformOperation } from './types';\n\nexport const generatedAt = ${JSON.stringify(new Date().toISOString())};\nexport const platformOperations = ${JSON.stringify(operations, null, 2)} as const satisfies readonly PlatformOperation[];\nexport const openApiSchemas = ${JSON.stringify(schemas, null, 2)} as const;\n`; +writeFileSync(path.join(apiDir, 'platform-operations.generated.ts'), source); +console.log(`已生成 ${operations.length} 个平台接口契约,来源:${openApiUrl}`); diff --git a/Tiku.PlatformAdmin.Web/src/api/groups.test.ts b/Tiku.PlatformAdmin.Web/src/api/groups.test.ts new file mode 100644 index 0000000..8ef1262 --- /dev/null +++ b/Tiku.PlatformAdmin.Web/src/api/groups.test.ts @@ -0,0 +1,18 @@ +import { describe, expect, it } from 'vitest'; +import { platformOperations } from './platform-operations.generated'; +import { groupForOperation, platformGroups } from './groups'; + +describe('平台 OpenAPI 页面覆盖', () => { + it('每个后端平台接口恰好归入一个页面组', () => { + const knownGroups = new Set(platformGroups.map((group) => group.key)); + const grouped = platformOperations.map((operation) => ({ id: operation.id, group: groupForOperation(operation) })); + expect(grouped).toHaveLength(platformOperations.length); + expect(new Set(grouped.map((item) => item.id)).size).toBe(platformOperations.length); + expect(grouped.every((item) => knownGroups.has(item.group))).toBe(true); + }); + + it('契约只包含平台权限域接口', () => { + expect(platformOperations.length).toBeGreaterThan(0); + expect(platformOperations.every((operation) => operation.path.startsWith('/api/platform-admin/') || operation.path.startsWith('/api/backoffice/platform/'))).toBe(true); + }); +}); diff --git a/Tiku.PlatformAdmin.Web/src/api/groups.ts b/Tiku.PlatformAdmin.Web/src/api/groups.ts new file mode 100644 index 0000000..e49b578 --- /dev/null +++ b/Tiku.PlatformAdmin.Web/src/api/groups.ts @@ -0,0 +1,31 @@ +import type { PlatformOperation } from './types'; + +export const platformGroups = [ + { key: 'overview', label: '经营概览', description: '平台经营指标与实时概览' }, + { key: 'tenants', label: '租户管理', description: '租户、详情、域名与账务资料' }, + { key: 'catalog', label: 'SaaS 商品', description: '功能、限额、套餐与版本生命周期' }, + { key: 'billing', label: '订阅与账务', description: '订单、订阅、支付、退款、发票、用量与催缴' }, + { key: 'question-banks', label: '公共题库', description: '题库结构、题目、导入与资源上传' }, + { key: 'crm', label: 'CRM 能力', description: '租户 CRM 配置、线索队列与推送日志' }, + { key: 'sms', label: '短信能力', description: '租户短信渠道、模板与发送日志' }, + { key: 'payments', label: '支付设置', description: '平台支付与租户支付应用托管' }, + { key: 'staff', label: '平台权限', description: '平台员工、角色与权限绑定' }, + { key: 'audit', label: '审计与告警', description: '平台审计日志、告警与通知' }, +] as const; + +export type PlatformGroupKey = (typeof platformGroups)[number]['key']; + +export function groupForOperation(operation: PlatformOperation): PlatformGroupKey { + const route = operation.path; + if (route === '/api/platform-admin/overview') return 'overview'; + if (route.startsWith('/api/platform-admin/tenants') || route.startsWith('/api/platform-admin/domains')) return 'tenants'; + if (route.startsWith('/api/platform-admin/question-banks')) return 'question-banks'; + if (route.startsWith('/api/platform-admin/tenant-capabilities/crm')) return 'crm'; + if (route.startsWith('/api/platform-admin/tenant-capabilities/sms')) return 'sms'; + if (route.startsWith('/api/platform-admin/payment-settings') || route.startsWith('/api/platform-admin/tenant-capabilities/payments')) return 'payments'; + if (route.startsWith('/api/backoffice/platform') || route.startsWith('/api/platform-admin/staff')) return 'staff'; + if (route.startsWith('/api/platform-admin/audit-')) return 'audit'; + if (route.startsWith('/api/platform-admin/saas/features') || route.startsWith('/api/platform-admin/saas/feature-limits') || route.startsWith('/api/platform-admin/saas/offerings') || route.startsWith('/api/platform-admin/saas/offering-versions') || route.startsWith('/api/platform-admin/saas/catalog') || route.startsWith('/api/platform-admin/saas/tenant-feature-overrides')) return 'catalog'; + if (route.startsWith('/api/platform-admin/saas/')) return 'billing'; + throw new Error(`平台接口尚未归入页面:${operation.id}`); +} diff --git a/Tiku.PlatformAdmin.Web/src/api/http.ts b/Tiku.PlatformAdmin.Web/src/api/http.ts new file mode 100644 index 0000000..93c572e --- /dev/null +++ b/Tiku.PlatformAdmin.Web/src/api/http.ts @@ -0,0 +1,105 @@ +import type { OperationInput, PlatformOperation } from './types'; +import { tokenStore, type TokenPair } from './token-store'; + +const apiBaseUrl = (import.meta.env.VITE_API_BASE_URL || '').replace(/\/$/, ''); +let refreshPromise: Promise | null = null; + +export class ApiError extends Error { + constructor( + message: string, + readonly status: number, + readonly details?: unknown, + ) { + super(message); + } +} + +async function parseResponse(response: Response): Promise { + if (response.status === 204) return null; + const contentType = response.headers.get('content-type') || ''; + if (contentType.includes('json')) return response.json(); + const text = await response.text(); + return text || null; +} + +async function refreshTokens(): Promise { + const tokens = tokenStore.get(); + if (!tokens?.refreshToken) return null; + const response = await fetch(`${apiBaseUrl}/api/auth/refresh`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ refreshToken: tokens.refreshToken }), + }); + if (!response.ok) { + tokenStore.set(null); + return null; + } + const next = (await response.json()) as TokenPair; + tokenStore.set(next); + return next; +} + +async function authorizedFetch(url: string, init: RequestInit, retry = true): Promise { + const accessToken = tokenStore.get()?.accessToken; + const headers = new Headers(init.headers); + if (accessToken) headers.set('Authorization', `Bearer ${accessToken}`); + const response = await fetch(`${apiBaseUrl}${url}`, { ...init, headers }); + if (response.status !== 401 || !retry) return response; + refreshPromise ??= refreshTokens().finally(() => { refreshPromise = null; }); + const refreshed = await refreshPromise; + return refreshed ? authorizedFetch(url, init, false) : response; +} + +function appendQuery(url: URL, query: Record) { + for (const [key, value] of Object.entries(query)) { + if (value === undefined || value === null || value === '') continue; + if (Array.isArray(value)) value.forEach((item) => url.searchParams.append(key, String(item))); + else url.searchParams.set(key, String(value)); + } +} + +export async function apiRequest( + operation: PlatformOperation, + input: OperationInput = {}, + signal?: AbortSignal, +): Promise { + const pathValues = (input.path || {}) as Record; + let route = operation.path.replace(/\{([^}]+)\}/g, (_, name: string) => encodeURIComponent(String(pathValues[name] ?? ''))); + const url = new URL(route, window.location.origin); + appendQuery(url, ((input.query || {}) as Record)); + route = `${url.pathname}${url.search}`; + const headers: Record = {}; + const init: RequestInit = { method: operation.method, headers, signal }; + if (input.body !== undefined && operation.method !== 'GET') { + headers['Content-Type'] = 'application/json'; + init.body = JSON.stringify(input.body); + } + const response = await authorizedFetch(route, init); + const payload = await parseResponse(response); + if (!response.ok) { + const problem = payload as { detail?: string; title?: string } | null; + throw new ApiError(problem?.detail || problem?.title || `请求失败(HTTP ${response.status})`, response.status, payload); + } + return payload as T; +} + +export async function authRequest(path: string, body?: unknown): Promise { + const response = await fetch(`${apiBaseUrl}${path}`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: body === undefined ? undefined : JSON.stringify(body), + }); + const payload = await parseResponse(response); + if (!response.ok) { + const problem = payload as { detail?: string; title?: string } | null; + throw new ApiError(problem?.detail || problem?.title || `请求失败(HTTP ${response.status})`, response.status, payload); + } + return payload as T; +} + +export async function getCurrentUser(): Promise { + const response = await authorizedFetch('/api/me', { method: 'GET' }); + const payload = await parseResponse(response); + if (!response.ok) throw new ApiError('登录会话已失效', response.status, payload); + return payload as T; +} diff --git a/Tiku.PlatformAdmin.Web/src/api/platform-operations.generated.ts b/Tiku.PlatformAdmin.Web/src/api/platform-operations.generated.ts new file mode 100644 index 0000000..2828593 --- /dev/null +++ b/Tiku.PlatformAdmin.Web/src/api/platform-operations.generated.ts @@ -0,0 +1,31952 @@ +/* eslint-disable */ +// 由 scripts/generate-platform-operations.mjs 根据后端 OpenAPI 自动生成,请勿手改。 +import type { PlatformOperation } from './types'; + +export const generatedAt = "2026-07-30T05:41:34.952Z"; +export const platformOperations = [ + { + "id": "GET /api/backoffice/platform/bootstrap", + "method": "GET", + "path": "/api/backoffice/platform/bootstrap", + "tag": "平台端-后台权限", + "summary": "查询平台角色管理初始化数据", + "description": "", + "parameters": [], + "requestSchema": null, + "responseSchema": { + "$ref": "#/components/schemas/BackofficeBootstrap" + } + }, + { + "id": "POST /api/backoffice/platform/roles", + "method": "POST", + "path": "/api/backoffice/platform/roles", + "tag": "平台端-后台权限", + "summary": "创建或更新平台后台角色", + "description": "", + "parameters": [], + "requestSchema": { + "$ref": "#/components/schemas/UpsertBackofficeRoleDto" + }, + "responseSchema": { + "$ref": "#/components/schemas/BackofficeRoleItem" + } + }, + { + "id": "PUT /api/backoffice/platform/roles/{roleId}/bindings", + "method": "PUT", + "path": "/api/backoffice/platform/roles/{roleId}/bindings", + "tag": "平台端-后台权限", + "summary": "替换平台后台角色权限绑定", + "description": "", + "parameters": [ + { + "name": "roleId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "requestSchema": { + "$ref": "#/components/schemas/ReplaceRoleBindingsDto" + }, + "responseSchema": { + "$ref": "#/components/schemas/BackofficeRoleItem" + } + }, + { + "id": "GET /api/backoffice/platform/ui-bootstrap", + "method": "GET", + "path": "/api/backoffice/platform/ui-bootstrap", + "tag": "平台端-后台权限", + "summary": "查询平台后台菜单与权限", + "description": "返回当前平台管理员可见的后台菜单、权限和模块启用状态。", + "parameters": [], + "requestSchema": null, + "responseSchema": { + "$ref": "#/components/schemas/BackofficeUiBootstrap" + } + }, + { + "id": "PUT /api/backoffice/platform/users/{userId}/roles", + "method": "PUT", + "path": "/api/backoffice/platform/users/{userId}/roles", + "tag": "平台端-后台权限", + "summary": "替换平台用户后台角色", + "description": "", + "parameters": [ + { + "name": "userId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "requestSchema": { + "$ref": "#/components/schemas/ReplaceUserRolesDto" + }, + "responseSchema": null + }, + { + "id": "GET /api/platform-admin/audit-alerts", + "method": "GET", + "path": "/api/platform-admin/audit-alerts", + "tag": "平台端-平台管理", + "summary": "查询平台审计告警", + "description": "", + "parameters": [ + { + "name": "Status", + "in": "query", + "description": "状态。", + "schema": { + "maxLength": 32, + "minLength": 0, + "type": "string" + } + }, + { + "name": "Search", + "in": "query", + "description": "搜索关键字。", + "schema": { + "maxLength": 200, + "minLength": 0, + "type": "string" + } + }, + { + "name": "Limit", + "in": "query", + "description": "返回数量上限。", + "schema": { + "maximum": 200, + "minimum": 1, + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + } + } + ], + "requestSchema": null, + "responseSchema": { + "$ref": "#/components/schemas/PlatformAuditAlertList" + } + }, + { + "id": "POST /api/platform-admin/audit-alerts/status", + "method": "POST", + "path": "/api/platform-admin/audit-alerts/status", + "tag": "平台端-平台管理", + "summary": "更新平台审计告警状态", + "description": "", + "parameters": [], + "requestSchema": { + "$ref": "#/components/schemas/UpdatePlatformAuditAlertStatusDto" + }, + "responseSchema": { + "$ref": "#/components/schemas/PlatformAuditAlert" + } + }, + { + "id": "GET /api/platform-admin/audit-logs", + "method": "GET", + "path": "/api/platform-admin/audit-logs", + "tag": "平台端-平台管理", + "summary": "查询平台审计日志", + "description": "", + "parameters": [ + { + "name": "Status", + "in": "query", + "description": "状态。", + "schema": { + "maxLength": 32, + "minLength": 0, + "type": "string" + } + }, + { + "name": "Search", + "in": "query", + "description": "搜索关键字。", + "schema": { + "maxLength": 200, + "minLength": 0, + "type": "string" + } + }, + { + "name": "Limit", + "in": "query", + "description": "返回数量上限。", + "schema": { + "maximum": 200, + "minimum": 1, + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + } + } + ], + "requestSchema": null, + "responseSchema": { + "$ref": "#/components/schemas/PlatformAuditLogList" + } + }, + { + "id": "GET /api/platform-admin/domains", + "method": "GET", + "path": "/api/platform-admin/domains", + "tag": "平台端-平台管理", + "summary": "查询租户域名状态", + "description": "", + "parameters": [ + { + "name": "Status", + "in": "query", + "description": "状态。", + "schema": { + "maxLength": 32, + "minLength": 0, + "type": "string" + } + }, + { + "name": "Search", + "in": "query", + "description": "搜索关键字。", + "schema": { + "maxLength": 200, + "minLength": 0, + "type": "string" + } + }, + { + "name": "Limit", + "in": "query", + "description": "返回数量上限。", + "schema": { + "maximum": 200, + "minimum": 1, + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + } + } + ], + "requestSchema": null, + "responseSchema": { + "$ref": "#/components/schemas/PlatformDomainList" + } + }, + { + "id": "POST /api/platform-admin/domains/{domainId}/recheck", + "method": "POST", + "path": "/api/platform-admin/domains/{domainId}/recheck", + "tag": "平台端-平台管理", + "summary": "重新触发租户域名 DNS/TLS 验证", + "description": "", + "parameters": [ + { + "name": "domainId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "requestSchema": null, + "responseSchema": { + "$ref": "#/components/schemas/PlatformDomainRecheckResult" + } + }, + { + "id": "GET /api/platform-admin/overview", + "method": "GET", + "path": "/api/platform-admin/overview", + "tag": "平台端-平台管理", + "summary": "查询平台经营概览", + "description": "", + "parameters": [], + "requestSchema": null, + "responseSchema": { + "$ref": "#/components/schemas/PlatformOverview" + } + }, + { + "id": "GET /api/platform-admin/payment-settings/apps", + "method": "GET", + "path": "/api/platform-admin/payment-settings/apps", + "tag": "平台端-支付设置", + "summary": "查询平台支付应用", + "description": "", + "parameters": [ + { + "name": "status", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "limit", + "in": "query", + "schema": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32", + "default": 100 + } + } + ], + "requestSchema": null, + "responseSchema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/PlatformPaymentApp" + } + } + }, + { + "id": "PUT /api/platform-admin/payment-settings/apps", + "method": "PUT", + "path": "/api/platform-admin/payment-settings/apps", + "tag": "平台端-支付设置", + "summary": "新增或更新平台支付应用", + "description": "", + "parameters": [], + "requestSchema": { + "$ref": "#/components/schemas/UpsertPlatformPaymentAppDto" + }, + "responseSchema": { + "$ref": "#/components/schemas/PlatformPaymentApp" + } + }, + { + "id": "GET /api/platform-admin/payment-settings/channels", + "method": "GET", + "path": "/api/platform-admin/payment-settings/channels", + "tag": "平台端-支付设置", + "summary": "查询平台支付渠道", + "description": "", + "parameters": [ + { + "name": "appId", + "in": "query", + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "status", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "limit", + "in": "query", + "schema": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32", + "default": 100 + } + } + ], + "requestSchema": null, + "responseSchema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/PlatformPaymentChannel" + } + } + }, + { + "id": "PUT /api/platform-admin/payment-settings/channels", + "method": "PUT", + "path": "/api/platform-admin/payment-settings/channels", + "tag": "平台端-支付设置", + "summary": "新增或更新平台支付渠道", + "description": "", + "parameters": [], + "requestSchema": { + "$ref": "#/components/schemas/UpsertPlatformPaymentChannelDto" + }, + "responseSchema": { + "$ref": "#/components/schemas/PlatformPaymentChannel" + } + }, + { + "id": "POST /api/platform-admin/payment-settings/channels/{id}/disable", + "method": "POST", + "path": "/api/platform-admin/payment-settings/channels/{id}/disable", + "tag": "平台端-支付设置", + "summary": "禁用平台支付渠道", + "description": "", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "requestSchema": null, + "responseSchema": { + "$ref": "#/components/schemas/PlatformPaymentChannel" + } + }, + { + "id": "GET /api/platform-admin/payment-settings/events", + "method": "GET", + "path": "/api/platform-admin/payment-settings/events", + "tag": "平台端-支付设置", + "summary": "查询平台支付事件", + "description": "", + "parameters": [ + { + "name": "status", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "limit", + "in": "query", + "schema": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32", + "default": 100 + } + } + ], + "requestSchema": null, + "responseSchema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/PlatformBillingPaymentEvent" + } + } + }, + { + "id": "GET /api/platform-admin/payment-settings/rebates/summary", + "method": "GET", + "path": "/api/platform-admin/payment-settings/rebates/summary", + "tag": "平台端-支付设置", + "summary": "查询平台返佣汇总", + "description": "", + "parameters": [], + "requestSchema": null, + "responseSchema": { + "$ref": "#/components/schemas/PlatformRebateSummary" + } + }, + { + "id": "GET /api/platform-admin/question-banks", + "method": "GET", + "path": "/api/platform-admin/question-banks", + "tag": "平台端-公共题库", + "summary": "查询平台公共题库", + "description": "", + "parameters": [ + { + "name": "keyword", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "status", + "in": "query", + "schema": { + "type": "string" + } + } + ], + "requestSchema": null, + "responseSchema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/PlatformQuestionBankItem" + } + } + }, + { + "id": "PUT /api/platform-admin/question-banks", + "method": "PUT", + "path": "/api/platform-admin/question-banks", + "tag": "平台端-公共题库", + "summary": "新增或更新平台公共题库", + "description": "", + "parameters": [], + "requestSchema": { + "$ref": "#/components/schemas/UpsertPlatformQuestionBankCommand" + }, + "responseSchema": { + "$ref": "#/components/schemas/PlatformQuestionBankItem" + } + }, + { + "id": "POST /api/platform-admin/question-banks/{bankId}/archive", + "method": "POST", + "path": "/api/platform-admin/question-banks/{bankId}/archive", + "tag": "平台端-公共题库", + "summary": "归档平台公共题库", + "description": "", + "parameters": [ + { + "name": "bankId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "requestSchema": null, + "responseSchema": { + "$ref": "#/components/schemas/PlatformQuestionBankItem" + } + }, + { + "id": "GET /api/platform-admin/question-banks/{bankId}/nodes", + "method": "GET", + "path": "/api/platform-admin/question-banks/{bankId}/nodes", + "tag": "平台端-公共题库", + "summary": "查询公共题库内容结构", + "description": "", + "parameters": [ + { + "name": "bankId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "requestSchema": null, + "responseSchema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/PlatformQuestionBankNodeItem" + } + } + }, + { + "id": "POST /api/platform-admin/question-banks/assets/upload-confirm", + "method": "POST", + "path": "/api/platform-admin/question-banks/assets/upload-confirm", + "tag": "平台端-公共题库", + "summary": "确认公共题库图片上传结果", + "description": "", + "parameters": [], + "requestSchema": { + "$ref": "#/components/schemas/AssetUploadConfirmDto" + }, + "responseSchema": { + "$ref": "#/components/schemas/AssetUploadConfirmResult" + } + }, + { + "id": "POST /api/platform-admin/question-banks/assets/upload-sign", + "method": "POST", + "path": "/api/platform-admin/question-banks/assets/upload-sign", + "tag": "平台端-公共题库", + "summary": "签发公共题库图片上传地址", + "description": "", + "parameters": [], + "requestSchema": { + "$ref": "#/components/schemas/AssetUploadSignDto" + }, + "responseSchema": { + "$ref": "#/components/schemas/AssetUploadSignResult" + } + }, + { + "id": "POST /api/platform-admin/question-banks/imports", + "method": "POST", + "path": "/api/platform-admin/question-banks/imports", + "tag": "平台端-公共题库", + "summary": "执行公共题库 JSON 导入", + "description": "", + "parameters": [], + "requestSchema": { + "$ref": "#/components/schemas/PlatformQuestionImportCommand" + }, + "responseSchema": { + "$ref": "#/components/schemas/PlatformQuestionImportResult" + } + }, + { + "id": "GET /api/platform-admin/question-banks/imports/{jobId}", + "method": "GET", + "path": "/api/platform-admin/question-banks/imports/{jobId}", + "tag": "平台端-公共题库", + "summary": "查询公共题库导入结果", + "description": "", + "parameters": [ + { + "name": "jobId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "requestSchema": null, + "responseSchema": { + "$ref": "#/components/schemas/ContentImportJobDetail" + } + }, + { + "id": "POST /api/platform-admin/question-banks/imports/preview", + "method": "POST", + "path": "/api/platform-admin/question-banks/imports/preview", + "tag": "平台端-公共题库", + "summary": "预检公共题库 JSON 导入", + "description": "", + "parameters": [], + "requestSchema": { + "$ref": "#/components/schemas/PlatformQuestionImportCommand" + }, + "responseSchema": { + "$ref": "#/components/schemas/PlatformQuestionImportResult" + } + }, + { + "id": "PUT /api/platform-admin/question-banks/nodes", + "method": "PUT", + "path": "/api/platform-admin/question-banks/nodes", + "tag": "平台端-公共题库", + "summary": "新增或更新公共题库内容节点", + "description": "", + "parameters": [], + "requestSchema": { + "$ref": "#/components/schemas/UpsertPlatformQuestionBankNodeCommand" + }, + "responseSchema": { + "$ref": "#/components/schemas/PlatformQuestionBankNodeItem" + } + }, + { + "id": "POST /api/platform-admin/question-banks/nodes/{nodeId}/archive", + "method": "POST", + "path": "/api/platform-admin/question-banks/nodes/{nodeId}/archive", + "tag": "平台端-公共题库", + "summary": "归档公共题库内容节点", + "description": "", + "parameters": [ + { + "name": "nodeId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "requestSchema": null, + "responseSchema": { + "$ref": "#/components/schemas/PlatformQuestionBankNodeItem" + } + }, + { + "id": "POST /api/platform-admin/question-banks/nodes/batch", + "method": "POST", + "path": "/api/platform-admin/question-banks/nodes/batch", + "tag": "平台端-公共题库", + "summary": "批量创建公共题库章节或试卷", + "description": "", + "parameters": [], + "requestSchema": { + "$ref": "#/components/schemas/BatchCreatePlatformQuestionBankNodesCommand" + }, + "responseSchema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/PlatformQuestionBankNodeItem" + } + } + }, + { + "id": "GET /api/platform-admin/question-banks/questions", + "method": "GET", + "path": "/api/platform-admin/question-banks/questions", + "tag": "平台端-公共题库", + "summary": "分页查询公共题库题目", + "description": "", + "parameters": [ + { + "name": "questionBankId", + "in": "query", + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "contentNodeId", + "in": "query", + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "keyword", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "type", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "difficulty", + "in": "query", + "schema": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + } + }, + { + "name": "status", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "page", + "in": "query", + "schema": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32", + "default": 1 + } + }, + { + "name": "pageSize", + "in": "query", + "schema": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32", + "default": 20 + } + } + ], + "requestSchema": null, + "responseSchema": { + "$ref": "#/components/schemas/PlatformQuestionPage" + } + }, + { + "id": "PUT /api/platform-admin/question-banks/questions", + "method": "PUT", + "path": "/api/platform-admin/question-banks/questions", + "tag": "平台端-公共题库", + "summary": "新增或更新公共题库题目并保留版本", + "description": "", + "parameters": [], + "requestSchema": { + "$ref": "#/components/schemas/UpsertPlatformQuestionCommand" + }, + "responseSchema": { + "$ref": "#/components/schemas/PlatformQuestionItem" + } + }, + { + "id": "POST /api/platform-admin/question-banks/questions/archive", + "method": "POST", + "path": "/api/platform-admin/question-banks/questions/archive", + "tag": "平台端-公共题库", + "summary": "批量归档公共题库题目", + "description": "", + "parameters": [], + "requestSchema": { + "$ref": "#/components/schemas/ArchivePlatformQuestionsCommand" + }, + "responseSchema": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + } + }, + { + "id": "GET /api/platform-admin/saas/catalog", + "method": "GET", + "path": "/api/platform-admin/saas/catalog", + "tag": "平台端-SaaS 套餐", + "summary": "查询平台 SaaS 商品目录", + "description": "", + "parameters": [], + "requestSchema": null, + "responseSchema": { + "$ref": "#/components/schemas/SaasCatalogSnapshot" + } + }, + { + "id": "GET /api/platform-admin/saas/dunning/channels", + "method": "GET", + "path": "/api/platform-admin/saas/dunning/channels", + "tag": "平台端-平台管理", + "summary": "查询平台催缴通知渠道", + "description": "", + "parameters": [ + { + "name": "Status", + "in": "query", + "description": "状态。", + "schema": { + "maxLength": 32, + "minLength": 0, + "type": "string" + } + }, + { + "name": "Search", + "in": "query", + "description": "搜索关键字。", + "schema": { + "maxLength": 200, + "minLength": 0, + "type": "string" + } + }, + { + "name": "Limit", + "in": "query", + "description": "返回数量上限。", + "schema": { + "maximum": 200, + "minimum": 1, + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + } + } + ], + "requestSchema": null, + "responseSchema": { + "$ref": "#/components/schemas/PlatformBillingDunningChannelList" + } + }, + { + "id": "PUT /api/platform-admin/saas/dunning/channels", + "method": "PUT", + "path": "/api/platform-admin/saas/dunning/channels", + "tag": "平台端-平台管理", + "summary": "创建或更新平台催缴通知渠道", + "description": "", + "parameters": [], + "requestSchema": { + "$ref": "#/components/schemas/UpsertPlatformBillingDunningChannelDto" + }, + "responseSchema": { + "$ref": "#/components/schemas/PlatformBillingDunningChannelItem" + } + }, + { + "id": "POST /api/platform-admin/saas/dunning/channels/disable", + "method": "POST", + "path": "/api/platform-admin/saas/dunning/channels/disable", + "tag": "平台端-平台管理", + "summary": "禁用平台催缴通知渠道", + "description": "", + "parameters": [], + "requestSchema": { + "$ref": "#/components/schemas/DisablePlatformBillingDunningChannelDto" + }, + "responseSchema": { + "$ref": "#/components/schemas/PlatformBillingDunningChannelItem" + } + }, + { + "id": "GET /api/platform-admin/saas/dunning/events", + "method": "GET", + "path": "/api/platform-admin/saas/dunning/events", + "tag": "平台端-平台管理", + "summary": "查询平台催缴通知事件", + "description": "", + "parameters": [ + { + "name": "Status", + "in": "query", + "description": "状态。", + "schema": { + "maxLength": 32, + "minLength": 0, + "type": "string" + } + }, + { + "name": "Search", + "in": "query", + "description": "搜索关键字。", + "schema": { + "maxLength": 200, + "minLength": 0, + "type": "string" + } + }, + { + "name": "Limit", + "in": "query", + "description": "返回数量上限。", + "schema": { + "maximum": 200, + "minimum": 1, + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + } + } + ], + "requestSchema": null, + "responseSchema": { + "$ref": "#/components/schemas/PlatformBillingDunningEventList" + } + }, + { + "id": "GET /api/platform-admin/saas/dunning/events/detail", + "method": "GET", + "path": "/api/platform-admin/saas/dunning/events/detail", + "tag": "平台端-平台管理", + "summary": "查询平台催缴通知事件详情", + "description": "", + "parameters": [ + { + "name": "eventId", + "in": "query", + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "requestSchema": null, + "responseSchema": { + "$ref": "#/components/schemas/PlatformBillingDunningEventItem" + } + }, + { + "id": "POST /api/platform-admin/saas/dunning/events/retry", + "method": "POST", + "path": "/api/platform-admin/saas/dunning/events/retry", + "tag": "平台端-平台管理", + "summary": "重新标记平台催缴通知事件待发送", + "description": "", + "parameters": [], + "requestSchema": { + "$ref": "#/components/schemas/RetryPlatformBillingDunningEventDto" + }, + "responseSchema": { + "$ref": "#/components/schemas/PlatformBillingDunningEventItem" + } + }, + { + "id": "PUT /api/platform-admin/saas/feature-limits", + "method": "PUT", + "path": "/api/platform-admin/saas/feature-limits", + "tag": "平台端-SaaS 套餐", + "summary": "新增或更新 SaaS 功能限额", + "description": "", + "parameters": [], + "requestSchema": { + "$ref": "#/components/schemas/UpsertSaasFeatureLimitDto" + }, + "responseSchema": { + "$ref": "#/components/schemas/SaasFeatureLimitDefinition" + } + }, + { + "id": "PUT /api/platform-admin/saas/features", + "method": "PUT", + "path": "/api/platform-admin/saas/features", + "tag": "平台端-SaaS 套餐", + "summary": "新增或更新 SaaS 功能", + "description": "", + "parameters": [], + "requestSchema": { + "$ref": "#/components/schemas/UpsertSaasFeatureDto" + }, + "responseSchema": { + "$ref": "#/components/schemas/SaasFeature" + } + }, + { + "id": "GET /api/platform-admin/saas/invoices", + "method": "GET", + "path": "/api/platform-admin/saas/invoices", + "tag": "平台端-SaaS 套餐", + "summary": "查询平台 SaaS 发票", + "description": "", + "parameters": [ + { + "name": "tenantId", + "in": "query", + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "status", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "limit", + "in": "query", + "schema": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32", + "default": 100 + } + } + ], + "requestSchema": null, + "responseSchema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/PlatformBillingInvoice" + } + } + }, + { + "id": "GET /api/platform-admin/saas/invoices/reminders", + "method": "GET", + "path": "/api/platform-admin/saas/invoices/reminders", + "tag": "平台端-SaaS 套餐", + "summary": "查询平台 SaaS 账单提醒", + "description": "", + "parameters": [ + { + "name": "tenantId", + "in": "query", + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "status", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "limit", + "in": "query", + "schema": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32", + "default": 100 + } + } + ], + "requestSchema": null, + "responseSchema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/PlatformBillingInvoiceReminder" + } + } + }, + { + "id": "PUT /api/platform-admin/saas/offering-versions", + "method": "PUT", + "path": "/api/platform-admin/saas/offering-versions", + "tag": "平台端-SaaS 套餐", + "summary": "新增或更新 SaaS 套餐版本草稿", + "description": "", + "parameters": [], + "requestSchema": { + "$ref": "#/components/schemas/UpsertSaasOfferingVersionDto" + }, + "responseSchema": { + "$ref": "#/components/schemas/SaasOfferingVersionItem" + } + }, + { + "id": "POST /api/platform-admin/saas/offering-versions/{versionId}/clone", + "method": "POST", + "path": "/api/platform-admin/saas/offering-versions/{versionId}/clone", + "tag": "平台端-SaaS 套餐", + "summary": "克隆 SaaS 套餐版本", + "description": "", + "parameters": [ + { + "name": "versionId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "requestSchema": null, + "responseSchema": { + "$ref": "#/components/schemas/SaasOfferingVersionItem" + } + }, + { + "id": "POST /api/platform-admin/saas/offering-versions/{versionId}/publish", + "method": "POST", + "path": "/api/platform-admin/saas/offering-versions/{versionId}/publish", + "tag": "平台端-SaaS 套餐", + "summary": "发布 SaaS 套餐版本", + "description": "", + "parameters": [ + { + "name": "versionId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "requestSchema": null, + "responseSchema": { + "$ref": "#/components/schemas/SaasOfferingVersionItem" + } + }, + { + "id": "POST /api/platform-admin/saas/offering-versions/{versionId}/retire", + "method": "POST", + "path": "/api/platform-admin/saas/offering-versions/{versionId}/retire", + "tag": "平台端-SaaS 套餐", + "summary": "下架 SaaS 套餐版本", + "description": "", + "parameters": [ + { + "name": "versionId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "requestSchema": null, + "responseSchema": { + "$ref": "#/components/schemas/SaasOfferingVersionItem" + } + }, + { + "id": "PUT /api/platform-admin/saas/offerings", + "method": "PUT", + "path": "/api/platform-admin/saas/offerings", + "tag": "平台端-SaaS 套餐", + "summary": "新增或更新 SaaS 套餐", + "description": "", + "parameters": [], + "requestSchema": { + "$ref": "#/components/schemas/UpsertSaasOfferingDto" + }, + "responseSchema": { + "$ref": "#/components/schemas/SaasOffering" + } + }, + { + "id": "GET /api/platform-admin/saas/orders", + "method": "GET", + "path": "/api/platform-admin/saas/orders", + "tag": "平台端-SaaS 套餐", + "summary": "查询平台 SaaS 订单", + "description": "", + "parameters": [ + { + "name": "tenantId", + "in": "query", + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "status", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "limit", + "in": "query", + "schema": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32", + "default": 100 + } + } + ], + "requestSchema": null, + "responseSchema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/PlatformBillingOrder" + } + } + }, + { + "id": "GET /api/platform-admin/saas/payments", + "method": "GET", + "path": "/api/platform-admin/saas/payments", + "tag": "平台端-SaaS 套餐", + "summary": "查询平台 SaaS 支付记录", + "description": "", + "parameters": [ + { + "name": "tenantId", + "in": "query", + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "status", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "limit", + "in": "query", + "schema": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32", + "default": 100 + } + } + ], + "requestSchema": null, + "responseSchema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/PlatformBillingPayment" + } + } + }, + { + "id": "POST /api/platform-admin/saas/payments/manual/confirm", + "method": "POST", + "path": "/api/platform-admin/saas/payments/manual/confirm", + "tag": "平台端-SaaS 套餐", + "summary": "确认平台手工支付", + "description": "", + "parameters": [], + "requestSchema": { + "$ref": "#/components/schemas/ConfirmManualPlatformPaymentDto" + }, + "responseSchema": { + "$ref": "#/components/schemas/PlatformBillingPayment" + } + }, + { + "id": "GET /api/platform-admin/saas/refunds", + "method": "GET", + "path": "/api/platform-admin/saas/refunds", + "tag": "平台端-SaaS 套餐", + "summary": "查询平台 SaaS 退款记录", + "description": "", + "parameters": [ + { + "name": "tenantId", + "in": "query", + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "status", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "limit", + "in": "query", + "schema": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32", + "default": 100 + } + } + ], + "requestSchema": null, + "responseSchema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/PlatformBillingRefund" + } + } + }, + { + "id": "GET /api/platform-admin/saas/subscriptions", + "method": "GET", + "path": "/api/platform-admin/saas/subscriptions", + "tag": "平台端-SaaS 套餐", + "summary": "查询租户 SaaS 订阅", + "description": "", + "parameters": [ + { + "name": "tenantId", + "in": "query", + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "status", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "limit", + "in": "query", + "schema": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32", + "default": 100 + } + } + ], + "requestSchema": null, + "responseSchema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/TenantSaasSubscription" + } + } + }, + { + "id": "PUT /api/platform-admin/saas/tenant-feature-overrides", + "method": "PUT", + "path": "/api/platform-admin/saas/tenant-feature-overrides", + "tag": "平台端-SaaS 套餐", + "summary": "新增或更新租户功能覆盖规则", + "description": "", + "parameters": [], + "requestSchema": { + "$ref": "#/components/schemas/UpsertTenantFeatureOverrideDto" + }, + "responseSchema": { + "$ref": "#/components/schemas/TenantFeatureOverride" + } + }, + { + "id": "GET /api/platform-admin/saas/usage", + "method": "GET", + "path": "/api/platform-admin/saas/usage", + "tag": "平台端-SaaS 套餐", + "summary": "查询租户 SaaS 用量", + "description": "", + "parameters": [ + { + "name": "tenantId", + "in": "query", + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "limit", + "in": "query", + "schema": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32", + "default": 100 + } + } + ], + "requestSchema": null, + "responseSchema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/TenantFeatureUsage" + } + } + }, + { + "id": "GET /api/platform-admin/staff", + "method": "GET", + "path": "/api/platform-admin/staff", + "tag": "平台端-平台管理", + "summary": "查询平台员工列表", + "description": "", + "parameters": [ + { + "name": "Status", + "in": "query", + "description": "状态。", + "schema": { + "maxLength": 32, + "minLength": 0, + "type": "string" + } + }, + { + "name": "Search", + "in": "query", + "description": "搜索关键字。", + "schema": { + "maxLength": 200, + "minLength": 0, + "type": "string" + } + }, + { + "name": "Limit", + "in": "query", + "description": "返回数量上限。", + "schema": { + "maximum": 200, + "minimum": 1, + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + } + } + ], + "requestSchema": null, + "responseSchema": { + "$ref": "#/components/schemas/PlatformStaffList" + } + }, + { + "id": "PUT /api/platform-admin/staff", + "method": "PUT", + "path": "/api/platform-admin/staff", + "tag": "平台端-平台管理", + "summary": "创建或更新平台员工", + "description": "", + "parameters": [], + "requestSchema": { + "$ref": "#/components/schemas/UpsertPlatformStaffDto" + }, + "responseSchema": { + "$ref": "#/components/schemas/PlatformStaffItem" + } + }, + { + "id": "PATCH /api/platform-admin/staff/status", + "method": "PATCH", + "path": "/api/platform-admin/staff/status", + "tag": "平台端-平台管理", + "summary": "启用或禁用平台员工", + "description": "", + "parameters": [], + "requestSchema": { + "$ref": "#/components/schemas/UpdatePlatformStaffStatusDto" + }, + "responseSchema": { + "$ref": "#/components/schemas/PlatformStaffItem" + } + }, + { + "id": "GET /api/platform-admin/tenant-capabilities/crm/configs", + "method": "GET", + "path": "/api/platform-admin/tenant-capabilities/crm/configs", + "tag": "平台端-租户 CRM 能力", + "summary": "查询租户 CRM 配置", + "description": "", + "parameters": [ + { + "name": "TenantId", + "in": "query", + "description": "租户 ID。", + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "Status", + "in": "query", + "description": "状态。", + "schema": { + "maxLength": 50, + "minLength": 0, + "type": "string" + } + }, + { + "name": "Limit", + "in": "query", + "description": "返回数量上限。", + "schema": { + "maximum": 500, + "minimum": 1, + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + } + } + ], + "requestSchema": null, + "responseSchema": { + "$ref": "#/components/schemas/PlatformTenantCapabilityListOfPlatformCrmConfigItem" + } + }, + { + "id": "PUT /api/platform-admin/tenant-capabilities/crm/configs", + "method": "PUT", + "path": "/api/platform-admin/tenant-capabilities/crm/configs", + "tag": "平台端-租户 CRM 能力", + "summary": "新增或更新租户 CRM 配置", + "description": "", + "parameters": [], + "requestSchema": { + "$ref": "#/components/schemas/UpsertPlatformCrmConfigDto" + }, + "responseSchema": { + "$ref": "#/components/schemas/PlatformCrmConfigItem" + } + }, + { + "id": "GET /api/platform-admin/tenant-capabilities/crm/leads", + "method": "GET", + "path": "/api/platform-admin/tenant-capabilities/crm/leads", + "tag": "平台端-租户 CRM 能力", + "summary": "查询租户 CRM 线索队列", + "description": "", + "parameters": [ + { + "name": "TenantId", + "in": "query", + "description": "租户 ID。", + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "Status", + "in": "query", + "description": "状态。", + "schema": { + "maxLength": 50, + "minLength": 0, + "type": "string" + } + }, + { + "name": "Limit", + "in": "query", + "description": "返回数量上限。", + "schema": { + "maximum": 500, + "minimum": 1, + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + } + } + ], + "requestSchema": null, + "responseSchema": { + "$ref": "#/components/schemas/PlatformTenantCapabilityListOfCrmWebhookQueueItem" + } + }, + { + "id": "POST /api/platform-admin/tenant-capabilities/crm/leads/retry", + "method": "POST", + "path": "/api/platform-admin/tenant-capabilities/crm/leads/retry", + "tag": "平台端-租户 CRM 能力", + "summary": "重试租户 CRM 线索推送", + "description": "", + "parameters": [], + "requestSchema": { + "$ref": "#/components/schemas/RetryPlatformCrmLeadDto" + }, + "responseSchema": { + "$ref": "#/components/schemas/CrmWebhookQueueItem" + } + }, + { + "id": "GET /api/platform-admin/tenant-capabilities/crm/logs", + "method": "GET", + "path": "/api/platform-admin/tenant-capabilities/crm/logs", + "tag": "平台端-租户 CRM 能力", + "summary": "查询租户 CRM 推送日志", + "description": "", + "parameters": [ + { + "name": "QueueId", + "in": "query", + "description": "队列任务 ID。", + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "TenantId", + "in": "query", + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "Status", + "in": "query", + "schema": { + "maxLength": 50, + "minLength": 0, + "type": "string" + } + }, + { + "name": "Limit", + "in": "query", + "schema": { + "maximum": 500, + "minimum": 1, + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + } + } + ], + "requestSchema": null, + "responseSchema": { + "$ref": "#/components/schemas/PlatformTenantCapabilityListOfCrmWebhookLog" + } + }, + { + "id": "GET /api/platform-admin/tenant-capabilities/payments/apps", + "method": "GET", + "path": "/api/platform-admin/tenant-capabilities/payments/apps", + "tag": "平台端-租户支付能力", + "summary": "查询租户支付应用", + "description": "", + "parameters": [ + { + "name": "TenantId", + "in": "query", + "description": "租户 ID。", + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "Status", + "in": "query", + "description": "状态。", + "schema": { + "maxLength": 50, + "minLength": 0, + "type": "string" + } + }, + { + "name": "Limit", + "in": "query", + "description": "返回数量上限。", + "schema": { + "maximum": 500, + "minimum": 1, + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + } + } + ], + "requestSchema": null, + "responseSchema": { + "$ref": "#/components/schemas/PlatformTenantCapabilityListOfTenantExternalProviderItem" + } + }, + { + "id": "PUT /api/platform-admin/tenant-capabilities/payments/apps", + "method": "PUT", + "path": "/api/platform-admin/tenant-capabilities/payments/apps", + "tag": "平台端-租户支付能力", + "summary": "新增或更新租户支付应用", + "description": "", + "parameters": [], + "requestSchema": { + "$ref": "#/components/schemas/UpsertPlatformTenantPaymentAppDto" + }, + "responseSchema": { + "$ref": "#/components/schemas/TenantExternalProviderItem" + } + }, + { + "id": "GET /api/platform-admin/tenant-capabilities/payments/events", + "method": "GET", + "path": "/api/platform-admin/tenant-capabilities/payments/events", + "tag": "平台端-租户支付能力", + "summary": "查询租户支付事件", + "description": "", + "parameters": [ + { + "name": "TenantId", + "in": "query", + "description": "租户 ID。", + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "Status", + "in": "query", + "description": "状态。", + "schema": { + "maxLength": 50, + "minLength": 0, + "type": "string" + } + }, + { + "name": "Limit", + "in": "query", + "description": "返回数量上限。", + "schema": { + "maximum": 500, + "minimum": 1, + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + } + } + ], + "requestSchema": null, + "responseSchema": { + "$ref": "#/components/schemas/PlatformTenantCapabilityListOfObject" + } + }, + { + "id": "GET /api/platform-admin/tenant-capabilities/sms/channels", + "method": "GET", + "path": "/api/platform-admin/tenant-capabilities/sms/channels", + "tag": "平台端-租户短信能力", + "summary": "查询租户短信渠道", + "description": "", + "parameters": [ + { + "name": "TenantId", + "in": "query", + "description": "租户 ID。", + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "Status", + "in": "query", + "description": "状态。", + "schema": { + "maxLength": 50, + "minLength": 0, + "type": "string" + } + }, + { + "name": "Limit", + "in": "query", + "description": "返回数量上限。", + "schema": { + "maximum": 500, + "minimum": 1, + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + } + } + ], + "requestSchema": null, + "responseSchema": { + "$ref": "#/components/schemas/PlatformTenantCapabilityListOfPlatformSmsChannelItem" + } + }, + { + "id": "PUT /api/platform-admin/tenant-capabilities/sms/channels", + "method": "PUT", + "path": "/api/platform-admin/tenant-capabilities/sms/channels", + "tag": "平台端-租户短信能力", + "summary": "新增或更新租户短信渠道", + "description": "", + "parameters": [], + "requestSchema": { + "$ref": "#/components/schemas/UpsertPlatformSmsChannelDto" + }, + "responseSchema": { + "$ref": "#/components/schemas/PlatformSmsChannelItem" + } + }, + { + "id": "POST /api/platform-admin/tenant-capabilities/sms/channels/{id}/disable", + "method": "POST", + "path": "/api/platform-admin/tenant-capabilities/sms/channels/{id}/disable", + "tag": "平台端-租户短信能力", + "summary": "禁用租户短信渠道", + "description": "", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "requestSchema": null, + "responseSchema": { + "$ref": "#/components/schemas/PlatformSmsChannelItem" + } + }, + { + "id": "GET /api/platform-admin/tenant-capabilities/sms/logs", + "method": "GET", + "path": "/api/platform-admin/tenant-capabilities/sms/logs", + "tag": "平台端-租户短信能力", + "summary": "查询租户短信发送日志", + "description": "", + "parameters": [ + { + "name": "TenantId", + "in": "query", + "description": "租户 ID。", + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "Status", + "in": "query", + "description": "状态。", + "schema": { + "maxLength": 50, + "minLength": 0, + "type": "string" + } + }, + { + "name": "Limit", + "in": "query", + "description": "返回数量上限。", + "schema": { + "maximum": 500, + "minimum": 1, + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + } + } + ], + "requestSchema": null, + "responseSchema": { + "$ref": "#/components/schemas/PlatformTenantCapabilityListOfSmsSendLog" + } + }, + { + "id": "GET /api/platform-admin/tenant-capabilities/sms/templates", + "method": "GET", + "path": "/api/platform-admin/tenant-capabilities/sms/templates", + "tag": "平台端-租户短信能力", + "summary": "查询租户短信模板", + "description": "", + "parameters": [ + { + "name": "TenantId", + "in": "query", + "description": "租户 ID。", + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "Status", + "in": "query", + "description": "状态。", + "schema": { + "maxLength": 50, + "minLength": 0, + "type": "string" + } + }, + { + "name": "Limit", + "in": "query", + "description": "返回数量上限。", + "schema": { + "maximum": 500, + "minimum": 1, + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + } + } + ], + "requestSchema": null, + "responseSchema": { + "$ref": "#/components/schemas/PlatformTenantCapabilityListOfPlatformSmsTemplateItem" + } + }, + { + "id": "PUT /api/platform-admin/tenant-capabilities/sms/templates", + "method": "PUT", + "path": "/api/platform-admin/tenant-capabilities/sms/templates", + "tag": "平台端-租户短信能力", + "summary": "新增或更新租户短信模板", + "description": "", + "parameters": [], + "requestSchema": { + "$ref": "#/components/schemas/UpsertPlatformSmsTemplateDto" + }, + "responseSchema": { + "$ref": "#/components/schemas/PlatformSmsTemplateItem" + } + }, + { + "id": "POST /api/platform-admin/tenant-capabilities/sms/templates/{id}/disable", + "method": "POST", + "path": "/api/platform-admin/tenant-capabilities/sms/templates/{id}/disable", + "tag": "平台端-租户短信能力", + "summary": "禁用租户短信模板", + "description": "", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "requestSchema": null, + "responseSchema": { + "$ref": "#/components/schemas/PlatformSmsTemplateItem" + } + }, + { + "id": "POST /api/platform-admin/tenant-capabilities/sms/templates/{id}/submit-review", + "method": "POST", + "path": "/api/platform-admin/tenant-capabilities/sms/templates/{id}/submit-review", + "tag": "平台端-租户短信能力", + "summary": "提交租户短信模板审核", + "description": "", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "requestSchema": null, + "responseSchema": { + "$ref": "#/components/schemas/PlatformSmsTemplateItem" + } + }, + { + "id": "GET /api/platform-admin/tenants", + "method": "GET", + "path": "/api/platform-admin/tenants", + "tag": "平台端-平台管理", + "summary": "查询平台租户列表", + "description": "", + "parameters": [ + { + "name": "Status", + "in": "query", + "description": "状态。", + "schema": { + "maxLength": 32, + "minLength": 0, + "type": "string" + } + }, + { + "name": "Search", + "in": "query", + "description": "搜索关键字。", + "schema": { + "maxLength": 200, + "minLength": 0, + "type": "string" + } + }, + { + "name": "Limit", + "in": "query", + "description": "返回数量上限。", + "schema": { + "maximum": 200, + "minimum": 1, + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + } + } + ], + "requestSchema": null, + "responseSchema": { + "$ref": "#/components/schemas/PlatformTenantList" + } + }, + { + "id": "POST /api/platform-admin/tenants", + "method": "POST", + "path": "/api/platform-admin/tenants", + "tag": "平台端-平台管理", + "summary": "创建平台租户", + "description": "", + "parameters": [], + "requestSchema": { + "$ref": "#/components/schemas/CreatePlatformTenantDto" + }, + "responseSchema": { + "$ref": "#/components/schemas/PlatformTenantProvisioningResult" + } + }, + { + "id": "PUT /api/platform-admin/tenants/billing-profile", + "method": "PUT", + "path": "/api/platform-admin/tenants/billing-profile", + "tag": "平台端-平台管理", + "summary": "保存租户账务与开票资料", + "description": "", + "parameters": [], + "requestSchema": { + "$ref": "#/components/schemas/UpsertPlatformTenantBillingProfileDto" + }, + "responseSchema": { + "$ref": "#/components/schemas/TenantBillingProfileItem" + } + }, + { + "id": "GET /api/platform-admin/tenants/detail", + "method": "GET", + "path": "/api/platform-admin/tenants/detail", + "tag": "平台端-平台管理", + "summary": "查询平台租户详情", + "description": "", + "parameters": [ + { + "name": "tenantId", + "in": "query", + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "requestSchema": null, + "responseSchema": { + "$ref": "#/components/schemas/PlatformTenantDetail" + } + }, + { + "id": "PATCH /api/platform-admin/tenants/status", + "method": "PATCH", + "path": "/api/platform-admin/tenants/status", + "tag": "平台端-平台管理", + "summary": "更新租户业务与账务状态", + "description": "", + "parameters": [], + "requestSchema": { + "$ref": "#/components/schemas/UpdatePlatformTenantStatusDto" + }, + "responseSchema": { + "$ref": "#/components/schemas/PlatformTenantItem" + } + } +] as const satisfies readonly PlatformOperation[]; +export const openApiSchemas = { + "ActivationCodeItem": { + "required": [ + "id", + "batchId", + "code", + "days", + "isUsed", + "usedBy", + "usedAt", + "saleType", + "soldTo", + "remark", + "createdAt" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "batchId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "code": { + "type": "string" + }, + "days": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "isUsed": { + "type": "boolean" + }, + "usedBy": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "usedAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "saleType": { + "type": [ + "null", + "string" + ] + }, + "soldTo": { + "type": [ + "null", + "string" + ] + }, + "remark": { + "type": [ + "null", + "string" + ] + }, + "createdAt": { + "type": "string", + "format": "date-time" + } + } + }, + "ActivationCodeList": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ActivationCodeItem" + } + } + } + }, + "AdminOrderList": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/CommerceOrderItem" + } + } + } + }, + "AdminPaymentList": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/CommercePaymentItem" + } + } + } + }, + "AnnouncementCatalogItem": { + "required": [ + "id", + "legacyId", + "content", + "link", + "backgroundColor", + "order", + "isActive" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "legacyId": { + "type": [ + "null", + "string" + ] + }, + "content": { + "type": [ + "null", + "string" + ] + }, + "link": { + "type": [ + "null", + "string" + ] + }, + "backgroundColor": { + "type": [ + "null", + "string" + ] + }, + "order": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "isActive": { + "type": "boolean" + } + } + }, + "AnswerRecordItem": { + "required": [ + "id", + "sessionQuestionId", + "practiceSessionId", + "selectedOptions", + "answerText", + "isCorrect", + "answeredAt" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "sessionQuestionId": { + "type": "string", + "format": "uuid" + }, + "practiceSessionId": { + "type": "string", + "format": "uuid" + }, + "selectedOptions": { + "$ref": "#/components/schemas/JsonElement" + }, + "answerText": { + "type": [ + "null", + "string" + ] + }, + "isCorrect": { + "type": [ + "null", + "boolean" + ] + }, + "answeredAt": { + "type": "string", + "format": "date-time" + } + } + }, + "AppAssetCatalogItem": { + "required": [ + "id", + "legacyId", + "assetKey", + "fileName", + "description", + "metadata" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "legacyId": { + "type": [ + "null", + "string" + ] + }, + "assetKey": { + "type": "string" + }, + "fileName": { + "type": [ + "null", + "string" + ] + }, + "description": { + "type": [ + "null", + "string" + ] + }, + "metadata": { + "$ref": "#/components/schemas/JsonElement" + } + } + }, + "ArchivePlatformQuestionsCommand": { + "required": [ + "questionIds" + ], + "type": "object", + "properties": { + "questionIds": { + "type": "array", + "items": { + "type": "string", + "format": "uuid" + } + } + } + }, + "AssetAccessActorRole": { + "type": "integer" + }, + "AssetAccessDisposition": { + "type": "integer" + }, + "AssetAccessPrincipalDto": { + "required": [ + "userId", + "isMember", + "hasSvip" + ], + "type": "object", + "properties": { + "userId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "isMember": { + "type": "boolean" + }, + "hasSvip": { + "type": "boolean" + } + }, + "description": "资产访问Principal请求 DTO。" + }, + "AssetAccessResponseDto": { + "required": [ + "item", + "access", + "url", + "watermark" + ], + "type": "object", + "properties": { + "item": { + "$ref": "#/components/schemas/ContentAssetAccessSummaryDto" + }, + "access": { + "$ref": "#/components/schemas/AssetAccessPrincipalDto" + }, + "url": { + "$ref": "#/components/schemas/SignedStorageUrlDto" + }, + "watermark": { + "$ref": "#/components/schemas/JsonElement" + } + }, + "description": "资产访问签名响应。" + }, + "AssetAccessResult": { + "type": "integer" + }, + "AssetAccessSignDto": { + "required": [ + "assetId" + ], + "type": "object", + "properties": { + "assetId": { + "type": "string", + "description": "资产 ID。", + "format": "uuid" + }, + "expiresInSeconds": { + "maximum": 3600, + "minimum": 60, + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "description": "有效期秒数。", + "format": "int32" + } + }, + "description": "创建资产访问签名请求。" + }, + "AssetAccessType": { + "type": "integer" + }, + "AssetManagementSignedAccessResult": { + "required": [ + "item", + "url" + ], + "type": "object", + "properties": { + "item": { + "$ref": "#/components/schemas/ContentAssetManagementItem" + }, + "url": { + "$ref": "#/components/schemas/ObjectStorageSignedUrl" + } + } + }, + "AssetPreviewStatus": { + "type": "integer" + }, + "AssetSecurityRiskLevel": { + "type": "integer" + }, + "AssetSecurityScanStatus": { + "type": "integer" + }, + "AssetStorageProvider": { + "type": "integer" + }, + "AssetUploadConfirmDto": { + "required": [ + "assetId" + ], + "type": "object", + "properties": { + "assetId": { + "type": "string", + "description": "资产 ID。", + "format": "uuid" + }, + "mimeType": { + "maxLength": 200, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "MIME 类型。" + }, + "fileSizeBytes": { + "maximum": 9223372036854776000, + "minimum": 0, + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "description": "文件大小,单位为字节。", + "format": "int64" + }, + "checksumSha256": { + "pattern": "^[A-Fa-f0-9]{64}$", + "type": [ + "null", + "string" + ], + "description": "SHA-256 校验值。" + } + }, + "description": "确认资产上传请求。" + }, + "AssetUploadConfirmResult": { + "required": [ + "item", + "metadata" + ], + "type": "object", + "properties": { + "item": { + "$ref": "#/components/schemas/ContentAssetManagementItem" + }, + "metadata": { + "$ref": "#/components/schemas/ObjectStorageMetadata" + } + } + }, + "AssetUploadSignDto": { + "required": [ + "fileName", + "mimeType" + ], + "type": "object", + "properties": { + "assetId": { + "type": [ + "null", + "string" + ], + "description": "资产 ID。", + "format": "uuid" + }, + "regionId": { + "type": [ + "null", + "string" + ], + "description": "地区 ID。", + "format": "uuid" + }, + "subjectId": { + "type": [ + "null", + "string" + ], + "description": "科目 ID。", + "format": "uuid" + }, + "categoryId": { + "type": [ + "null", + "string" + ], + "description": "分类 ID。", + "format": "uuid" + }, + "contentNodeId": { + "type": [ + "null", + "string" + ], + "description": "内容节点 ID。", + "format": "uuid" + }, + "assetKey": { + "maxLength": 200, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "资产键。" + }, + "title": { + "maxLength": 300, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "标题。" + }, + "category": { + "maxLength": 100, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "分类。" + }, + "description": { + "maxLength": 1000, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "说明。" + }, + "fileName": { + "maxLength": 500, + "minLength": 0, + "type": "string", + "description": "文件名。" + }, + "mimeType": { + "maxLength": 200, + "minLength": 0, + "type": "string", + "description": "MIME 类型。" + }, + "fileSizeBytes": { + "maximum": 9223372036854776000, + "minimum": 0, + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "description": "文件大小,单位为字节。", + "format": "int64" + }, + "checksumSha256": { + "pattern": "^[A-Fa-f0-9]{64}$", + "type": [ + "null", + "string" + ], + "description": "SHA-256 校验值。" + }, + "assetType": { + "maxLength": 50, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "资产类型。" + }, + "visibility": { + "maxLength": 50, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "可见性。" + }, + "isPublic": { + "type": [ + "null", + "boolean" + ], + "description": "是否公开。" + }, + "provider": { + "maxLength": 50, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "服务提供方。" + }, + "bucket": { + "maxLength": 200, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "存储桶。" + }, + "objectKey": { + "maxLength": 1000, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "对象存储键。" + }, + "expiresInSeconds": { + "maximum": 3600, + "minimum": 1, + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "description": "有效期秒数。", + "format": "int32" + }, + "metadata": { + "description": "扩展元数据。", + "$ref": "#/components/schemas/JsonElement" + } + }, + "description": "创建资产上传签名请求。" + }, + "AssetUploadSignResult": { + "required": [ + "item", + "upload" + ], + "type": "object", + "properties": { + "item": { + "$ref": "#/components/schemas/ContentAssetManagementItem" + }, + "upload": { + "$ref": "#/components/schemas/ObjectStorageSignedUrl" + } + } + }, + "AssetUploadStatus": { + "type": "integer" + }, + "AuthenticatedUserDto": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "用户 ID。", + "format": "uuid" + }, + "phone": { + "type": [ + "null", + "string" + ], + "description": "手机号。" + }, + "email": { + "type": [ + "null", + "string" + ], + "description": "邮箱。" + }, + "name": { + "type": [ + "null", + "string" + ], + "description": "名称。" + }, + "realm": { + "description": "认证域。", + "$ref": "#/components/schemas/AuthRealm" + }, + "tenant": { + "oneOf": [ + { + "type": "null" + }, + { + "description": "租户成员摘要。", + "$ref": "#/components/schemas/TenantMembershipSummary" + } + ] + }, + "tokens": { + "description": "访问令牌和刷新令牌。", + "$ref": "#/components/schemas/AuthTokenPair" + } + }, + "description": "Authenticated用户请求 DTO。" + }, + "AuthenticationResultDto": { + "type": "object", + "properties": { + "status": { + "description": "状态。", + "$ref": "#/components/schemas/AuthenticationStatus" + }, + "user": { + "oneOf": [ + { + "type": "null" + }, + { + "description": "用户信息。", + "$ref": "#/components/schemas/AuthenticatedUserDto" + } + ] + }, + "challengeToken": { + "type": [ + "null", + "string" + ], + "description": "挑战令牌。" + }, + "challengeExpiresAt": { + "type": [ + "null", + "string" + ], + "description": "挑战令牌过期时间。", + "format": "date-time" + } + }, + "description": "登录认证结果。" + }, + "AuthenticationStatus": { + "type": "integer" + }, + "AuthRealm": { + "type": "integer" + }, + "AuthTokenPair": { + "required": [ + "accessToken", + "refreshToken", + "accessTokenExpiresAt", + "refreshTokenExpiresAt" + ], + "type": "object", + "properties": { + "accessToken": { + "type": "string", + "description": "用于访问 API 的 JWT access token。" + }, + "refreshToken": { + "type": "string", + "description": "用于刷新会话的 refresh token,服务端只保存哈希。" + }, + "accessTokenExpiresAt": { + "type": "string", + "description": "access token 过期时间。", + "format": "date-time" + }, + "refreshTokenExpiresAt": { + "type": "string", + "description": "refresh token 过期时间。", + "format": "date-time" + } + }, + "description": "认证令牌对。" + }, + "BackendPermissionArea": { + "type": "integer" + }, + "BackendRoleStatus": { + "type": "integer" + }, + "BackgroundJobItem": { + "required": [ + "id", + "tenantId", + "jobType", + "status", + "retryCount", + "maxRetries", + "runAfter", + "startedAt", + "completedAt", + "lastError", + "outputAssetId", + "result" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "tenantId": { + "type": "string", + "format": "uuid" + }, + "jobType": { + "type": "string" + }, + "status": { + "$ref": "#/components/schemas/BackgroundJobStatus" + }, + "retryCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "maxRetries": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "runAfter": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "startedAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "completedAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "lastError": { + "type": [ + "null", + "string" + ] + }, + "outputAssetId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "result": { + "$ref": "#/components/schemas/JsonElement" + } + } + }, + "BackgroundJobStatus": { + "type": "integer" + }, + "BackofficeBootstrap": { + "required": [ + "permissions", + "menus", + "roles" + ], + "type": "object", + "properties": { + "permissions": { + "type": "array", + "items": { + "$ref": "#/components/schemas/BackofficePermissionItem" + } + }, + "menus": { + "type": "array", + "items": { + "$ref": "#/components/schemas/BackofficeMenuItem" + } + }, + "roles": { + "type": "array", + "items": { + "$ref": "#/components/schemas/BackofficeRoleItem" + } + } + } + }, + "BackofficeMenuItem": { + "required": [ + "id", + "code", + "parentCode", + "title", + "area", + "path", + "icon", + "permissionCode", + "sortOrder", + "isActive" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "code": { + "type": "string" + }, + "parentCode": { + "type": [ + "null", + "string" + ] + }, + "title": { + "type": "string" + }, + "area": { + "$ref": "#/components/schemas/BackendPermissionArea" + }, + "path": { + "type": [ + "null", + "string" + ] + }, + "icon": { + "type": [ + "null", + "string" + ] + }, + "permissionCode": { + "type": [ + "null", + "string" + ] + }, + "sortOrder": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "isActive": { + "type": "boolean" + } + } + }, + "BackofficePermissionItem": { + "required": [ + "id", + "code", + "name", + "area", + "permissionModuleCode", + "description", + "sortOrder" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "code": { + "type": "string" + }, + "name": { + "type": "string" + }, + "area": { + "$ref": "#/components/schemas/BackendPermissionArea" + }, + "permissionModuleCode": { + "type": "string" + }, + "description": { + "type": [ + "null", + "string" + ] + }, + "sortOrder": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + } + } + }, + "BackofficeRoleItem": { + "required": [ + "id", + "code", + "name", + "status", + "isSystem", + "description", + "permissionCodes", + "menuCodes" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "code": { + "type": "string" + }, + "name": { + "type": "string" + }, + "status": { + "$ref": "#/components/schemas/BackendRoleStatus" + }, + "isSystem": { + "type": "boolean" + }, + "description": { + "type": [ + "null", + "string" + ] + }, + "permissionCodes": { + "type": "array", + "items": { + "type": "string" + } + }, + "menuCodes": { + "type": "array", + "items": { + "type": "string" + } + }, + "dataScope": {} + } + }, + "BackofficeUiBootstrap": { + "required": [ + "permissionCodes", + "menus", + "enabledFeatures", + "quotas" + ], + "type": "object", + "properties": { + "permissionCodes": { + "type": "array", + "items": { + "type": "string" + } + }, + "menus": { + "type": "array", + "items": { + "$ref": "#/components/schemas/BackofficeMenuItem" + } + }, + "enabledFeatures": { + "type": "array", + "items": { + "type": "string" + } + }, + "quotas": { + "type": "array", + "items": { + "$ref": "#/components/schemas/FeatureQuotaSnapshot" + } + } + } + }, + "BadgeItem": { + "required": [ + "id", + "name", + "description", + "category", + "iconUrl", + "level", + "unlockType", + "conditionExtra", + "isUnlocked", + "grantedAt", + "note", + "order" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "name": { + "type": "string" + }, + "description": { + "type": [ + "null", + "string" + ] + }, + "category": { + "type": [ + "null", + "string" + ] + }, + "iconUrl": { + "type": [ + "null", + "string" + ] + }, + "level": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "format": "int32" + }, + "unlockType": { + "type": [ + "null", + "string" + ] + }, + "conditionExtra": { + "$ref": "#/components/schemas/JsonElement" + }, + "isUnlocked": { + "type": "boolean" + }, + "grantedAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "note": { + "type": [ + "null", + "string" + ] + }, + "order": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + } + } + }, + "BadgeList": { + "required": [ + "items", + "total", + "unlocked", + "includeLocked" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/BadgeItem" + } + }, + "total": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "unlocked": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "includeLocked": { + "type": "boolean" + } + } + }, + "BannerCatalogItem": { + "required": [ + "id", + "legacyId", + "regionId", + "title", + "subtitle", + "content", + "buttonText", + "buttonLink", + "backgroundColor", + "borderColor", + "order", + "isActive" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "legacyId": { + "type": [ + "null", + "string" + ] + }, + "regionId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "title": { + "type": [ + "null", + "string" + ] + }, + "subtitle": { + "type": [ + "null", + "string" + ] + }, + "content": { + "type": [ + "null", + "string" + ] + }, + "buttonText": { + "type": [ + "null", + "string" + ] + }, + "buttonLink": { + "type": [ + "null", + "string" + ] + }, + "backgroundColor": { + "type": [ + "null", + "string" + ] + }, + "borderColor": { + "type": [ + "null", + "string" + ] + }, + "order": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "isActive": { + "type": "boolean" + } + } + }, + "BatchCreatePlatformQuestionBankNodesCommand": { + "required": [ + "questionBankId", + "parentId", + "nodeType", + "names" + ], + "type": "object", + "properties": { + "questionBankId": { + "type": "string", + "format": "uuid" + }, + "parentId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "nodeType": { + "$ref": "#/components/schemas/ContentNodeType" + }, + "names": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "BillingStatus": { + "type": "integer" + }, + "BindReferralDto": { + "required": [ + "refCode" + ], + "type": "object", + "properties": { + "refCode": { + "maxLength": 100, + "minLength": 0, + "type": "string", + "description": "推荐码。" + }, + "source": { + "maxLength": 100, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "来源。" + }, + "metadata": { + "oneOf": [ + { + "type": "null" + }, + { + "description": "扩展元数据。", + "$ref": "#/components/schemas/JsonElement" + } + ] + } + }, + "description": "绑定推荐请求 DTO。" + }, + "CatalogListOfAnnouncementCatalogItem": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/AnnouncementCatalogItem" + } + } + } + }, + "CatalogListOfAppAssetCatalogItem": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/AppAssetCatalogItem" + } + } + } + }, + "CatalogListOfBannerCatalogItem": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/BannerCatalogItem" + } + } + } + }, + "CatalogListOfCategoryCatalogItem": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/CategoryCatalogItem" + } + } + } + }, + "CatalogListOfCollectionQuestionCatalogItem": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/CollectionQuestionCatalogItem" + } + } + } + }, + "CatalogListOfContentAssetAccessEventItem": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ContentAssetAccessEventItem" + } + } + } + }, + "CatalogListOfContentAssetCatalogItem": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ContentAssetCatalogItem" + } + } + } + }, + "CatalogListOfContentAssetManagementItem": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ContentAssetManagementItem" + } + } + } + }, + "CatalogListOfContentAssetSecurityScanEventItem": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ContentAssetSecurityScanEventItem" + } + } + } + }, + "CatalogListOfContentEntryCatalogItem": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ContentEntryCatalogItem" + } + } + } + }, + "CatalogListOfContentEntryManagementItem": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ContentEntryManagementItem" + } + } + } + }, + "CatalogListOfContentImportIssueModel": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ContentImportIssueModel" + } + } + } + }, + "CatalogListOfContentImportJobItem": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ContentImportJobItem" + } + } + } + }, + "CatalogListOfContentNodeCatalogItem": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ContentNodeCatalogItem" + } + } + } + }, + "CatalogListOfContentNodeManagementItem": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ContentNodeManagementItem" + } + } + } + }, + "CatalogListOfExamDateCatalogItem": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ExamDateCatalogItem" + } + } + } + }, + "CatalogListOfFaqCatalogItem": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/FaqCatalogItem" + } + } + } + }, + "CatalogListOfHandbookChapter": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/HandbookChapter" + } + } + } + }, + "CatalogListOfHandbookChapterCatalogItem": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/HandbookChapterCatalogItem" + } + } + } + }, + "CatalogListOfHandbookEntry": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/HandbookEntry" + } + } + } + }, + "CatalogListOfHandbookEntryCatalogItem": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/HandbookEntryCatalogItem" + } + } + } + }, + "CatalogListOfHandbookSubject": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/HandbookSubject" + } + } + } + }, + "CatalogListOfHandbookSubjectCatalogItem": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/HandbookSubjectCatalogItem" + } + } + } + }, + "CatalogListOfImageAssetCatalogItem": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ImageAssetCatalogItem" + } + } + } + }, + "CatalogListOfint": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + } + } + } + }, + "CatalogListOfMajor": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Major" + } + } + } + }, + "CatalogListOfMajorCatalogItem": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/MajorCatalogItem" + } + } + } + }, + "CatalogListOfModuleNodeCatalogItem": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ModuleNodeCatalogItem" + } + } + } + }, + "CatalogListOfOperationContentItem": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/OperationContentItem" + } + } + } + }, + "CatalogListOfPracticeBlueprintCatalogItem": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/PracticeBlueprintCatalogItem" + } + } + } + }, + "CatalogListOfPracticeBlueprintManagementItem": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/PracticeBlueprintManagementItem" + } + } + } + }, + "CatalogListOfProductCatalogItem": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ProductCatalogItem" + } + } + } + }, + "CatalogListOfQuestionBankCatalogItem": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/QuestionBankCatalogItem" + } + } + } + }, + "CatalogListOfQuestionCatalogItem": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/QuestionCatalogItem" + } + } + } + }, + "CatalogListOfQuestionCollectionCatalogItem": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/QuestionCollectionCatalogItem" + } + } + } + }, + "CatalogListOfQuestionCollectionManagementItem": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/QuestionCollectionManagementItem" + } + } + } + }, + "CatalogListOfQuestionVersionCatalogItem": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/QuestionVersionCatalogItem" + } + } + } + }, + "CatalogListOfQuestionVideoCatalogItem": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/QuestionVideoCatalogItem" + } + } + } + }, + "CatalogListOfRegionCatalogItem": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/RegionCatalogItem" + } + } + } + }, + "CatalogListOfRegionModuleCatalogItem": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/RegionModuleCatalogItem" + } + } + } + }, + "CatalogListOfSchool": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/School" + } + } + } + }, + "CatalogListOfSchoolCatalogItem": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/SchoolCatalogItem" + } + } + } + }, + "CatalogListOfScorelineField": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ScorelineField" + } + } + } + }, + "CatalogListOfScorelineFieldItem": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ScorelineFieldItem" + } + } + } + }, + "CatalogListOfScorelineRecord": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ScorelineRecord" + } + } + } + }, + "CatalogListOfScorelineRecordItem": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ScorelineRecordItem" + } + } + } + }, + "CatalogListOfScorelineTrendItem": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ScorelineTrendItem" + } + } + } + }, + "CatalogListOfSubjectCatalogItem": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/SubjectCatalogItem" + } + } + } + }, + "CatalogListOfSvipPlanCatalogItem": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/SvipPlanCatalogItem" + } + } + } + }, + "CatalogListOfTenantAdminAuditLogItem": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/TenantAdminAuditLogItem" + } + } + } + }, + "CatalogListOfTenantAdminBadgeGrantItem": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/TenantAdminBadgeGrantItem" + } + } + } + }, + "CatalogListOfTenantAdminBadgeItem": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/TenantAdminBadgeItem" + } + } + } + }, + "CatalogListOfTenantAdminClassMemberItem": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/TenantAdminClassMemberItem" + } + } + } + }, + "CatalogListOfTenantAdminFeedbackItem": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/TenantAdminFeedbackItem" + } + } + } + }, + "CatalogListOfTenantAdminMemberItem": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/TenantAdminMemberItem" + } + } + } + }, + "CatalogListOfTenantAdminNotificationItem": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/TenantAdminNotificationItem" + } + } + } + }, + "CatalogListOfTenantAdminStudentFollowupItem": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/TenantAdminStudentFollowupItem" + } + } + } + }, + "CatalogListOfTenantAdminStudentNoteItem": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/TenantAdminStudentNoteItem" + } + } + } + }, + "CatalogListOfTenantDomainItem": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/TenantDomainItem" + } + } + } + }, + "CatalogListOfTenantIdentityProviderItem": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/TenantIdentityProviderItem" + } + } + } + }, + "CatalogListOfTenantSupervisionRuleItem": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/TenantSupervisionRuleItem" + } + } + } + }, + "CatalogListOfTenantThemeTemplateItem": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/TenantThemeTemplateItem" + } + } + } + }, + "CatalogListOfVideoExplanationCatalogItem": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/VideoExplanationCatalogItem" + } + } + } + }, + "CatalogListOfVideoManagementItem": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/VideoManagementItem" + } + } + } + }, + "CatalogListOfVocabularyUnit": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/VocabularyUnit" + } + } + } + }, + "CatalogListOfVocabularyUnitCatalogItem": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/VocabularyUnitCatalogItem" + } + } + } + }, + "CatalogListOfVocabularyWord": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/VocabularyWord" + } + } + } + }, + "CatalogListOfVocabularyWordCatalogItem": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/VocabularyWordCatalogItem" + } + } + } + }, + "CategoryCatalogItem": { + "required": [ + "id", + "legacyId", + "subjectId", + "nodeId", + "name", + "categoryType", + "order", + "svipQuestionLimit" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "legacyId": { + "type": [ + "null", + "string" + ] + }, + "subjectId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "nodeId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "name": { + "type": "string" + }, + "categoryType": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/components/schemas/CategoryType" + } + ] + }, + "order": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "svipQuestionLimit": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "format": "int32" + } + } + }, + "CategoryType": { + "type": "integer" + }, + "ChangeTenantSubscriptionDto": { + "required": [ + "baseOfferingVersionId", + "addOnOfferingVersionIds", + "idempotencyKey" + ], + "type": "object", + "properties": { + "baseOfferingVersionId": { + "type": "string", + "format": "uuid" + }, + "addOnOfferingVersionIds": { + "type": [ + "null", + "array" + ], + "items": { + "type": "string", + "format": "uuid" + } + }, + "idempotencyKey": { + "type": "string" + } + }, + "description": "变更租户订阅请求 DTO。" + }, + "CheckCommerceCouponDto": { + "required": [ + "planId" + ], + "type": "object", + "properties": { + "couponCode": { + "maxLength": 100, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "优惠券码。" + }, + "couponRedemptionId": { + "type": [ + "null", + "string" + ], + "description": "优惠券领取记录 ID。", + "format": "uuid" + }, + "planId": { + "type": "string", + "description": "套餐 ID。", + "format": "uuid" + }, + "quantity": { + "maximum": 99, + "minimum": 1, + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "description": "数量。", + "format": "int32" + }, + "regionId": { + "type": [ + "null", + "string" + ], + "description": "地区 ID。", + "format": "uuid" + } + }, + "description": "校验交易优惠券请求 DTO。" + }, + "CheckInResult": { + "required": [ + "checkInDate", + "alreadyCheckedIn", + "points", + "balanceAfter", + "claimId", + "scoreEventId" + ], + "type": "object", + "properties": { + "checkInDate": { + "type": "string", + "format": "date" + }, + "alreadyCheckedIn": { + "type": "boolean" + }, + "points": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "balanceAfter": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "claimId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "scoreEventId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + } + } + }, + "ClaimCommerceCouponDto": { + "required": [ + "couponCode" + ], + "type": "object", + "properties": { + "couponCode": { + "maxLength": 100, + "minLength": 0, + "type": "string", + "description": "优惠券码。" + } + }, + "description": "领取交易优惠券请求 DTO。" + }, + "ClaimPointTaskDto": { + "required": [ + "taskKey" + ], + "type": "object", + "properties": { + "taskKey": { + "maxLength": 100, + "minLength": 0, + "type": "string", + "description": "任务键。" + }, + "sourceType": { + "maxLength": 100, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "来源类型。" + }, + "sourceId": { + "type": [ + "null", + "string" + ], + "description": "来源 ID。", + "format": "uuid" + } + }, + "description": "领取积分任务请求 DTO。" + }, + "CodeBatchItem": { + "required": [ + "id", + "name", + "totalCount", + "days", + "regionId", + "saleType", + "channel", + "defaultUnitPriceCents", + "costPriceCents", + "issuedAt", + "remark", + "createdAt" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "name": { + "type": "string" + }, + "totalCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "days": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "regionId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "saleType": { + "type": [ + "null", + "string" + ] + }, + "channel": { + "type": [ + "null", + "string" + ] + }, + "defaultUnitPriceCents": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "costPriceCents": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "issuedAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "remark": { + "type": [ + "null", + "string" + ] + }, + "createdAt": { + "type": "string", + "format": "date-time" + } + } + }, + "CollectionItemsReplaceResult": { + "required": [ + "collectionId", + "questionCount", + "items" + ], + "type": "object", + "properties": { + "collectionId": { + "type": "string", + "format": "uuid" + }, + "questionCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/QuestionCollectionItemManagementItem" + } + } + } + }, + "CollectionQuestionCatalogItem": { + "required": [ + "id", + "legacyId", + "entryId", + "contentNodeId", + "primaryCollectionId", + "subjectId", + "categoryId", + "nodeId", + "type", + "typeLabel", + "difficulty", + "tags", + "examMarkers", + "mediaUrl", + "hasVideoExplanation", + "sectionKey", + "score", + "order", + "versionId", + "content", + "options", + "correctOptionIndex", + "correctOptionIndices", + "answerText", + "explanation", + "subQuestions", + "codeLang", + "codeTemplate" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "legacyId": { + "type": [ + "null", + "string" + ] + }, + "entryId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "contentNodeId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "primaryCollectionId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "subjectId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "categoryId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "nodeId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "type": { + "type": "string" + }, + "typeLabel": { + "type": [ + "null", + "string" + ] + }, + "difficulty": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "format": "int32" + }, + "tags": { + "$ref": "#/components/schemas/JsonElement" + }, + "examMarkers": { + "$ref": "#/components/schemas/JsonElement" + }, + "mediaUrl": { + "type": [ + "null", + "string" + ] + }, + "hasVideoExplanation": { + "type": "boolean" + }, + "sectionKey": { + "type": [ + "null", + "string" + ] + }, + "score": { + "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$", + "type": [ + "null", + "number", + "string" + ], + "format": "double" + }, + "order": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "versionId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "content": { + "type": [ + "null", + "string" + ] + }, + "options": { + "$ref": "#/components/schemas/JsonElement" + }, + "correctOptionIndex": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "format": "int32" + }, + "correctOptionIndices": { + "$ref": "#/components/schemas/JsonElement" + }, + "answerText": { + "type": [ + "null", + "string" + ] + }, + "explanation": { + "type": [ + "null", + "string" + ] + }, + "subQuestions": { + "$ref": "#/components/schemas/JsonElement" + }, + "codeLang": { + "type": [ + "null", + "string" + ] + }, + "codeTemplate": { + "type": [ + "null", + "string" + ] + } + } + }, + "CollectionQuestionDto": { + "required": [ + "questionId", + "source" + ], + "type": "object", + "properties": { + "questionId": { + "type": "string", + "description": "题目 ID。", + "format": "uuid" + }, + "source": { + "description": "来源。", + "$ref": "#/components/schemas/QuestionSource" + }, + "sectionKey": { + "maxLength": 100, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "分段键。" + }, + "order": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "description": "显示顺序。", + "format": "int32" + }, + "score": { + "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$", + "type": [ + "null", + "number", + "string" + ], + "description": "分数。", + "format": "double" + }, + "required": { + "type": [ + "null", + "boolean" + ], + "description": "是否必填。" + }, + "metadata": { + "description": "扩展元数据。", + "$ref": "#/components/schemas/JsonElement" + } + }, + "description": "题集题目请求 DTO。" + }, + "CommerceAdjustmentDirection": { + "type": "integer" + }, + "CommerceAdjustmentVoucher": { + "type": "object", + "properties": { + "issueId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "batchId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "itemId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "orderId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "paymentId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "refundRequestId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "createdBy": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "reviewedBy": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "voucherNo": { + "type": "string" + }, + "status": { + "$ref": "#/components/schemas/CommerceAdjustmentVoucherStatus" + }, + "direction": { + "$ref": "#/components/schemas/CommerceAdjustmentDirection" + }, + "amountCents": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "currency": { + "type": "string" + }, + "reason": { + "type": "string" + }, + "proofAssetKey": { + "type": [ + "null", + "string" + ] + }, + "reviewedAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "closedAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "metadata": { + "$ref": "#/components/schemas/JsonElement" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "tenantId": { + "type": "string", + "format": "uuid" + }, + "id": { + "type": "string", + "format": "uuid" + } + } + }, + "CommerceAdjustmentVoucherEvent": { + "type": "object", + "properties": { + "tenantId": { + "type": "string", + "format": "uuid" + }, + "voucherId": { + "type": "string", + "format": "uuid" + }, + "fromStatus": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/components/schemas/CommerceAdjustmentVoucherStatus" + } + ] + }, + "toStatus": { + "$ref": "#/components/schemas/CommerceAdjustmentVoucherStatus" + }, + "actorUserId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "note": { + "type": [ + "null", + "string" + ] + }, + "details": { + "$ref": "#/components/schemas/JsonElement" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "id": { + "type": "string", + "format": "uuid" + } + } + }, + "CommerceAdjustmentVoucherStatus": { + "type": "integer" + }, + "CommerceCouponCheckResult": { + "required": [ + "valid", + "reasonCode", + "couponId", + "couponRedemptionId", + "couponCode", + "originalAmountCents", + "discountCents", + "payableAmountCents", + "payablePrice" + ], + "type": "object", + "properties": { + "valid": { + "type": "boolean" + }, + "reasonCode": { + "type": [ + "null", + "string" + ] + }, + "couponId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "couponRedemptionId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "couponCode": { + "type": [ + "null", + "string" + ] + }, + "originalAmountCents": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "discountCents": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "payableAmountCents": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "payablePrice": { + "type": "string" + } + } + }, + "CommerceCouponItem": { + "required": [ + "id", + "couponId", + "couponCode", + "status", + "planId", + "regionId", + "discountType", + "discountValue", + "discountPreviewCents", + "discountPreview", + "validFrom", + "validTo", + "claimedAt", + "usedAt" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "couponId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "couponCode": { + "type": "string" + }, + "status": { + "type": "string" + }, + "planId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "regionId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "discountType": { + "type": [ + "null", + "string" + ] + }, + "discountValue": { + "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$", + "type": [ + "null", + "number", + "string" + ], + "format": "double" + }, + "discountPreviewCents": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "format": "int32" + }, + "discountPreview": { + "type": [ + "null", + "string" + ] + }, + "validFrom": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "validTo": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "claimedAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "usedAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + } + } + }, + "CommerceCouponList": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/CommerceCouponItem" + } + } + } + }, + "CommerceOrderItem": { + "required": [ + "id", + "orderNo", + "status", + "planId", + "regionId", + "productType", + "productName", + "amountCents", + "price", + "payMethod", + "payProvider", + "tradeNo", + "days", + "paidAt", + "createdAt", + "rawPayload" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "orderNo": { + "type": "string" + }, + "status": { + "type": "string" + }, + "planId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "regionId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "productType": { + "type": [ + "null", + "string" + ] + }, + "productName": { + "type": [ + "null", + "string" + ] + }, + "amountCents": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "price": { + "type": "string" + }, + "payMethod": { + "type": [ + "null", + "string" + ] + }, + "payProvider": { + "type": [ + "null", + "string" + ] + }, + "tradeNo": { + "type": [ + "null", + "string" + ] + }, + "days": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "format": "int32" + }, + "paidAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "rawPayload": { + "$ref": "#/components/schemas/JsonElement" + } + } + }, + "CommerceOrderList": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/CommerceOrderItem" + } + } + } + }, + "CommercePaymentItem": { + "required": [ + "id", + "orderId", + "orderNo", + "provider", + "method", + "status", + "amountCents", + "price", + "providerTradeNo", + "paidAt", + "clientPayload", + "rawPayload" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "orderId": { + "type": "string", + "format": "uuid" + }, + "orderNo": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "method": { + "type": [ + "null", + "string" + ] + }, + "status": { + "type": "string" + }, + "amountCents": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "price": { + "type": "string" + }, + "providerTradeNo": { + "type": [ + "null", + "string" + ] + }, + "paidAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "clientPayload": { + "$ref": "#/components/schemas/JsonElement" + }, + "rawPayload": { + "$ref": "#/components/schemas/JsonElement" + } + } + }, + "CommerceReconciliationBatch": { + "type": "object", + "properties": { + "createdBy": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "provider": { + "type": "string" + }, + "billDate": { + "type": "string", + "format": "date" + }, + "billType": { + "$ref": "#/components/schemas/ReconciliationBillType" + }, + "source": { + "$ref": "#/components/schemas/ReconciliationSource" + }, + "sourceName": { + "type": [ + "null", + "string" + ] + }, + "sourceHash": { + "type": "string" + }, + "status": { + "$ref": "#/components/schemas/ReconciliationBatchStatus" + }, + "totalCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "matchedCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "mismatchCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "missingLocalCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "missingProviderCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "duplicateCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "ignoredCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "amountCents": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "refundAmountCents": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "feeCents": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "completedAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "error": { + "type": [ + "null", + "string" + ] + }, + "metadata": { + "$ref": "#/components/schemas/JsonElement" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "tenantId": { + "type": "string", + "format": "uuid" + }, + "id": { + "type": "string", + "format": "uuid" + } + } + }, + "CommerceReconciliationIssue": { + "type": "object", + "properties": { + "batchId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "itemId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "orderId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "paymentId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "refundRequestId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "assignedTo": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "createdBy": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "resolvedBy": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "issueNo": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "transactionType": { + "$ref": "#/components/schemas/ReconciliationTransactionType" + }, + "issueCode": { + "type": [ + "null", + "string" + ] + }, + "matchStatus": { + "$ref": "#/components/schemas/ReconciliationIssueMatchStatus" + }, + "severity": { + "$ref": "#/components/schemas/NotificationSeverity" + }, + "status": { + "$ref": "#/components/schemas/ReconciliationIssueStatus" + }, + "resolutionType": { + "$ref": "#/components/schemas/ReconciliationResolutionType" + }, + "orderNo": { + "type": [ + "null", + "string" + ] + }, + "refundNo": { + "type": [ + "null", + "string" + ] + }, + "providerTradeNo": { + "type": [ + "null", + "string" + ] + }, + "providerRefundNo": { + "type": [ + "null", + "string" + ] + }, + "amountCents": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "refundAmountCents": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "resolvedAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "dueAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "summary": { + "type": [ + "null", + "string" + ] + }, + "resolutionNote": { + "type": [ + "null", + "string" + ] + }, + "metadata": { + "$ref": "#/components/schemas/JsonElement" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "tenantId": { + "type": "string", + "format": "uuid" + }, + "id": { + "type": "string", + "format": "uuid" + } + } + }, + "CommerceReconciliationIssueEvent": { + "type": "object", + "properties": { + "tenantId": { + "type": "string", + "format": "uuid" + }, + "issueId": { + "type": "string", + "format": "uuid" + }, + "fromStatus": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/components/schemas/ReconciliationIssueStatus" + } + ] + }, + "toStatus": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/components/schemas/ReconciliationIssueStatus" + } + ] + }, + "eventType": { + "type": "string" + }, + "actorUserId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "note": { + "type": [ + "null", + "string" + ] + }, + "details": { + "$ref": "#/components/schemas/JsonElement" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "id": { + "type": "string", + "format": "uuid" + } + } + }, + "CommerceReconciliationItem": { + "type": "object", + "properties": { + "tenantId": { + "type": "string", + "format": "uuid" + }, + "batchId": { + "type": "string", + "format": "uuid" + }, + "orderId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "paymentId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "refundRequestId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "rowNo": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "provider": { + "type": "string" + }, + "transactionType": { + "$ref": "#/components/schemas/ReconciliationTransactionType" + }, + "providerTradeNo": { + "type": [ + "null", + "string" + ] + }, + "providerRefundNo": { + "type": [ + "null", + "string" + ] + }, + "orderNo": { + "type": [ + "null", + "string" + ] + }, + "refundNo": { + "type": [ + "null", + "string" + ] + }, + "amountCents": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "refundAmountCents": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "feeCents": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "paidAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "refundedAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "providerStatus": { + "type": [ + "null", + "string" + ] + }, + "localStatus": { + "type": [ + "null", + "string" + ] + }, + "matchStatus": { + "$ref": "#/components/schemas/ReconciliationMatchStatus" + }, + "severity": { + "$ref": "#/components/schemas/NotificationSeverity" + }, + "issueCode": { + "type": [ + "null", + "string" + ] + }, + "details": { + "$ref": "#/components/schemas/JsonElement" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "id": { + "type": "string", + "format": "uuid" + } + } + }, + "CommerceRefundEvent": { + "type": "object", + "properties": { + "tenantId": { + "type": "string", + "format": "uuid" + }, + "refundRequestId": { + "type": "string", + "format": "uuid" + }, + "fromStatus": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/components/schemas/CommerceRefundStatus" + } + ] + }, + "toStatus": { + "$ref": "#/components/schemas/CommerceRefundStatus" + }, + "eventType": { + "type": "string" + }, + "actorUserId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "details": { + "$ref": "#/components/schemas/JsonElement" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "id": { + "type": "string", + "format": "uuid" + } + } + }, + "CommerceRefundRequest": { + "type": "object", + "properties": { + "orderId": { + "type": "string", + "format": "uuid" + }, + "paymentId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "requestedBy": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "reviewedBy": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "processedBy": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "refundNo": { + "type": "string" + }, + "provider": { + "type": [ + "null", + "string" + ] + }, + "providerRefundNo": { + "type": [ + "null", + "string" + ] + }, + "status": { + "$ref": "#/components/schemas/CommerceRefundStatus" + }, + "amountCents": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "reason": { + "type": [ + "null", + "string" + ] + }, + "entitlementAction": { + "$ref": "#/components/schemas/RefundEntitlementAction" + }, + "requestedAt": { + "type": "string", + "format": "date-time" + }, + "reviewedAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "processedAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "succeededAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "failedAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "cancelledAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "failureReason": { + "type": [ + "null", + "string" + ] + }, + "metadata": { + "$ref": "#/components/schemas/JsonElement" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "tenantId": { + "type": "string", + "format": "uuid" + }, + "id": { + "type": "string", + "format": "uuid" + } + } + }, + "CommerceRefundStatus": { + "type": "integer" + }, + "CommissionExportItem": { + "required": [ + "settlementId", + "filename", + "format", + "mimeType", + "rowCount", + "contentBase64", + "sha256", + "sizeBytes" + ], + "type": "object", + "properties": { + "settlementId": { + "type": "string", + "format": "uuid" + }, + "filename": { + "type": "string" + }, + "format": { + "type": "string" + }, + "mimeType": { + "type": "string" + }, + "rowCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "contentBase64": { + "type": "string" + }, + "sha256": { + "type": "string" + }, + "sizeBytes": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + } + } + }, + "CommissionListOfCommissionProofItem": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/CommissionProofItem" + } + } + } + }, + "CommissionListOfCommissionSettlementItemDto": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/CommissionSettlementItemDto" + } + } + } + }, + "CommissionListOfCommissionSourceItem": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/CommissionSourceItem" + } + } + } + }, + "CommissionProofItem": { + "required": [ + "id", + "settlementId", + "proofType", + "status", + "title", + "assetId", + "externalUrl", + "amountCents", + "paymentMethod", + "paymentAccount", + "paidAt", + "reviewedAt" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "settlementId": { + "type": "string", + "format": "uuid" + }, + "proofType": { + "type": "string" + }, + "status": { + "type": "string" + }, + "title": { + "type": [ + "null", + "string" + ] + }, + "assetId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "externalUrl": { + "type": [ + "null", + "string" + ] + }, + "amountCents": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "format": "int32" + }, + "paymentMethod": { + "type": [ + "null", + "string" + ] + }, + "paymentAccount": { + "type": [ + "null", + "string" + ] + }, + "paidAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "reviewedAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + } + } + }, + "CommissionSettingsItem": { + "required": [ + "defaultRate", + "minSettlementCents", + "settlementCycle", + "config" + ], + "type": "object", + "properties": { + "defaultRate": { + "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$", + "type": [ + "number", + "string" + ], + "format": "double" + }, + "minSettlementCents": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "settlementCycle": { + "type": "string" + }, + "config": { + "$ref": "#/components/schemas/JsonElement" + } + } + }, + "CommissionSettlementItemDto": { + "required": [ + "id", + "settlementNo", + "referrerUserId", + "status", + "periodStart", + "periodEnd", + "sourceCount", + "paidUserCount", + "grossAmountCents", + "commissionAmountCents", + "reviewedAt", + "paidAt" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "settlementNo": { + "type": "string" + }, + "referrerUserId": { + "type": "string", + "format": "uuid" + }, + "status": { + "type": "string" + }, + "periodStart": { + "type": "string", + "format": "date" + }, + "periodEnd": { + "type": "string", + "format": "date" + }, + "sourceCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "paidUserCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "grossAmountCents": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "commissionAmountCents": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "reviewedAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "paidAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + } + } + }, + "CommissionSourceItem": { + "required": [ + "sourceType", + "sourceId", + "sourceNo", + "referrerUserId", + "studentUserId", + "grossAmountCents", + "commissionRate", + "commissionAmountCents", + "rateSource", + "settlementId" + ], + "type": "object", + "properties": { + "sourceType": { + "type": "string" + }, + "sourceId": { + "type": "string", + "format": "uuid" + }, + "sourceNo": { + "type": [ + "null", + "string" + ] + }, + "referrerUserId": { + "type": "string", + "format": "uuid" + }, + "studentUserId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "grossAmountCents": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "commissionRate": { + "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$", + "type": [ + "number", + "string" + ], + "format": "double" + }, + "commissionAmountCents": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "rateSource": { + "type": "string" + }, + "settlementId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + } + } + }, + "CommissionSummaryItem": { + "required": [ + "sourceCount", + "paidUserCount", + "grossAmountCents", + "commissionAmountCents" + ], + "type": "object", + "properties": { + "sourceCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "paidUserCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "grossAmountCents": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "commissionAmountCents": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + } + } + }, + "ConfirmManualPlatformPaymentDto": { + "required": [ + "paymentId", + "providerTradeNo", + "paidAt", + "reason" + ], + "type": "object", + "properties": { + "paymentId": { + "type": "string", + "format": "uuid" + }, + "providerTradeNo": { + "type": [ + "null", + "string" + ] + }, + "paidAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "reason": { + "type": "string" + } + }, + "description": "确认人工平台支付请求 DTO。" + }, + "ContentAssetAccessEventItem": { + "required": [ + "id", + "assetId", + "userId", + "actorRole", + "accessType", + "visibility", + "assetType", + "storageProvider", + "disposition", + "expiresInSeconds", + "signatureMode", + "result", + "denyCode", + "ipAddress", + "userAgent", + "metadata", + "createdAt" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "assetId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "userId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "actorRole": { + "$ref": "#/components/schemas/AssetAccessActorRole" + }, + "accessType": { + "$ref": "#/components/schemas/AssetAccessType" + }, + "visibility": { + "type": [ + "null", + "string" + ] + }, + "assetType": { + "type": [ + "null", + "string" + ] + }, + "storageProvider": { + "type": [ + "null", + "string" + ] + }, + "disposition": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/components/schemas/AssetAccessDisposition" + } + ] + }, + "expiresInSeconds": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "format": "int32" + }, + "signatureMode": { + "type": [ + "null", + "string" + ] + }, + "result": { + "$ref": "#/components/schemas/AssetAccessResult" + }, + "denyCode": { + "type": [ + "null", + "string" + ] + }, + "ipAddress": { + "type": [ + "null", + "string" + ] + }, + "userAgent": { + "type": [ + "null", + "string" + ] + }, + "metadata": { + "$ref": "#/components/schemas/JsonElement" + }, + "createdAt": { + "type": "string", + "format": "date-time" + } + } + }, + "ContentAssetAccessSummaryDto": { + "required": [ + "id", + "assetType", + "title", + "fileName", + "previewUrl", + "uploadStatus", + "securityScanStatus", + "previewStatus", + "visibility" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "assetType": { + "$ref": "#/components/schemas/ContentAssetType" + }, + "title": { + "type": [ + "null", + "string" + ] + }, + "fileName": { + "type": [ + "null", + "string" + ] + }, + "previewUrl": { + "type": [ + "null", + "string" + ] + }, + "uploadStatus": { + "$ref": "#/components/schemas/AssetUploadStatus" + }, + "securityScanStatus": { + "$ref": "#/components/schemas/AssetSecurityScanStatus" + }, + "previewStatus": { + "$ref": "#/components/schemas/AssetPreviewStatus" + }, + "visibility": { + "$ref": "#/components/schemas/ContentVisibility" + } + }, + "description": "内容资产访问摘要。" + }, + "ContentAssetCatalogItem": { + "required": [ + "id", + "legacyId", + "regionId", + "subjectId", + "categoryId", + "contentNodeId", + "assetKey", + "title", + "category", + "description", + "fileName", + "cdnUrl", + "isPublic", + "assetType", + "storageProvider", + "bucket", + "objectKey", + "mimeType", + "fileSizeBytes", + "checksumSha256", + "visibility", + "previewUrl", + "status", + "order", + "uploadStatus", + "verifiedAt", + "previewStatus", + "securityScanStatus", + "metadata" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "legacyId": { + "type": [ + "null", + "string" + ] + }, + "regionId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "subjectId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "categoryId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "contentNodeId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "assetKey": { + "type": [ + "null", + "string" + ] + }, + "title": { + "type": [ + "null", + "string" + ] + }, + "category": { + "type": [ + "null", + "string" + ] + }, + "description": { + "type": [ + "null", + "string" + ] + }, + "fileName": { + "type": [ + "null", + "string" + ] + }, + "cdnUrl": { + "type": [ + "null", + "string" + ] + }, + "isPublic": { + "type": "boolean" + }, + "assetType": { + "$ref": "#/components/schemas/ContentAssetType" + }, + "storageProvider": { + "$ref": "#/components/schemas/AssetStorageProvider" + }, + "bucket": { + "type": [ + "null", + "string" + ] + }, + "objectKey": { + "type": [ + "null", + "string" + ] + }, + "mimeType": { + "type": [ + "null", + "string" + ] + }, + "fileSizeBytes": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "format": "int64" + }, + "checksumSha256": { + "type": [ + "null", + "string" + ] + }, + "visibility": { + "$ref": "#/components/schemas/ContentVisibility" + }, + "previewUrl": { + "type": [ + "null", + "string" + ] + }, + "status": { + "$ref": "#/components/schemas/ContentStatus" + }, + "order": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "uploadStatus": { + "$ref": "#/components/schemas/AssetUploadStatus" + }, + "verifiedAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "previewStatus": { + "$ref": "#/components/schemas/AssetPreviewStatus" + }, + "securityScanStatus": { + "$ref": "#/components/schemas/AssetSecurityScanStatus" + }, + "metadata": { + "$ref": "#/components/schemas/JsonElement" + } + } + }, + "ContentAssetManagementItem": { + "required": [ + "id", + "legacyId", + "regionId", + "subjectId", + "categoryId", + "contentNodeId", + "assetKey", + "title", + "category", + "description", + "fileName", + "cdnUrl", + "isPublic", + "assetType", + "storageProvider", + "bucket", + "objectKey", + "mimeType", + "fileSizeBytes", + "checksumSha256", + "visibility", + "status", + "order", + "uploadStatus", + "verifiedAt", + "verifiedSizeBytes", + "verifiedChecksumSha256", + "previewStatus", + "securityScanStatus", + "metadata", + "createdAt", + "updatedAt" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "legacyId": { + "type": [ + "null", + "string" + ] + }, + "regionId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "subjectId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "categoryId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "contentNodeId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "assetKey": { + "type": [ + "null", + "string" + ] + }, + "title": { + "type": [ + "null", + "string" + ] + }, + "category": { + "type": [ + "null", + "string" + ] + }, + "description": { + "type": [ + "null", + "string" + ] + }, + "fileName": { + "type": [ + "null", + "string" + ] + }, + "cdnUrl": { + "type": [ + "null", + "string" + ] + }, + "isPublic": { + "type": "boolean" + }, + "assetType": { + "$ref": "#/components/schemas/ContentAssetType" + }, + "storageProvider": { + "$ref": "#/components/schemas/AssetStorageProvider" + }, + "bucket": { + "type": [ + "null", + "string" + ] + }, + "objectKey": { + "type": [ + "null", + "string" + ] + }, + "mimeType": { + "type": [ + "null", + "string" + ] + }, + "fileSizeBytes": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "format": "int64" + }, + "checksumSha256": { + "type": [ + "null", + "string" + ] + }, + "visibility": { + "$ref": "#/components/schemas/ContentVisibility" + }, + "status": { + "$ref": "#/components/schemas/ContentStatus" + }, + "order": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "uploadStatus": { + "$ref": "#/components/schemas/AssetUploadStatus" + }, + "verifiedAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "verifiedSizeBytes": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "format": "int64" + }, + "verifiedChecksumSha256": { + "type": [ + "null", + "string" + ] + }, + "previewStatus": { + "$ref": "#/components/schemas/AssetPreviewStatus" + }, + "securityScanStatus": { + "$ref": "#/components/schemas/AssetSecurityScanStatus" + }, + "metadata": { + "$ref": "#/components/schemas/JsonElement" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + } + } + }, + "ContentAssetSecurityScanEventItem": { + "required": [ + "id", + "assetId", + "provider", + "scanStatus", + "riskLevel", + "issueCodes", + "details", + "createdAt" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "assetId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "provider": { + "type": "string" + }, + "scanStatus": { + "$ref": "#/components/schemas/AssetSecurityScanStatus" + }, + "riskLevel": { + "$ref": "#/components/schemas/AssetSecurityRiskLevel" + }, + "issueCodes": { + "type": "array", + "items": { + "type": "string" + } + }, + "details": { + "$ref": "#/components/schemas/JsonElement" + }, + "createdAt": { + "type": "string", + "format": "date-time" + } + } + }, + "ContentAssetType": { + "type": "integer" + }, + "ContentEntryCatalogItem": { + "required": [ + "id", + "regionId", + "legacyId", + "entryKey", + "name", + "entryType", + "icon", + "route", + "description", + "visibility", + "accessRules", + "layoutConfig", + "order" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "regionId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "legacyId": { + "type": [ + "null", + "string" + ] + }, + "entryKey": { + "type": "string" + }, + "name": { + "type": "string" + }, + "entryType": { + "$ref": "#/components/schemas/ContentEntryType" + }, + "icon": { + "type": [ + "null", + "string" + ] + }, + "route": { + "type": [ + "null", + "string" + ] + }, + "description": { + "type": [ + "null", + "string" + ] + }, + "visibility": { + "$ref": "#/components/schemas/ContentVisibility" + }, + "accessRules": { + "$ref": "#/components/schemas/JsonElement" + }, + "layoutConfig": { + "$ref": "#/components/schemas/JsonElement" + }, + "order": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + } + } + }, + "ContentEntryManagementItem": { + "required": [ + "id", + "regionId", + "legacyId", + "entryKey", + "name", + "entryType", + "icon", + "route", + "description", + "visibility", + "accessRules", + "layoutConfig", + "order", + "isActive", + "createdAt", + "updatedAt" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "regionId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "legacyId": { + "type": [ + "null", + "string" + ] + }, + "entryKey": { + "type": "string" + }, + "name": { + "type": "string" + }, + "entryType": { + "$ref": "#/components/schemas/ContentEntryType" + }, + "icon": { + "type": [ + "null", + "string" + ] + }, + "route": { + "type": [ + "null", + "string" + ] + }, + "description": { + "type": [ + "null", + "string" + ] + }, + "visibility": { + "$ref": "#/components/schemas/ContentVisibility" + }, + "accessRules": { + "$ref": "#/components/schemas/JsonElement" + }, + "layoutConfig": { + "$ref": "#/components/schemas/JsonElement" + }, + "order": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "isActive": { + "type": "boolean" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + } + } + }, + "ContentEntryType": { + "type": "integer" + }, + "ContentImportIssueModel": { + "required": [ + "id", + "jobId", + "itemId", + "rowNo", + "severity", + "code", + "fieldPath", + "message", + "details" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "jobId": { + "type": "string", + "format": "uuid" + }, + "itemId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "rowNo": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "format": "int32" + }, + "severity": { + "$ref": "#/components/schemas/ImportIssueSeverity" + }, + "code": { + "type": "string" + }, + "fieldPath": { + "type": [ + "null", + "string" + ] + }, + "message": { + "type": "string" + }, + "details": { + "$ref": "#/components/schemas/JsonElement" + } + } + }, + "ContentImportItemModel": { + "required": [ + "id", + "jobId", + "rowNo", + "externalId", + "status", + "targetType", + "targetId", + "sourcePayload", + "normalizedPayload", + "contentHash", + "issuesCount" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "jobId": { + "type": "string", + "format": "uuid" + }, + "rowNo": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "externalId": { + "type": [ + "null", + "string" + ] + }, + "status": { + "$ref": "#/components/schemas/ContentImportItemStatus" + }, + "targetType": { + "type": [ + "null", + "string" + ] + }, + "targetId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "sourcePayload": { + "$ref": "#/components/schemas/JsonElement" + }, + "normalizedPayload": { + "$ref": "#/components/schemas/JsonElement" + }, + "contentHash": { + "type": [ + "null", + "string" + ] + }, + "issuesCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + } + } + }, + "ContentImportItemStatus": { + "type": "integer" + }, + "ContentImportJobDetail": { + "required": [ + "job", + "items", + "issues" + ], + "type": "object", + "properties": { + "job": { + "$ref": "#/components/schemas/ContentImportJobItem" + }, + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ContentImportItemModel" + } + }, + "issues": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ContentImportIssueModel" + } + } + } + }, + "ContentImportJobItem": { + "required": [ + "id", + "targetRegionId", + "targetSubjectId", + "targetCategoryId", + "targetContentNodeId", + "targetQuestionBankId", + "importType", + "sourceFormat", + "status", + "sourceName", + "sourceHash", + "dryRun", + "totalCount", + "validCount", + "errorCount", + "warningCount", + "insertedCount", + "updatedCount", + "skippedCount", + "summary", + "errorMessage", + "startedAt", + "finishedAt", + "createdAt", + "updatedAt" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "targetRegionId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "targetSubjectId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "targetCategoryId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "targetContentNodeId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "targetQuestionBankId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "importType": { + "$ref": "#/components/schemas/ContentImportType" + }, + "sourceFormat": { + "$ref": "#/components/schemas/ImportSourceFormat" + }, + "status": { + "$ref": "#/components/schemas/ContentImportStatus" + }, + "sourceName": { + "type": [ + "null", + "string" + ] + }, + "sourceHash": { + "type": [ + "null", + "string" + ] + }, + "dryRun": { + "type": "boolean" + }, + "totalCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "validCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "errorCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "warningCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "insertedCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "updatedCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "skippedCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "summary": { + "$ref": "#/components/schemas/JsonElement" + }, + "errorMessage": { + "type": [ + "null", + "string" + ] + }, + "startedAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "finishedAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + } + } + }, + "ContentImportStatus": { + "type": "integer" + }, + "ContentImportType": { + "type": "integer" + }, + "ContentManagementResultOfContentAssetManagementItem": { + "required": [ + "item" + ], + "type": "object", + "properties": { + "item": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/components/schemas/ContentAssetManagementItem" + } + ] + } + } + }, + "ContentManagementResultOfContentEntryManagementItem": { + "required": [ + "item" + ], + "type": "object", + "properties": { + "item": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/components/schemas/ContentEntryManagementItem" + } + ] + } + } + }, + "ContentManagementResultOfContentNodeManagementItem": { + "required": [ + "item" + ], + "type": "object", + "properties": { + "item": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/components/schemas/ContentNodeManagementItem" + } + ] + } + } + }, + "ContentManagementResultOfHandbookChapter": { + "required": [ + "item" + ], + "type": "object", + "properties": { + "item": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/components/schemas/HandbookChapter" + } + ] + } + } + }, + "ContentManagementResultOfHandbookEntry": { + "required": [ + "item" + ], + "type": "object", + "properties": { + "item": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/components/schemas/HandbookEntry" + } + ] + } + } + }, + "ContentManagementResultOfHandbookSubject": { + "required": [ + "item" + ], + "type": "object", + "properties": { + "item": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/components/schemas/HandbookSubject" + } + ] + } + } + }, + "ContentManagementResultOfMajor": { + "required": [ + "item" + ], + "type": "object", + "properties": { + "item": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/components/schemas/Major" + } + ] + } + } + }, + "ContentManagementResultOfOperationContentItem": { + "required": [ + "item" + ], + "type": "object", + "properties": { + "item": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/components/schemas/OperationContentItem" + } + ] + } + } + }, + "ContentManagementResultOfPracticeBlueprintManagementItem": { + "required": [ + "item" + ], + "type": "object", + "properties": { + "item": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/components/schemas/PracticeBlueprintManagementItem" + } + ] + } + } + }, + "ContentManagementResultOfQuestionCollectionManagementItem": { + "required": [ + "item" + ], + "type": "object", + "properties": { + "item": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/components/schemas/QuestionCollectionManagementItem" + } + ] + } + } + }, + "ContentManagementResultOfQuestionManagementItem": { + "required": [ + "item" + ], + "type": "object", + "properties": { + "item": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/components/schemas/QuestionManagementItem" + } + ] + } + } + }, + "ContentManagementResultOfQuestionVideoManagementItem": { + "required": [ + "item" + ], + "type": "object", + "properties": { + "item": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/components/schemas/QuestionVideoManagementItem" + } + ] + } + } + }, + "ContentManagementResultOfSchool": { + "required": [ + "item" + ], + "type": "object", + "properties": { + "item": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/components/schemas/School" + } + ] + } + } + }, + "ContentManagementResultOfScorelineField": { + "required": [ + "item" + ], + "type": "object", + "properties": { + "item": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/components/schemas/ScorelineField" + } + ] + } + } + }, + "ContentManagementResultOfScorelineRecord": { + "required": [ + "item" + ], + "type": "object", + "properties": { + "item": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/components/schemas/ScorelineRecord" + } + ] + } + } + }, + "ContentManagementResultOfTenantAdminBadgeGrantItem": { + "required": [ + "item" + ], + "type": "object", + "properties": { + "item": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/components/schemas/TenantAdminBadgeGrantItem" + } + ] + } + } + }, + "ContentManagementResultOfTenantAdminBadgeItem": { + "required": [ + "item" + ], + "type": "object", + "properties": { + "item": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/components/schemas/TenantAdminBadgeItem" + } + ] + } + } + }, + "ContentManagementResultOfTenantAdminClassItem": { + "required": [ + "item" + ], + "type": "object", + "properties": { + "item": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/components/schemas/TenantAdminClassItem" + } + ] + } + } + }, + "ContentManagementResultOfTenantAdminClassMemberItem": { + "required": [ + "item" + ], + "type": "object", + "properties": { + "item": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/components/schemas/TenantAdminClassMemberItem" + } + ] + } + } + }, + "ContentManagementResultOfTenantAdminFeedbackItem": { + "required": [ + "item" + ], + "type": "object", + "properties": { + "item": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/components/schemas/TenantAdminFeedbackItem" + } + ] + } + } + }, + "ContentManagementResultOfTenantAdminMemberItem": { + "required": [ + "item" + ], + "type": "object", + "properties": { + "item": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/components/schemas/TenantAdminMemberItem" + } + ] + } + } + }, + "ContentManagementResultOfTenantAdminNotificationItem": { + "required": [ + "item" + ], + "type": "object", + "properties": { + "item": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/components/schemas/TenantAdminNotificationItem" + } + ] + } + } + }, + "ContentManagementResultOfTenantAdminStudentFollowupItem": { + "required": [ + "item" + ], + "type": "object", + "properties": { + "item": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/components/schemas/TenantAdminStudentFollowupItem" + } + ] + } + } + }, + "ContentManagementResultOfTenantAdminStudentItem": { + "required": [ + "item" + ], + "type": "object", + "properties": { + "item": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/components/schemas/TenantAdminStudentItem" + } + ] + } + } + }, + "ContentManagementResultOfTenantAdminStudentNoteItem": { + "required": [ + "item" + ], + "type": "object", + "properties": { + "item": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/components/schemas/TenantAdminStudentNoteItem" + } + ] + } + } + }, + "ContentManagementResultOfTenantAdminStudentStatusItem": { + "required": [ + "item" + ], + "type": "object", + "properties": { + "item": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/components/schemas/TenantAdminStudentStatusItem" + } + ] + } + } + }, + "ContentManagementResultOfTenantBrandingItem": { + "required": [ + "item" + ], + "type": "object", + "properties": { + "item": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/components/schemas/TenantBrandingItem" + } + ] + } + } + }, + "ContentManagementResultOfTenantDomainItem": { + "required": [ + "item" + ], + "type": "object", + "properties": { + "item": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/components/schemas/TenantDomainItem" + } + ] + } + } + }, + "ContentManagementResultOfTenantIdentityProviderItem": { + "required": [ + "item" + ], + "type": "object", + "properties": { + "item": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/components/schemas/TenantIdentityProviderItem" + } + ] + } + } + }, + "ContentManagementResultOfTenantSettingsItem": { + "required": [ + "item" + ], + "type": "object", + "properties": { + "item": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/components/schemas/TenantSettingsItem" + } + ] + } + } + }, + "ContentManagementResultOfTenantSupervisionRuleItem": { + "required": [ + "item" + ], + "type": "object", + "properties": { + "item": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/components/schemas/TenantSupervisionRuleItem" + } + ] + } + } + }, + "ContentManagementResultOfTenantThemeItem": { + "required": [ + "item" + ], + "type": "object", + "properties": { + "item": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/components/schemas/TenantThemeItem" + } + ] + } + } + }, + "ContentManagementResultOfVideoManagementItem": { + "required": [ + "item" + ], + "type": "object", + "properties": { + "item": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/components/schemas/VideoManagementItem" + } + ] + } + } + }, + "ContentManagementResultOfVocabularyUnit": { + "required": [ + "item" + ], + "type": "object", + "properties": { + "item": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/components/schemas/VocabularyUnit" + } + ] + } + } + }, + "ContentManagementResultOfVocabularyWord": { + "required": [ + "item" + ], + "type": "object", + "properties": { + "item": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/components/schemas/VocabularyWord" + } + ] + } + } + }, + "ContentMarkerType": { + "type": "integer" + }, + "ContentNodeCatalogItem": { + "required": [ + "id", + "entryId", + "regionId", + "parentId", + "legacyId", + "nodeKey", + "name", + "nodeType", + "markerType", + "markerConfig", + "path", + "depth", + "order", + "isSelectable", + "isLeaf", + "accessRules", + "metadata" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "entryId": { + "type": "string", + "format": "uuid" + }, + "regionId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "parentId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "legacyId": { + "type": [ + "null", + "string" + ] + }, + "nodeKey": { + "type": [ + "null", + "string" + ] + }, + "name": { + "type": "string" + }, + "nodeType": { + "$ref": "#/components/schemas/ContentNodeType" + }, + "markerType": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/components/schemas/ContentMarkerType" + } + ] + }, + "markerConfig": { + "$ref": "#/components/schemas/JsonElement" + }, + "path": { + "type": [ + "null", + "string" + ] + }, + "depth": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "order": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "isSelectable": { + "type": "boolean" + }, + "isLeaf": { + "type": "boolean" + }, + "accessRules": { + "$ref": "#/components/schemas/JsonElement" + }, + "metadata": { + "$ref": "#/components/schemas/JsonElement" + } + } + }, + "ContentNodeManagementItem": { + "required": [ + "id", + "entryId", + "regionId", + "parentId", + "legacyId", + "nodeKey", + "name", + "nodeType", + "markerType", + "markerConfig", + "path", + "depth", + "order", + "isActive", + "isSelectable", + "isLeaf", + "accessRules", + "metadata", + "createdAt", + "updatedAt" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "entryId": { + "type": "string", + "format": "uuid" + }, + "regionId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "parentId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "legacyId": { + "type": [ + "null", + "string" + ] + }, + "nodeKey": { + "type": [ + "null", + "string" + ] + }, + "name": { + "type": "string" + }, + "nodeType": { + "$ref": "#/components/schemas/ContentNodeType" + }, + "markerType": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/components/schemas/ContentMarkerType" + } + ] + }, + "markerConfig": { + "$ref": "#/components/schemas/JsonElement" + }, + "path": { + "type": [ + "null", + "string" + ] + }, + "depth": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "order": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "isActive": { + "type": "boolean" + }, + "isSelectable": { + "type": "boolean" + }, + "isLeaf": { + "type": "boolean" + }, + "accessRules": { + "$ref": "#/components/schemas/JsonElement" + }, + "metadata": { + "$ref": "#/components/schemas/JsonElement" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + } + } + }, + "ContentNodeType": { + "type": "integer" + }, + "ContentStatus": { + "type": "integer" + }, + "ContentVisibility": { + "type": "integer" + }, + "Coupon": { + "type": "object", + "properties": { + "planId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "legacyId": { + "type": [ + "null", + "string" + ] + }, + "code": { + "type": "string" + }, + "discountType": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/components/schemas/DiscountType" + } + ] + }, + "discountValue": { + "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$", + "type": [ + "null", + "number", + "string" + ], + "format": "double" + }, + "validFrom": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "validTo": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "maxUses": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "format": "int32" + }, + "usedCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "source": { + "type": [ + "null", + "string" + ] + }, + "remark": { + "type": [ + "null", + "string" + ] + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "tenantId": { + "type": "string", + "format": "uuid" + }, + "id": { + "type": "string", + "format": "uuid" + } + } + }, + "CouponRedemption": { + "type": "object", + "properties": { + "couponId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "userId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "planId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "orderId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "regionId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "legacyId": { + "type": [ + "null", + "string" + ] + }, + "couponCode": { + "type": [ + "null", + "string" + ] + }, + "status": { + "$ref": "#/components/schemas/CouponRedemptionStatus" + }, + "discountAppliedCents": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "format": "int32" + }, + "source": { + "type": [ + "null", + "string" + ] + }, + "remark": { + "type": [ + "null", + "string" + ] + }, + "claimedAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "usedAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "tenantId": { + "type": "string", + "format": "uuid" + }, + "id": { + "type": "string", + "format": "uuid" + } + } + }, + "CouponRedemptionStatus": { + "type": "integer" + }, + "CreateAdjustmentVoucherDto": { + "required": [ + "reason" + ], + "type": "object", + "properties": { + "issueId": { + "type": [ + "null", + "string" + ], + "description": "工单 ID。", + "format": "uuid" + }, + "batchId": { + "type": [ + "null", + "string" + ], + "description": "批次 ID。", + "format": "uuid" + }, + "itemId": { + "type": [ + "null", + "string" + ], + "description": "兑换项 ID。", + "format": "uuid" + }, + "orderId": { + "type": [ + "null", + "string" + ], + "description": "订单 ID。", + "format": "uuid" + }, + "paymentId": { + "type": [ + "null", + "string" + ], + "description": "支付记录 ID。", + "format": "uuid" + }, + "refundRequestId": { + "type": [ + "null", + "string" + ], + "description": "退款申请 ID。", + "format": "uuid" + }, + "direction": { + "description": "方向。", + "$ref": "#/components/schemas/CommerceAdjustmentDirection" + }, + "amountCents": { + "maximum": 2147483647, + "minimum": 1, + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "description": "金额,单位为分。", + "format": "int32" + }, + "currency": { + "maxLength": 10, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "币种。" + }, + "reason": { + "maxLength": 1000, + "minLength": 0, + "type": "string", + "description": "原因。" + }, + "proofAssetKey": { + "maxLength": 500, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "证明资产键。" + }, + "metadata": { + "description": "扩展元数据。", + "$ref": "#/components/schemas/JsonElement" + } + }, + "description": "创建调账凭证请求 DTO。" + }, + "CreateBackgroundJobDto": { + "type": "object", + "properties": { + "jobType": { + "type": "string", + "description": "任务类型。" + }, + "payload": { + "description": "任务载荷。", + "$ref": "#/components/schemas/JsonElement" + }, + "runAfter": { + "type": [ + "null", + "string" + ], + "description": "计划运行时间。", + "format": "date-time" + }, + "maxRetries": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "description": "最大重试次数。", + "format": "int32" + } + }, + "description": "创建租户后台任务请求。" + }, + "CreateCodeBatchDto": { + "required": [ + "name" + ], + "type": "object", + "properties": { + "name": { + "maxLength": 200, + "minLength": 0, + "type": "string", + "description": "名称。" + }, + "totalCount": { + "maximum": 1000, + "minimum": 1, + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "description": "总数量。", + "format": "int32" + }, + "days": { + "maximum": 3650, + "minimum": 1, + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "description": "天数。", + "format": "int32" + }, + "regionId": { + "type": [ + "null", + "string" + ], + "description": "地区 ID。", + "format": "uuid" + }, + "saleType": { + "maxLength": 50, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "售卖类型。" + }, + "channel": { + "maxLength": 100, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "渠道。" + }, + "defaultUnitPriceCents": { + "maximum": 2147483647, + "minimum": 0, + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "description": "默认单价,单位为分。", + "format": "int32" + }, + "costPriceCents": { + "maximum": 2147483647, + "minimum": 0, + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "description": "成本价,单位为分。", + "format": "int32" + }, + "remark": { + "maxLength": 1000, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "备注。" + } + }, + "description": "创建编码批次请求 DTO。" + }, + "CreateCommerceOrderDto": { + "required": [ + "planId" + ], + "type": "object", + "properties": { + "planId": { + "type": "string", + "description": "套餐 ID。", + "format": "uuid" + }, + "quantity": { + "maximum": 99, + "minimum": 1, + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "description": "数量。", + "format": "int32" + }, + "payMethod": { + "maxLength": 50, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "支付方式。" + }, + "payProvider": { + "maxLength": 50, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "支付渠道。" + }, + "regionId": { + "type": [ + "null", + "string" + ], + "description": "地区 ID。", + "format": "uuid" + }, + "couponCode": { + "maxLength": 100, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "优惠券码。" + }, + "couponRedemptionId": { + "type": [ + "null", + "string" + ], + "description": "优惠券领取记录 ID。", + "format": "uuid" + } + }, + "description": "创建交易订单请求 DTO。" + }, + "CreateCommercePaymentDto": { + "required": [ + "orderNo", + "provider", + "method" + ], + "type": "object", + "properties": { + "orderNo": { + "maxLength": 100, + "minLength": 0, + "type": "string", + "description": "订单号。" + }, + "provider": { + "maxLength": 50, + "minLength": 0, + "type": "string", + "description": "服务提供方。" + }, + "method": { + "maxLength": 50, + "minLength": 0, + "type": "string", + "description": "方式。" + }, + "openId": { + "maxLength": 255, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "微信或支付渠道 openid。" + }, + "returnUrl": { + "maxLength": 2048, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "支付完成返回地址。" + }, + "quitUrl": { + "maxLength": 2048, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "支付取消返回地址。" + } + }, + "description": "创建交易支付请求 DTO。" + }, + "CreateCommissionProofDto": { + "required": [ + "settlementId" + ], + "type": "object", + "properties": { + "settlementId": { + "type": "string", + "description": "结算单 ID。", + "format": "uuid" + }, + "proofType": { + "maxLength": 50, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "凭证类型。" + }, + "title": { + "maxLength": 200, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "标题。" + }, + "description": { + "maxLength": 2000, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "说明。" + }, + "assetId": { + "type": [ + "null", + "string" + ], + "description": "资产 ID。", + "format": "uuid" + }, + "externalUrl": { + "maxLength": 2048, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "外部链接。" + }, + "amountCents": { + "maximum": 2147483647, + "minimum": 0, + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "description": "金额,单位为分。", + "format": "int32" + }, + "paymentMethod": { + "maxLength": 100, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "支付方式。" + }, + "paymentAccount": { + "maxLength": 200, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "收款账号。" + }, + "paidAt": { + "type": [ + "null", + "string" + ], + "description": "支付时间。", + "format": "date-time" + }, + "metadata": { + "oneOf": [ + { + "type": "null" + }, + { + "description": "扩展元数据。", + "$ref": "#/components/schemas/JsonElement" + } + ] + } + }, + "description": "创建佣金结算凭证请求。" + }, + "CreatePlatformBillingOrderDto": { + "required": [ + "quoteId", + "idempotencyKey" + ], + "type": "object", + "properties": { + "quoteId": { + "type": "string", + "format": "uuid" + }, + "idempotencyKey": { + "type": "string" + } + }, + "description": "创建平台账务订单请求 DTO。" + }, + "CreatePlatformBillingPaymentDto": { + "required": [ + "provider", + "method", + "idempotencyKey", + "openId", + "returnUrl", + "quitUrl" + ], + "type": "object", + "properties": { + "provider": { + "type": "string" + }, + "method": { + "type": "string" + }, + "idempotencyKey": { + "type": "string" + }, + "openId": { + "type": [ + "null", + "string" + ] + }, + "returnUrl": { + "type": [ + "null", + "string" + ] + }, + "quitUrl": { + "type": [ + "null", + "string" + ] + } + }, + "description": "创建平台账务支付请求 DTO。" + }, + "CreatePlatformBillingQuoteDto": { + "required": [ + "baseOfferingVersionId", + "addOnOfferingVersionIds", + "purpose", + "idempotencyKey" + ], + "type": "object", + "properties": { + "baseOfferingVersionId": { + "type": "string", + "format": "uuid" + }, + "addOnOfferingVersionIds": { + "type": [ + "null", + "array" + ], + "items": { + "type": "string", + "format": "uuid" + } + }, + "purpose": { + "$ref": "#/components/schemas/PlatformBillingOrderPurpose" + }, + "idempotencyKey": { + "type": "string" + } + }, + "description": "创建平台账务报价请求 DTO。" + }, + "CreatePlatformTenantDto": { + "required": [ + "slug", + "name", + "ownerName", + "temporaryPassword" + ], + "type": "object", + "properties": { + "slug": { + "maxLength": 100, + "minLength": 0, + "type": "string", + "description": "短编码。" + }, + "name": { + "maxLength": 200, + "minLength": 0, + "type": "string", + "description": "名称。" + }, + "legalName": { + "maxLength": 300, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "法定名称。" + }, + "status": { + "description": "状态。", + "$ref": "#/components/schemas/TenantStatus" + }, + "billingStatus": { + "description": "账务状态。", + "$ref": "#/components/schemas/BillingStatus" + }, + "metadata": { + "description": "扩展元数据。", + "$ref": "#/components/schemas/JsonElement" + }, + "ownerEmail": { + "maxLength": 320, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "租户负责人邮箱。" + }, + "ownerPhone": { + "maxLength": 32, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "租户负责人手机号。" + }, + "ownerName": { + "maxLength": 100, + "minLength": 0, + "type": "string", + "description": "租户负责人姓名。" + }, + "temporaryPassword": { + "maxLength": 200, + "minLength": 12, + "type": "string", + "description": "临时密码。" + } + }, + "description": "创建平台租户请求 DTO。" + }, + "CreatePointExchangeOrderDto": { + "required": [ + "itemId" + ], + "type": "object", + "properties": { + "itemId": { + "type": "string", + "description": "兑换项 ID。", + "format": "uuid" + } + }, + "description": "创建积分兑换订单请求 DTO。" + }, + "CreatePracticeSessionDto": { + "type": "object", + "properties": { + "mode": { + "maxLength": 50, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "模式。" + }, + "targetType": { + "maxLength": 50, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "目标类型。" + }, + "targetId": { + "type": [ + "null", + "string" + ], + "description": "目标 ID。", + "format": "uuid" + }, + "blueprintId": { + "type": [ + "null", + "string" + ], + "description": "练习蓝图 ID。", + "format": "uuid" + }, + "collectionId": { + "type": [ + "null", + "string" + ], + "description": "题集 ID。", + "format": "uuid" + }, + "entryId": { + "type": [ + "null", + "string" + ], + "description": "内容入口 ID。", + "format": "uuid" + }, + "contentNodeId": { + "type": [ + "null", + "string" + ], + "description": "内容节点 ID。", + "format": "uuid" + }, + "questionLimit": { + "maximum": 500, + "minimum": 1, + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "description": "题目数量上限。", + "format": "int32" + }, + "durationMinutes": { + "maximum": 1440, + "minimum": 1, + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "description": "时长,单位为分钟。", + "format": "int32" + }, + "totalScore": { + "maximum": 99999, + "minimum": 0, + "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$", + "type": [ + "null", + "number", + "string" + ], + "description": "总分。", + "format": "double" + }, + "metadata": { + "description": "扩展元数据。", + "$ref": "#/components/schemas/JsonElement" + } + }, + "description": "创建练习会话请求 DTO。" + }, + "CreateReconciliationBatchDto": { + "required": [ + "provider", + "sourceHash" + ], + "type": "object", + "properties": { + "provider": { + "maxLength": 50, + "minLength": 0, + "type": "string", + "description": "服务提供方。" + }, + "billDate": { + "type": "string", + "description": "账单日期。", + "format": "date" + }, + "billType": { + "description": "账单类型。", + "$ref": "#/components/schemas/ReconciliationBillType" + }, + "source": { + "description": "来源。", + "$ref": "#/components/schemas/ReconciliationSource" + }, + "sourceName": { + "maxLength": 200, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "来源名称。" + }, + "sourceHash": { + "maxLength": 200, + "minLength": 0, + "type": "string", + "description": "来源哈希。" + }, + "metadata": { + "description": "扩展元数据。", + "$ref": "#/components/schemas/JsonElement" + } + }, + "description": "创建对账批次请求 DTO。" + }, + "CreateRefundRequestDto": { + "required": [ + "orderId" + ], + "type": "object", + "properties": { + "orderId": { + "type": "string", + "description": "订单 ID。", + "format": "uuid" + }, + "paymentId": { + "type": [ + "null", + "string" + ], + "description": "支付记录 ID。", + "format": "uuid" + }, + "amountCents": { + "maximum": 2147483647, + "minimum": 1, + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "description": "金额,单位为分。", + "format": "int32" + }, + "reason": { + "maxLength": 1000, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "原因。" + }, + "entitlementAction": { + "description": "权益动作。", + "$ref": "#/components/schemas/RefundEntitlementAction" + }, + "metadata": { + "description": "扩展元数据。", + "$ref": "#/components/schemas/JsonElement" + } + }, + "description": "创建退款Request请求 DTO。" + }, + "CreateTaxonomyNodeDto": { + "required": [ + "nodeType", + "code", + "name" + ], + "type": "object", + "properties": { + "parentId": { + "type": [ + "null", + "string" + ], + "description": "父节点 ID。", + "format": "uuid" + }, + "parentSource": { + "oneOf": [ + { + "type": "null" + }, + { + "description": "父级来源。", + "$ref": "#/components/schemas/QuestionSource" + } + ] + }, + "nodeType": { + "description": "节点Type。", + "$ref": "#/components/schemas/TaxonomyNodeType" + }, + "code": { + "maxLength": 100, + "minLength": 0, + "type": "string", + "description": "编码。" + }, + "name": { + "maxLength": 300, + "minLength": 0, + "type": "string", + "description": "名称。" + }, + "sortOrder": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "description": "排序值。", + "format": "int32" + }, + "metadata": { + "description": "扩展元数据。", + "$ref": "#/components/schemas/JsonElement" + } + }, + "description": "创建分类节点请求 DTO。" + }, + "CreateTenantDomainDto": { + "required": [ + "host" + ], + "type": "object", + "properties": { + "host": { + "type": "string", + "description": "访问域名。" + }, + "domainType": { + "type": [ + "null", + "string" + ], + "description": "域名类型。" + }, + "isPrimary": { + "type": "boolean", + "description": "是否主域名。" + } + }, + "description": "创建租户域名请求 DTO。" + }, + "CrmConfigItem": { + "required": [ + "id", + "enabled", + "url", + "secretRef", + "assignmentMode", + "assignmentPool", + "formName", + "examType", + "timeoutSeconds", + "delaySeconds", + "updatedAt" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "enabled": { + "type": "boolean" + }, + "url": { + "type": [ + "null", + "string" + ] + }, + "secretRef": { + "type": [ + "null", + "string" + ] + }, + "assignmentMode": { + "type": "string" + }, + "assignmentPool": { + "$ref": "#/components/schemas/JsonElement" + }, + "formName": { + "type": [ + "null", + "string" + ] + }, + "examType": { + "type": [ + "null", + "string" + ] + }, + "timeoutSeconds": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "format": "int32" + }, + "delaySeconds": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "format": "int32" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + } + } + }, + "CrmDeadLetterResult": { + "required": [ + "summary", + "items" + ], + "type": "object", + "properties": { + "summary": { + "$ref": "#/components/schemas/CrmDeadLetterSummary" + }, + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/CrmQueueItem" + } + } + } + }, + "CrmDeadLetterSummary": { + "required": [ + "failed", + "discarded", + "total", + "oldestOpenAt" + ], + "type": "object", + "properties": { + "failed": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "discarded": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "total": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "oldestOpenAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + } + } + }, + "CrmListOfCrmQueueItem": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/CrmQueueItem" + } + } + } + }, + "CrmListOfCrmQueueLogItem": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/CrmQueueLogItem" + } + } + } + }, + "CrmQueueActionDto": { + "required": [ + "queueId" + ], + "type": "object", + "properties": { + "queueId": { + "type": "string", + "description": "队列任务 ID。", + "format": "uuid" + }, + "action": { + "maxLength": 50, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "操作。" + }, + "note": { + "maxLength": 500, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "备注。" + }, + "metadata": { + "oneOf": [ + { + "type": "null" + }, + { + "description": "扩展元数据。", + "$ref": "#/components/schemas/JsonElement" + } + ] + } + }, + "description": "CRM队列Action请求 DTO。" + }, + "CrmQueueItem": { + "required": [ + "id", + "status", + "attempts", + "leadId", + "recordId", + "source", + "provider", + "lastError", + "scheduledAt", + "nextAttemptAt", + "payload" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "status": { + "type": "string" + }, + "attempts": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "leadId": { + "type": [ + "null", + "string" + ] + }, + "recordId": { + "type": [ + "null", + "string" + ] + }, + "source": { + "type": [ + "null", + "string" + ] + }, + "provider": { + "type": [ + "null", + "string" + ] + }, + "lastError": { + "type": [ + "null", + "string" + ] + }, + "scheduledAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "nextAttemptAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "payload": { + "$ref": "#/components/schemas/JsonElement" + } + } + }, + "CrmQueueLogItem": { + "required": [ + "id", + "queueId", + "recordId", + "leadId", + "httpCode", + "outcome", + "errorMessage", + "operation", + "requestPayload", + "responseSummary", + "createdAt" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "queueId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "recordId": { + "type": [ + "null", + "string" + ] + }, + "leadId": { + "type": [ + "null", + "string" + ] + }, + "httpCode": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "format": "int32" + }, + "outcome": { + "type": "string" + }, + "errorMessage": { + "type": [ + "null", + "string" + ] + }, + "operation": { + "type": [ + "null", + "string" + ] + }, + "requestPayload": { + "$ref": "#/components/schemas/JsonElement" + }, + "responseSummary": { + "type": [ + "null", + "string" + ] + }, + "createdAt": { + "type": "string", + "format": "date-time" + } + } + }, + "CrmQueuePreviewItem": { + "required": [ + "id", + "status", + "source" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "status": { + "type": "string" + }, + "source": { + "type": [ + "null", + "string" + ] + } + } + }, + "CrmWebhookLog": { + "type": "object", + "properties": { + "legacyId": { + "type": [ + "null", + "string" + ] + }, + "recordId": { + "type": [ + "null", + "string" + ] + }, + "leadId": { + "type": [ + "null", + "string" + ] + }, + "httpCode": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "format": "int32" + }, + "outcome": { + "type": [ + "null", + "string" + ] + }, + "errorMessage": { + "type": [ + "null", + "string" + ] + }, + "requestBody": { + "type": [ + "null", + "string" + ] + }, + "requestPayload": { + "$ref": "#/components/schemas/JsonElement" + }, + "responseSummary": { + "type": [ + "null", + "string" + ] + }, + "signedAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "attempt": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "format": "int32" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "tenantId": { + "type": "string", + "format": "uuid" + }, + "id": { + "type": "string", + "format": "uuid" + } + } + }, + "CrmWebhookQueueItem": { + "type": "object", + "properties": { + "legacyId": { + "type": [ + "null", + "string" + ] + }, + "recordId": { + "type": [ + "null", + "string" + ] + }, + "leadId": { + "type": [ + "null", + "string" + ] + }, + "source": { + "type": [ + "null", + "string" + ] + }, + "provider": { + "type": [ + "null", + "string" + ] + }, + "status": { + "$ref": "#/components/schemas/CrmWebhookQueueStatus" + }, + "scheduledAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "attempts": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "nextAttemptAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "lastAttemptAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "lastError": { + "type": [ + "null", + "string" + ] + }, + "lastHttpCode": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "format": "int32" + }, + "lastResponseSummary": { + "type": [ + "null", + "string" + ] + }, + "sentAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "idempotencyKey": { + "type": [ + "null", + "string" + ] + }, + "targetUrl": { + "type": [ + "null", + "string" + ] + }, + "payload": { + "$ref": "#/components/schemas/JsonElement" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "tenantId": { + "type": "string", + "format": "uuid" + }, + "id": { + "type": "string", + "format": "uuid" + } + } + }, + "CrmWebhookQueueStatus": { + "type": "integer" + }, + "CurrentEntitlementItem": { + "required": [ + "isActive", + "entitlementType", + "startsAt", + "expiresAt", + "status", + "daysLeft" + ], + "type": "object", + "properties": { + "isActive": { + "type": "boolean" + }, + "entitlementType": { + "type": "string" + }, + "startsAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "expiresAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "status": { + "type": "string" + }, + "daysLeft": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "format": "int32" + } + } + }, + "CurrentTenantResponse": { + "required": [ + "tenantId", + "tenantName", + "tenantSlug", + "status", + "role" + ], + "type": "object", + "properties": { + "tenantId": { + "type": "string", + "description": "租户 ID。", + "format": "uuid" + }, + "tenantName": { + "type": "string", + "description": "租户名称。" + }, + "tenantSlug": { + "type": "string", + "description": "租户编码。" + }, + "status": { + "description": "租户状态。", + "$ref": "#/components/schemas/TenantStatus" + }, + "role": { + "description": "当前用户在租户内的角色。", + "$ref": "#/components/schemas/TenantRole" + } + }, + "description": "当前请求租户和当前用户在该租户内的权限摘要。" + }, + "DirectHandbookChapterDto": { + "required": [ + "name" + ], + "type": "object", + "properties": { + "id": { + "type": [ + "null", + "string" + ], + "description": "ID。", + "format": "uuid" + }, + "subjectId": { + "type": [ + "null", + "string" + ], + "description": "科目 ID。", + "format": "uuid" + }, + "entryId": { + "type": [ + "null", + "string" + ], + "description": "内容入口 ID。", + "format": "uuid" + }, + "contentNodeId": { + "type": [ + "null", + "string" + ], + "description": "内容节点 ID。", + "format": "uuid" + }, + "legacyId": { + "type": [ + "null", + "string" + ], + "description": "历史系统 ID。" + }, + "name": { + "type": "string", + "description": "名称。" + }, + "description": { + "type": [ + "null", + "string" + ], + "description": "说明。" + }, + "order": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "description": "显示顺序。", + "format": "int32" + }, + "isActive": { + "type": [ + "null", + "boolean" + ], + "description": "是否启用。" + }, + "metadata": { + "description": "扩展元数据。", + "$ref": "#/components/schemas/JsonElement" + } + }, + "description": "管理侧知识手册章节写入请求。" + }, + "DirectHandbookEntryDto": { + "required": [ + "title" + ], + "type": "object", + "properties": { + "id": { + "type": [ + "null", + "string" + ], + "description": "ID。", + "format": "uuid" + }, + "chapterId": { + "type": [ + "null", + "string" + ], + "description": "章节 ID。", + "format": "uuid" + }, + "entryId": { + "type": [ + "null", + "string" + ], + "description": "内容入口 ID。", + "format": "uuid" + }, + "contentNodeId": { + "type": [ + "null", + "string" + ], + "description": "内容节点 ID。", + "format": "uuid" + }, + "legacyId": { + "type": [ + "null", + "string" + ], + "description": "历史系统 ID。" + }, + "title": { + "type": "string", + "description": "标题。" + }, + "summary": { + "type": [ + "null", + "string" + ], + "description": "摘要。" + }, + "content": { + "type": [ + "null", + "string" + ], + "description": "内容。" + }, + "tags": { + "description": "标签列表。", + "$ref": "#/components/schemas/JsonElement" + }, + "order": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "description": "显示顺序。", + "format": "int32" + }, + "isActive": { + "type": [ + "null", + "boolean" + ], + "description": "是否启用。" + }, + "metadata": { + "description": "扩展元数据。", + "$ref": "#/components/schemas/JsonElement" + } + }, + "description": "管理侧知识手册条目写入请求。" + }, + "DirectHandbookSubjectDto": { + "required": [ + "name" + ], + "type": "object", + "properties": { + "id": { + "type": [ + "null", + "string" + ], + "description": "ID。", + "format": "uuid" + }, + "regionId": { + "type": [ + "null", + "string" + ], + "description": "地区 ID。", + "format": "uuid" + }, + "schoolId": { + "type": [ + "null", + "string" + ], + "description": "院校 ID。", + "format": "uuid" + }, + "majorId": { + "type": [ + "null", + "string" + ], + "description": "专业 ID。", + "format": "uuid" + }, + "entryId": { + "type": [ + "null", + "string" + ], + "description": "内容入口 ID。", + "format": "uuid" + }, + "contentNodeId": { + "type": [ + "null", + "string" + ], + "description": "内容节点 ID。", + "format": "uuid" + }, + "legacyId": { + "type": [ + "null", + "string" + ], + "description": "历史系统 ID。" + }, + "name": { + "type": "string", + "description": "名称。" + }, + "type": { + "type": [ + "null", + "string" + ], + "description": "类型。" + }, + "icon": { + "type": [ + "null", + "string" + ], + "description": "图标。" + }, + "color": { + "type": [ + "null", + "string" + ], + "description": "颜色。" + }, + "description": { + "type": [ + "null", + "string" + ], + "description": "说明。" + }, + "order": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "description": "显示顺序。", + "format": "int32" + }, + "isActive": { + "type": [ + "null", + "boolean" + ], + "description": "是否启用。" + }, + "metadata": { + "description": "扩展元数据。", + "$ref": "#/components/schemas/JsonElement" + } + }, + "description": "管理侧知识手册科目写入请求。" + }, + "DirectImportDto": { + "type": "object", + "properties": { + "sourceFormat": { + "type": [ + "null", + "string" + ], + "description": "来源格式。" + }, + "sourceName": { + "type": [ + "null", + "string" + ], + "description": "来源名称。" + }, + "regionId": { + "type": [ + "null", + "string" + ], + "description": "地区 ID。", + "format": "uuid" + }, + "entryId": { + "type": [ + "null", + "string" + ], + "description": "内容入口 ID。", + "format": "uuid" + }, + "contentNodeId": { + "type": [ + "null", + "string" + ], + "description": "内容节点 ID。", + "format": "uuid" + }, + "subjectId": { + "type": [ + "null", + "string" + ], + "description": "科目 ID。", + "format": "uuid" + }, + "categoryId": { + "type": [ + "null", + "string" + ], + "description": "分类 ID。", + "format": "uuid" + }, + "questionBankId": { + "type": [ + "null", + "string" + ], + "description": "题库 ID。", + "format": "uuid" + }, + "collectionId": { + "type": [ + "null", + "string" + ], + "description": "题集 ID。", + "format": "uuid" + }, + "async": { + "type": [ + "null", + "boolean" + ], + "description": "是否异步执行。" + }, + "items": { + "type": [ + "null", + "array" + ], + "description": "数据项列表。" + }, + "units": { + "type": [ + "null", + "array" + ], + "description": "单元数据列表。" + }, + "words": { + "type": [ + "null", + "array" + ], + "description": "单词数据列表。" + }, + "subjects": { + "type": [ + "null", + "array" + ], + "description": "科目数据列表。" + }, + "entries": { + "type": [ + "null", + "array" + ], + "description": "条目数据列表。" + }, + "fields": { + "type": [ + "null", + "array" + ], + "description": "字段数据列表。" + }, + "schools": { + "type": [ + "null", + "array" + ], + "description": "院校数据列表。" + }, + "majors": { + "type": [ + "null", + "array" + ], + "description": "专业数据列表。" + }, + "records": { + "type": [ + "null", + "array" + ], + "description": "记录数据列表。" + }, + "videos": { + "type": [ + "null", + "array" + ], + "description": "视频数据列表。" + } + }, + "description": "管理侧内容导入请求。" + }, + "DirectImportJobDto": { + "type": "object", + "properties": { + "jobId": { + "type": "string", + "description": "任务 ID。", + "format": "uuid" + } + }, + "description": "管理侧内容导入任务查询请求。" + }, + "DirectMajorDto": { + "required": [ + "name" + ], + "type": "object", + "properties": { + "id": { + "type": [ + "null", + "string" + ], + "description": "ID。", + "format": "uuid" + }, + "regionId": { + "type": [ + "null", + "string" + ], + "description": "地区 ID。", + "format": "uuid" + }, + "schoolId": { + "type": [ + "null", + "string" + ], + "description": "院校 ID。", + "format": "uuid" + }, + "legacyId": { + "type": [ + "null", + "string" + ], + "description": "历史系统 ID。" + }, + "name": { + "type": "string", + "description": "名称。" + }, + "description": { + "type": [ + "null", + "string" + ], + "description": "说明。" + }, + "studyTips": { + "type": [ + "null", + "string" + ], + "description": "备考建议。" + }, + "order": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "description": "显示顺序。", + "format": "int32" + }, + "isActive": { + "type": [ + "null", + "boolean" + ], + "description": "是否启用。" + } + }, + "description": "管理侧专业写入请求。" + }, + "DirectOperationContentDto": { + "type": "object", + "properties": { + "id": { + "type": [ + "null", + "string" + ], + "description": "ID。", + "format": "uuid" + }, + "regionId": { + "type": [ + "null", + "string" + ], + "description": "地区 ID。", + "format": "uuid" + }, + "schoolId": { + "type": [ + "null", + "string" + ], + "description": "院校 ID。", + "format": "uuid" + }, + "legacyId": { + "type": [ + "null", + "string" + ], + "description": "历史系统 ID。" + }, + "title": { + "type": [ + "null", + "string" + ], + "description": "标题。" + }, + "subtitle": { + "type": [ + "null", + "string" + ], + "description": "副标题。" + }, + "content": { + "type": [ + "null", + "string" + ], + "description": "内容。" + }, + "question": { + "type": [ + "null", + "string" + ], + "description": "问题。" + }, + "answer": { + "type": [ + "null", + "string" + ], + "description": "答案。" + }, + "link": { + "type": [ + "null", + "string" + ], + "description": "链接地址。" + }, + "buttonText": { + "type": [ + "null", + "string" + ], + "description": "按钮文案。" + }, + "buttonLink": { + "type": [ + "null", + "string" + ], + "description": "按钮链接。" + }, + "backgroundColor": { + "type": [ + "null", + "string" + ], + "description": "背景颜色。" + }, + "borderColor": { + "type": [ + "null", + "string" + ], + "description": "边框颜色。" + }, + "examName": { + "type": [ + "null", + "string" + ], + "description": "考试名称。" + }, + "examAt": { + "type": [ + "null", + "string" + ], + "description": "考试时间。", + "format": "date-time" + }, + "examType": { + "type": [ + "null", + "string" + ], + "description": "考试类型。" + }, + "description": { + "type": [ + "null", + "string" + ], + "description": "说明。" + }, + "order": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "description": "显示顺序。", + "format": "int32" + }, + "isActive": { + "type": [ + "null", + "boolean" + ], + "description": "是否启用。" + }, + "metadata": { + "description": "扩展元数据。", + "$ref": "#/components/schemas/JsonElement" + } + }, + "description": "管理侧运营内容写入请求。" + }, + "DirectQuestionVideoDto": { + "type": "object", + "properties": { + "questionId": { + "type": "string", + "description": "题目 ID。", + "format": "uuid" + }, + "videoId": { + "type": "string", + "description": "视频 ID。", + "format": "uuid" + }, + "legacyId": { + "type": [ + "null", + "string" + ], + "description": "历史系统 ID。" + }, + "videoType": { + "type": [ + "null", + "string" + ], + "description": "视频类型。" + }, + "order": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "description": "显示顺序。", + "format": "int32" + }, + "metadata": { + "description": "扩展元数据。", + "$ref": "#/components/schemas/JsonElement" + } + }, + "description": "管理侧题目视频绑定请求。" + }, + "DirectQuestionWriteDto": { + "type": "object", + "properties": { + "questionId": { + "type": [ + "null", + "string" + ], + "description": "题目 ID。", + "format": "uuid" + }, + "questionBankId": { + "type": [ + "null", + "string" + ], + "description": "题库 ID。", + "format": "uuid" + }, + "subjectId": { + "type": [ + "null", + "string" + ], + "description": "科目 ID。", + "format": "uuid" + }, + "categoryId": { + "type": [ + "null", + "string" + ], + "description": "分类 ID。", + "format": "uuid" + }, + "nodeId": { + "type": [ + "null", + "string" + ], + "description": "节点 ID。", + "format": "uuid" + }, + "entryId": { + "type": [ + "null", + "string" + ], + "description": "内容入口 ID。", + "format": "uuid" + }, + "contentNodeId": { + "type": [ + "null", + "string" + ], + "description": "内容节点 ID。", + "format": "uuid" + }, + "primaryCollectionId": { + "type": [ + "null", + "string" + ], + "description": "主题集 ID。", + "format": "uuid" + }, + "legacyId": { + "type": [ + "null", + "string" + ], + "description": "历史系统 ID。" + }, + "type": { + "type": [ + "null", + "string" + ], + "description": "类型。" + }, + "typeLabel": { + "type": [ + "null", + "string" + ], + "description": "类型显示名。" + }, + "difficulty": { + "maximum": 5, + "minimum": 1, + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "description": "难度。", + "format": "int32" + }, + "tags": { + "description": "标签列表。", + "$ref": "#/components/schemas/JsonElement" + }, + "content": { + "type": [ + "null", + "string" + ], + "description": "内容。" + }, + "options": { + "description": "选项配置。", + "$ref": "#/components/schemas/JsonElement" + }, + "correctOptionIndex": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "description": "正确选项索引。", + "format": "int32" + }, + "correctOptionIndices": { + "description": "正确选项索引列表。", + "$ref": "#/components/schemas/JsonElement" + }, + "answerText": { + "type": [ + "null", + "string" + ], + "description": "文字答案。" + }, + "explanation": { + "type": [ + "null", + "string" + ], + "description": "解析。" + }, + "subQuestions": { + "description": "子题列表。", + "$ref": "#/components/schemas/JsonElement" + }, + "codeLang": { + "type": [ + "null", + "string" + ], + "description": "代码语言。" + }, + "codeTemplate": { + "type": [ + "null", + "string" + ], + "description": "代码模板。" + }, + "mediaUrl": { + "type": [ + "null", + "string" + ], + "description": "媒体地址。" + }, + "status": { + "type": [ + "null", + "string" + ], + "description": "状态。" + }, + "examMarkers": { + "description": "考试标记配置。", + "$ref": "#/components/schemas/JsonElement" + }, + "sourceHash": { + "type": [ + "null", + "string" + ], + "description": "来源哈希。" + }, + "createVersion": { + "type": [ + "null", + "boolean" + ], + "description": "是否创建题目版本。" + } + }, + "description": "管理侧题目写入请求。" + }, + "DirectSchoolDto": { + "required": [ + "name" + ], + "type": "object", + "properties": { + "id": { + "type": [ + "null", + "string" + ], + "description": "ID。", + "format": "uuid" + }, + "regionId": { + "type": [ + "null", + "string" + ], + "description": "地区 ID。", + "format": "uuid" + }, + "legacyId": { + "type": [ + "null", + "string" + ], + "description": "历史系统 ID。" + }, + "name": { + "type": "string", + "description": "名称。" + }, + "professionalExamDate": { + "type": [ + "null", + "string" + ], + "description": "专业考试日期。" + }, + "metadata": { + "description": "扩展元数据。", + "$ref": "#/components/schemas/JsonElement" + } + }, + "description": "管理侧院校写入请求。" + }, + "DirectScorelineFieldDto": { + "required": [ + "fieldKey", + "fieldName" + ], + "type": "object", + "properties": { + "id": { + "type": [ + "null", + "string" + ], + "description": "ID。", + "format": "uuid" + }, + "regionId": { + "type": [ + "null", + "string" + ], + "description": "地区 ID。", + "format": "uuid" + }, + "legacyId": { + "type": [ + "null", + "string" + ], + "description": "历史系统 ID。" + }, + "fieldKey": { + "type": "string", + "description": "字段键。" + }, + "fieldName": { + "type": "string", + "description": "字段名称。" + }, + "fieldType": { + "type": [ + "null", + "string" + ], + "description": "字段类型。" + }, + "unit": { + "type": [ + "null", + "string" + ], + "description": "单位。" + }, + "isFilter": { + "type": [ + "null", + "boolean" + ], + "description": "是否可筛选。" + }, + "isRequired": { + "type": [ + "null", + "boolean" + ], + "description": "是否必填。" + }, + "isVisible": { + "type": [ + "null", + "boolean" + ], + "description": "是否可见。" + }, + "isTrend": { + "type": [ + "null", + "boolean" + ], + "description": "是否参与趋势展示。" + }, + "options": { + "description": "选项配置。", + "$ref": "#/components/schemas/JsonElement" + }, + "placeholder": { + "type": [ + "null", + "string" + ], + "description": "占位提示。" + }, + "description": { + "type": [ + "null", + "string" + ], + "description": "说明。" + }, + "order": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "description": "显示顺序。", + "format": "int32" + } + }, + "description": "管理侧分数线字段写入请求。" + }, + "DirectScorelineRecordDto": { + "type": "object", + "properties": { + "id": { + "type": [ + "null", + "string" + ], + "description": "ID。", + "format": "uuid" + }, + "regionId": { + "type": [ + "null", + "string" + ], + "description": "地区 ID。", + "format": "uuid" + }, + "schoolId": { + "type": [ + "null", + "string" + ], + "description": "院校 ID。", + "format": "uuid" + }, + "majorId": { + "type": [ + "null", + "string" + ], + "description": "专业 ID。", + "format": "uuid" + }, + "legacyId": { + "type": [ + "null", + "string" + ], + "description": "历史系统 ID。" + }, + "year": { + "maximum": 3000, + "minimum": 1900, + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "description": "年份。", + "format": "int32" + }, + "schoolName": { + "type": [ + "null", + "string" + ], + "description": "院校名称。" + }, + "majorName": { + "type": [ + "null", + "string" + ], + "description": "专业名称。" + }, + "fieldValues": { + "description": "动态字段值。", + "$ref": "#/components/schemas/JsonElement" + } + }, + "description": "管理侧分数线记录写入请求。" + }, + "DirectVideoDto": { + "required": [ + "title" + ], + "type": "object", + "properties": { + "id": { + "type": [ + "null", + "string" + ], + "description": "ID。", + "format": "uuid" + }, + "subjectId": { + "type": [ + "null", + "string" + ], + "description": "科目 ID。", + "format": "uuid" + }, + "legacyId": { + "type": [ + "null", + "string" + ], + "description": "历史系统 ID。" + }, + "title": { + "type": "string", + "description": "标题。" + }, + "description": { + "type": [ + "null", + "string" + ], + "description": "说明。" + }, + "videoUrl": { + "type": [ + "null", + "string" + ], + "description": "视频地址。" + }, + "thumbnailUrl": { + "type": [ + "null", + "string" + ], + "description": "缩略图地址。" + }, + "durationSeconds": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "description": "时长,单位为秒。", + "format": "int32" + }, + "knowledgeTags": { + "description": "知识标签。", + "$ref": "#/components/schemas/JsonElement" + }, + "isGeneral": { + "type": [ + "null", + "boolean" + ], + "description": "是否通用视频。" + }, + "difficulty": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "description": "难度。", + "format": "int32" + }, + "order": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "description": "显示顺序。", + "format": "int32" + }, + "isActive": { + "type": [ + "null", + "boolean" + ], + "description": "是否启用。" + }, + "metadata": { + "description": "扩展元数据。", + "$ref": "#/components/schemas/JsonElement" + } + }, + "description": "管理侧视频写入请求。" + }, + "DirectVocabularyUnitDto": { + "required": [ + "name" + ], + "type": "object", + "properties": { + "id": { + "type": [ + "null", + "string" + ], + "description": "ID。", + "format": "uuid" + }, + "regionId": { + "type": [ + "null", + "string" + ], + "description": "地区 ID。", + "format": "uuid" + }, + "entryId": { + "type": [ + "null", + "string" + ], + "description": "内容入口 ID。", + "format": "uuid" + }, + "contentNodeId": { + "type": [ + "null", + "string" + ], + "description": "内容节点 ID。", + "format": "uuid" + }, + "legacyId": { + "type": [ + "null", + "string" + ], + "description": "历史系统 ID。" + }, + "name": { + "type": "string", + "description": "名称。" + }, + "description": { + "type": [ + "null", + "string" + ], + "description": "说明。" + }, + "wordCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "description": "单词数量。", + "format": "int32" + }, + "order": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "description": "显示顺序。", + "format": "int32" + }, + "isActive": { + "type": [ + "null", + "boolean" + ], + "description": "是否启用。" + }, + "metadata": { + "description": "扩展元数据。", + "$ref": "#/components/schemas/JsonElement" + } + }, + "description": "管理侧词汇单元写入请求。" + }, + "DirectVocabularyWordDto": { + "required": [ + "word" + ], + "type": "object", + "properties": { + "id": { + "type": [ + "null", + "string" + ], + "description": "ID。", + "format": "uuid" + }, + "unitId": { + "type": [ + "null", + "string" + ], + "description": "单元 ID。", + "format": "uuid" + }, + "entryId": { + "type": [ + "null", + "string" + ], + "description": "内容入口 ID。", + "format": "uuid" + }, + "contentNodeId": { + "type": [ + "null", + "string" + ], + "description": "内容节点 ID。", + "format": "uuid" + }, + "legacyId": { + "type": [ + "null", + "string" + ], + "description": "历史系统 ID。" + }, + "word": { + "type": "string", + "description": "单词。" + }, + "phonetic": { + "type": [ + "null", + "string" + ], + "description": "音标。" + }, + "meaning": { + "type": [ + "null", + "string" + ], + "description": "释义。" + }, + "example": { + "type": [ + "null", + "string" + ], + "description": "例句。" + }, + "exampleTranslation": { + "type": [ + "null", + "string" + ], + "description": "例句翻译。" + }, + "difficulty": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "description": "难度。", + "format": "int32" + }, + "tags": { + "description": "标签列表。", + "$ref": "#/components/schemas/JsonElement" + }, + "order": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "description": "显示顺序。", + "format": "int32" + }, + "isActive": { + "type": [ + "null", + "boolean" + ], + "description": "是否启用。" + }, + "metadata": { + "description": "扩展元数据。", + "$ref": "#/components/schemas/JsonElement" + } + }, + "description": "管理侧词汇单词写入请求。" + }, + "DisablePlatformBillingDunningChannelDto": { + "required": [ + "channelId" + ], + "type": "object", + "properties": { + "channelId": { + "type": "string", + "description": "通知渠道 ID。", + "format": "uuid" + }, + "reason": { + "maxLength": 1000, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "原因。" + } + }, + "description": "禁用平台DunningChannel请求 DTO。" + }, + "DisableTenantAdminMemberDto": { + "required": [ + "membershipId" + ], + "type": "object", + "properties": { + "membershipId": { + "type": "string", + "description": "成员关系 ID。", + "format": "uuid" + } + }, + "description": "禁用租户管理端成员请求 DTO。" + }, + "DiscountType": { + "type": "integer" + }, + "ExamCountdownItem": { + "required": [ + "id", + "legacyId", + "regionId", + "schoolId", + "examName", + "examAt", + "examType", + "description", + "metadata", + "order", + "isActive", + "daysLeft" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "legacyId": { + "type": [ + "null", + "string" + ] + }, + "regionId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "schoolId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "examName": { + "type": "string" + }, + "examAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "examType": { + "type": [ + "null", + "string" + ] + }, + "description": { + "type": [ + "null", + "string" + ] + }, + "metadata": { + "$ref": "#/components/schemas/JsonElement" + }, + "order": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "isActive": { + "type": "boolean" + }, + "daysLeft": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "format": "int32" + } + } + }, + "ExamCountdownList": { + "required": [ + "items", + "regionId", + "schoolId" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ExamCountdownItem" + } + }, + "regionId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "schoolId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + } + } + }, + "ExamDateCatalogItem": { + "required": [ + "id", + "legacyId", + "regionId", + "schoolId", + "examName", + "examAt", + "examType", + "description", + "metadata", + "order", + "isActive", + "daysLeft" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "legacyId": { + "type": [ + "null", + "string" + ] + }, + "regionId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "schoolId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "examName": { + "type": "string" + }, + "examAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "examType": { + "type": [ + "null", + "string" + ] + }, + "description": { + "type": [ + "null", + "string" + ] + }, + "metadata": { + "$ref": "#/components/schemas/JsonElement" + }, + "order": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "isActive": { + "type": "boolean" + }, + "daysLeft": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "format": "int32" + } + } + }, + "FaqCatalogItem": { + "required": [ + "id", + "legacyId", + "regionId", + "question", + "answer", + "order", + "isActive" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "legacyId": { + "type": [ + "null", + "string" + ] + }, + "regionId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "question": { + "type": [ + "null", + "string" + ] + }, + "answer": { + "type": [ + "null", + "string" + ] + }, + "order": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "isActive": { + "type": "boolean" + } + } + }, + "FavoriteQuestionItem": { + "required": [ + "questionReferenceId", + "locator", + "createdAt" + ], + "type": "object", + "properties": { + "questionReferenceId": { + "type": "string", + "format": "uuid" + }, + "locator": { + "$ref": "#/components/schemas/QuestionLocator" + }, + "createdAt": { + "type": "string", + "format": "date-time" + } + } + }, + "FavoriteWordDto": { + "required": [ + "wordId" + ], + "type": "object", + "properties": { + "wordId": { + "type": "string", + "description": "单词 ID。", + "format": "uuid" + }, + "favorite": { + "type": [ + "null", + "boolean" + ], + "description": "是否收藏。" + }, + "note": { + "maxLength": 1000, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "备注。" + } + }, + "description": "收藏单词请求 DTO。" + }, + "FavoriteWordItem": { + "required": [ + "wordId", + "note", + "favoritedAt" + ], + "type": "object", + "properties": { + "wordId": { + "type": "string", + "format": "uuid" + }, + "note": { + "type": [ + "null", + "string" + ] + }, + "favoritedAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + } + } + }, + "FeatureQuotaSnapshot": { + "required": [ + "metricCode", + "usedValue", + "limitValue", + "usedPercent", + "warning", + "exceeded", + "periodStart", + "periodEnd" + ], + "type": "object", + "properties": { + "metricCode": { + "type": "string" + }, + "usedValue": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int64" + }, + "limitValue": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int64" + }, + "usedPercent": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "warning": { + "type": "boolean" + }, + "exceeded": { + "type": "boolean" + }, + "periodStart": { + "type": "string", + "format": "date-time" + }, + "periodEnd": { + "type": "string", + "format": "date-time" + } + } + }, + "FeedbackItem": { + "required": [ + "id", + "questionId", + "type", + "title", + "category", + "description", + "status", + "priority", + "contact", + "attachments", + "metadata", + "createdAt", + "updatedAt" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "questionId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "type": { + "type": [ + "null", + "string" + ] + }, + "title": { + "type": [ + "null", + "string" + ] + }, + "category": { + "type": [ + "null", + "string" + ] + }, + "description": { + "type": [ + "null", + "string" + ] + }, + "status": { + "type": "string" + }, + "priority": { + "type": "string" + }, + "contact": { + "type": [ + "null", + "string" + ] + }, + "attachments": { + "$ref": "#/components/schemas/JsonElement" + }, + "metadata": { + "$ref": "#/components/schemas/JsonElement" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + } + } + }, + "GenerateCommissionSettlementDto": { + "required": [ + "startDate", + "endDate", + "referrerUserId" + ], + "type": "object", + "properties": { + "startDate": { + "pattern": "^\\d{4}-\\d{2}-\\d{2}$", + "type": "string", + "description": "开始日期,格式为 yyyy-MM-dd。" + }, + "endDate": { + "pattern": "^\\d{4}-\\d{2}-\\d{2}$", + "type": "string", + "description": "结束日期,格式为 yyyy-MM-dd。" + }, + "referrerUserId": { + "type": "string", + "description": "推荐人用户 ID。", + "format": "uuid" + }, + "status": { + "maxLength": 50, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "状态。" + }, + "remark": { + "maxLength": 1000, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "备注。" + }, + "metadata": { + "oneOf": [ + { + "type": "null" + }, + { + "description": "扩展元数据。", + "$ref": "#/components/schemas/JsonElement" + } + ] + } + }, + "description": "生成佣金结算单请求 DTO。" + }, + "GrantTenantAdminBadgeDto": { + "required": [ + "userId", + "badgeId" + ], + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "用户 ID。", + "format": "uuid" + }, + "badgeId": { + "type": "string", + "description": "徽章 ID。", + "format": "uuid" + }, + "legacyId": { + "type": [ + "null", + "string" + ], + "description": "历史系统 ID。" + }, + "note": { + "type": [ + "null", + "string" + ], + "description": "备注。" + }, + "grantedAt": { + "type": [ + "null", + "string" + ], + "description": "授予时间。", + "format": "date-time" + }, + "metadata": { + "description": "扩展元数据。", + "$ref": "#/components/schemas/JsonElement" + } + }, + "description": "授予租户管理端徽章请求 DTO。" + }, + "HandbookChapter": { + "type": "object", + "properties": { + "subjectId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "entryId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "contentNodeId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "legacyId": { + "type": [ + "null", + "string" + ] + }, + "name": { + "type": "string" + }, + "description": { + "type": [ + "null", + "string" + ] + }, + "sortOrder": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "isActive": { + "type": "boolean" + }, + "sourceHash": { + "type": [ + "null", + "string" + ] + }, + "metadata": { + "$ref": "#/components/schemas/JsonElement" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "tenantId": { + "type": "string", + "format": "uuid" + }, + "id": { + "type": "string", + "format": "uuid" + } + } + }, + "HandbookChapterCatalogItem": { + "required": [ + "id", + "legacyId", + "subjectId", + "entryId", + "contentNodeId", + "name", + "description", + "order", + "metadata" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "legacyId": { + "type": [ + "null", + "string" + ] + }, + "subjectId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "entryId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "contentNodeId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "name": { + "type": "string" + }, + "description": { + "type": [ + "null", + "string" + ] + }, + "order": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "metadata": { + "$ref": "#/components/schemas/JsonElement" + } + } + }, + "HandbookEntry": { + "type": "object", + "properties": { + "chapterId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "entryId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "contentNodeId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "legacyId": { + "type": [ + "null", + "string" + ] + }, + "title": { + "type": "string" + }, + "summary": { + "type": [ + "null", + "string" + ] + }, + "content": { + "type": [ + "null", + "string" + ] + }, + "tags": { + "$ref": "#/components/schemas/JsonElement" + }, + "sortOrder": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "isActive": { + "type": "boolean" + }, + "sourceHash": { + "type": [ + "null", + "string" + ] + }, + "metadata": { + "$ref": "#/components/schemas/JsonElement" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "tenantId": { + "type": "string", + "format": "uuid" + }, + "id": { + "type": "string", + "format": "uuid" + } + } + }, + "HandbookEntryCatalogItem": { + "required": [ + "id", + "legacyId", + "chapterId", + "entryId", + "contentNodeId", + "title", + "summary", + "content", + "tags", + "order", + "metadata" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "legacyId": { + "type": [ + "null", + "string" + ] + }, + "chapterId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "entryId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "contentNodeId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "title": { + "type": "string" + }, + "summary": { + "type": [ + "null", + "string" + ] + }, + "content": { + "type": [ + "null", + "string" + ] + }, + "tags": { + "$ref": "#/components/schemas/JsonElement" + }, + "order": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "metadata": { + "$ref": "#/components/schemas/JsonElement" + } + } + }, + "HandbookSubject": { + "type": "object", + "properties": { + "regionId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "schoolId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "majorId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "entryId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "contentNodeId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "legacyId": { + "type": [ + "null", + "string" + ] + }, + "name": { + "type": "string" + }, + "type": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/components/schemas/HandbookSubjectType" + } + ] + }, + "icon": { + "type": [ + "null", + "string" + ] + }, + "color": { + "type": [ + "null", + "string" + ] + }, + "description": { + "type": [ + "null", + "string" + ] + }, + "majorLegacyIds": { + "$ref": "#/components/schemas/JsonElement" + }, + "sortOrder": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "isActive": { + "type": "boolean" + }, + "sourceHash": { + "type": [ + "null", + "string" + ] + }, + "metadata": { + "$ref": "#/components/schemas/JsonElement" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "tenantId": { + "type": "string", + "format": "uuid" + }, + "id": { + "type": "string", + "format": "uuid" + } + } + }, + "HandbookSubjectCatalogItem": { + "required": [ + "id", + "legacyId", + "regionId", + "schoolId", + "majorId", + "entryId", + "contentNodeId", + "name", + "type", + "icon", + "color", + "description", + "order", + "metadata" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "legacyId": { + "type": [ + "null", + "string" + ] + }, + "regionId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "schoolId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "majorId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "entryId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "contentNodeId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "name": { + "type": "string" + }, + "type": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/components/schemas/HandbookSubjectType" + } + ] + }, + "icon": { + "type": [ + "null", + "string" + ] + }, + "color": { + "type": [ + "null", + "string" + ] + }, + "description": { + "type": [ + "null", + "string" + ] + }, + "order": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "metadata": { + "$ref": "#/components/schemas/JsonElement" + } + } + }, + "HandbookSubjectType": { + "type": "integer" + }, + "HealthResponseDto": { + "required": [ + "status", + "service", + "checkedAt" + ], + "type": "object", + "properties": { + "status": { + "type": "string", + "description": "服务状态,例如 ok。" + }, + "service": { + "type": "string", + "description": "服务名称。" + }, + "checkedAt": { + "type": "string", + "description": "检查时间。", + "format": "date-time" + } + }, + "description": "健康检查响应。" + }, + "IdempotentTenantBillingDto": { + "required": [ + "idempotencyKey" + ], + "type": "object", + "properties": { + "idempotencyKey": { + "type": "string" + } + }, + "description": "Idempotent租户账务请求 DTO。" + }, + "ImageAssetCatalogItem": { + "required": [ + "id", + "legacyId", + "title", + "category", + "fileName", + "isPublic", + "cdnUrl", + "metadata" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "legacyId": { + "type": [ + "null", + "string" + ] + }, + "title": { + "type": [ + "null", + "string" + ] + }, + "category": { + "type": [ + "null", + "string" + ] + }, + "fileName": { + "type": [ + "null", + "string" + ] + }, + "isPublic": { + "type": "boolean" + }, + "cdnUrl": { + "type": [ + "null", + "string" + ] + }, + "metadata": { + "$ref": "#/components/schemas/JsonElement" + } + } + }, + "ImportFieldMappingItem": { + "required": [ + "importType", + "title", + "description", + "fields", + "requiredFields" + ], + "type": "object", + "properties": { + "importType": { + "type": "string" + }, + "title": { + "type": "string" + }, + "description": { + "type": "string" + }, + "fields": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ImportFieldSpec" + } + }, + "requiredFields": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "ImportFieldSpec": { + "required": [ + "field", + "label", + "required", + "aliases", + "description", + "example" + ], + "type": "object", + "properties": { + "field": { + "type": "string" + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "aliases": { + "type": "array", + "items": { + "type": "string" + } + }, + "description": { + "type": "string" + }, + "example": { + "$ref": "#/components/schemas/JsonElement" + } + } + }, + "ImportIssueSeverity": { + "type": "integer" + }, + "ImportPostCheckResult": { + "required": [ + "jobId", + "status", + "counts", + "issues" + ], + "type": "object", + "properties": { + "jobId": { + "type": "string", + "format": "uuid" + }, + "status": { + "type": "string" + }, + "counts": { + "$ref": "#/components/schemas/JsonElement" + }, + "issues": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ContentImportIssueModel" + } + } + } + }, + "ImportSourceFormat": { + "type": "integer" + }, + "ImportTemplateItem": { + "required": [ + "importType", + "format", + "fileName", + "mimeType", + "contentBase64", + "contentPreview", + "fields" + ], + "type": "object", + "properties": { + "importType": { + "type": "string" + }, + "format": { + "type": "string" + }, + "fileName": { + "type": "string" + }, + "mimeType": { + "type": "string" + }, + "contentBase64": { + "type": "string" + }, + "contentPreview": { + "type": "string" + }, + "fields": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ImportFieldSpec" + } + } + } + }, + "JsonElement": {}, + "LearningActionResult": { + "required": [ + "ok" + ], + "type": "object", + "properties": { + "ok": { + "type": "boolean" + }, + "isFavorite": { + "type": [ + "null", + "boolean" + ] + } + } + }, + "LearningLeaderboardItem": { + "required": [ + "userId", + "displayName", + "answerCount", + "correctCount", + "wrongCount", + "accuracy" + ], + "type": "object", + "properties": { + "userId": { + "type": "string", + "format": "uuid" + }, + "displayName": { + "type": [ + "null", + "string" + ] + }, + "answerCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "correctCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "wrongCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "accuracy": { + "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$", + "type": [ + "number", + "string" + ], + "format": "double" + } + } + }, + "LearningLeaderboardResult": { + "required": [ + "metric", + "period", + "items", + "currentUser", + "generatedAt" + ], + "type": "object", + "properties": { + "metric": { + "type": "string" + }, + "period": { + "type": "string" + }, + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/LearningLeaderboardItem" + } + }, + "currentUser": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/components/schemas/LearningLeaderboardItem" + } + ] + }, + "generatedAt": { + "type": "string", + "format": "date-time" + } + } + }, + "LearningListOfFavoriteQuestionItem": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/FavoriteQuestionItem" + } + } + } + }, + "LearningListOfFavoriteWordItem": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/FavoriteWordItem" + } + } + } + }, + "LearningListOfLearningTrendItem": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/LearningTrendItem" + } + } + } + }, + "LearningListOfPracticeHistoryItem": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/PracticeHistoryItem" + } + } + } + }, + "LearningListOfPracticeSessionReportItem": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/PracticeSessionReportItem" + } + } + } + }, + "LearningListOfWordProgressItem": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/WordProgressItem" + } + } + } + }, + "LearningListOfWrongQuestionItem": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/WrongQuestionItem" + } + } + } + }, + "LearningStatsItem": { + "required": [ + "answerCount", + "correctCount", + "wrongCount", + "favoriteQuestionCount", + "favoriteWordCount", + "wordProgressCount", + "practiceSessionCount", + "practiceReportCount" + ], + "type": "object", + "properties": { + "answerCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "correctCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "wrongCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "favoriteQuestionCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "favoriteWordCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "wordProgressCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "practiceSessionCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "practiceReportCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + } + } + }, + "LearningTrendItem": { + "required": [ + "date", + "answerCount", + "correctCount", + "wrongCount" + ], + "type": "object", + "properties": { + "date": { + "type": "string", + "format": "date" + }, + "answerCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "correctCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "wrongCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + } + } + }, + "Major": { + "type": "object", + "properties": { + "regionId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "schoolId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "legacyId": { + "type": [ + "null", + "string" + ] + }, + "name": { + "type": "string" + }, + "description": { + "type": [ + "null", + "string" + ] + }, + "studyTips": { + "type": [ + "null", + "string" + ] + }, + "sortOrder": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "isActive": { + "type": "boolean" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "tenantId": { + "type": "string", + "format": "uuid" + }, + "id": { + "type": "string", + "format": "uuid" + } + } + }, + "MajorCatalogItem": { + "required": [ + "id", + "legacyId", + "regionId", + "schoolId", + "name", + "description", + "studyTips", + "order" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "legacyId": { + "type": [ + "null", + "string" + ] + }, + "regionId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "schoolId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "name": { + "type": "string" + }, + "description": { + "type": [ + "null", + "string" + ] + }, + "studyTips": { + "type": [ + "null", + "string" + ] + }, + "order": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + } + } + }, + "ManualBindReferralDto": { + "required": [ + "studentUserId", + "referrerUserId" + ], + "type": "object", + "properties": { + "studentUserId": { + "type": "string", + "description": "学生用户 ID。", + "format": "uuid" + }, + "referrerUserId": { + "type": "string", + "description": "推荐人用户 ID。", + "format": "uuid" + }, + "source": { + "maxLength": 100, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "来源。" + }, + "force": { + "type": "boolean", + "description": "是否强制执行。" + }, + "metadata": { + "oneOf": [ + { + "type": "null" + }, + { + "description": "扩展元数据。", + "$ref": "#/components/schemas/JsonElement" + } + ] + } + }, + "description": "人工绑定推荐请求 DTO。" + }, + "MembershipStatus": { + "type": "integer" + }, + "MeResponse": { + "required": [ + "userId", + "phone", + "email", + "name", + "tenants" + ], + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "用户 ID。", + "format": "uuid" + }, + "phone": { + "type": [ + "null", + "string" + ], + "description": "手机号。" + }, + "email": { + "type": [ + "null", + "string" + ], + "description": "邮箱。" + }, + "name": { + "type": [ + "null", + "string" + ], + "description": "用户显示名称。" + }, + "tenants": { + "type": "array", + "items": { + "$ref": "#/components/schemas/TenantMembershipResponse" + }, + "description": "当前用户拥有的活跃租户成员列表。" + } + }, + "description": "当前用户基础信息和租户成员摘要。" + }, + "ModuleNodeCatalogItem": { + "required": [ + "id", + "legacyId", + "regionId", + "moduleId", + "parentId", + "legacyParentId", + "type", + "name", + "path", + "order", + "metadata" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "legacyId": { + "type": [ + "null", + "string" + ] + }, + "regionId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "moduleId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "parentId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "legacyParentId": { + "type": [ + "null", + "string" + ] + }, + "type": { + "$ref": "#/components/schemas/ModuleNodeType" + }, + "name": { + "type": "string" + }, + "path": { + "type": [ + "null", + "string" + ] + }, + "order": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "metadata": { + "$ref": "#/components/schemas/JsonElement" + } + } + }, + "ModuleNodeType": { + "type": "integer" + }, + "NotificationSeverity": { + "type": "integer" + }, + "NotificationStatus": { + "type": "integer" + }, + "NotificationStatusDto": { + "required": [ + "notificationIds" + ], + "type": "object", + "properties": { + "notificationIds": { + "maxItems": 100, + "minItems": 1, + "type": "array", + "items": { + "type": "string", + "format": "uuid" + }, + "description": "通知 ID 列表。" + }, + "status": { + "maxLength": 32, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "状态。" + } + }, + "description": "通知状态请求 DTO。" + }, + "OAuthCodeDto": { + "required": [ + "realm", + "code" + ], + "type": "object", + "properties": { + "realm": { + "oneOf": [ + { + "type": "null" + }, + { + "description": "认证域。", + "$ref": "#/components/schemas/AuthRealm" + } + ] + }, + "tenantCode": { + "maxLength": 100, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "租户编码。" + }, + "code": { + "maxLength": 512, + "minLength": 0, + "type": "string", + "description": "编码。" + }, + "profile": { + "type": [ + "null", + "object" + ], + "description": "公开用户资料。" + }, + "lang": { + "maxLength": 20, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "语言。" + } + }, + "description": "O认证编码请求 DTO。" + }, + "ObjectStorageMetadata": { + "required": [ + "provider", + "bucket", + "objectKey", + "exists", + "sizeBytes", + "mimeType", + "checksumSha256", + "eTag", + "lastModified", + "rawHeaders", + "verificationSource" + ], + "type": "object", + "properties": { + "provider": { + "type": "string" + }, + "bucket": { + "type": [ + "null", + "string" + ] + }, + "objectKey": { + "type": [ + "null", + "string" + ] + }, + "exists": { + "type": "boolean" + }, + "sizeBytes": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "format": "int64" + }, + "mimeType": { + "type": [ + "null", + "string" + ] + }, + "checksumSha256": { + "type": [ + "null", + "string" + ] + }, + "eTag": { + "type": [ + "null", + "string" + ] + }, + "lastModified": { + "type": [ + "null", + "string" + ] + }, + "rawHeaders": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "verificationSource": { + "type": "string" + } + } + }, + "ObjectStorageSignedUrl": { + "required": [ + "provider", + "bucket", + "objectKey", + "method", + "url", + "headers", + "expiresAt", + "expiresIn", + "signatureMode" + ], + "type": "object", + "properties": { + "provider": { + "type": "string" + }, + "bucket": { + "type": [ + "null", + "string" + ] + }, + "objectKey": { + "type": [ + "null", + "string" + ] + }, + "method": { + "type": "string" + }, + "url": { + "type": "string", + "format": "uri" + }, + "headers": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "expiresAt": { + "type": "string", + "format": "date-time" + }, + "expiresIn": { + "pattern": "^-?(\\d+\\.)?\\d{2}:\\d{2}:\\d{2}(\\.\\d{1,7})?$", + "type": "string" + }, + "signatureMode": { + "type": "string" + } + } + }, + "OperationContentItem": { + "required": [ + "id", + "kind", + "regionId", + "schoolId", + "legacyId", + "title", + "content", + "question", + "answer", + "examAt", + "examType", + "order", + "isActive", + "metadata" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "kind": { + "type": "string" + }, + "regionId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "schoolId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "legacyId": { + "type": [ + "null", + "string" + ] + }, + "title": { + "type": [ + "null", + "string" + ] + }, + "content": { + "type": [ + "null", + "string" + ] + }, + "question": { + "type": [ + "null", + "string" + ] + }, + "answer": { + "type": [ + "null", + "string" + ] + }, + "examAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "examType": { + "type": [ + "null", + "string" + ] + }, + "order": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "isActive": { + "type": "boolean" + }, + "metadata": { + "$ref": "#/components/schemas/JsonElement" + } + } + }, + "PasswordLoginDto": { + "required": [ + "realm", + "password" + ], + "type": "object", + "properties": { + "realm": { + "oneOf": [ + { + "type": "null" + }, + { + "description": "认证域。", + "$ref": "#/components/schemas/AuthRealm" + } + ] + }, + "tenantCode": { + "maxLength": 100, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "租户编码。" + }, + "identifier": { + "maxLength": 320, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "账号标识。" + }, + "phone": { + "maxLength": 32, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "兼容手机号字段;新客户端应使用 identifier。" + }, + "password": { + "maxLength": 128, + "minLength": 8, + "type": "string", + "description": "密码。" + } + }, + "description": "PasswordLogin请求 DTO。" + }, + "PaymentNotificationProcessResult": { + "required": [ + "provider", + "eventId", + "orderNo", + "status", + "idempotent" + ], + "type": "object", + "properties": { + "provider": { + "type": "string" + }, + "eventId": { + "type": "string" + }, + "orderNo": { + "type": "string" + }, + "status": { + "type": "string" + }, + "idempotent": { + "type": "boolean" + } + } + }, + "PlatformAlertSeverity": { + "type": "integer" + }, + "PlatformAuditAlert": { + "type": "object", + "properties": { + "ruleId": { + "type": "string", + "format": "uuid" + }, + "auditLogId": { + "type": "string", + "format": "uuid" + }, + "tenantId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "acknowledgedBy": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "resolvedBy": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "severity": { + "$ref": "#/components/schemas/PlatformAlertSeverity" + }, + "status": { + "$ref": "#/components/schemas/PlatformAuditAlertStatus" + }, + "action": { + "type": "string" + }, + "targetType": { + "type": [ + "null", + "string" + ] + }, + "targetId": { + "type": [ + "null", + "string" + ] + }, + "title": { + "type": "string" + }, + "summary": { + "type": [ + "null", + "string" + ] + }, + "details": { + "$ref": "#/components/schemas/JsonElement" + }, + "firstSeenAt": { + "type": "string", + "format": "date-time" + }, + "lastSeenAt": { + "type": "string", + "format": "date-time" + }, + "acknowledgedAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "resolvedAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "resolutionNote": { + "type": [ + "null", + "string" + ] + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "id": { + "type": "string", + "format": "uuid" + } + } + }, + "PlatformAuditAlertList": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/PlatformAuditAlert" + } + } + } + }, + "PlatformAuditAlertStatus": { + "type": "integer" + }, + "PlatformAuditLogItem": { + "required": [ + "id", + "tenantId", + "actorUserId", + "action", + "targetType", + "targetId", + "details", + "ipAddress", + "userAgent", + "createdAt" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "tenantId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "actorUserId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "action": { + "type": "string" + }, + "targetType": { + "type": [ + "null", + "string" + ] + }, + "targetId": { + "type": [ + "null", + "string" + ] + }, + "details": { + "$ref": "#/components/schemas/JsonElement" + }, + "ipAddress": { + "type": [ + "null", + "string" + ] + }, + "userAgent": { + "type": [ + "null", + "string" + ] + }, + "createdAt": { + "type": "string", + "format": "date-time" + } + } + }, + "PlatformAuditLogList": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/PlatformAuditLogItem" + } + } + } + }, + "PlatformBillingCycle": { + "type": "integer" + }, + "PlatformBillingDunningChannelItem": { + "required": [ + "id", + "channelCode", + "name", + "description", + "enabled", + "provider", + "webhookUrlMasked", + "secretRef", + "reminderTypes", + "reminderChannels", + "minReminderLevel", + "tenantIds", + "timeoutSeconds", + "metadata", + "createdAt", + "updatedAt" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "channelCode": { + "type": "string" + }, + "name": { + "type": "string" + }, + "description": { + "type": [ + "null", + "string" + ] + }, + "enabled": { + "type": "boolean" + }, + "provider": { + "$ref": "#/components/schemas/PlatformBillingDunningProvider" + }, + "webhookUrlMasked": { + "type": "string" + }, + "secretRef": { + "type": [ + "null", + "string" + ] + }, + "reminderTypes": { + "type": "array", + "items": { + "type": "string" + } + }, + "reminderChannels": { + "type": "array", + "items": { + "type": "string" + } + }, + "minReminderLevel": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "tenantIds": { + "type": "array", + "items": { + "type": "string", + "format": "uuid" + } + }, + "timeoutSeconds": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "metadata": { + "$ref": "#/components/schemas/JsonElement" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + } + } + }, + "PlatformBillingDunningChannelList": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/PlatformBillingDunningChannelItem" + } + } + } + }, + "PlatformBillingDunningEventItem": { + "required": [ + "id", + "tenantId", + "channelId", + "reminderId", + "invoiceId", + "provider", + "status", + "attempts", + "scheduledAt", + "nextAttemptAt", + "lastAttemptAt", + "sentAt", + "lastError", + "lastHttpCode", + "lastResponseSummary", + "requestPayload", + "metadata", + "createdAt", + "updatedAt" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "tenantId": { + "type": "string", + "format": "uuid" + }, + "channelId": { + "type": "string", + "format": "uuid" + }, + "reminderId": { + "type": "string", + "format": "uuid" + }, + "invoiceId": { + "type": "string", + "format": "uuid" + }, + "provider": { + "$ref": "#/components/schemas/PlatformBillingDunningProvider" + }, + "status": { + "$ref": "#/components/schemas/PlatformBillingDunningNotificationStatus" + }, + "attempts": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "scheduledAt": { + "type": "string", + "format": "date-time" + }, + "nextAttemptAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "lastAttemptAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "sentAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "lastError": { + "type": [ + "null", + "string" + ] + }, + "lastHttpCode": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "format": "int32" + }, + "lastResponseSummary": { + "type": [ + "null", + "string" + ] + }, + "requestPayload": { + "$ref": "#/components/schemas/JsonElement" + }, + "metadata": { + "$ref": "#/components/schemas/JsonElement" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + } + } + }, + "PlatformBillingDunningEventList": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/PlatformBillingDunningEventItem" + } + } + } + }, + "PlatformBillingDunningNotificationStatus": { + "type": "integer" + }, + "PlatformBillingDunningProvider": { + "type": "integer" + }, + "PlatformBillingInvoice": { + "type": "object", + "properties": { + "orderId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "invoiceNo": { + "type": "string" + }, + "status": { + "$ref": "#/components/schemas/PlatformBillingInvoiceStatus" + }, + "totalAmountCents": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "currency": { + "type": "string" + }, + "dueDate": { + "type": [ + "null", + "string" + ], + "format": "date" + }, + "issuedAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "paidAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "billingProfileSnapshot": { + "$ref": "#/components/schemas/JsonElement" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "tenantId": { + "type": "string", + "format": "uuid" + }, + "id": { + "type": "string", + "format": "uuid" + } + } + }, + "PlatformBillingInvoiceReminder": { + "type": "object", + "properties": { + "invoiceId": { + "type": "string", + "format": "uuid" + }, + "createdBy": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "reminderType": { + "$ref": "#/components/schemas/PlatformBillingInvoiceReminderType" + }, + "channel": { + "$ref": "#/components/schemas/PlatformBillingInvoiceReminderChannel" + }, + "status": { + "$ref": "#/components/schemas/PlatformBillingInvoiceReminderStatus" + }, + "reminderDate": { + "type": "string", + "format": "date" + }, + "reminderLevel": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "dueDate": { + "type": [ + "null", + "string" + ], + "format": "date" + }, + "balanceCentsSnapshot": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "message": { + "type": [ + "null", + "string" + ] + }, + "metadata": { + "$ref": "#/components/schemas/JsonElement" + }, + "sentAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "acknowledgedAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "tenantId": { + "type": "string", + "format": "uuid" + }, + "id": { + "type": "string", + "format": "uuid" + } + } + }, + "PlatformBillingInvoiceReminderChannel": { + "type": "integer" + }, + "PlatformBillingInvoiceReminderStatus": { + "type": "integer" + }, + "PlatformBillingInvoiceReminderType": { + "type": "integer" + }, + "PlatformBillingInvoiceStatus": { + "type": "integer" + }, + "PlatformBillingItemType": { + "type": "integer" + }, + "PlatformBillingOrder": { + "type": "object", + "properties": { + "quoteId": { + "type": "string", + "format": "uuid" + }, + "orderNo": { + "type": "string" + }, + "idempotencyKey": { + "type": "string" + }, + "purpose": { + "$ref": "#/components/schemas/PlatformBillingOrderPurpose" + }, + "status": { + "$ref": "#/components/schemas/PlatformBillingOrderStatus" + }, + "originalAmountCents": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "discountAmountCents": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "totalAmountCents": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "currency": { + "type": "string" + }, + "expiresAt": { + "type": "string", + "format": "date-time" + }, + "paidAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "cancelledAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "snapshot": { + "$ref": "#/components/schemas/JsonElement" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "tenantId": { + "type": "string", + "format": "uuid" + }, + "id": { + "type": "string", + "format": "uuid" + } + } + }, + "PlatformBillingOrderPurpose": { + "type": "integer" + }, + "PlatformBillingOrderStatus": { + "type": "integer" + }, + "PlatformBillingOrderView": { + "required": [ + "id", + "orderNo", + "purpose", + "status", + "totalAmountCents", + "currency", + "expiresAt", + "paidAt", + "items" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "orderNo": { + "type": "string" + }, + "purpose": { + "$ref": "#/components/schemas/PlatformBillingOrderPurpose" + }, + "status": { + "$ref": "#/components/schemas/PlatformBillingOrderStatus" + }, + "totalAmountCents": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "currency": { + "type": "string" + }, + "expiresAt": { + "type": "string", + "format": "date-time" + }, + "paidAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/PlatformBillingQuoteItemView" + } + } + } + }, + "PlatformBillingPayment": { + "type": "object", + "properties": { + "orderId": { + "type": "string", + "format": "uuid" + }, + "paymentNo": { + "type": "string" + }, + "idempotencyKey": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "method": { + "type": "string" + }, + "status": { + "$ref": "#/components/schemas/PlatformBillingPaymentStatus" + }, + "amountCents": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "providerTradeNo": { + "type": [ + "null", + "string" + ] + }, + "paidAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "clientPayload": { + "$ref": "#/components/schemas/JsonElement" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "tenantId": { + "type": "string", + "format": "uuid" + }, + "id": { + "type": "string", + "format": "uuid" + } + } + }, + "PlatformBillingPaymentEvent": { + "type": "object", + "properties": { + "tenantId": { + "type": "string", + "format": "uuid" + }, + "paymentId": { + "type": "string", + "format": "uuid" + }, + "provider": { + "type": "string" + }, + "providerEventId": { + "type": "string" + }, + "eventType": { + "type": "string" + }, + "payload": { + "$ref": "#/components/schemas/JsonElement" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "id": { + "type": "string", + "format": "uuid" + } + } + }, + "PlatformBillingPaymentStatus": { + "type": "integer" + }, + "PlatformBillingPaymentView": { + "required": [ + "id", + "paymentNo", + "provider", + "method", + "status", + "amountCents", + "clientPayload" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "paymentNo": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "method": { + "type": "string" + }, + "status": { + "$ref": "#/components/schemas/PlatformBillingPaymentStatus" + }, + "amountCents": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "clientPayload": { + "$ref": "#/components/schemas/JsonElement" + } + } + }, + "PlatformBillingQuoteItemView": { + "required": [ + "offeringVersionId", + "offeringCode", + "offeringName", + "itemType", + "unitAmountCents", + "amountCents" + ], + "type": "object", + "properties": { + "offeringVersionId": { + "type": "string", + "format": "uuid" + }, + "offeringCode": { + "type": "string" + }, + "offeringName": { + "type": "string" + }, + "itemType": { + "$ref": "#/components/schemas/PlatformBillingItemType" + }, + "unitAmountCents": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "amountCents": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + } + } + }, + "PlatformBillingQuoteStatus": { + "type": "integer" + }, + "PlatformBillingQuoteView": { + "required": [ + "id", + "quoteNo", + "status", + "purpose", + "originalAmountCents", + "discountAmountCents", + "totalAmountCents", + "currency", + "expiresAt", + "items", + "featureCodes", + "limits" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "quoteNo": { + "type": "string" + }, + "status": { + "$ref": "#/components/schemas/PlatformBillingQuoteStatus" + }, + "purpose": { + "$ref": "#/components/schemas/PlatformBillingOrderPurpose" + }, + "originalAmountCents": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "discountAmountCents": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "totalAmountCents": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "currency": { + "type": "string" + }, + "expiresAt": { + "type": "string", + "format": "date-time" + }, + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/PlatformBillingQuoteItemView" + } + }, + "featureCodes": { + "type": "array", + "items": { + "type": "string" + } + }, + "limits": { + "type": "object", + "additionalProperties": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int64" + } + } + } + }, + "PlatformBillingRefund": { + "type": "object", + "properties": { + "orderId": { + "type": "string", + "format": "uuid" + }, + "paymentId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "refundNo": { + "type": "string" + }, + "status": { + "$ref": "#/components/schemas/PlatformBillingRefundStatus" + }, + "amountCents": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "reason": { + "type": "string" + }, + "providerRefundNo": { + "type": [ + "null", + "string" + ] + }, + "completedAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "tenantId": { + "type": "string", + "format": "uuid" + }, + "id": { + "type": "string", + "format": "uuid" + } + } + }, + "PlatformBillingRefundStatus": { + "type": "integer" + }, + "PlatformCrmConfigItem": { + "required": [ + "id", + "tenantId", + "tenantName", + "enabled", + "url", + "secretRef", + "formName", + "examType", + "timeoutSeconds", + "delaySeconds", + "assignmentMode", + "assignmentPool", + "assignmentConfig", + "updatedAt" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "tenantId": { + "type": "string", + "format": "uuid" + }, + "tenantName": { + "type": "string" + }, + "enabled": { + "type": "boolean" + }, + "url": { + "type": [ + "null", + "string" + ] + }, + "secretRef": { + "type": [ + "null", + "string" + ] + }, + "formName": { + "type": [ + "null", + "string" + ] + }, + "examType": { + "type": [ + "null", + "string" + ] + }, + "timeoutSeconds": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "format": "int32" + }, + "delaySeconds": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "format": "int32" + }, + "assignmentMode": { + "$ref": "#/components/schemas/ReferralAssignmentMode" + }, + "assignmentPool": { + "$ref": "#/components/schemas/JsonElement" + }, + "assignmentConfig": { + "$ref": "#/components/schemas/JsonElement" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + } + } + }, + "PlatformDomainList": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/PlatformTenantDomainItem" + } + } + } + }, + "PlatformDomainRecheckResult": { + "required": [ + "domainId", + "status", + "lastCheckedAt" + ], + "type": "object", + "properties": { + "domainId": { + "type": "string", + "format": "uuid" + }, + "status": { + "$ref": "#/components/schemas/TenantDomainStatus" + }, + "lastCheckedAt": { + "type": "string", + "format": "date-time" + } + } + }, + "PlatformOverview": { + "required": [ + "tenantCount", + "activeTenantCount", + "suspendedTenantCount", + "orderCount", + "paidOrderCount", + "revenueCents", + "questionBankCount", + "questionCount", + "learningActiveUserCount" + ], + "type": "object", + "properties": { + "tenantCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "activeTenantCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "suspendedTenantCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "orderCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "paidOrderCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "revenueCents": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "questionBankCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "questionCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "learningActiveUserCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + } + } + }, + "PlatformPaymentApp": { + "type": "object", + "properties": { + "appCode": { + "type": "string" + }, + "appName": { + "type": "string" + }, + "status": { + "$ref": "#/components/schemas/PlatformPaymentAppStatus" + }, + "settlementMode": { + "type": "string" + }, + "description": { + "type": [ + "null", + "string" + ] + }, + "metadata": { + "$ref": "#/components/schemas/JsonElement" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "id": { + "type": "string", + "format": "uuid" + } + } + }, + "PlatformPaymentAppStatus": { + "type": "integer" + }, + "PlatformPaymentChannel": { + "type": "object", + "properties": { + "appId": { + "type": "string", + "format": "uuid" + }, + "provider": { + "type": "string" + }, + "mode": { + "type": "string" + }, + "status": { + "$ref": "#/components/schemas/PlatformPaymentChannelStatus" + }, + "displayName": { + "type": "string" + }, + "secretRef": { + "type": [ + "null", + "string" + ] + }, + "callbackPath": { + "type": [ + "null", + "string" + ] + }, + "priority": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "configPublic": { + "$ref": "#/components/schemas/JsonElement" + }, + "metadata": { + "$ref": "#/components/schemas/JsonElement" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "id": { + "type": "string", + "format": "uuid" + } + } + }, + "PlatformPaymentChannelStatus": { + "type": "integer" + }, + "PlatformQuestionBankItem": { + "required": [ + "id", + "contentEntryId", + "name", + "status", + "nodeCount", + "questionCount", + "metadata", + "createdAt", + "updatedAt" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "contentEntryId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "name": { + "type": "string" + }, + "status": { + "$ref": "#/components/schemas/QuestionBankStatus" + }, + "nodeCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "questionCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "metadata": { + "$ref": "#/components/schemas/JsonElement" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + } + } + }, + "PlatformQuestionBankNodeItem": { + "required": [ + "id", + "questionBankId", + "entryId", + "parentId", + "nodeKey", + "name", + "nodeType", + "depth", + "sortOrder", + "isActive", + "isSelectable", + "isLeaf", + "questionCount", + "metadata" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "questionBankId": { + "type": "string", + "format": "uuid" + }, + "entryId": { + "type": "string", + "format": "uuid" + }, + "parentId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "nodeKey": { + "type": [ + "null", + "string" + ] + }, + "name": { + "type": "string" + }, + "nodeType": { + "$ref": "#/components/schemas/ContentNodeType" + }, + "depth": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "sortOrder": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "isActive": { + "type": "boolean" + }, + "isSelectable": { + "type": "boolean" + }, + "isLeaf": { + "type": "boolean" + }, + "questionCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "metadata": { + "$ref": "#/components/schemas/JsonElement" + } + } + }, + "PlatformQuestionImportCommand": { + "required": [ + "questionBankId", + "contentNodeId", + "format", + "sourceName", + "payload" + ], + "type": "object", + "properties": { + "questionBankId": { + "type": "string", + "format": "uuid" + }, + "contentNodeId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "format": { + "type": "string" + }, + "sourceName": { + "type": [ + "null", + "string" + ] + }, + "payload": { + "$ref": "#/components/schemas/JsonElement" + } + } + }, + "PlatformQuestionImportResult": { + "required": [ + "detail", + "createdNodeCount", + "insertedQuestionCount", + "updatedQuestionCount", + "skippedQuestionCount" + ], + "type": "object", + "properties": { + "detail": { + "$ref": "#/components/schemas/ContentImportJobDetail" + }, + "createdNodeCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "insertedQuestionCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "updatedQuestionCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "skippedQuestionCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + } + } + }, + "PlatformQuestionItem": { + "required": [ + "id", + "versionId", + "questionBankId", + "entryId", + "contentNodeId", + "legacyId", + "type", + "typeLabel", + "difficulty", + "tags", + "content", + "options", + "correctOptionIndex", + "correctOptionIndices", + "answerText", + "explanation", + "subQuestions", + "codeLang", + "codeTemplate", + "mediaUrl", + "status", + "versionNo", + "createdAt", + "updatedAt" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "versionId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "questionBankId": { + "type": "string", + "format": "uuid" + }, + "entryId": { + "type": "string", + "format": "uuid" + }, + "contentNodeId": { + "type": "string", + "format": "uuid" + }, + "legacyId": { + "type": [ + "null", + "string" + ] + }, + "type": { + "type": "string" + }, + "typeLabel": { + "type": [ + "null", + "string" + ] + }, + "difficulty": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "format": "int32" + }, + "tags": { + "$ref": "#/components/schemas/JsonElement" + }, + "content": { + "type": [ + "null", + "string" + ] + }, + "options": { + "$ref": "#/components/schemas/JsonElement" + }, + "correctOptionIndex": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "format": "int32" + }, + "correctOptionIndices": { + "$ref": "#/components/schemas/JsonElement" + }, + "answerText": { + "type": [ + "null", + "string" + ] + }, + "explanation": { + "type": [ + "null", + "string" + ] + }, + "subQuestions": { + "$ref": "#/components/schemas/JsonElement" + }, + "codeLang": { + "type": [ + "null", + "string" + ] + }, + "codeTemplate": { + "type": [ + "null", + "string" + ] + }, + "mediaUrl": { + "type": [ + "null", + "string" + ] + }, + "status": { + "$ref": "#/components/schemas/QuestionStatus" + }, + "versionNo": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + } + } + }, + "PlatformQuestionPage": { + "required": [ + "items", + "total", + "page", + "pageSize" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/PlatformQuestionItem" + } + }, + "total": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "page": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "pageSize": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + } + } + }, + "PlatformRebateSummary": { + "required": [ + "grossAmountCents", + "commissionAmountCents", + "pendingSettlementCents", + "paidSettlementCents", + "exceptionCount" + ], + "type": "object", + "properties": { + "grossAmountCents": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "commissionAmountCents": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "pendingSettlementCents": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "paidSettlementCents": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "exceptionCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + } + } + }, + "PlatformSmsChannelItem": { + "required": [ + "id", + "tenantId", + "tenantName", + "provider", + "name", + "signature", + "scene", + "status", + "secretRef", + "priority", + "monthlyQuota", + "sentThisMonth", + "configPublic", + "metadata", + "updatedAt" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "tenantId": { + "type": "string", + "format": "uuid" + }, + "tenantName": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "name": { + "type": "string" + }, + "signature": { + "type": "string" + }, + "scene": { + "type": "string" + }, + "status": { + "$ref": "#/components/schemas/TenantExternalProviderStatus" + }, + "secretRef": { + "type": [ + "null", + "string" + ] + }, + "priority": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "monthlyQuota": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "sentThisMonth": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "configPublic": { + "$ref": "#/components/schemas/JsonElement" + }, + "metadata": { + "$ref": "#/components/schemas/JsonElement" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + } + } + }, + "PlatformSmsTemplateItem": { + "required": [ + "id", + "tenantId", + "tenantName", + "channelId", + "channelName", + "code", + "name", + "type", + "auditStatus", + "status", + "providerTemplateCode", + "content", + "remark", + "sentCount", + "failedCount", + "updatedAt" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "tenantId": { + "type": "string", + "format": "uuid" + }, + "tenantName": { + "type": "string" + }, + "channelId": { + "type": "string", + "format": "uuid" + }, + "channelName": { + "type": "string" + }, + "code": { + "type": "string" + }, + "name": { + "type": "string" + }, + "type": { + "$ref": "#/components/schemas/SmsTemplateType" + }, + "auditStatus": { + "$ref": "#/components/schemas/SmsTemplateAuditStatus" + }, + "status": { + "$ref": "#/components/schemas/SmsTemplateStatus" + }, + "providerTemplateCode": { + "type": [ + "null", + "string" + ] + }, + "content": { + "type": "string" + }, + "remark": { + "type": [ + "null", + "string" + ] + }, + "sentCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "failedCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + } + } + }, + "PlatformStaffItem": { + "required": [ + "userId", + "name", + "phoneMasked", + "email", + "status", + "roleCodes", + "createdAt", + "updatedAt" + ], + "type": "object", + "properties": { + "userId": { + "type": "string", + "format": "uuid" + }, + "name": { + "type": [ + "null", + "string" + ] + }, + "phoneMasked": { + "type": [ + "null", + "string" + ] + }, + "email": { + "type": [ + "null", + "string" + ] + }, + "status": { + "$ref": "#/components/schemas/UserStatus" + }, + "roleCodes": { + "type": "array", + "items": { + "type": "string" + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + } + } + }, + "PlatformStaffList": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/PlatformStaffItem" + } + } + } + }, + "PlatformTenantCapabilityListOfCrmWebhookLog": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/CrmWebhookLog" + } + } + } + }, + "PlatformTenantCapabilityListOfCrmWebhookQueueItem": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/CrmWebhookQueueItem" + } + } + } + }, + "PlatformTenantCapabilityListOfObject": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array" + } + } + }, + "PlatformTenantCapabilityListOfPlatformCrmConfigItem": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/PlatformCrmConfigItem" + } + } + } + }, + "PlatformTenantCapabilityListOfPlatformSmsChannelItem": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/PlatformSmsChannelItem" + } + } + } + }, + "PlatformTenantCapabilityListOfPlatformSmsTemplateItem": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/PlatformSmsTemplateItem" + } + } + } + }, + "PlatformTenantCapabilityListOfSmsSendLog": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/SmsSendLog" + } + } + } + }, + "PlatformTenantCapabilityListOfTenantExternalProviderItem": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/TenantExternalProviderItem" + } + } + } + }, + "PlatformTenantDetail": { + "required": [ + "tenant", + "domains", + "subscriptions", + "billingProfile" + ], + "type": "object", + "properties": { + "tenant": { + "$ref": "#/components/schemas/PlatformTenantItem" + }, + "domains": { + "type": "array", + "items": { + "$ref": "#/components/schemas/PlatformTenantDomainItem" + } + }, + "subscriptions": { + "type": "array", + "items": { + "$ref": "#/components/schemas/PlatformTenantSubscriptionItem" + } + }, + "billingProfile": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/components/schemas/TenantBillingProfileItem" + } + ] + } + } + }, + "PlatformTenantDomainItem": { + "required": [ + "id", + "tenantId", + "host", + "domainType", + "status", + "isPrimary", + "verifiedAt", + "dnsVerifiedAt", + "tlsReadyAt", + "lastCheckedAt", + "lastFailureReason" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "tenantId": { + "type": "string", + "format": "uuid" + }, + "host": { + "type": "string" + }, + "domainType": { + "$ref": "#/components/schemas/TenantDomainType" + }, + "status": { + "$ref": "#/components/schemas/TenantDomainStatus" + }, + "isPrimary": { + "type": "boolean" + }, + "verifiedAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "dnsVerifiedAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "tlsReadyAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "lastCheckedAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "lastFailureReason": { + "type": [ + "null", + "string" + ] + } + } + }, + "PlatformTenantItem": { + "required": [ + "id", + "slug", + "name", + "legalName", + "status", + "mode", + "billingStatus", + "subscriptionExpiresAt", + "domainCount", + "createdAt", + "updatedAt" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "slug": { + "type": "string" + }, + "name": { + "type": "string" + }, + "legalName": { + "type": [ + "null", + "string" + ] + }, + "status": { + "$ref": "#/components/schemas/TenantStatus" + }, + "mode": { + "$ref": "#/components/schemas/TenantMode" + }, + "billingStatus": { + "$ref": "#/components/schemas/BillingStatus" + }, + "subscriptionExpiresAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "domainCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + } + } + }, + "PlatformTenantList": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/PlatformTenantItem" + } + } + } + }, + "PlatformTenantProvisioningResult": { + "required": [ + "tenant", + "ownerUserId", + "ownerIdentifier", + "mustChangePassword" + ], + "type": "object", + "properties": { + "tenant": { + "$ref": "#/components/schemas/PlatformTenantItem" + }, + "ownerUserId": { + "type": "string", + "format": "uuid" + }, + "ownerIdentifier": { + "type": "string" + }, + "mustChangePassword": { + "type": "boolean" + } + } + }, + "PlatformTenantSubscriptionItem": { + "required": [ + "id", + "tenantId", + "baseOfferingVersionId", + "status", + "startsAt", + "currentPeriodStart", + "currentPeriodEnd", + "cancelAtPeriodEnd", + "metadata" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "tenantId": { + "type": "string", + "format": "uuid" + }, + "baseOfferingVersionId": { + "type": "string", + "format": "uuid" + }, + "status": { + "$ref": "#/components/schemas/TenantSaasSubscriptionStatus" + }, + "startsAt": { + "type": "string", + "format": "date-time" + }, + "currentPeriodStart": { + "type": "string", + "format": "date-time" + }, + "currentPeriodEnd": { + "type": "string", + "format": "date-time" + }, + "cancelAtPeriodEnd": { + "type": "boolean" + }, + "metadata": { + "$ref": "#/components/schemas/JsonElement" + } + } + }, + "PointActivityClaim": { + "type": "object", + "properties": { + "taskId": { + "type": "string", + "format": "uuid" + }, + "userId": { + "type": "string", + "format": "uuid" + }, + "taskKey": { + "type": "string" + }, + "points": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "status": { + "$ref": "#/components/schemas/PointActivityClaimStatus" + }, + "sourceType": { + "type": [ + "null", + "string" + ] + }, + "sourceId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "claimedAt": { + "type": "string", + "format": "date-time" + }, + "metadata": { + "$ref": "#/components/schemas/JsonElement" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "tenantId": { + "type": "string", + "format": "uuid" + }, + "id": { + "type": "string", + "format": "uuid" + } + } + }, + "PointActivityClaimStatus": { + "type": "integer" + }, + "PointActivityTask": { + "type": "object", + "properties": { + "taskKey": { + "type": "string" + }, + "title": { + "type": "string" + }, + "description": { + "type": [ + "null", + "string" + ] + }, + "taskType": { + "$ref": "#/components/schemas/PointActivityTaskType" + }, + "status": { + "$ref": "#/components/schemas/PointActivityTaskStatus" + }, + "points": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "maxClaimsPerUser": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "startsAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "endsAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "sortOrder": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "rules": { + "$ref": "#/components/schemas/JsonElement" + }, + "metadata": { + "$ref": "#/components/schemas/JsonElement" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "tenantId": { + "type": "string", + "format": "uuid" + }, + "id": { + "type": "string", + "format": "uuid" + } + } + }, + "PointActivityTaskStatus": { + "type": "integer" + }, + "PointActivityTaskType": { + "type": "integer" + }, + "PointClaimItem": { + "required": [ + "id", + "taskId", + "taskKey", + "points", + "status", + "sourceType", + "sourceId", + "claimedAt", + "metadata" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "taskId": { + "type": "string", + "format": "uuid" + }, + "taskKey": { + "type": "string" + }, + "points": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "status": { + "type": "string" + }, + "sourceType": { + "type": [ + "null", + "string" + ] + }, + "sourceId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "claimedAt": { + "type": "string", + "format": "date-time" + }, + "metadata": { + "$ref": "#/components/schemas/JsonElement" + } + } + }, + "PointExchangeItem": { + "type": "object", + "properties": { + "regionId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "itemKey": { + "type": "string" + }, + "name": { + "type": "string" + }, + "description": { + "type": [ + "null", + "string" + ] + }, + "itemType": { + "$ref": "#/components/schemas/PointExchangeItemType" + }, + "status": { + "$ref": "#/components/schemas/PointExchangeItemStatus" + }, + "pointsCost": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "stock": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "format": "int32" + }, + "days": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "format": "int32" + }, + "sortOrder": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "startsAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "endsAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "fulfillmentPayload": { + "$ref": "#/components/schemas/JsonElement" + }, + "metadata": { + "$ref": "#/components/schemas/JsonElement" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "tenantId": { + "type": "string", + "format": "uuid" + }, + "id": { + "type": "string", + "format": "uuid" + } + } + }, + "PointExchangeItemDto": { + "required": [ + "id", + "regionId", + "itemKey", + "name", + "description", + "itemType", + "status", + "pointsCost", + "stock", + "days", + "canExchange", + "sortOrder", + "fulfillmentPayload", + "metadata" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "regionId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "itemKey": { + "type": "string" + }, + "name": { + "type": "string" + }, + "description": { + "type": [ + "null", + "string" + ] + }, + "itemType": { + "type": "string" + }, + "status": { + "type": "string" + }, + "pointsCost": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "stock": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "format": "int32" + }, + "days": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "format": "int32" + }, + "canExchange": { + "type": "boolean" + }, + "sortOrder": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "fulfillmentPayload": { + "$ref": "#/components/schemas/JsonElement" + }, + "metadata": { + "$ref": "#/components/schemas/JsonElement" + } + } + }, + "PointExchangeItemStatus": { + "type": "integer" + }, + "PointExchangeItemType": { + "type": "integer" + }, + "PointExchangeOrder": { + "type": "object", + "properties": { + "itemId": { + "type": "string", + "format": "uuid" + }, + "userId": { + "type": "string", + "format": "uuid" + }, + "orderNo": { + "type": "string" + }, + "itemName": { + "type": "string" + }, + "itemType": { + "$ref": "#/components/schemas/PointExchangeItemType" + }, + "status": { + "$ref": "#/components/schemas/PointExchangeOrderStatus" + }, + "pointsCost": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "orderedAt": { + "type": "string", + "format": "date-time" + }, + "completedAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "cancelledAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "fulfillmentSnapshot": { + "$ref": "#/components/schemas/JsonElement" + }, + "metadata": { + "$ref": "#/components/schemas/JsonElement" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "tenantId": { + "type": "string", + "format": "uuid" + }, + "id": { + "type": "string", + "format": "uuid" + } + } + }, + "PointExchangeOrderItem": { + "required": [ + "id", + "itemId", + "orderNo", + "itemName", + "itemType", + "status", + "pointsCost", + "orderedAt", + "completedAt", + "fulfillmentSnapshot", + "metadata" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "itemId": { + "type": "string", + "format": "uuid" + }, + "orderNo": { + "type": "string" + }, + "itemName": { + "type": "string" + }, + "itemType": { + "type": "string" + }, + "status": { + "type": "string" + }, + "pointsCost": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "orderedAt": { + "type": "string", + "format": "date-time" + }, + "completedAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "fulfillmentSnapshot": { + "$ref": "#/components/schemas/JsonElement" + }, + "metadata": { + "$ref": "#/components/schemas/JsonElement" + } + } + }, + "PointExchangeOrderStatus": { + "type": "integer" + }, + "PointListOfPointExchangeItemDto": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/PointExchangeItemDto" + } + } + } + }, + "PointListOfPointExchangeOrderItem": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/PointExchangeOrderItem" + } + } + } + }, + "PointListOfPointTaskItem": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/PointTaskItem" + } + } + } + }, + "PointSummaryItem": { + "required": [ + "earnedPoints", + "spentPoints", + "balancePoints" + ], + "type": "object", + "properties": { + "earnedPoints": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "spentPoints": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "balancePoints": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + } + } + }, + "PointTaskItem": { + "required": [ + "id", + "taskKey", + "title", + "description", + "taskType", + "status", + "points", + "maxClaimsPerUser", + "claimedCount", + "canClaim", + "startsAt", + "endsAt", + "sortOrder", + "rules", + "metadata" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "taskKey": { + "type": "string" + }, + "title": { + "type": "string" + }, + "description": { + "type": [ + "null", + "string" + ] + }, + "taskType": { + "type": "string" + }, + "status": { + "type": "string" + }, + "points": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "maxClaimsPerUser": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "claimedCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "canClaim": { + "type": "boolean" + }, + "startsAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "endsAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "sortOrder": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "rules": { + "$ref": "#/components/schemas/JsonElement" + }, + "metadata": { + "$ref": "#/components/schemas/JsonElement" + } + } + }, + "PracticeAccessMode": { + "type": "integer" + }, + "PracticeAssemblyType": { + "type": "integer" + }, + "PracticeBlueprintCatalogItem": { + "required": [ + "id", + "regionId", + "entryId", + "nodeId", + "collectionId", + "legacyId", + "name", + "mode", + "assemblyType", + "questionLimit", + "durationMinutes", + "totalScore", + "passScore", + "sections", + "rules", + "accessRules", + "status", + "order" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "regionId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "entryId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "nodeId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "collectionId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "legacyId": { + "type": [ + "null", + "string" + ] + }, + "name": { + "type": "string" + }, + "mode": { + "$ref": "#/components/schemas/PracticeMode" + }, + "assemblyType": { + "$ref": "#/components/schemas/PracticeAssemblyType" + }, + "questionLimit": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "format": "int32" + }, + "durationMinutes": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "format": "int32" + }, + "totalScore": { + "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$", + "type": [ + "null", + "number", + "string" + ], + "format": "double" + }, + "passScore": { + "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$", + "type": [ + "null", + "number", + "string" + ], + "format": "double" + }, + "sections": { + "$ref": "#/components/schemas/JsonElement" + }, + "rules": { + "$ref": "#/components/schemas/JsonElement" + }, + "accessRules": { + "$ref": "#/components/schemas/JsonElement" + }, + "status": { + "$ref": "#/components/schemas/ContentStatus" + }, + "order": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + } + } + }, + "PracticeBlueprintManagementItem": { + "required": [ + "id", + "regionId", + "entryId", + "nodeId", + "collectionId", + "legacyId", + "name", + "mode", + "assemblyType", + "questionLimit", + "durationMinutes", + "totalScore", + "passScore", + "sections", + "rules", + "accessRules", + "status", + "order", + "createdAt", + "updatedAt" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "regionId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "entryId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "nodeId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "collectionId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "legacyId": { + "type": [ + "null", + "string" + ] + }, + "name": { + "type": "string" + }, + "mode": { + "$ref": "#/components/schemas/PracticeMode" + }, + "assemblyType": { + "$ref": "#/components/schemas/PracticeAssemblyType" + }, + "questionLimit": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "format": "int32" + }, + "durationMinutes": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "format": "int32" + }, + "totalScore": { + "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$", + "type": [ + "null", + "number", + "string" + ], + "format": "double" + }, + "passScore": { + "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$", + "type": [ + "null", + "number", + "string" + ], + "format": "double" + }, + "sections": { + "$ref": "#/components/schemas/JsonElement" + }, + "rules": { + "$ref": "#/components/schemas/JsonElement" + }, + "accessRules": { + "$ref": "#/components/schemas/JsonElement" + }, + "status": { + "$ref": "#/components/schemas/ContentStatus" + }, + "order": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + } + } + }, + "PracticeHistoryItem": { + "required": [ + "id", + "mode", + "targetType", + "targetId", + "blueprintId", + "collectionId", + "entryId", + "contentNodeId", + "questionCount", + "answeredCount", + "correctCount", + "wrongCount", + "startedAt", + "finishedAt", + "expiresAt", + "status", + "reportId", + "score", + "reportTotalScore", + "accuracy" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "mode": { + "type": "string" + }, + "targetType": { + "type": [ + "null", + "string" + ] + }, + "targetId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "blueprintId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "collectionId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "entryId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "contentNodeId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "questionCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "answeredCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "correctCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "wrongCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "startedAt": { + "type": "string", + "format": "date-time" + }, + "finishedAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "expiresAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "status": { + "type": "string" + }, + "reportId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "score": { + "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$", + "type": [ + "null", + "number", + "string" + ], + "format": "double" + }, + "reportTotalScore": { + "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$", + "type": [ + "null", + "number", + "string" + ], + "format": "double" + }, + "accuracy": { + "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$", + "type": [ + "null", + "number", + "string" + ], + "format": "double" + } + } + }, + "PracticeMode": { + "type": "integer" + }, + "PracticeSessionDetailItem": { + "required": [ + "session", + "questions", + "answersBySessionQuestion" + ], + "type": "object", + "properties": { + "session": { + "$ref": "#/components/schemas/PracticeSessionItem" + }, + "questions": { + "type": "array", + "items": { + "$ref": "#/components/schemas/PracticeSessionQuestionItem" + } + }, + "answersBySessionQuestion": { + "type": "object", + "additionalProperties": { + "$ref": "#/components/schemas/AnswerRecordItem" + } + } + } + }, + "PracticeSessionItem": { + "required": [ + "id", + "mode", + "targetType", + "targetId", + "blueprintId", + "collectionId", + "entryId", + "contentNodeId", + "questionCount", + "durationMinutes", + "totalScore", + "accessMode", + "accessEntitlementId", + "consumedFreeQuota", + "accessSnapshot", + "startedAt", + "finishedAt", + "expiresAt", + "metadata", + "status" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "mode": { + "type": "string" + }, + "targetType": { + "type": [ + "null", + "string" + ] + }, + "targetId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "blueprintId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "collectionId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "entryId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "contentNodeId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "questionCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "durationMinutes": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "format": "int32" + }, + "totalScore": { + "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$", + "type": [ + "null", + "number", + "string" + ], + "format": "double" + }, + "accessMode": { + "$ref": "#/components/schemas/PracticeAccessMode" + }, + "accessEntitlementId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "consumedFreeQuota": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "accessSnapshot": { + "$ref": "#/components/schemas/JsonElement" + }, + "startedAt": { + "type": "string", + "format": "date-time" + }, + "finishedAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "expiresAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "metadata": { + "$ref": "#/components/schemas/JsonElement" + }, + "status": { + "type": "string" + } + } + }, + "PracticeSessionQuestionItem": { + "required": [ + "sessionQuestionId", + "questionReferenceId", + "locator", + "questionId", + "type", + "typeLabel", + "difficulty", + "tags", + "versionId", + "content", + "options", + "explanation" + ], + "type": "object", + "properties": { + "sessionQuestionId": { + "type": "string", + "format": "uuid" + }, + "questionReferenceId": { + "type": "string", + "format": "uuid" + }, + "locator": { + "$ref": "#/components/schemas/QuestionLocator" + }, + "questionId": { + "type": "string", + "format": "uuid" + }, + "type": { + "type": "string" + }, + "typeLabel": { + "type": [ + "null", + "string" + ] + }, + "difficulty": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "format": "int32" + }, + "tags": { + "$ref": "#/components/schemas/JsonElement" + }, + "versionId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "content": { + "type": [ + "null", + "string" + ] + }, + "options": { + "$ref": "#/components/schemas/JsonElement" + }, + "explanation": { + "type": [ + "null", + "string" + ] + } + } + }, + "PracticeSessionReportItem": { + "required": [ + "id", + "practiceSessionId", + "blueprintId", + "collectionId", + "mode", + "totalQuestions", + "answeredCount", + "correctCount", + "wrongCount", + "unansweredCount", + "score", + "totalScore", + "accuracy", + "durationSeconds", + "startedAt", + "submittedAt", + "sectionStats", + "questionResults", + "wrongQuestionIds", + "metadata" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "practiceSessionId": { + "type": "string", + "format": "uuid" + }, + "blueprintId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "collectionId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "mode": { + "type": "string" + }, + "totalQuestions": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "answeredCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "correctCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "wrongCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "unansweredCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "score": { + "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$", + "type": [ + "number", + "string" + ], + "format": "double" + }, + "totalScore": { + "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$", + "type": [ + "number", + "string" + ], + "format": "double" + }, + "accuracy": { + "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$", + "type": [ + "number", + "string" + ], + "format": "double" + }, + "durationSeconds": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "startedAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "submittedAt": { + "type": "string", + "format": "date-time" + }, + "sectionStats": { + "$ref": "#/components/schemas/JsonElement" + }, + "questionResults": { + "$ref": "#/components/schemas/JsonElement" + }, + "wrongQuestionIds": { + "$ref": "#/components/schemas/JsonElement" + }, + "metadata": { + "$ref": "#/components/schemas/JsonElement" + } + } + }, + "PreviewReconciliationImportDto": { + "required": [ + "provider", + "sourceName" + ], + "type": "object", + "properties": { + "provider": { + "maxLength": 50, + "minLength": 0, + "type": "string", + "description": "服务提供方。" + }, + "billDate": { + "type": "string", + "description": "账单日期。", + "format": "date" + }, + "billType": { + "description": "账单类型。", + "$ref": "#/components/schemas/ReconciliationBillType" + }, + "sourceName": { + "maxLength": 300, + "minLength": 0, + "type": "string", + "description": "来源名称。" + }, + "rows": { + "description": "数据行列表。", + "$ref": "#/components/schemas/JsonElement" + } + }, + "description": "预览对账导入请求 DTO。" + }, + "PreviewTenantThemeDto": { + "required": [ + "templateCode" + ], + "type": "object", + "properties": { + "templateCode": { + "type": "string", + "description": "模板编码。" + }, + "theme": { + "description": "主题配置。", + "$ref": "#/components/schemas/JsonElement" + }, + "publicAssets": { + "description": "公开资源配置。", + "$ref": "#/components/schemas/JsonElement" + } + }, + "description": "预览租户主题请求 DTO。" + }, + "ProblemDetails": { + "type": "object", + "properties": { + "type": { + "type": [ + "null", + "string" + ] + }, + "title": { + "type": [ + "null", + "string" + ] + }, + "status": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "format": "int32" + }, + "detail": { + "type": [ + "null", + "string" + ] + }, + "instance": { + "type": [ + "null", + "string" + ] + } + } + }, + "ProductCatalogItem": { + "required": [ + "id", + "legacyId", + "regionId", + "title", + "price", + "priceLabel", + "link", + "type", + "tags", + "cover", + "previewIframe", + "detailImages", + "order", + "isActive" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "legacyId": { + "type": [ + "null", + "string" + ] + }, + "regionId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "title": { + "type": "string" + }, + "price": { + "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$", + "type": [ + "null", + "number", + "string" + ], + "format": "double" + }, + "priceLabel": { + "type": [ + "null", + "string" + ] + }, + "link": { + "type": [ + "null", + "string" + ] + }, + "type": { + "$ref": "#/components/schemas/ProductType" + }, + "tags": { + "$ref": "#/components/schemas/JsonElement" + }, + "cover": { + "type": [ + "null", + "string" + ] + }, + "previewIframe": { + "type": [ + "null", + "string" + ] + }, + "detailImages": { + "$ref": "#/components/schemas/JsonElement" + }, + "order": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "isActive": { + "type": "boolean" + } + } + }, + "ProductType": { + "type": "integer" + }, + "ProfileNotificationItem": { + "required": [ + "id", + "notificationType", + "status", + "severity", + "title", + "message", + "actionLabel", + "actionPath", + "sourceType", + "sourceId", + "metadata", + "readAt", + "createdAt" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "notificationType": { + "type": "string" + }, + "status": { + "type": "string" + }, + "severity": { + "type": "string" + }, + "title": { + "type": "string" + }, + "message": { + "type": "string" + }, + "actionLabel": { + "type": [ + "null", + "string" + ] + }, + "actionPath": { + "type": [ + "null", + "string" + ] + }, + "sourceType": { + "type": [ + "null", + "string" + ] + }, + "sourceId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "metadata": { + "$ref": "#/components/schemas/JsonElement" + }, + "readAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "createdAt": { + "type": "string", + "format": "date-time" + } + } + }, + "ProfileNotificationList": { + "required": [ + "items", + "summary" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ProfileNotificationItem" + } + }, + "summary": { + "type": "object", + "additionalProperties": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + } + } + } + }, + "ProfileScoreEventItem": { + "required": [ + "id", + "eventType", + "points", + "balanceAfter", + "sourceType", + "sourceId", + "metadata", + "createdAt" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "eventType": { + "type": "string" + }, + "points": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "balanceAfter": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "sourceType": { + "type": [ + "null", + "string" + ] + }, + "sourceId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "metadata": { + "$ref": "#/components/schemas/JsonElement" + }, + "createdAt": { + "type": "string", + "format": "date-time" + } + } + }, + "ProfileScoreEventList": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ProfileScoreEventItem" + } + } + } + }, + "PublicTenantBrandingDto": { + "required": [ + "brandName", + "shortName", + "slogan", + "logoUrl", + "faviconUrl", + "serviceWechat", + "serviceAccountName", + "theme", + "publicAssets" + ], + "type": "object", + "properties": { + "brandName": { + "type": [ + "null", + "string" + ], + "description": "品牌名称。" + }, + "shortName": { + "type": [ + "null", + "string" + ], + "description": "品牌短名称。" + }, + "slogan": { + "type": [ + "null", + "string" + ], + "description": "品牌标语。" + }, + "logoUrl": { + "type": [ + "null", + "string" + ], + "description": "Logo 地址。" + }, + "faviconUrl": { + "type": [ + "null", + "string" + ], + "description": "Favicon 地址。" + }, + "serviceWechat": { + "type": [ + "null", + "string" + ], + "description": "客服微信。" + }, + "serviceAccountName": { + "type": [ + "null", + "string" + ], + "description": "公众号或服务号名称。" + }, + "theme": { + "description": "公开主题配置。", + "$ref": "#/components/schemas/JsonElement" + }, + "publicAssets": { + "description": "公开资源配置。", + "$ref": "#/components/schemas/JsonElement" + } + }, + "description": "可公开给客户端的租户品牌信息。" + }, + "PublicTenantDto": { + "required": [ + "id", + "slug", + "name", + "status", + "mode", + "host" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "租户 ID。", + "format": "uuid" + }, + "slug": { + "type": "string", + "description": "租户编码。" + }, + "name": { + "type": "string", + "description": "租户名称。" + }, + "status": { + "description": "租户状态。", + "$ref": "#/components/schemas/TenantStatus" + }, + "mode": { + "description": "租户模式。", + "$ref": "#/components/schemas/TenantMode" + }, + "host": { + "type": [ + "null", + "string" + ], + "description": "当前匹配到的访问域名。" + } + }, + "description": "可公开给客户端的租户基础信息。" + }, + "PublishTenantFrontendConfigDto": { + "type": "object", + "properties": { + "expectedVersion": { + "maximum": 2147483647, + "minimum": 1, + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "description": "期望配置版本。", + "format": "int32" + } + }, + "description": "发布租户前端配置请求。" + }, + "PublishTenantThemeDto": { + "type": "object", + "properties": { + "useDraft": { + "type": [ + "null", + "boolean" + ], + "description": "是否使用草稿配置。" + }, + "templateCode": { + "type": [ + "null", + "string" + ], + "description": "模板编码。" + }, + "theme": { + "description": "主题配置。", + "$ref": "#/components/schemas/JsonElement" + }, + "publicAssets": { + "description": "公开资源配置。", + "$ref": "#/components/schemas/JsonElement" + } + }, + "description": "发布租户主题请求 DTO。" + }, + "QuestionActionDto": { + "required": [ + "questionId", + "source" + ], + "type": "object", + "properties": { + "questionId": { + "type": "string", + "description": "题目 ID。", + "format": "uuid" + }, + "source": { + "description": "来源。", + "$ref": "#/components/schemas/QuestionSource" + }, + "favorite": { + "type": [ + "null", + "boolean" + ], + "description": "是否收藏。" + } + }, + "description": "题目Action请求 DTO。" + }, + "QuestionBankCatalogItem": { + "required": [ + "id", + "regionId", + "name", + "source", + "status", + "metadata" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "regionId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "name": { + "type": "string" + }, + "source": { + "$ref": "#/components/schemas/QuestionSource" + }, + "status": { + "$ref": "#/components/schemas/QuestionBankStatus" + }, + "metadata": { + "$ref": "#/components/schemas/JsonElement" + } + } + }, + "QuestionBankStatus": { + "type": "integer" + }, + "QuestionCatalogItem": { + "required": [ + "id", + "questionBankId", + "subjectId", + "categoryId", + "nodeId", + "entryId", + "contentNodeId", + "primaryCollectionId", + "legacyId", + "legacySubjectId", + "legacyCategoryId", + "legacyNodeId", + "type", + "typeLabel", + "difficulty", + "tags", + "examMarkers", + "mediaUrl", + "hasVideoExplanation", + "status", + "versionId", + "versionNo", + "content", + "options", + "correctOptionIndex", + "correctOptionIndices", + "answerText", + "explanation", + "subQuestions", + "codeLang", + "codeTemplate", + "locator" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "questionBankId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "subjectId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "categoryId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "nodeId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "entryId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "contentNodeId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "primaryCollectionId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "legacyId": { + "type": [ + "null", + "string" + ] + }, + "legacySubjectId": { + "type": [ + "null", + "string" + ] + }, + "legacyCategoryId": { + "type": [ + "null", + "string" + ] + }, + "legacyNodeId": { + "type": [ + "null", + "string" + ] + }, + "type": { + "type": "string" + }, + "typeLabel": { + "type": [ + "null", + "string" + ] + }, + "difficulty": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "format": "int32" + }, + "tags": { + "$ref": "#/components/schemas/JsonElement" + }, + "examMarkers": { + "$ref": "#/components/schemas/JsonElement" + }, + "mediaUrl": { + "type": [ + "null", + "string" + ] + }, + "hasVideoExplanation": { + "type": "boolean" + }, + "status": { + "$ref": "#/components/schemas/QuestionStatus" + }, + "versionId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "versionNo": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "format": "int32" + }, + "content": { + "type": [ + "null", + "string" + ] + }, + "options": { + "$ref": "#/components/schemas/JsonElement" + }, + "correctOptionIndex": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "format": "int32" + }, + "correctOptionIndices": { + "$ref": "#/components/schemas/JsonElement" + }, + "answerText": { + "type": [ + "null", + "string" + ] + }, + "explanation": { + "type": [ + "null", + "string" + ] + }, + "subQuestions": { + "$ref": "#/components/schemas/JsonElement" + }, + "codeLang": { + "type": [ + "null", + "string" + ] + }, + "codeTemplate": { + "type": [ + "null", + "string" + ] + }, + "locator": { + "$ref": "#/components/schemas/QuestionLocator" + } + } + }, + "QuestionCollectionCatalogItem": { + "required": [ + "id", + "regionId", + "entryId", + "nodeId", + "subjectId", + "categoryId", + "questionBankId", + "legacyId", + "name", + "collectionType", + "sourceType", + "filters", + "questionCount", + "totalScore", + "durationMinutes", + "status", + "order", + "accessRules", + "metadata" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "regionId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "entryId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "nodeId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "subjectId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "categoryId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "questionBankId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "legacyId": { + "type": [ + "null", + "string" + ] + }, + "name": { + "type": "string" + }, + "collectionType": { + "$ref": "#/components/schemas/QuestionCollectionType" + }, + "sourceType": { + "$ref": "#/components/schemas/QuestionCollectionSourceType" + }, + "filters": { + "$ref": "#/components/schemas/JsonElement" + }, + "questionCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "totalScore": { + "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$", + "type": [ + "null", + "number", + "string" + ], + "format": "double" + }, + "durationMinutes": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "format": "int32" + }, + "status": { + "$ref": "#/components/schemas/ContentStatus" + }, + "order": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "accessRules": { + "$ref": "#/components/schemas/JsonElement" + }, + "metadata": { + "$ref": "#/components/schemas/JsonElement" + } + } + }, + "QuestionCollectionItemManagementItem": { + "required": [ + "id", + "collectionId", + "questionId", + "locator", + "sectionKey", + "order", + "score", + "required", + "metadata" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "collectionId": { + "type": "string", + "format": "uuid" + }, + "questionId": { + "type": "string", + "format": "uuid" + }, + "locator": { + "$ref": "#/components/schemas/QuestionLocator" + }, + "sectionKey": { + "type": [ + "null", + "string" + ] + }, + "order": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "score": { + "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$", + "type": [ + "null", + "number", + "string" + ], + "format": "double" + }, + "required": { + "type": "boolean" + }, + "metadata": { + "$ref": "#/components/schemas/JsonElement" + } + } + }, + "QuestionCollectionManagementItem": { + "required": [ + "id", + "regionId", + "entryId", + "nodeId", + "subjectId", + "categoryId", + "questionBankId", + "legacyId", + "name", + "collectionType", + "sourceType", + "filters", + "questionCount", + "totalScore", + "durationMinutes", + "status", + "order", + "accessRules", + "metadata", + "createdAt", + "updatedAt" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "regionId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "entryId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "nodeId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "subjectId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "categoryId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "questionBankId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "legacyId": { + "type": [ + "null", + "string" + ] + }, + "name": { + "type": "string" + }, + "collectionType": { + "$ref": "#/components/schemas/QuestionCollectionType" + }, + "sourceType": { + "$ref": "#/components/schemas/QuestionCollectionSourceType" + }, + "filters": { + "$ref": "#/components/schemas/JsonElement" + }, + "questionCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "totalScore": { + "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$", + "type": [ + "null", + "number", + "string" + ], + "format": "double" + }, + "durationMinutes": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "format": "int32" + }, + "status": { + "$ref": "#/components/schemas/ContentStatus" + }, + "order": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "accessRules": { + "$ref": "#/components/schemas/JsonElement" + }, + "metadata": { + "$ref": "#/components/schemas/JsonElement" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + } + } + }, + "QuestionCollectionSourceType": { + "type": "integer" + }, + "QuestionCollectionType": { + "type": "integer" + }, + "QuestionLocator": { + "required": [ + "source", + "questionId" + ], + "type": "object", + "properties": { + "source": { + "$ref": "#/components/schemas/QuestionSource" + }, + "questionId": { + "type": "string", + "format": "uuid" + } + } + }, + "QuestionManagementItem": { + "required": [ + "id", + "versionId", + "questionBankId", + "subjectId", + "categoryId", + "nodeId", + "entryId", + "contentNodeId", + "primaryCollectionId", + "legacyId", + "type", + "typeLabel", + "difficulty", + "tags", + "content", + "options", + "correctOptionIndex", + "correctOptionIndices", + "answerText", + "explanation", + "subQuestions", + "codeLang", + "codeTemplate", + "mediaUrl", + "hasVideoExplanation", + "status" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "versionId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "questionBankId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "subjectId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "categoryId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "nodeId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "entryId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "contentNodeId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "primaryCollectionId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "legacyId": { + "type": [ + "null", + "string" + ] + }, + "type": { + "type": "string" + }, + "typeLabel": { + "type": [ + "null", + "string" + ] + }, + "difficulty": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "format": "int32" + }, + "tags": { + "$ref": "#/components/schemas/JsonElement" + }, + "content": { + "type": [ + "null", + "string" + ] + }, + "options": { + "$ref": "#/components/schemas/JsonElement" + }, + "correctOptionIndex": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "format": "int32" + }, + "correctOptionIndices": { + "$ref": "#/components/schemas/JsonElement" + }, + "answerText": { + "type": [ + "null", + "string" + ] + }, + "explanation": { + "type": [ + "null", + "string" + ] + }, + "subQuestions": { + "$ref": "#/components/schemas/JsonElement" + }, + "codeLang": { + "type": [ + "null", + "string" + ] + }, + "codeTemplate": { + "type": [ + "null", + "string" + ] + }, + "mediaUrl": { + "type": [ + "null", + "string" + ] + }, + "hasVideoExplanation": { + "type": "boolean" + }, + "status": { + "$ref": "#/components/schemas/QuestionStatus" + } + } + }, + "QuestionSource": { + "type": "integer" + }, + "QuestionStatus": { + "type": "integer" + }, + "QuestionVersionCatalogItem": { + "required": [ + "id", + "questionId", + "versionNo", + "content", + "options", + "correctOptionIndex", + "correctOptionIndices", + "answerText", + "explanation", + "subQuestions", + "codeLang", + "codeTemplate", + "createdAt" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "questionId": { + "type": "string", + "format": "uuid" + }, + "versionNo": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "content": { + "type": [ + "null", + "string" + ] + }, + "options": { + "$ref": "#/components/schemas/JsonElement" + }, + "correctOptionIndex": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "format": "int32" + }, + "correctOptionIndices": { + "$ref": "#/components/schemas/JsonElement" + }, + "answerText": { + "type": [ + "null", + "string" + ] + }, + "explanation": { + "type": [ + "null", + "string" + ] + }, + "subQuestions": { + "$ref": "#/components/schemas/JsonElement" + }, + "codeLang": { + "type": [ + "null", + "string" + ] + }, + "codeTemplate": { + "type": [ + "null", + "string" + ] + }, + "createdAt": { + "type": "string", + "format": "date-time" + } + } + }, + "QuestionVideoCatalogItem": { + "required": [ + "id", + "legacyId", + "questionId", + "videoId", + "videoType", + "order", + "metadata", + "video" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "legacyId": { + "type": [ + "null", + "string" + ] + }, + "questionId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "videoId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "videoType": { + "$ref": "#/components/schemas/QuestionVideoType" + }, + "order": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "metadata": { + "$ref": "#/components/schemas/JsonElement" + }, + "video": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/components/schemas/VideoExplanationCatalogItem" + } + ] + } + } + }, + "QuestionVideoManagementItem": { + "required": [ + "id", + "questionId", + "videoId", + "legacyId", + "videoType", + "order", + "metadata" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "questionId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "videoId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "legacyId": { + "type": [ + "null", + "string" + ] + }, + "videoType": { + "$ref": "#/components/schemas/QuestionVideoType" + }, + "order": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "metadata": { + "$ref": "#/components/schemas/JsonElement" + } + } + }, + "QuestionVideoQueryDto": { + "type": "object", + "properties": { + "questionId": { + "type": [ + "null", + "string" + ], + "description": "题目 ID。", + "format": "uuid" + }, + "questionIds": { + "maxItems": 100, + "type": [ + "null", + "array" + ], + "items": { + "type": "string", + "format": "uuid" + }, + "description": "题目 ID 列表。" + }, + "limit": { + "maximum": 500, + "minimum": 1, + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "description": "返回数量上限。", + "format": "int32" + } + }, + "description": "题目视频查询参数。" + }, + "QuestionVideoType": { + "type": "integer" + }, + "RecentPracticeItem": { + "required": [ + "id", + "practiceType", + "targetName", + "progress", + "lastAccessAt", + "lastPracticeAt" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "practiceType": { + "type": [ + "null", + "string" + ] + }, + "targetName": { + "type": [ + "null", + "string" + ] + }, + "progress": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "lastAccessAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "lastPracticeAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + } + } + }, + "ReconciliationBatchStatus": { + "type": "integer" + }, + "ReconciliationBillType": { + "type": "integer" + }, + "ReconciliationImportPreview": { + "required": [ + "totalCount", + "paymentCount", + "refundCount", + "invalidCount", + "amountCents", + "refundAmountCents", + "sourceHash" + ], + "type": "object", + "properties": { + "totalCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "paymentCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "refundCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "invalidCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "amountCents": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "refundAmountCents": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "sourceHash": { + "type": "string" + } + } + }, + "ReconciliationIssueMatchStatus": { + "type": "integer" + }, + "ReconciliationIssueStatus": { + "type": "integer" + }, + "ReconciliationMatchStatus": { + "type": "integer" + }, + "ReconciliationResolutionType": { + "type": "integer" + }, + "ReconciliationSource": { + "type": "integer" + }, + "ReconciliationTransactionType": { + "type": "integer" + }, + "RedeemActivationCodeDto": { + "required": [ + "code", + "userId" + ], + "type": "object", + "properties": { + "code": { + "maxLength": 100, + "minLength": 0, + "type": "string", + "description": "编码。" + }, + "userId": { + "type": "string", + "description": "用户 ID。", + "format": "uuid" + }, + "regionId": { + "type": [ + "null", + "string" + ], + "description": "地区 ID。", + "format": "uuid" + } + }, + "description": "核销激活码编码请求 DTO。" + }, + "ReferralAssignmentMode": { + "type": "integer" + }, + "ReferralBindResult": { + "required": [ + "lead", + "crmQueue" + ], + "type": "object", + "properties": { + "lead": { + "$ref": "#/components/schemas/ReferralLeadItem" + }, + "crmQueue": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/components/schemas/CrmQueuePreviewItem" + } + ] + } + } + }, + "ReferralConversionReport": { + "required": [ + "startDate", + "endDate", + "leadCount", + "paidLeadCount", + "paidAmountCents", + "conversionRate", + "topReferrers", + "recentUnconvertedLeads" + ], + "type": "object", + "properties": { + "startDate": { + "type": "string", + "format": "date" + }, + "endDate": { + "type": "string", + "format": "date" + }, + "leadCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "paidLeadCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "paidAmountCents": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "conversionRate": { + "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$", + "type": [ + "number", + "string" + ], + "format": "double" + }, + "topReferrers": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ReferralStatsItem" + } + }, + "recentUnconvertedLeads": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ReferralLeadItem" + } + } + } + }, + "ReferralInviteDto": { + "type": "object", + "properties": { + "channel": { + "maxLength": 100, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "渠道。" + }, + "landingPath": { + "maxLength": 2048, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "落地页路径。" + } + }, + "description": "推荐邀请码请求 DTO。" + }, + "ReferralInviteItem": { + "required": [ + "inviteCode" + ], + "type": "object", + "properties": { + "inviteCode": { + "type": "string" + } + } + }, + "ReferralLeadItem": { + "required": [ + "id", + "studentUserId", + "referrerUserId", + "refCode", + "status", + "boundAt", + "changed" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "studentUserId": { + "type": "string", + "format": "uuid" + }, + "referrerUserId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "refCode": { + "type": [ + "null", + "string" + ] + }, + "status": { + "type": "string" + }, + "boundAt": { + "type": "string", + "format": "date-time" + }, + "changed": { + "type": "boolean" + } + } + }, + "ReferralListOfReferralLeadItem": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ReferralLeadItem" + } + } + } + }, + "ReferralListOfReferralStatsItem": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ReferralStatsItem" + } + } + } + }, + "ReferralListOfReferralTeamItem": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ReferralTeamItem" + } + } + } + }, + "ReferralQrcodeDto": { + "type": "object", + "properties": { + "page": { + "maxLength": 500, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "页码。" + }, + "scene": { + "maxLength": 128, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "场景参数。" + }, + "provider": { + "maxLength": 100, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "服务提供方。" + }, + "qrcodeUrl": { + "maxLength": 2048, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "二维码地址。" + }, + "metadata": { + "oneOf": [ + { + "type": "null" + }, + { + "description": "扩展元数据。", + "$ref": "#/components/schemas/JsonElement" + } + ] + } + }, + "description": "推荐二维码请求 DTO。" + }, + "ReferralQrcodeItem": { + "required": [ + "id", + "refCode", + "scene", + "page", + "provider", + "qrcodeUrl", + "status", + "metadata" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "refCode": { + "type": "string" + }, + "scene": { + "type": "string" + }, + "page": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "qrcodeUrl": { + "type": [ + "null", + "string" + ] + }, + "status": { + "type": "string" + }, + "metadata": { + "$ref": "#/components/schemas/JsonElement" + } + } + }, + "ReferralResolutionItem": { + "required": [ + "valid", + "inviterId", + "inviteCode", + "role", + "name" + ], + "type": "object", + "properties": { + "valid": { + "type": "boolean" + }, + "inviterId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "inviteCode": { + "type": [ + "null", + "string" + ] + }, + "role": { + "type": [ + "null", + "string" + ] + }, + "name": { + "type": [ + "null", + "string" + ] + } + } + }, + "ReferralStatsItem": { + "required": [ + "referrerUserId", + "name", + "role", + "inviteCode", + "leadCount", + "paidLeadCount", + "paidAmountCents", + "trackCount", + "conversionRate" + ], + "type": "object", + "properties": { + "referrerUserId": { + "type": "string", + "format": "uuid" + }, + "name": { + "type": [ + "null", + "string" + ] + }, + "role": { + "type": "string" + }, + "inviteCode": { + "type": [ + "null", + "string" + ] + }, + "leadCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "paidLeadCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "paidAmountCents": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "trackCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "conversionRate": { + "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$", + "type": [ + "number", + "string" + ], + "format": "double" + } + } + }, + "ReferralTeamItem": { + "required": [ + "id", + "memberUserId", + "leaderUserId", + "relationType", + "status", + "metadata" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "memberUserId": { + "type": "string", + "format": "uuid" + }, + "leaderUserId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "relationType": { + "type": "string" + }, + "status": { + "type": "string" + }, + "metadata": { + "$ref": "#/components/schemas/JsonElement" + } + } + }, + "ReferralTrackItem": { + "required": [ + "id", + "eventType", + "refCode", + "referrerUserId", + "targetUserId", + "source", + "createdAt" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "eventType": { + "type": "string" + }, + "refCode": { + "type": [ + "null", + "string" + ] + }, + "referrerUserId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "targetUserId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "source": { + "type": [ + "null", + "string" + ] + }, + "createdAt": { + "type": "string", + "format": "date-time" + } + } + }, + "ReferralTrackResult": { + "required": [ + "item", + "lead", + "crmQueue" + ], + "type": "object", + "properties": { + "item": { + "$ref": "#/components/schemas/ReferralTrackItem" + }, + "lead": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/components/schemas/ReferralLeadItem" + } + ] + }, + "crmQueue": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/components/schemas/CrmQueuePreviewItem" + } + ] + } + } + }, + "RefreshSessionDto": { + "required": [ + "refreshToken" + ], + "type": "object", + "properties": { + "refreshToken": { + "maxLength": 2048, + "minLength": 0, + "type": "string", + "description": "刷新令牌。" + } + }, + "description": "刷新会话请求 DTO。" + }, + "RefundEntitlementAction": { + "type": "integer" + }, + "RefundNotificationDto": { + "required": [ + "refundNo" + ], + "type": "object", + "properties": { + "refundNo": { + "maxLength": 100, + "minLength": 0, + "type": "string", + "description": "退款单号。" + }, + "providerRefundNo": { + "maxLength": 200, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "渠道退款单号。" + }, + "status": { + "description": "状态。", + "$ref": "#/components/schemas/CommerceRefundStatus" + }, + "eventId": { + "maxLength": 200, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "事件 ID。" + }, + "payload": { + "description": "任务载荷。", + "$ref": "#/components/schemas/JsonElement" + } + }, + "description": "退款通知请求 DTO。" + }, + "RegionCatalogItem": { + "required": [ + "id", + "legacyId", + "name", + "code", + "shortName", + "fullName", + "icon", + "pinyin", + "order", + "isHot" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "legacyId": { + "type": [ + "null", + "string" + ] + }, + "name": { + "type": "string" + }, + "code": { + "type": [ + "null", + "string" + ] + }, + "shortName": { + "type": [ + "null", + "string" + ] + }, + "fullName": { + "type": [ + "null", + "string" + ] + }, + "icon": { + "type": [ + "null", + "string" + ] + }, + "pinyin": { + "type": [ + "null", + "string" + ] + }, + "order": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "isHot": { + "type": "boolean" + } + } + }, + "RegionModuleCatalogItem": { + "required": [ + "id", + "legacyId", + "regionId", + "name", + "type", + "icon", + "color", + "textColor", + "description", + "route", + "order", + "isPrimarySchoolModule" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "legacyId": { + "type": [ + "null", + "string" + ] + }, + "regionId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "name": { + "type": "string" + }, + "type": { + "type": [ + "null", + "string" + ] + }, + "icon": { + "type": [ + "null", + "string" + ] + }, + "color": { + "type": [ + "null", + "string" + ] + }, + "textColor": { + "type": [ + "null", + "string" + ] + }, + "description": { + "type": [ + "null", + "string" + ] + }, + "route": { + "type": [ + "null", + "string" + ] + }, + "order": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "isPrimarySchoolModule": { + "type": "boolean" + } + } + }, + "RemoveTenantAdminClassMemberDto": { + "required": [ + "classMemberId" + ], + "type": "object", + "properties": { + "classMemberId": { + "type": "string", + "description": "班级成员 ID。", + "format": "uuid" + } + }, + "description": "移除租户管理端班级成员请求 DTO。" + }, + "ReplaceCollectionItemsDto": { + "required": [ + "collectionId" + ], + "type": "object", + "properties": { + "collectionId": { + "type": "string", + "description": "题集 ID。", + "format": "uuid" + }, + "questions": { + "type": "array", + "items": { + "$ref": "#/components/schemas/CollectionQuestionDto" + }, + "description": "题目列表。" + } + }, + "description": "替换题集Items请求 DTO。" + }, + "ReplaceRoleBindingsDto": { + "type": "object", + "properties": { + "permissionCodes": { + "type": "array", + "items": { + "type": "string" + }, + "description": "权限编码列表。" + }, + "menuCodes": { + "type": "array", + "items": { + "type": "string" + }, + "description": "菜单编码列表。" + } + }, + "description": "替换角色权限绑定请求。" + }, + "ReplaceUserRolesDto": { + "type": "object", + "properties": { + "roleIds": { + "type": "array", + "items": { + "type": "string", + "format": "uuid" + }, + "description": "角色 ID 列表。" + } + }, + "description": "替换用户角色请求。" + }, + "ReportPriority": { + "type": "integer" + }, + "ReportStatus": { + "type": "integer" + }, + "ReportType": { + "type": "integer" + }, + "RequestProviderBillJobDto": { + "required": [ + "provider" + ], + "type": "object", + "properties": { + "provider": { + "maxLength": 50, + "minLength": 0, + "type": "string", + "description": "服务提供方。" + }, + "billDate": { + "type": "string", + "description": "账单日期。", + "format": "date" + }, + "billType": { + "description": "账单类型。", + "$ref": "#/components/schemas/ReconciliationBillType" + }, + "runAfter": { + "type": [ + "null", + "string" + ], + "description": "计划运行时间。", + "format": "date-time" + } + }, + "description": "RequestProviderBill任务请求 DTO。" + }, + "RequiredPasswordChangeDto": { + "required": [ + "challengeToken", + "newPassword" + ], + "type": "object", + "properties": { + "challengeToken": { + "maxLength": 2048, + "minLength": 0, + "type": "string", + "description": "挑战令牌。" + }, + "newPassword": { + "maxLength": 128, + "minLength": 8, + "type": "string", + "description": "新密码。" + } + }, + "description": "首次登录必改密码请求。" + }, + "ResolveReferralDto": { + "type": "object", + "properties": { + "code": { + "maxLength": 100, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "编码。" + }, + "tenantCode": { + "maxLength": 100, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "租户编码。" + } + }, + "description": "解析推荐请求 DTO。" + }, + "RetryPlatformBillingDunningEventDto": { + "required": [ + "eventId" + ], + "type": "object", + "properties": { + "eventId": { + "type": "string", + "description": "事件 ID。", + "format": "uuid" + }, + "reason": { + "maxLength": 1000, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "原因。" + } + }, + "description": "重试平台Dunning事件请求 DTO。" + }, + "RetryPlatformCrmLeadDto": { + "required": [ + "queueId" + ], + "type": "object", + "properties": { + "queueId": { + "type": "string", + "description": "队列任务 ID。", + "format": "uuid" + }, + "note": { + "maxLength": 500, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "备注。" + } + }, + "description": "重试租户 CRM 线索推送请求。" + }, + "SaasCatalogSnapshot": { + "required": [ + "features", + "limitDefinitions", + "offerings", + "versions" + ], + "type": "object", + "properties": { + "features": { + "type": "array", + "items": { + "$ref": "#/components/schemas/SaasFeature" + } + }, + "limitDefinitions": { + "type": "array", + "items": { + "$ref": "#/components/schemas/SaasFeatureLimitDefinition" + } + }, + "offerings": { + "type": "array", + "items": { + "$ref": "#/components/schemas/SaasOffering" + } + }, + "versions": { + "type": "array", + "items": { + "$ref": "#/components/schemas/SaasOfferingVersionItem" + } + } + } + }, + "SaasFeature": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "name": { + "type": "string" + }, + "category": { + "type": "string" + }, + "description": { + "type": [ + "null", + "string" + ] + }, + "referencePriceCents": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "currency": { + "type": "string" + }, + "status": { + "$ref": "#/components/schemas/SaasFeatureStatus" + }, + "isCore": { + "type": "boolean" + }, + "sortOrder": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "id": { + "type": "string", + "format": "uuid" + } + } + }, + "SaasFeatureLimitDefinition": { + "type": "object", + "properties": { + "metricCode": { + "type": "string" + }, + "featureCode": { + "type": "string" + }, + "name": { + "type": "string" + }, + "unit": { + "type": "string" + }, + "kind": { + "$ref": "#/components/schemas/SaasFeatureLimitKind" + }, + "warningPercent": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "isHardLimit": { + "type": "boolean" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "id": { + "type": "string", + "format": "uuid" + } + } + }, + "SaasFeatureLimitKind": { + "type": "integer" + }, + "SaasFeatureStatus": { + "type": "integer" + }, + "SaasOffering": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "name": { + "type": "string" + }, + "type": { + "$ref": "#/components/schemas/SaasOfferingType" + }, + "status": { + "$ref": "#/components/schemas/SaasOfferingStatus" + }, + "description": { + "type": [ + "null", + "string" + ] + }, + "sortOrder": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "id": { + "type": "string", + "format": "uuid" + } + } + }, + "SaasOfferingStatus": { + "type": "integer" + }, + "SaasOfferingType": { + "type": "integer" + }, + "SaasOfferingVersionItem": { + "required": [ + "id", + "offeringId", + "offeringCode", + "offeringName", + "offeringType", + "version", + "status", + "billingCycle", + "originalAmountCents", + "amountCents", + "currency", + "effectiveAt", + "publishedAt", + "featureCodes", + "limits" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "offeringId": { + "type": "string", + "format": "uuid" + }, + "offeringCode": { + "type": "string" + }, + "offeringName": { + "type": "string" + }, + "offeringType": { + "$ref": "#/components/schemas/SaasOfferingType" + }, + "version": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "status": { + "$ref": "#/components/schemas/SaasOfferingVersionStatus" + }, + "billingCycle": { + "$ref": "#/components/schemas/PlatformBillingCycle" + }, + "originalAmountCents": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "amountCents": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "currency": { + "type": "string" + }, + "effectiveAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "publishedAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "featureCodes": { + "type": "array", + "items": { + "type": "string" + } + }, + "limits": { + "type": "object", + "additionalProperties": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int64" + } + } + } + }, + "SaasOfferingVersionStatus": { + "type": "integer" + }, + "SaveTenantFrontendConfigDraftDto": { + "type": "object", + "properties": { + "branding": { + "description": "品牌配置。", + "$ref": "#/components/schemas/JsonElement" + }, + "theme": { + "description": "主题配置。", + "$ref": "#/components/schemas/JsonElement" + }, + "features": { + "description": "功能配置。", + "$ref": "#/components/schemas/JsonElement" + }, + "navigation": { + "description": "导航配置。", + "$ref": "#/components/schemas/JsonElement" + }, + "homeModules": { + "description": "首页模块配置。", + "$ref": "#/components/schemas/JsonElement" + } + }, + "description": "保存租户前端配置草稿请求。" + }, + "School": { + "type": "object", + "properties": { + "regionId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "moduleId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "legacyId": { + "type": [ + "null", + "string" + ] + }, + "name": { + "type": "string" + }, + "professionalExamDate": { + "type": [ + "null", + "string" + ] + }, + "metadata": { + "$ref": "#/components/schemas/JsonElement" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "tenantId": { + "type": "string", + "format": "uuid" + }, + "id": { + "type": "string", + "format": "uuid" + } + } + }, + "SchoolCatalogItem": { + "required": [ + "id", + "legacyId", + "regionId", + "moduleId", + "name", + "professionalExamDate", + "metadata" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "legacyId": { + "type": [ + "null", + "string" + ] + }, + "regionId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "moduleId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "name": { + "type": "string" + }, + "professionalExamDate": { + "type": [ + "null", + "string" + ] + }, + "metadata": { + "$ref": "#/components/schemas/JsonElement" + } + } + }, + "ScorelineField": { + "type": "object", + "properties": { + "regionId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "legacyId": { + "type": [ + "null", + "string" + ] + }, + "fieldKey": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "fieldType": { + "type": "string" + }, + "unit": { + "type": [ + "null", + "string" + ] + }, + "isFilter": { + "type": "boolean" + }, + "isRequired": { + "type": "boolean" + }, + "isVisible": { + "type": "boolean" + }, + "isTrend": { + "type": "boolean" + }, + "options": { + "$ref": "#/components/schemas/JsonElement" + }, + "placeholder": { + "type": [ + "null", + "string" + ] + }, + "description": { + "type": [ + "null", + "string" + ] + }, + "sortOrder": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "tenantId": { + "type": "string", + "format": "uuid" + }, + "id": { + "type": "string", + "format": "uuid" + } + } + }, + "ScorelineFieldItem": { + "required": [ + "id", + "legacyId", + "regionId", + "fieldKey", + "fieldName", + "fieldType", + "unit", + "isFilter", + "isRequired", + "isVisible", + "isTrend", + "options", + "placeholder", + "description", + "sortOrder" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "legacyId": { + "type": [ + "null", + "string" + ] + }, + "regionId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "fieldKey": { + "type": "string" + }, + "fieldName": { + "type": "string" + }, + "fieldType": { + "type": "string" + }, + "unit": { + "type": [ + "null", + "string" + ] + }, + "isFilter": { + "type": "boolean" + }, + "isRequired": { + "type": "boolean" + }, + "isVisible": { + "type": "boolean" + }, + "isTrend": { + "type": "boolean" + }, + "options": { + "$ref": "#/components/schemas/JsonElement" + }, + "placeholder": { + "type": [ + "null", + "string" + ] + }, + "description": { + "type": [ + "null", + "string" + ] + }, + "sortOrder": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + } + } + }, + "ScorelineRecord": { + "type": "object", + "properties": { + "regionId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "schoolId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "majorId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "legacyId": { + "type": [ + "null", + "string" + ] + }, + "year": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "schoolName": { + "type": [ + "null", + "string" + ] + }, + "majorName": { + "type": [ + "null", + "string" + ] + }, + "fieldValues": { + "$ref": "#/components/schemas/JsonElement" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "tenantId": { + "type": "string", + "format": "uuid" + }, + "id": { + "type": "string", + "format": "uuid" + } + } + }, + "ScorelineRecordCursorPage": { + "required": [ + "pageSize", + "hasMore", + "nextCursor", + "items" + ], + "type": "object", + "properties": { + "pageSize": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "hasMore": { + "type": "boolean" + }, + "nextCursor": { + "type": [ + "null", + "string" + ] + }, + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ScorelineRecordItem" + } + } + } + }, + "ScorelineRecordItem": { + "required": [ + "id", + "legacyId", + "regionId", + "schoolId", + "majorId", + "year", + "schoolName", + "majorName", + "fieldValues" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "legacyId": { + "type": [ + "null", + "string" + ] + }, + "regionId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "schoolId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "majorId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "year": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "schoolName": { + "type": [ + "null", + "string" + ] + }, + "majorName": { + "type": [ + "null", + "string" + ] + }, + "fieldValues": { + "$ref": "#/components/schemas/JsonElement" + } + } + }, + "ScorelineRecordPage": { + "required": [ + "page", + "pageSize", + "total", + "items" + ], + "type": "object", + "properties": { + "page": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "pageSize": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "total": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ScorelineRecordItem" + } + } + } + }, + "ScorelineTrendItem": { + "required": [ + "year", + "schoolCount", + "majorCount" + ], + "type": "object", + "properties": { + "year": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "schoolCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "majorCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + } + } + }, + "SendSmsCodeDto": { + "required": [ + "realm", + "phone" + ], + "type": "object", + "properties": { + "realm": { + "oneOf": [ + { + "type": "null" + }, + { + "description": "认证域。", + "$ref": "#/components/schemas/AuthRealm" + } + ] + }, + "tenantCode": { + "maxLength": 100, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "租户编码。" + }, + "phone": { + "maxLength": 32, + "minLength": 0, + "type": "string", + "description": "手机号。" + }, + "deviceId": { + "maxLength": 256, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "设备 ID。" + } + }, + "description": "发送短信验证码请求。" + }, + "SignedStorageUrlDto": { + "required": [ + "provider", + "bucket", + "objectKey", + "method", + "url", + "headers", + "expiresAt", + "expiresInSeconds", + "signatureMode" + ], + "type": "object", + "properties": { + "provider": { + "type": "string" + }, + "bucket": { + "type": [ + "null", + "string" + ] + }, + "objectKey": { + "type": [ + "null", + "string" + ] + }, + "method": { + "type": "string" + }, + "url": { + "type": "string" + }, + "headers": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "expiresAt": { + "type": "string", + "format": "date-time" + }, + "expiresInSeconds": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "signatureMode": { + "type": "string" + } + }, + "description": "SignedStorageUrl请求 DTO。" + }, + "SimpleImportResult": { + "required": [ + "job", + "items", + "issues" + ], + "type": "object", + "properties": { + "job": { + "$ref": "#/components/schemas/ContentImportJobItem" + }, + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ContentImportItemModel" + } + }, + "issues": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ContentImportIssueModel" + } + } + } + }, + "SmsLoginDto": { + "required": [ + "realm", + "phone", + "code" + ], + "type": "object", + "properties": { + "realm": { + "oneOf": [ + { + "type": "null" + }, + { + "description": "认证域。", + "$ref": "#/components/schemas/AuthRealm" + } + ] + }, + "tenantCode": { + "maxLength": 100, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "租户编码。" + }, + "phone": { + "maxLength": 32, + "minLength": 0, + "type": "string", + "description": "手机号。" + }, + "code": { + "maxLength": 12, + "minLength": 4, + "type": "string", + "description": "编码。" + } + }, + "description": "SmsLogin请求 DTO。" + }, + "SmsSendLog": { + "type": "object", + "properties": { + "tenantId": { + "type": "string", + "format": "uuid" + }, + "channelId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "templateId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "provider": { + "type": "string" + }, + "scene": { + "type": "string" + }, + "phoneMasked": { + "type": [ + "null", + "string" + ] + }, + "status": { + "$ref": "#/components/schemas/SmsSendLogStatus" + }, + "providerMessageId": { + "type": [ + "null", + "string" + ] + }, + "errorCode": { + "type": [ + "null", + "string" + ] + }, + "errorMessage": { + "type": [ + "null", + "string" + ] + }, + "sentAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "metadata": { + "$ref": "#/components/schemas/JsonElement" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "id": { + "type": "string", + "format": "uuid" + } + } + }, + "SmsSendLogStatus": { + "type": "integer" + }, + "SmsSendResult": { + "required": [ + "verificationId", + "expiresAt" + ], + "type": "object", + "properties": { + "verificationId": { + "type": "string", + "format": "uuid" + }, + "expiresAt": { + "type": "string", + "format": "date-time" + } + } + }, + "SmsTemplateAuditStatus": { + "type": "integer" + }, + "SmsTemplateStatus": { + "type": "integer" + }, + "SmsTemplateType": { + "type": "integer" + }, + "StudentFollowupPriority": { + "type": "integer" + }, + "StudentFollowupStatus": { + "type": "integer" + }, + "StudentFollowupType": { + "type": "integer" + }, + "StudentMembershipItem": { + "required": [ + "isSvip", + "expiresAt" + ], + "type": "object", + "properties": { + "isSvip": { + "type": "boolean" + }, + "expiresAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + } + } + }, + "StudentNoteType": { + "type": "integer" + }, + "StudentNoteVisibility": { + "type": "integer" + }, + "StudentProfileItem": { + "required": [ + "profileId", + "userId", + "username", + "phone", + "email", + "name", + "avatarPreset", + "avatarDisplayUrl", + "primaryRole", + "score", + "regionId", + "regionName", + "selectedSchoolId", + "selectedSchoolName", + "selectedMajorId", + "selectedMajorName", + "questionsAnsweredToday", + "masteredWordsCount", + "lastCheckInDate", + "stats", + "progress", + "moduleSelections", + "recentActivities", + "recentPractices", + "membership" + ], + "type": "object", + "properties": { + "profileId": { + "type": "string", + "format": "uuid" + }, + "userId": { + "type": "string", + "format": "uuid" + }, + "username": { + "type": [ + "null", + "string" + ] + }, + "phone": { + "type": [ + "null", + "string" + ] + }, + "email": { + "type": [ + "null", + "string" + ] + }, + "name": { + "type": [ + "null", + "string" + ] + }, + "avatarPreset": { + "type": "string" + }, + "avatarDisplayUrl": { + "type": "string" + }, + "primaryRole": { + "type": "string" + }, + "score": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "regionId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "regionName": { + "type": [ + "null", + "string" + ] + }, + "selectedSchoolId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "selectedSchoolName": { + "type": [ + "null", + "string" + ] + }, + "selectedMajorId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "selectedMajorName": { + "type": [ + "null", + "string" + ] + }, + "questionsAnsweredToday": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "masteredWordsCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "lastCheckInDate": { + "type": [ + "null", + "string" + ], + "format": "date" + }, + "stats": { + "$ref": "#/components/schemas/JsonElement" + }, + "progress": { + "$ref": "#/components/schemas/JsonElement" + }, + "moduleSelections": { + "$ref": "#/components/schemas/JsonElement" + }, + "recentActivities": { + "$ref": "#/components/schemas/JsonElement" + }, + "recentPractices": { + "type": "array", + "items": { + "$ref": "#/components/schemas/RecentPracticeItem" + } + }, + "membership": { + "$ref": "#/components/schemas/StudentMembershipItem" + } + } + }, + "SubjectCatalogItem": { + "required": [ + "id", + "legacyId", + "regionId", + "moduleId", + "schoolId", + "majorId", + "nodeId", + "name", + "type", + "icon", + "description", + "stats", + "order" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "legacyId": { + "type": [ + "null", + "string" + ] + }, + "regionId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "moduleId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "schoolId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "majorId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "nodeId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "name": { + "type": "string" + }, + "type": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/components/schemas/SubjectType" + } + ] + }, + "icon": { + "type": [ + "null", + "string" + ] + }, + "description": { + "type": [ + "null", + "string" + ] + }, + "stats": { + "$ref": "#/components/schemas/JsonElement" + }, + "order": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + } + } + }, + "SubjectType": { + "type": "integer" + }, + "SubmitAnswerDto": { + "required": [ + "sessionQuestionId" + ], + "type": "object", + "properties": { + "sessionQuestionId": { + "type": "string", + "description": "会话题目 ID。", + "format": "uuid" + }, + "selectedOptions": { + "type": [ + "null", + "array" + ], + "items": { + "type": "string" + }, + "description": "已选选项。" + }, + "answerText": { + "maxLength": 10000, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "文字答案。" + }, + "selfJudgedCorrect": { + "type": [ + "null", + "boolean" + ], + "description": "主观题自评是否正确。" + } + }, + "description": "提交答案请求 DTO。" + }, + "SubmitFeedbackDto": { + "required": [ + "description" + ], + "type": "object", + "properties": { + "questionId": { + "type": [ + "null", + "string" + ], + "description": "题目 ID。", + "format": "uuid" + }, + "type": { + "maxLength": 50, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "类型。" + }, + "category": { + "maxLength": 100, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "分类。" + }, + "title": { + "maxLength": 200, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "标题。" + }, + "description": { + "maxLength": 5000, + "minLength": 0, + "type": "string", + "description": "说明。" + }, + "priority": { + "maxLength": 32, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "优先级。" + }, + "contact": { + "maxLength": 200, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "联系方式。" + }, + "attachments": { + "description": "附件列表。", + "$ref": "#/components/schemas/JsonElement" + }, + "metadata": { + "description": "扩展元数据。", + "$ref": "#/components/schemas/JsonElement" + } + }, + "description": "提交反馈请求 DTO。" + }, + "SubmitPracticeSessionDto": { + "required": [ + "practiceSessionId" + ], + "type": "object", + "properties": { + "practiceSessionId": { + "type": "string", + "description": "练习会话 ID。", + "format": "uuid" + } + }, + "description": "提交练习会话请求 DTO。" + }, + "SvipPlanCatalogItem": { + "required": [ + "id", + "legacyId", + "regionId", + "name", + "priceCents", + "price", + "originalPriceCents", + "originalPrice", + "days", + "description", + "perDayLabel", + "badge", + "recommended", + "couponOnly", + "vpProductId", + "vpEnabled", + "order", + "isActive" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "legacyId": { + "type": [ + "null", + "string" + ] + }, + "regionId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "name": { + "type": "string" + }, + "priceCents": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "price": { + "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$", + "type": [ + "number", + "string" + ], + "format": "double" + }, + "originalPriceCents": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "format": "int32" + }, + "originalPrice": { + "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$", + "type": [ + "null", + "number", + "string" + ], + "format": "double" + }, + "days": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "description": { + "type": [ + "null", + "string" + ] + }, + "perDayLabel": { + "type": [ + "null", + "string" + ] + }, + "badge": { + "type": [ + "null", + "string" + ] + }, + "recommended": { + "type": "boolean" + }, + "couponOnly": { + "type": "boolean" + }, + "vpProductId": { + "type": [ + "null", + "string" + ] + }, + "vpEnabled": { + "type": "boolean" + }, + "order": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "isActive": { + "type": "boolean" + } + } + }, + "TaxonomyNodeItem": { + "required": [ + "id", + "source", + "parentId", + "parentSource", + "nodeType", + "code", + "name", + "path", + "depth", + "sortOrder", + "metadata" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "source": { + "$ref": "#/components/schemas/QuestionSource" + }, + "parentId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "parentSource": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/components/schemas/QuestionSource" + } + ] + }, + "nodeType": { + "$ref": "#/components/schemas/TaxonomyNodeType" + }, + "code": { + "type": "string" + }, + "name": { + "type": "string" + }, + "path": { + "type": [ + "null", + "string" + ] + }, + "depth": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "sortOrder": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "metadata": { + "$ref": "#/components/schemas/JsonElement" + } + } + }, + "TaxonomyNodeType": { + "type": "integer" + }, + "TenantAdjustmentReport": { + "required": [ + "draftCount", + "pendingReviewCount", + "approvedCount", + "closedCount", + "increaseRevenueCents", + "decreaseRevenueCents" + ], + "type": "object", + "properties": { + "draftCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "pendingReviewCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "approvedCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "closedCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "increaseRevenueCents": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "decreaseRevenueCents": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + } + } + }, + "TenantAdjustmentVoucherEventList": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/CommerceAdjustmentVoucherEvent" + } + } + } + }, + "TenantAdjustmentVoucherList": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/CommerceAdjustmentVoucher" + } + } + } + }, + "TenantAdminAuditLogItem": { + "required": [ + "id", + "actorUserId", + "action", + "targetType", + "targetId", + "details", + "ipAddress", + "userAgent", + "actorName", + "actorPhone", + "createdAt" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "actorUserId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "action": { + "type": "string" + }, + "targetType": { + "type": [ + "null", + "string" + ] + }, + "targetId": { + "type": [ + "null", + "string" + ] + }, + "details": { + "$ref": "#/components/schemas/JsonElement" + }, + "ipAddress": { + "type": [ + "null", + "string" + ] + }, + "userAgent": { + "type": [ + "null", + "string" + ] + }, + "actorName": { + "type": [ + "null", + "string" + ] + }, + "actorPhone": { + "type": [ + "null", + "string" + ] + }, + "createdAt": { + "type": "string", + "format": "date-time" + } + } + }, + "TenantAdminBadgeGrantItem": { + "required": [ + "id", + "legacyId", + "userId", + "userName", + "userPhone", + "badgeId", + "badgeName", + "badgeCategory", + "iconUrl", + "level", + "grantedBy", + "grantedByName", + "note", + "grantedAt", + "createdAt", + "updatedAt" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "legacyId": { + "type": [ + "null", + "string" + ] + }, + "userId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "userName": { + "type": [ + "null", + "string" + ] + }, + "userPhone": { + "type": [ + "null", + "string" + ] + }, + "badgeId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "badgeName": { + "type": [ + "null", + "string" + ] + }, + "badgeCategory": { + "type": [ + "null", + "string" + ] + }, + "iconUrl": { + "type": [ + "null", + "string" + ] + }, + "level": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "format": "int32" + }, + "grantedBy": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "grantedByName": { + "type": [ + "null", + "string" + ] + }, + "note": { + "type": [ + "null", + "string" + ] + }, + "grantedAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + } + } + }, + "TenantAdminBadgeItem": { + "required": [ + "id", + "legacyId", + "name", + "description", + "category", + "iconUrl", + "level", + "unlockType", + "conditionField", + "conditionOperator", + "conditionValue", + "conditionExtra", + "order", + "isActive", + "createdAt", + "updatedAt" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "legacyId": { + "type": [ + "null", + "string" + ] + }, + "name": { + "type": "string" + }, + "description": { + "type": [ + "null", + "string" + ] + }, + "category": { + "type": [ + "null", + "string" + ] + }, + "iconUrl": { + "type": [ + "null", + "string" + ] + }, + "level": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "format": "int32" + }, + "unlockType": { + "type": [ + "null", + "string" + ] + }, + "conditionField": { + "type": [ + "null", + "string" + ] + }, + "conditionOperator": { + "type": [ + "null", + "string" + ] + }, + "conditionValue": { + "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$", + "type": [ + "null", + "number", + "string" + ], + "format": "double" + }, + "conditionExtra": { + "$ref": "#/components/schemas/JsonElement" + }, + "order": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "isActive": { + "type": "boolean" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + } + } + }, + "TenantAdminBulkAssignClassDto": { + "required": [ + "classId", + "userIds" + ], + "type": "object", + "properties": { + "classId": { + "type": "string", + "description": "班级 ID。", + "format": "uuid" + }, + "userIds": { + "type": "array", + "items": { + "type": "string", + "format": "uuid" + }, + "description": "用户 ID 列表。" + } + }, + "description": "租户管理端批量分配班级请求 DTO。" + }, + "TenantAdminBulkOperationResult": { + "required": [ + "requestedCount", + "succeededCount", + "failedCount", + "failedUserIds" + ], + "type": "object", + "properties": { + "requestedCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "succeededCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "failedCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "failedUserIds": { + "type": "array", + "items": { + "type": "string", + "format": "uuid" + } + } + } + }, + "TenantAdminBulkStatusDto": { + "required": [ + "userIds" + ], + "type": "object", + "properties": { + "userIds": { + "type": "array", + "items": { + "type": "string", + "format": "uuid" + }, + "description": "用户 ID 列表。" + }, + "status": { + "type": [ + "null", + "string" + ], + "description": "状态。" + }, + "reason": { + "maxLength": 1000, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "原因。" + } + }, + "description": "租户管理端批量状态请求 DTO。" + }, + "TenantAdminClassItem": { + "required": [ + "id", + "regionId", + "regionName", + "legacyId", + "code", + "name", + "description", + "status", + "order", + "metadata", + "studentCount", + "staffCount", + "createdAt", + "updatedAt" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "regionId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "regionName": { + "type": [ + "null", + "string" + ] + }, + "legacyId": { + "type": [ + "null", + "string" + ] + }, + "code": { + "type": [ + "null", + "string" + ] + }, + "name": { + "type": "string" + }, + "description": { + "type": [ + "null", + "string" + ] + }, + "status": { + "$ref": "#/components/schemas/TenantRecordStatus" + }, + "order": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "metadata": { + "$ref": "#/components/schemas/JsonElement" + }, + "studentCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "staffCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + } + } + }, + "TenantAdminClassList": { + "required": [ + "items", + "scoped" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/TenantAdminClassItem" + } + }, + "scoped": { + "type": "boolean" + } + } + }, + "TenantAdminClassMemberItem": { + "required": [ + "id", + "classId", + "userId", + "memberType", + "status", + "joinedAt", + "leftAt", + "metadata", + "user" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "classId": { + "type": "string", + "format": "uuid" + }, + "userId": { + "type": "string", + "format": "uuid" + }, + "memberType": { + "$ref": "#/components/schemas/TenantClassMemberType" + }, + "status": { + "$ref": "#/components/schemas/TenantClassMemberStatus" + }, + "joinedAt": { + "type": "string", + "format": "date-time" + }, + "leftAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "metadata": { + "$ref": "#/components/schemas/JsonElement" + }, + "user": { + "$ref": "#/components/schemas/TenantAdminUserSummary" + } + } + }, + "TenantAdminFeedbackItem": { + "required": [ + "id", + "userId", + "userName", + "userPhone", + "questionId", + "type", + "title", + "category", + "description", + "status", + "priority", + "handledBy", + "handledAt", + "resolution", + "contact", + "attachments", + "metadata", + "createdAt", + "updatedAt" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "userId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "userName": { + "type": [ + "null", + "string" + ] + }, + "userPhone": { + "type": [ + "null", + "string" + ] + }, + "questionId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "type": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/components/schemas/ReportType" + } + ] + }, + "title": { + "type": [ + "null", + "string" + ] + }, + "category": { + "type": [ + "null", + "string" + ] + }, + "description": { + "type": [ + "null", + "string" + ] + }, + "status": { + "$ref": "#/components/schemas/ReportStatus" + }, + "priority": { + "$ref": "#/components/schemas/ReportPriority" + }, + "handledBy": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "handledAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "resolution": { + "type": [ + "null", + "string" + ] + }, + "contact": { + "type": [ + "null", + "string" + ] + }, + "attachments": { + "$ref": "#/components/schemas/JsonElement" + }, + "metadata": { + "$ref": "#/components/schemas/JsonElement" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + } + } + }, + "TenantAdminMemberItem": { + "required": [ + "membershipId", + "userId", + "role", + "status", + "legacyRole", + "user", + "createdAt", + "updatedAt" + ], + "type": "object", + "properties": { + "membershipId": { + "type": "string", + "format": "uuid" + }, + "userId": { + "type": "string", + "format": "uuid" + }, + "role": { + "$ref": "#/components/schemas/TenantRole" + }, + "status": { + "$ref": "#/components/schemas/MembershipStatus" + }, + "legacyRole": { + "type": [ + "null", + "string" + ] + }, + "user": { + "$ref": "#/components/schemas/TenantAdminUserSummary" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + } + } + }, + "TenantAdminNotificationItem": { + "required": [ + "id", + "userId", + "notificationType", + "status", + "severity", + "title", + "message", + "actionLabel", + "actionPath", + "sourceType", + "sourceId", + "dedupeKey", + "metadata", + "createdBy", + "readAt", + "createdAt", + "updatedAt" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "userId": { + "type": "string", + "format": "uuid" + }, + "notificationType": { + "type": "string" + }, + "status": { + "$ref": "#/components/schemas/NotificationStatus" + }, + "severity": { + "$ref": "#/components/schemas/NotificationSeverity" + }, + "title": { + "type": "string" + }, + "message": { + "type": "string" + }, + "actionLabel": { + "type": [ + "null", + "string" + ] + }, + "actionPath": { + "type": [ + "null", + "string" + ] + }, + "sourceType": { + "type": [ + "null", + "string" + ] + }, + "sourceId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "dedupeKey": { + "type": [ + "null", + "string" + ] + }, + "metadata": { + "$ref": "#/components/schemas/JsonElement" + }, + "createdBy": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "readAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + } + } + }, + "TenantAdminOverviewItem": { + "required": [ + "studentCount", + "classCount", + "staffCount", + "activePracticeCount", + "todayPracticeCount", + "pendingFollowupCount", + "unreadNotificationCount", + "paidOrderCount", + "revenueCents", + "pendingRefundCount", + "openReconciliationIssueCount", + "generatedAt" + ], + "type": "object", + "properties": { + "studentCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "classCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "staffCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "activePracticeCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "todayPracticeCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "pendingFollowupCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "unreadNotificationCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "paidOrderCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "revenueCents": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "pendingRefundCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "openReconciliationIssueCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "generatedAt": { + "type": "string", + "format": "date-time" + } + } + }, + "TenantAdminStudentClassSummary": { + "required": [ + "classId", + "className", + "classCode", + "memberType", + "joinedAt" + ], + "type": "object", + "properties": { + "classId": { + "type": "string", + "format": "uuid" + }, + "className": { + "type": "string" + }, + "classCode": { + "type": [ + "null", + "string" + ] + }, + "memberType": { + "$ref": "#/components/schemas/TenantClassMemberType" + }, + "joinedAt": { + "type": "string", + "format": "date-time" + } + } + }, + "TenantAdminStudentFollowupItem": { + "required": [ + "id", + "studentUserId", + "assignedToUserId", + "classId", + "title", + "description", + "followupType", + "priority", + "status", + "dueAt", + "completedAt", + "completedBy", + "metadata", + "createdBy", + "updatedBy", + "createdAt", + "updatedAt" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "studentUserId": { + "type": "string", + "format": "uuid" + }, + "assignedToUserId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "classId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "title": { + "type": "string" + }, + "description": { + "type": [ + "null", + "string" + ] + }, + "followupType": { + "$ref": "#/components/schemas/StudentFollowupType" + }, + "priority": { + "$ref": "#/components/schemas/StudentFollowupPriority" + }, + "status": { + "$ref": "#/components/schemas/StudentFollowupStatus" + }, + "dueAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "completedAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "completedBy": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "metadata": { + "$ref": "#/components/schemas/JsonElement" + }, + "createdBy": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "updatedBy": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + } + } + }, + "TenantAdminStudentImportDto": { + "required": [ + "rows" + ], + "type": "object", + "properties": { + "rows": { + "type": "array", + "items": { + "$ref": "#/components/schemas/TenantAdminStudentImportRowDto" + }, + "description": "数据行列表。" + } + }, + "description": "租户管理端学生导入请求 DTO。" + }, + "TenantAdminStudentImportPreview": { + "required": [ + "totalCount", + "validCount", + "invalidCount", + "items" + ], + "type": "object", + "properties": { + "totalCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "validCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "invalidCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/TenantAdminStudentImportPreviewItem" + } + } + } + }, + "TenantAdminStudentImportPreviewItem": { + "required": [ + "rowNo", + "valid", + "reason", + "phone", + "email", + "name", + "regionId", + "classId" + ], + "type": "object", + "properties": { + "rowNo": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "valid": { + "type": "boolean" + }, + "reason": { + "type": [ + "null", + "string" + ] + }, + "phone": { + "type": [ + "null", + "string" + ] + }, + "email": { + "type": [ + "null", + "string" + ] + }, + "name": { + "type": [ + "null", + "string" + ] + }, + "regionId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "classId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + } + } + }, + "TenantAdminStudentImportResult": { + "required": [ + "totalCount", + "createdOrUpdatedCount", + "classAssignedCount", + "invalidItems" + ], + "type": "object", + "properties": { + "totalCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "createdOrUpdatedCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "classAssignedCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "invalidItems": { + "type": "array", + "items": { + "$ref": "#/components/schemas/TenantAdminStudentImportPreviewItem" + } + } + } + }, + "TenantAdminStudentImportRowDto": { + "type": "object", + "properties": { + "user": { + "description": "用户信息。", + "$ref": "#/components/schemas/TenantAdminUserLookupDto" + }, + "regionId": { + "type": [ + "null", + "string" + ], + "description": "地区 ID。", + "format": "uuid" + }, + "classId": { + "type": [ + "null", + "string" + ], + "description": "班级 ID。", + "format": "uuid" + }, + "avatarPreset": { + "type": [ + "null", + "string" + ], + "description": "头像预设。" + }, + "rawProfile": { + "description": "原始用户资料。", + "$ref": "#/components/schemas/JsonElement" + } + }, + "description": "租户管理端学生导入行请求 DTO。" + }, + "TenantAdminStudentItem": { + "required": [ + "membershipId", + "userId", + "status", + "user", + "profileId", + "avatarPreset", + "regionId", + "regionName", + "selectedSchoolId", + "selectedSchoolName", + "selectedMajorId", + "selectedMajorName", + "stats", + "progress", + "moduleSelections", + "classes", + "createdAt", + "updatedAt" + ], + "type": "object", + "properties": { + "membershipId": { + "type": "string", + "format": "uuid" + }, + "userId": { + "type": "string", + "format": "uuid" + }, + "status": { + "$ref": "#/components/schemas/MembershipStatus" + }, + "user": { + "$ref": "#/components/schemas/TenantAdminUserSummary" + }, + "profileId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "avatarPreset": { + "type": "string" + }, + "regionId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "regionName": { + "type": [ + "null", + "string" + ] + }, + "selectedSchoolId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "selectedSchoolName": { + "type": [ + "null", + "string" + ] + }, + "selectedMajorId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "selectedMajorName": { + "type": [ + "null", + "string" + ] + }, + "stats": { + "$ref": "#/components/schemas/JsonElement" + }, + "progress": { + "$ref": "#/components/schemas/JsonElement" + }, + "moduleSelections": { + "$ref": "#/components/schemas/JsonElement" + }, + "classes": { + "type": "array", + "items": { + "$ref": "#/components/schemas/TenantAdminStudentClassSummary" + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + } + } + }, + "TenantAdminStudentList": { + "required": [ + "items", + "scoped" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/TenantAdminStudentItem" + } + }, + "scoped": { + "type": "boolean" + } + } + }, + "TenantAdminStudentNoteItem": { + "required": [ + "id", + "studentUserId", + "noteType", + "content", + "visibility", + "isPinned", + "metadata", + "createdBy", + "updatedBy", + "createdAt", + "updatedAt" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "studentUserId": { + "type": "string", + "format": "uuid" + }, + "noteType": { + "$ref": "#/components/schemas/StudentNoteType" + }, + "content": { + "type": "string" + }, + "visibility": { + "$ref": "#/components/schemas/StudentNoteVisibility" + }, + "isPinned": { + "type": "boolean" + }, + "metadata": { + "$ref": "#/components/schemas/JsonElement" + }, + "createdBy": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "updatedBy": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + } + } + }, + "TenantAdminStudentStatusItem": { + "required": [ + "membershipId", + "userId", + "role", + "status", + "updatedAt" + ], + "type": "object", + "properties": { + "membershipId": { + "type": "string", + "format": "uuid" + }, + "userId": { + "type": "string", + "format": "uuid" + }, + "role": { + "$ref": "#/components/schemas/TenantRole" + }, + "status": { + "$ref": "#/components/schemas/MembershipStatus" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + } + } + }, + "TenantAdminUserLookupDto": { + "type": "object", + "properties": { + "userId": { + "type": [ + "null", + "string" + ], + "description": "用户 ID。", + "format": "uuid" + }, + "username": { + "type": [ + "null", + "string" + ], + "description": "用户名。" + }, + "email": { + "type": [ + "null", + "string" + ], + "description": "邮箱。" + }, + "phone": { + "type": [ + "null", + "string" + ], + "description": "手机号。" + }, + "name": { + "type": [ + "null", + "string" + ], + "description": "名称。" + }, + "avatarUrl": { + "type": [ + "null", + "string" + ], + "description": "头像地址。" + } + }, + "description": "租户管理端用户查找请求 DTO。" + }, + "TenantAdminUserSummary": { + "required": [ + "id", + "username", + "email", + "phone", + "name", + "avatarUrl", + "primaryRole" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "username": { + "type": [ + "null", + "string" + ] + }, + "email": { + "type": [ + "null", + "string" + ] + }, + "phone": { + "type": [ + "null", + "string" + ] + }, + "name": { + "type": [ + "null", + "string" + ] + }, + "avatarUrl": { + "type": [ + "null", + "string" + ] + }, + "primaryRole": { + "type": "string" + } + } + }, + "TenantBillingCatalog": { + "required": [ + "features", + "basePlans", + "addOns" + ], + "type": "object", + "properties": { + "features": { + "type": "array", + "items": { + "$ref": "#/components/schemas/SaasFeature" + } + }, + "basePlans": { + "type": "array", + "items": { + "$ref": "#/components/schemas/SaasOfferingVersionItem" + } + }, + "addOns": { + "type": "array", + "items": { + "$ref": "#/components/schemas/SaasOfferingVersionItem" + } + } + } + }, + "TenantBillingInvoiceTitleType": { + "type": "integer" + }, + "TenantBillingProfileItem": { + "required": [ + "tenantId", + "billingName", + "taxId", + "contactName", + "contactPhoneMasked", + "contactEmail", + "billingAddress", + "invoiceTitle", + "invoiceType", + "bankName", + "bankAccountMasked", + "metadata" + ], + "type": "object", + "properties": { + "tenantId": { + "type": "string", + "format": "uuid" + }, + "billingName": { + "type": [ + "null", + "string" + ] + }, + "taxId": { + "type": [ + "null", + "string" + ] + }, + "contactName": { + "type": [ + "null", + "string" + ] + }, + "contactPhoneMasked": { + "type": [ + "null", + "string" + ] + }, + "contactEmail": { + "type": [ + "null", + "string" + ] + }, + "billingAddress": { + "type": [ + "null", + "string" + ] + }, + "invoiceTitle": { + "type": [ + "null", + "string" + ] + }, + "invoiceType": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/components/schemas/TenantBillingInvoiceTitleType" + } + ] + }, + "bankName": { + "type": [ + "null", + "string" + ] + }, + "bankAccountMasked": { + "type": [ + "null", + "string" + ] + }, + "metadata": { + "$ref": "#/components/schemas/JsonElement" + } + } + }, + "TenantBrandingItem": { + "required": [ + "tenantId", + "brandName", + "shortName", + "slogan", + "organizationName", + "logoUrl", + "faviconUrl", + "serviceWechat", + "serviceAccountName", + "theme", + "publicAssets", + "updatedAt" + ], + "type": "object", + "properties": { + "tenantId": { + "type": "string", + "format": "uuid" + }, + "brandName": { + "type": "string" + }, + "shortName": { + "type": [ + "null", + "string" + ] + }, + "slogan": { + "type": [ + "null", + "string" + ] + }, + "organizationName": { + "type": [ + "null", + "string" + ] + }, + "logoUrl": { + "type": [ + "null", + "string" + ] + }, + "faviconUrl": { + "type": [ + "null", + "string" + ] + }, + "serviceWechat": { + "type": [ + "null", + "string" + ] + }, + "serviceAccountName": { + "type": [ + "null", + "string" + ] + }, + "theme": { + "$ref": "#/components/schemas/JsonElement" + }, + "publicAssets": { + "$ref": "#/components/schemas/JsonElement" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + } + } + }, + "TenantClassMemberStatus": { + "type": "integer" + }, + "TenantClassMemberType": { + "type": "integer" + }, + "TenantCommerceAnomalySummary": { + "required": [ + "openRefundCount", + "processingRefundCount", + "openReconciliationIssueCount", + "failedReconciliationBatchCount", + "pendingPaymentCount", + "paymentMismatchCount" + ], + "type": "object", + "properties": { + "openRefundCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "processingRefundCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "openReconciliationIssueCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "failedReconciliationBatchCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "pendingPaymentCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "paymentMismatchCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + } + } + }, + "TenantCouponList": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Coupon" + } + } + } + }, + "TenantCouponRedemptionList": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/CouponRedemption" + } + } + } + }, + "TenantCouponReport": { + "required": [ + "couponCount", + "claimedCount", + "usedCount", + "discountAppliedCents" + ], + "type": "object", + "properties": { + "couponCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "claimedCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "usedCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "discountAppliedCents": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + } + } + }, + "TenantDomainItem": { + "required": [ + "id", + "host", + "domainType", + "status", + "isPrimary", + "verificationToken", + "verifiedAt", + "lastCheckedAt", + "dnsVerifiedAt", + "tlsReadyAt", + "lastFailureReason", + "createdAt", + "updatedAt" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "host": { + "type": "string" + }, + "domainType": { + "$ref": "#/components/schemas/TenantDomainType" + }, + "status": { + "$ref": "#/components/schemas/TenantDomainStatus" + }, + "isPrimary": { + "type": "boolean" + }, + "verificationToken": { + "type": [ + "null", + "string" + ] + }, + "verifiedAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "lastCheckedAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "dnsVerifiedAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "tlsReadyAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "lastFailureReason": { + "type": [ + "null", + "string" + ] + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + } + } + }, + "TenantDomainStatus": { + "type": "integer" + }, + "TenantDomainType": { + "type": "integer" + }, + "TenantExternalProviderCapability": { + "type": "integer" + }, + "TenantExternalProviderItem": { + "required": [ + "id", + "capability", + "provider", + "status", + "displayName", + "secretRef", + "priority", + "configPublic", + "metadata", + "createdAt", + "updatedAt" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "capability": { + "$ref": "#/components/schemas/TenantExternalProviderCapability" + }, + "provider": { + "type": "string" + }, + "status": { + "$ref": "#/components/schemas/TenantExternalProviderStatus" + }, + "displayName": { + "type": [ + "null", + "string" + ] + }, + "secretRef": { + "type": [ + "null", + "string" + ] + }, + "priority": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "configPublic": { + "$ref": "#/components/schemas/JsonElement" + }, + "metadata": { + "$ref": "#/components/schemas/JsonElement" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + } + } + }, + "TenantExternalProviderStatus": { + "type": "integer" + }, + "TenantFeatureOverride": { + "type": "object", + "properties": { + "featureCode": { + "type": "string" + }, + "mode": { + "$ref": "#/components/schemas/TenantFeatureOverrideMode" + }, + "expiresAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "reason": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "tenantId": { + "type": "string", + "format": "uuid" + }, + "id": { + "type": "string", + "format": "uuid" + } + } + }, + "TenantFeatureOverrideMode": { + "type": "integer" + }, + "TenantFeatureUsage": { + "type": "object", + "properties": { + "metricCode": { + "type": "string" + }, + "periodStart": { + "type": "string", + "format": "date-time" + }, + "periodEnd": { + "type": "string", + "format": "date-time" + }, + "usedValue": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int64" + }, + "limitValueSnapshot": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int64" + }, + "warningIssued": { + "type": "boolean" + }, + "version": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int64" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "tenantId": { + "type": "string", + "format": "uuid" + }, + "id": { + "type": "string", + "format": "uuid" + } + } + }, + "TenantFeedbackReport": { + "required": [ + "pendingCount", + "acceptedCount", + "rejectedCount", + "resolvedCount", + "closedCount" + ], + "type": "object", + "properties": { + "pendingCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "acceptedCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "rejectedCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "resolvedCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "closedCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + } + } + }, + "TenantFollowupReport": { + "required": [ + "openCount", + "inProgressCount", + "doneCount", + "overdueCount" + ], + "type": "object", + "properties": { + "openCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "inProgressCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "doneCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "overdueCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + } + } + }, + "TenantFrontendConfigDraft": { + "required": [ + "branding", + "theme", + "features", + "navigation", + "homeModules" + ], + "type": "object", + "properties": { + "branding": { + "$ref": "#/components/schemas/JsonElement" + }, + "theme": { + "$ref": "#/components/schemas/JsonElement" + }, + "features": { + "$ref": "#/components/schemas/JsonElement" + }, + "navigation": { + "$ref": "#/components/schemas/JsonElement" + }, + "homeModules": { + "$ref": "#/components/schemas/JsonElement" + } + } + }, + "TenantFrontendConfigItem": { + "required": [ + "schemaVersion", + "configVersion", + "published", + "draft", + "publishedAt" + ], + "type": "object", + "properties": { + "schemaVersion": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "configVersion": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "published": { + "$ref": "#/components/schemas/TenantFrontendConfigDraft" + }, + "draft": { + "$ref": "#/components/schemas/TenantFrontendConfigDraft" + }, + "publishedAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + } + } + }, + "TenantIdentityProviderItem": { + "required": [ + "id", + "provider", + "status", + "displayName", + "secretRef", + "priority", + "configPublic", + "createdAt", + "updatedAt" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "provider": { + "type": "string" + }, + "status": { + "$ref": "#/components/schemas/TenantExternalProviderStatus" + }, + "displayName": { + "type": [ + "null", + "string" + ] + }, + "secretRef": { + "type": [ + "null", + "string" + ] + }, + "priority": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "configPublic": { + "$ref": "#/components/schemas/JsonElement" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + } + } + }, + "TenantMembershipResponse": { + "required": [ + "tenantId", + "tenantName", + "tenantSlug", + "role", + "status" + ], + "type": "object", + "properties": { + "tenantId": { + "type": "string", + "description": "租户 ID。", + "format": "uuid" + }, + "tenantName": { + "type": "string", + "description": "租户名称。" + }, + "tenantSlug": { + "type": "string", + "description": "租户编码。" + }, + "role": { + "description": "当前用户在该租户内的角色。", + "$ref": "#/components/schemas/TenantRole" + }, + "status": { + "description": "租户成员状态。", + "$ref": "#/components/schemas/MembershipStatus" + } + }, + "description": "用户在某个租户内的成员摘要。" + }, + "TenantMembershipSummary": { + "required": [ + "tenantId", + "tenantName", + "role", + "status" + ], + "type": "object", + "properties": { + "tenantId": { + "type": "string", + "description": "租户 ID。", + "format": "uuid" + }, + "tenantName": { + "type": "string", + "description": "租户名称。" + }, + "role": { + "description": "当前用户在租户内的角色。", + "$ref": "#/components/schemas/TenantRole" + }, + "status": { + "description": "租户成员状态。", + "$ref": "#/components/schemas/MembershipStatus" + } + }, + "description": "当前登录租户成员摘要。" + }, + "TenantMode": { + "type": "integer" + }, + "TenantOnboardingStatus": { + "required": [ + "tenantId", + "readyForStudentTraffic", + "completedRequiredSteps", + "requiredSteps", + "steps" + ], + "type": "object", + "properties": { + "tenantId": { + "type": "string", + "format": "uuid" + }, + "readyForStudentTraffic": { + "type": "boolean" + }, + "completedRequiredSteps": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "requiredSteps": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "steps": { + "type": "array", + "items": { + "$ref": "#/components/schemas/TenantOnboardingStep" + } + } + } + }, + "TenantOnboardingStep": { + "required": [ + "code", + "required", + "completed", + "detail" + ], + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "completed": { + "type": "boolean" + }, + "detail": { + "type": [ + "null", + "string" + ] + } + } + }, + "TenantPaymentProviderItem": { + "required": [ + "id", + "provider", + "mode", + "displayName", + "status", + "secretRef", + "priority", + "configPublic", + "createdAt", + "updatedAt" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "provider": { + "type": "string" + }, + "mode": { + "type": "string" + }, + "displayName": { + "type": [ + "null", + "string" + ] + }, + "status": { + "$ref": "#/components/schemas/TenantExternalProviderStatus" + }, + "secretRef": { + "type": [ + "null", + "string" + ] + }, + "priority": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "configPublic": { + "$ref": "#/components/schemas/JsonElement" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + } + } + }, + "TenantPointClaimList": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/PointActivityClaim" + } + } + } + }, + "TenantPointExchangeItemList": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/PointExchangeItem" + } + } + } + }, + "TenantPointExchangeOrderList": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/PointExchangeOrder" + } + } + } + }, + "TenantPointRiskReport": { + "required": [ + "negativeScoreUserCount", + "highPointClaimUserCount", + "cancelledExchangeOrderCount" + ], + "type": "object", + "properties": { + "negativeScoreUserCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "highPointClaimUserCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "cancelledExchangeOrderCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + } + } + }, + "TenantPointTaskList": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/PointActivityTask" + } + } + } + }, + "TenantReconciliationBatchList": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/CommerceReconciliationBatch" + } + } + } + }, + "TenantReconciliationIssueEventList": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/CommerceReconciliationIssueEvent" + } + } + } + }, + "TenantReconciliationIssueList": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/CommerceReconciliationIssue" + } + } + } + }, + "TenantReconciliationItemList": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/CommerceReconciliationItem" + } + } + } + }, + "TenantRecordStatus": { + "type": "integer" + }, + "TenantRefundEventList": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/CommerceRefundEvent" + } + } + } + }, + "TenantRefundList": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/CommerceRefundRequest" + } + } + } + }, + "TenantResolveResponseDto": { + "required": [ + "tenant", + "branding", + "features", + "adminFeatures", + "publicConfig" + ], + "type": "object", + "properties": { + "tenant": { + "description": "公开租户基础信息。", + "$ref": "#/components/schemas/PublicTenantDto" + }, + "branding": { + "description": "公开品牌配置。", + "$ref": "#/components/schemas/PublicTenantBrandingDto" + }, + "features": { + "description": "面向前端公开的功能开关。", + "$ref": "#/components/schemas/JsonElement" + }, + "adminFeatures": { + "description": "面向管理端公开的功能开关。", + "$ref": "#/components/schemas/JsonElement" + }, + "publicConfig": { + "description": "可公开的租户配置,不包含密钥或内部配置。", + "$ref": "#/components/schemas/JsonElement" + } + }, + "description": "租户解析响应。" + }, + "TenantRole": { + "type": "integer" + }, + "TenantRuntimeBootstrap": { + "required": [ + "schemaVersion", + "configVersion", + "tenantCode", + "tenantName", + "branding", + "theme", + "features", + "navigation", + "homeModules", + "enabledFeatures", + "loginMethods" + ], + "type": "object", + "properties": { + "schemaVersion": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "configVersion": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "tenantCode": { + "type": "string" + }, + "tenantName": { + "type": "string" + }, + "branding": { + "$ref": "#/components/schemas/JsonElement" + }, + "theme": { + "$ref": "#/components/schemas/JsonElement" + }, + "features": { + "$ref": "#/components/schemas/JsonElement" + }, + "navigation": { + "$ref": "#/components/schemas/JsonElement" + }, + "homeModules": { + "$ref": "#/components/schemas/JsonElement" + }, + "enabledFeatures": { + "type": "array", + "items": { + "type": "string" + } + }, + "loginMethods": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "TenantSaasSubscription": { + "type": "object", + "properties": { + "baseOfferingVersionId": { + "type": "string", + "format": "uuid" + }, + "scheduledBaseOfferingVersionId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "status": { + "$ref": "#/components/schemas/TenantSaasSubscriptionStatus" + }, + "startsAt": { + "type": "string", + "format": "date-time" + }, + "currentPeriodStart": { + "type": "string", + "format": "date-time" + }, + "currentPeriodEnd": { + "type": "string", + "format": "date-time" + }, + "cancelAtPeriodEnd": { + "type": "boolean" + }, + "cancelledAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "lifecycleVersion": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int64" + }, + "metadata": { + "$ref": "#/components/schemas/JsonElement" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "tenantId": { + "type": "string", + "format": "uuid" + }, + "id": { + "type": "string", + "format": "uuid" + } + } + }, + "TenantSaasSubscriptionStatus": { + "type": "integer" + }, + "TenantSecretItem": { + "required": [ + "id", + "purpose", + "provider", + "secretKey", + "secretRef", + "status", + "rotatedAt", + "expiresAt", + "updatedAt" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "purpose": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "secretKey": { + "type": "string" + }, + "secretRef": { + "type": "string" + }, + "status": { + "type": "string" + }, + "rotatedAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "expiresAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + } + } + }, + "TenantSecretStatus": { + "type": "integer" + }, + "TenantSettingsItem": { + "required": [ + "tenantId", + "featureFlags", + "adminFeatureFlags", + "publicConfig", + "updatedAt" + ], + "type": "object", + "properties": { + "tenantId": { + "type": "string", + "format": "uuid" + }, + "featureFlags": { + "$ref": "#/components/schemas/JsonElement" + }, + "adminFeatureFlags": { + "$ref": "#/components/schemas/JsonElement" + }, + "publicConfig": { + "$ref": "#/components/schemas/JsonElement" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + } + } + }, + "TenantStatus": { + "type": "integer" + }, + "TenantSubscriptionView": { + "required": [ + "id", + "status", + "startsAt", + "currentPeriodStart", + "currentPeriodEnd", + "cancelAtPeriodEnd", + "baseOfferingVersionId", + "scheduledBaseOfferingVersionId", + "featureCodes" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "status": { + "$ref": "#/components/schemas/TenantSaasSubscriptionStatus" + }, + "startsAt": { + "type": "string", + "format": "date-time" + }, + "currentPeriodStart": { + "type": "string", + "format": "date-time" + }, + "currentPeriodEnd": { + "type": "string", + "format": "date-time" + }, + "cancelAtPeriodEnd": { + "type": "boolean" + }, + "baseOfferingVersionId": { + "type": "string", + "format": "uuid" + }, + "scheduledBaseOfferingVersionId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "featureCodes": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "TenantSupervisionGenerateDto": { + "type": "object", + "properties": { + "userIds": { + "type": [ + "null", + "array" + ], + "items": { + "type": "string", + "format": "uuid" + }, + "description": "用户 ID 列表。" + }, + "assignedToUserId": { + "type": [ + "null", + "string" + ], + "description": "分配处理人用户 ID。", + "format": "uuid" + }, + "dueAt": { + "type": [ + "null", + "string" + ], + "description": "到期时间。", + "format": "date-time" + } + }, + "description": "租户督导生成请求 DTO。" + }, + "TenantSupervisionGenerateResult": { + "required": [ + "createdCount" + ], + "type": "object", + "properties": { + "createdCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + } + } + }, + "TenantSupervisionPreview": { + "required": [ + "items" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/TenantSupervisionRiskStudentItem" + } + } + } + }, + "TenantSupervisionRiskStudentItem": { + "required": [ + "userId", + "name", + "phoneMasked", + "regionId", + "ruleCodes", + "reasons" + ], + "type": "object", + "properties": { + "userId": { + "type": "string", + "format": "uuid" + }, + "name": { + "type": [ + "null", + "string" + ] + }, + "phoneMasked": { + "type": [ + "null", + "string" + ] + }, + "regionId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "ruleCodes": { + "type": "array", + "items": { + "type": "string" + } + }, + "reasons": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "TenantSupervisionRuleItem": { + "required": [ + "code", + "title", + "enabled", + "daysWithoutCheckIn", + "maxQuestionsAnsweredToday", + "followupType", + "priority", + "metadata" + ], + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "title": { + "type": "string" + }, + "enabled": { + "type": "boolean" + }, + "daysWithoutCheckIn": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "format": "int32" + }, + "maxQuestionsAnsweredToday": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "format": "int32" + }, + "followupType": { + "type": "string" + }, + "priority": { + "type": "string" + }, + "metadata": { + "$ref": "#/components/schemas/JsonElement" + } + } + }, + "TenantThemeConfigStatus": { + "type": "integer" + }, + "TenantThemeItem": { + "required": [ + "tenantId", + "activeTemplateCode", + "activeTheme", + "activePublicAssets", + "draftTemplateCode", + "draftTheme", + "draftPublicAssets", + "status", + "publishedAt", + "publishedBy", + "draftUpdatedBy", + "updatedAt" + ], + "type": "object", + "properties": { + "tenantId": { + "type": "string", + "format": "uuid" + }, + "activeTemplateCode": { + "type": [ + "null", + "string" + ] + }, + "activeTheme": { + "$ref": "#/components/schemas/JsonElement" + }, + "activePublicAssets": { + "$ref": "#/components/schemas/JsonElement" + }, + "draftTemplateCode": { + "type": [ + "null", + "string" + ] + }, + "draftTheme": { + "$ref": "#/components/schemas/JsonElement" + }, + "draftPublicAssets": { + "$ref": "#/components/schemas/JsonElement" + }, + "status": { + "$ref": "#/components/schemas/TenantThemeConfigStatus" + }, + "publishedAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "publishedBy": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "draftUpdatedBy": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + } + } + }, + "TenantThemeTemplateItem": { + "required": [ + "code", + "name", + "description", + "previewImageUrl", + "theme", + "publicAssets", + "order" + ], + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "name": { + "type": "string" + }, + "description": { + "type": [ + "null", + "string" + ] + }, + "previewImageUrl": { + "type": [ + "null", + "string" + ] + }, + "theme": { + "$ref": "#/components/schemas/JsonElement" + }, + "publicAssets": { + "$ref": "#/components/schemas/JsonElement" + }, + "order": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + } + } + }, + "TrackReferralEventDto": { + "required": [ + "refCode" + ], + "type": "object", + "properties": { + "refCode": { + "maxLength": 100, + "minLength": 0, + "type": "string", + "description": "推荐码。" + }, + "eventType": { + "maxLength": 100, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "事件类型。" + }, + "source": { + "maxLength": 100, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "来源。" + }, + "targetUserId": { + "type": [ + "null", + "string" + ], + "description": "目标用户 ID。", + "format": "uuid" + }, + "metadata": { + "oneOf": [ + { + "type": "null" + }, + { + "description": "扩展元数据。", + "$ref": "#/components/schemas/JsonElement" + } + ] + }, + "tenantCode": { + "maxLength": 100, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "租户编码。" + } + }, + "description": "记录推荐事件请求 DTO。" + }, + "UpdateAdjustmentVoucherStatusDto": { + "required": [ + "voucherId" + ], + "type": "object", + "properties": { + "voucherId": { + "type": "string", + "description": "凭证 ID。", + "format": "uuid" + }, + "status": { + "description": "状态。", + "$ref": "#/components/schemas/CommerceAdjustmentVoucherStatus" + }, + "note": { + "maxLength": 1000, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "备注。" + } + }, + "description": "更新调账凭证状态请求 DTO。" + }, + "UpdateCommissionProofStatusDto": { + "required": [ + "proofId" + ], + "type": "object", + "properties": { + "proofId": { + "type": "string", + "description": "凭证 ID。", + "format": "uuid" + }, + "status": { + "maxLength": 50, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "状态。" + }, + "reviewNote": { + "maxLength": 1000, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "审核备注。" + }, + "metadata": { + "oneOf": [ + { + "type": "null" + }, + { + "description": "扩展元数据。", + "$ref": "#/components/schemas/JsonElement" + } + ] + } + }, + "description": "更新佣金结算凭证状态请求。" + }, + "UpdateCommissionSettingsDto": { + "type": "object", + "properties": { + "defaultRate": { + "maximum": 1, + "minimum": 0, + "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$", + "type": [ + "null", + "number", + "string" + ], + "description": "默认佣金比例。", + "format": "double" + }, + "minSettlementCents": { + "maximum": 2147483647, + "minimum": 0, + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "description": "最低结算金额,单位为分。", + "format": "int32" + }, + "settlementCycle": { + "maxLength": 50, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "结算周期。" + }, + "config": { + "oneOf": [ + { + "type": "null" + }, + { + "description": "配置内容。", + "$ref": "#/components/schemas/JsonElement" + } + ] + } + }, + "description": "保存佣金配置请求。" + }, + "UpdateCommissionSettlementStatusDto": { + "required": [ + "settlementId" + ], + "type": "object", + "properties": { + "settlementId": { + "type": "string", + "description": "结算单 ID。", + "format": "uuid" + }, + "status": { + "maxLength": 50, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "状态。" + }, + "reviewNote": { + "maxLength": 1000, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "审核备注。" + }, + "paymentMethod": { + "maxLength": 100, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "支付方式。" + }, + "paymentAccount": { + "maxLength": 200, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "收款账号。" + }, + "metadata": { + "oneOf": [ + { + "type": "null" + }, + { + "description": "扩展元数据。", + "$ref": "#/components/schemas/JsonElement" + } + ] + } + }, + "description": "更新佣金结算单状态请求 DTO。" + }, + "UpdateMemberCommissionRateDto": { + "required": [ + "userId" + ], + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "用户 ID。", + "format": "uuid" + }, + "commissionRate": { + "maximum": 1, + "minimum": 0, + "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$", + "type": [ + "null", + "number", + "string" + ], + "description": "成员佣金比例。", + "format": "double" + }, + "commissionConfig": { + "oneOf": [ + { + "type": "null" + }, + { + "description": "佣金扩展配置。", + "$ref": "#/components/schemas/JsonElement" + } + ] + } + }, + "description": "调整成员佣金比例请求。" + }, + "UpdatePlatformAuditAlertStatusDto": { + "required": [ + "alertId" + ], + "type": "object", + "properties": { + "alertId": { + "type": "string", + "description": "告警 ID。", + "format": "uuid" + }, + "status": { + "description": "状态。", + "$ref": "#/components/schemas/PlatformAuditAlertStatus" + }, + "resolutionNote": { + "maxLength": 1000, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "处理备注。" + } + }, + "description": "更新平台审计Alert状态请求 DTO。" + }, + "UpdatePlatformStaffStatusDto": { + "required": [ + "userId" + ], + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "用户 ID。", + "format": "uuid" + }, + "status": { + "description": "状态。", + "$ref": "#/components/schemas/UserStatus" + }, + "reason": { + "maxLength": 1000, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "原因。" + } + }, + "description": "更新平台Staff状态请求 DTO。" + }, + "UpdatePlatformTenantStatusDto": { + "required": [ + "tenantId" + ], + "type": "object", + "properties": { + "tenantId": { + "type": "string", + "description": "租户 ID。", + "format": "uuid" + }, + "status": { + "description": "状态。", + "$ref": "#/components/schemas/TenantStatus" + }, + "billingStatus": { + "description": "账务状态。", + "$ref": "#/components/schemas/BillingStatus" + }, + "reason": { + "maxLength": 1000, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "原因。" + } + }, + "description": "更新平台租户状态请求 DTO。" + }, + "UpdatePointExchangeOrderStatusDto": { + "required": [ + "orderId" + ], + "type": "object", + "properties": { + "orderId": { + "type": "string", + "description": "订单 ID。", + "format": "uuid" + }, + "status": { + "description": "状态。", + "$ref": "#/components/schemas/PointExchangeOrderStatus" + } + }, + "description": "更新积分兑换订单状态请求 DTO。" + }, + "UpdateProfileDto": { + "type": "object", + "properties": { + "name": { + "maxLength": 100, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "名称。" + }, + "avatarPreset": { + "maxLength": 32, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "头像预设。" + }, + "regionId": { + "type": [ + "null", + "string" + ], + "description": "地区 ID。", + "format": "uuid" + }, + "selectedSchoolId": { + "type": [ + "null", + "string" + ], + "description": "已选择院校 ID。", + "format": "uuid" + }, + "selectedMajorId": { + "type": [ + "null", + "string" + ], + "description": "已选择专业 ID。", + "format": "uuid" + }, + "stats": { + "oneOf": [ + { + "type": "null" + }, + { + "description": "统计数据。", + "$ref": "#/components/schemas/JsonElement" + } + ] + }, + "progress": { + "oneOf": [ + { + "type": "null" + }, + { + "description": "进度数据。", + "$ref": "#/components/schemas/JsonElement" + } + ] + }, + "moduleSelections": { + "oneOf": [ + { + "type": "null" + }, + { + "description": "模块选择数据。", + "$ref": "#/components/schemas/JsonElement" + } + ] + }, + "recentActivities": { + "oneOf": [ + { + "type": "null" + }, + { + "description": "最近活动数据。", + "$ref": "#/components/schemas/JsonElement" + } + ] + } + }, + "description": "更新资料请求 DTO。" + }, + "UpdateReconciliationIssueDto": { + "required": [ + "issueId" + ], + "type": "object", + "properties": { + "issueId": { + "type": "string", + "description": "工单 ID。", + "format": "uuid" + }, + "status": { + "description": "状态。", + "$ref": "#/components/schemas/ReconciliationIssueStatus" + }, + "resolutionType": { + "description": "处理类型。", + "$ref": "#/components/schemas/ReconciliationResolutionType" + }, + "note": { + "maxLength": 1000, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "备注。" + }, + "assignedTo": { + "type": [ + "null", + "string" + ], + "description": "分配处理人。", + "format": "uuid" + } + }, + "description": "更新对账Issue请求 DTO。" + }, + "UpdateRefundStatusDto": { + "required": [ + "refundRequestId" + ], + "type": "object", + "properties": { + "refundRequestId": { + "type": "string", + "description": "退款申请 ID。", + "format": "uuid" + }, + "status": { + "description": "状态。", + "$ref": "#/components/schemas/CommerceRefundStatus" + }, + "reason": { + "maxLength": 1000, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "原因。" + }, + "providerRefundNo": { + "maxLength": 200, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "渠道退款单号。" + } + }, + "description": "更新退款状态请求 DTO。" + }, + "UpdateTenantAdminFeedbackDto": { + "required": [ + "feedbackId" + ], + "type": "object", + "properties": { + "feedbackId": { + "type": "string", + "description": "反馈 ID。", + "format": "uuid" + }, + "status": { + "type": [ + "null", + "string" + ], + "description": "状态。" + }, + "priority": { + "type": [ + "null", + "string" + ], + "description": "优先级。" + }, + "resolution": { + "type": [ + "null", + "string" + ], + "description": "处理结果。" + }, + "note": { + "type": [ + "null", + "string" + ], + "description": "备注。" + }, + "metadata": { + "description": "扩展元数据。", + "$ref": "#/components/schemas/JsonElement" + } + }, + "description": "更新租户管理端反馈请求 DTO。" + }, + "UpdateTenantAdminStudentStatusDto": { + "required": [ + "userId" + ], + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "用户 ID。", + "format": "uuid" + }, + "status": { + "type": [ + "null", + "string" + ], + "description": "状态。" + }, + "reason": { + "type": [ + "null", + "string" + ], + "description": "原因。" + } + }, + "description": "更新租户管理端学生状态请求 DTO。" + }, + "UpsertAssetDto": { + "type": "object", + "properties": { + "assetId": { + "type": [ + "null", + "string" + ], + "description": "资产 ID。", + "format": "uuid" + }, + "regionId": { + "type": [ + "null", + "string" + ], + "description": "地区 ID。", + "format": "uuid" + }, + "subjectId": { + "type": [ + "null", + "string" + ], + "description": "科目 ID。", + "format": "uuid" + }, + "categoryId": { + "type": [ + "null", + "string" + ], + "description": "分类 ID。", + "format": "uuid" + }, + "contentNodeId": { + "type": [ + "null", + "string" + ], + "description": "内容节点 ID。", + "format": "uuid" + }, + "legacyId": { + "type": [ + "null", + "string" + ], + "description": "历史系统 ID。" + }, + "assetKey": { + "type": [ + "null", + "string" + ], + "description": "资产键。" + }, + "title": { + "type": [ + "null", + "string" + ], + "description": "标题。" + }, + "category": { + "type": [ + "null", + "string" + ], + "description": "分类。" + }, + "description": { + "type": [ + "null", + "string" + ], + "description": "说明。" + }, + "fileName": { + "type": [ + "null", + "string" + ], + "description": "文件名。" + }, + "cdnUrl": { + "type": [ + "null", + "string" + ], + "description": "CDN 地址。" + }, + "isPublic": { + "type": [ + "null", + "boolean" + ], + "description": "是否公开。" + }, + "assetType": { + "type": [ + "null", + "string" + ], + "description": "资产类型。" + }, + "visibility": { + "type": [ + "null", + "string" + ], + "description": "可见性。" + }, + "status": { + "type": [ + "null", + "string" + ], + "description": "状态。" + }, + "provider": { + "type": [ + "null", + "string" + ], + "description": "服务提供方。" + }, + "bucket": { + "type": [ + "null", + "string" + ], + "description": "存储桶。" + }, + "objectKey": { + "type": [ + "null", + "string" + ], + "description": "对象存储键。" + }, + "mimeType": { + "type": [ + "null", + "string" + ], + "description": "MIME 类型。" + }, + "fileSizeBytes": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "description": "文件大小,单位为字节。", + "format": "int64" + }, + "checksumSha256": { + "type": [ + "null", + "string" + ], + "description": "SHA-256 校验值。" + }, + "previewUrl": { + "type": [ + "null", + "string" + ], + "description": "预览地址。" + }, + "previewObjectKey": { + "type": [ + "null", + "string" + ], + "description": "预览对象存储键。" + }, + "order": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "description": "显示顺序。", + "format": "int32" + }, + "accessRules": { + "description": "访问规则。", + "$ref": "#/components/schemas/JsonElement" + }, + "metadata": { + "description": "扩展元数据。", + "$ref": "#/components/schemas/JsonElement" + } + }, + "description": "新增或更新内容资产请求。" + }, + "UpsertBackofficeRoleDto": { + "type": "object", + "properties": { + "id": { + "type": [ + "null", + "string" + ], + "description": "ID。", + "format": "uuid" + }, + "code": { + "type": "string", + "description": "编码。" + }, + "name": { + "type": "string", + "description": "名称。" + }, + "status": { + "description": "状态。", + "$ref": "#/components/schemas/BackendRoleStatus" + }, + "description": { + "type": [ + "null", + "string" + ], + "description": "说明。" + }, + "dataScope": { + "oneOf": [ + { + "type": "null" + }, + { + "description": "数据范围配置。", + "$ref": "#/components/schemas/JsonElement" + } + ] + } + }, + "description": "创建或更新后台角色请求。" + }, + "UpsertContentEntryDto": { + "required": [ + "name" + ], + "type": "object", + "properties": { + "id": { + "type": [ + "null", + "string" + ], + "description": "ID。", + "format": "uuid" + }, + "regionId": { + "type": [ + "null", + "string" + ], + "description": "地区 ID。", + "format": "uuid" + }, + "legacyId": { + "maxLength": 64, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "历史系统 ID。" + }, + "entryKey": { + "maxLength": 100, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "入口键。" + }, + "name": { + "maxLength": 300, + "minLength": 0, + "type": "string", + "description": "名称。" + }, + "entryType": { + "maxLength": 50, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "入口类型。" + }, + "icon": { + "maxLength": 100, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "图标。" + }, + "route": { + "maxLength": 500, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "路由地址。" + }, + "description": { + "maxLength": 2000, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "说明。" + }, + "visibility": { + "maxLength": 50, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "可见性。" + }, + "accessRules": { + "description": "访问规则。", + "$ref": "#/components/schemas/JsonElement" + }, + "layoutConfig": { + "description": "布局配置。", + "$ref": "#/components/schemas/JsonElement" + }, + "order": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "description": "显示顺序。", + "format": "int32" + }, + "isActive": { + "type": [ + "null", + "boolean" + ], + "description": "是否启用。" + } + }, + "description": "新增或更新内容条目请求 DTO。" + }, + "UpsertContentNodeDto": { + "required": [ + "entryId", + "name" + ], + "type": "object", + "properties": { + "id": { + "type": [ + "null", + "string" + ], + "description": "ID。", + "format": "uuid" + }, + "entryId": { + "type": "string", + "description": "内容入口 ID。", + "format": "uuid" + }, + "regionId": { + "type": [ + "null", + "string" + ], + "description": "地区 ID。", + "format": "uuid" + }, + "parentId": { + "type": [ + "null", + "string" + ], + "description": "父节点 ID。", + "format": "uuid" + }, + "legacyId": { + "maxLength": 64, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "历史系统 ID。" + }, + "nodeKey": { + "maxLength": 100, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "节点键。" + }, + "name": { + "maxLength": 300, + "minLength": 0, + "type": "string", + "description": "名称。" + }, + "nodeType": { + "maxLength": 50, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "节点Type。" + }, + "markerType": { + "maxLength": 50, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "标记类型。" + }, + "markerConfig": { + "description": "标记配置。", + "$ref": "#/components/schemas/JsonElement" + }, + "order": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "description": "显示顺序。", + "format": "int32" + }, + "isActive": { + "type": [ + "null", + "boolean" + ], + "description": "是否启用。" + }, + "isSelectable": { + "type": [ + "null", + "boolean" + ], + "description": "是否可选择。" + }, + "isLeaf": { + "type": [ + "null", + "boolean" + ], + "description": "是否叶子节点。" + }, + "accessRules": { + "description": "访问规则。", + "$ref": "#/components/schemas/JsonElement" + }, + "metadata": { + "description": "扩展元数据。", + "$ref": "#/components/schemas/JsonElement" + } + }, + "description": "新增或更新内容节点请求 DTO。" + }, + "UpsertCrmConfigDto": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "description": "是否启用。" + }, + "url": { + "maxLength": 2048, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "访问地址。" + }, + "secretRef": { + "maxLength": 300, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "密钥引用。" + }, + "secret": { + "type": [ + "null", + "string" + ], + "description": "密钥内容。" + }, + "formName": { + "maxLength": 200, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "表单名称。" + }, + "examType": { + "maxLength": 100, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "考试类型。" + }, + "timeoutSeconds": { + "maximum": 120, + "minimum": 1, + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "description": "超时时长,单位为秒。", + "format": "int32" + }, + "delaySeconds": { + "maximum": 86400, + "minimum": 0, + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "description": "延迟秒数。", + "format": "int32" + }, + "assignmentMode": { + "maxLength": 50, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "分配模式。" + }, + "assignmentPool": { + "oneOf": [ + { + "type": "null" + }, + { + "description": "分配池。", + "$ref": "#/components/schemas/JsonElement" + } + ] + }, + "assignmentConfig": { + "oneOf": [ + { + "type": "null" + }, + { + "description": "分配配置。", + "$ref": "#/components/schemas/JsonElement" + } + ] + } + }, + "description": "新增或更新CRM配置请求 DTO。" + }, + "UpsertPaymentAccountDto": { + "required": [ + "provider" + ], + "type": "object", + "properties": { + "provider": { + "maxLength": 50, + "minLength": 0, + "type": "string", + "description": "服务提供方。" + }, + "mode": { + "maxLength": 50, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "模式。" + }, + "displayName": { + "maxLength": 200, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "显示名称。" + }, + "status": { + "description": "状态。", + "$ref": "#/components/schemas/TenantExternalProviderStatus" + }, + "secretRef": { + "maxLength": 300, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "密钥引用。" + }, + "priority": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "description": "优先级。", + "format": "int32" + }, + "configPublic": { + "description": "公开配置内容。", + "$ref": "#/components/schemas/JsonElement" + } + }, + "description": "新增或更新支付账号请求 DTO。" + }, + "UpsertPlatformBillingDunningChannelDto": { + "required": [ + "channelCode", + "name", + "webhookUrl" + ], + "type": "object", + "properties": { + "channelId": { + "type": [ + "null", + "string" + ], + "description": "通知渠道 ID。", + "format": "uuid" + }, + "channelCode": { + "maxLength": 100, + "minLength": 0, + "type": "string", + "description": "渠道编码。" + }, + "name": { + "maxLength": 200, + "minLength": 0, + "type": "string", + "description": "名称。" + }, + "description": { + "maxLength": 1000, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "说明。" + }, + "enabled": { + "type": "boolean", + "description": "是否启用。" + }, + "provider": { + "description": "服务提供方。", + "$ref": "#/components/schemas/PlatformBillingDunningProvider" + }, + "webhookUrl": { + "maxLength": 2048, + "minLength": 0, + "type": "string", + "description": "Webhook 地址。" + }, + "secretRef": { + "maxLength": 300, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "密钥引用。" + }, + "reminderTypes": { + "type": "array", + "items": { + "type": "string" + }, + "description": "提醒类型列表。" + }, + "reminderChannels": { + "type": "array", + "items": { + "type": "string" + }, + "description": "提醒渠道列表。" + }, + "minReminderLevel": { + "maximum": 20, + "minimum": 1, + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "description": "最低提醒级别。", + "format": "int32" + }, + "tenantIds": { + "type": "array", + "items": { + "type": "string", + "format": "uuid" + }, + "description": "租户 ID 列表。" + }, + "timeoutSeconds": { + "maximum": 60, + "minimum": 1, + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "description": "超时时长,单位为秒。", + "format": "int32" + }, + "metadata": { + "description": "扩展元数据。", + "$ref": "#/components/schemas/JsonElement" + } + }, + "description": "新增或更新平台DunningChannel请求 DTO。" + }, + "UpsertPlatformCrmConfigDto": { + "required": [ + "tenantId" + ], + "type": "object", + "properties": { + "id": { + "type": [ + "null", + "string" + ], + "description": "ID。", + "format": "uuid" + }, + "tenantId": { + "type": "string", + "description": "租户 ID。", + "format": "uuid" + }, + "enabled": { + "type": "boolean", + "description": "是否启用。" + }, + "url": { + "maxLength": 2048, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "回调地址。" + }, + "secretRef": { + "maxLength": 300, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "密钥引用。" + }, + "formName": { + "maxLength": 200, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "表单名称。" + }, + "examType": { + "maxLength": 100, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "考试类型。" + }, + "timeoutSeconds": { + "maximum": 120, + "minimum": 1, + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "description": "超时时长,单位为秒。", + "format": "int32" + }, + "delaySeconds": { + "maximum": 86400, + "minimum": 0, + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "description": "延迟秒数。", + "format": "int32" + }, + "assignmentMode": { + "maxLength": 50, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "分配模式。" + }, + "assignmentPool": { + "oneOf": [ + { + "type": "null" + }, + { + "description": "分配池。", + "$ref": "#/components/schemas/JsonElement" + } + ] + }, + "assignmentConfig": { + "oneOf": [ + { + "type": "null" + }, + { + "description": "分配配置。", + "$ref": "#/components/schemas/JsonElement" + } + ] + } + }, + "description": "新增或更新租户 CRM 配置请求。" + }, + "UpsertPlatformPaymentAppDto": { + "required": [ + "appCode", + "appName" + ], + "type": "object", + "properties": { + "id": { + "type": [ + "null", + "string" + ], + "description": "ID。", + "format": "uuid" + }, + "appCode": { + "maxLength": 100, + "minLength": 0, + "type": "string", + "description": "支付应用编码。" + }, + "appName": { + "maxLength": 200, + "minLength": 0, + "type": "string", + "description": "支付应用名称。" + }, + "status": { + "description": "状态。", + "$ref": "#/components/schemas/PlatformPaymentAppStatus" + }, + "settlementMode": { + "maxLength": 100, + "minLength": 0, + "type": "string", + "description": "结算模式。" + }, + "description": { + "maxLength": 500, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "说明。" + }, + "metadata": { + "description": "扩展元数据。", + "$ref": "#/components/schemas/JsonElement" + } + }, + "description": "新增或更新平台支付应用请求。" + }, + "UpsertPlatformPaymentChannelDto": { + "required": [ + "appId", + "provider", + "displayName" + ], + "type": "object", + "properties": { + "id": { + "type": [ + "null", + "string" + ], + "description": "ID。", + "format": "uuid" + }, + "appId": { + "type": "string", + "description": "支付应用 ID。", + "format": "uuid" + }, + "provider": { + "maxLength": 80, + "minLength": 0, + "type": "string", + "description": "服务提供方。" + }, + "mode": { + "maxLength": 100, + "minLength": 0, + "type": "string", + "description": "模式。" + }, + "status": { + "description": "状态。", + "$ref": "#/components/schemas/PlatformPaymentChannelStatus" + }, + "displayName": { + "maxLength": 200, + "minLength": 0, + "type": "string", + "description": "显示名称。" + }, + "secretRef": { + "maxLength": 300, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "密钥引用。" + }, + "callbackPath": { + "maxLength": 500, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "回调路径。" + }, + "priority": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "description": "优先级。", + "format": "int32" + }, + "configPublic": { + "description": "公开配置内容。", + "$ref": "#/components/schemas/JsonElement" + }, + "metadata": { + "description": "扩展元数据。", + "$ref": "#/components/schemas/JsonElement" + } + }, + "description": "新增或更新平台支付渠道请求。" + }, + "UpsertPlatformQuestionBankCommand": { + "required": [ + "id", + "name", + "metadata" + ], + "type": "object", + "properties": { + "id": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "name": { + "type": "string" + }, + "metadata": { + "$ref": "#/components/schemas/JsonElement" + } + } + }, + "UpsertPlatformQuestionBankNodeCommand": { + "required": [ + "id", + "questionBankId", + "parentId", + "nodeKey", + "name", + "nodeType", + "sortOrder", + "isSelectable", + "metadata" + ], + "type": "object", + "properties": { + "id": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "questionBankId": { + "type": "string", + "format": "uuid" + }, + "parentId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "nodeKey": { + "type": [ + "null", + "string" + ] + }, + "name": { + "type": "string" + }, + "nodeType": { + "$ref": "#/components/schemas/ContentNodeType" + }, + "sortOrder": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "isSelectable": { + "type": "boolean" + }, + "metadata": { + "$ref": "#/components/schemas/JsonElement" + } + } + }, + "UpsertPlatformQuestionCommand": { + "required": [ + "id", + "questionBankId", + "contentNodeId", + "legacyId", + "type", + "typeLabel", + "difficulty", + "tags", + "content", + "options", + "correctOptionIndex", + "correctOptionIndices", + "answerText", + "explanation", + "subQuestions", + "codeLang", + "codeTemplate", + "mediaUrl", + "status", + "examMarkers", + "sourceHash" + ], + "type": "object", + "properties": { + "id": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "questionBankId": { + "type": "string", + "format": "uuid" + }, + "contentNodeId": { + "type": "string", + "format": "uuid" + }, + "legacyId": { + "type": [ + "null", + "string" + ] + }, + "type": { + "type": [ + "null", + "string" + ] + }, + "typeLabel": { + "type": [ + "null", + "string" + ] + }, + "difficulty": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "format": "int32" + }, + "tags": { + "$ref": "#/components/schemas/JsonElement" + }, + "content": { + "type": [ + "null", + "string" + ] + }, + "options": { + "$ref": "#/components/schemas/JsonElement" + }, + "correctOptionIndex": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "format": "int32" + }, + "correctOptionIndices": { + "$ref": "#/components/schemas/JsonElement" + }, + "answerText": { + "type": [ + "null", + "string" + ] + }, + "explanation": { + "type": [ + "null", + "string" + ] + }, + "subQuestions": { + "$ref": "#/components/schemas/JsonElement" + }, + "codeLang": { + "type": [ + "null", + "string" + ] + }, + "codeTemplate": { + "type": [ + "null", + "string" + ] + }, + "mediaUrl": { + "type": [ + "null", + "string" + ] + }, + "status": { + "type": [ + "null", + "string" + ] + }, + "examMarkers": { + "$ref": "#/components/schemas/JsonElement" + }, + "sourceHash": { + "type": [ + "null", + "string" + ] + } + } + }, + "UpsertPlatformSmsChannelDto": { + "required": [ + "tenantId", + "provider", + "name", + "signature", + "scene" + ], + "type": "object", + "properties": { + "id": { + "type": [ + "null", + "string" + ], + "description": "ID。", + "format": "uuid" + }, + "tenantId": { + "type": "string", + "description": "租户 ID。", + "format": "uuid" + }, + "provider": { + "maxLength": 80, + "minLength": 0, + "type": "string", + "description": "服务提供方。" + }, + "name": { + "maxLength": 200, + "minLength": 0, + "type": "string", + "description": "名称。" + }, + "signature": { + "maxLength": 100, + "minLength": 0, + "type": "string", + "description": "短信签名。" + }, + "scene": { + "maxLength": 100, + "minLength": 0, + "type": "string", + "description": "使用场景。" + }, + "status": { + "description": "状态。", + "$ref": "#/components/schemas/TenantExternalProviderStatus" + }, + "secretRef": { + "maxLength": 300, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "密钥引用。" + }, + "priority": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "description": "优先级。", + "format": "int32" + }, + "monthlyQuota": { + "maximum": 2147483647, + "minimum": 0, + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "description": "月度配额。", + "format": "int32" + }, + "configPublic": { + "description": "公开配置内容。", + "$ref": "#/components/schemas/JsonElement" + }, + "metadata": { + "description": "扩展元数据。", + "$ref": "#/components/schemas/JsonElement" + } + }, + "description": "新增或更新租户短信渠道请求。" + }, + "UpsertPlatformSmsTemplateDto": { + "required": [ + "tenantId", + "channelId", + "code", + "name", + "content" + ], + "type": "object", + "properties": { + "id": { + "type": [ + "null", + "string" + ], + "description": "ID。", + "format": "uuid" + }, + "tenantId": { + "type": "string", + "description": "租户 ID。", + "format": "uuid" + }, + "channelId": { + "type": "string", + "description": "短信渠道 ID。", + "format": "uuid" + }, + "code": { + "maxLength": 120, + "minLength": 0, + "type": "string", + "description": "编码。" + }, + "name": { + "maxLength": 200, + "minLength": 0, + "type": "string", + "description": "名称。" + }, + "type": { + "description": "类型。", + "$ref": "#/components/schemas/SmsTemplateType" + }, + "auditStatus": { + "description": "审核状态。", + "$ref": "#/components/schemas/SmsTemplateAuditStatus" + }, + "status": { + "description": "状态。", + "$ref": "#/components/schemas/SmsTemplateStatus" + }, + "providerTemplateCode": { + "maxLength": 120, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "渠道模板编码。" + }, + "content": { + "maxLength": 1000, + "minLength": 0, + "type": "string", + "description": "模板内容。" + }, + "remark": { + "maxLength": 500, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "Remark。" + }, + "metadata": { + "description": "扩展元数据。", + "$ref": "#/components/schemas/JsonElement" + } + }, + "description": "新增或更新租户短信模板请求。" + }, + "UpsertPlatformStaffDto": { + "type": "object", + "properties": { + "userId": { + "type": [ + "null", + "string" + ], + "description": "用户 ID。", + "format": "uuid" + }, + "email": { + "maxLength": 320, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "邮箱。" + }, + "phone": { + "maxLength": 32, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "手机号。" + }, + "name": { + "maxLength": 200, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "名称。" + }, + "status": { + "description": "状态。", + "$ref": "#/components/schemas/UserStatus" + }, + "roleIds": { + "type": "array", + "items": { + "type": "string", + "format": "uuid" + }, + "description": "角色 ID 列表。" + } + }, + "description": "新增或更新平台Staff请求 DTO。" + }, + "UpsertPlatformTenantBillingProfileDto": { + "required": [ + "tenantId" + ], + "type": "object", + "properties": { + "tenantId": { + "type": "string", + "description": "租户 ID。", + "format": "uuid" + }, + "billingName": { + "maxLength": 300, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "账务名称。" + }, + "taxId": { + "maxLength": 100, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "税号。" + }, + "contactName": { + "maxLength": 100, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "联系人姓名。" + }, + "contactPhone": { + "maxLength": 32, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "联系人手机号。" + }, + "contactEmail": { + "maxLength": 320, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "联系人邮箱。" + }, + "billingAddress": { + "maxLength": 1000, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "账务地址。" + }, + "invoiceTitle": { + "maxLength": 300, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "发票抬头。" + }, + "invoiceType": { + "oneOf": [ + { + "type": "null" + }, + { + "description": "发票类型。", + "$ref": "#/components/schemas/TenantBillingInvoiceTitleType" + } + ] + }, + "bankName": { + "maxLength": 300, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "开户银行。" + }, + "bankAccountMasked": { + "maxLength": 100, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "脱敏银行账号。" + }, + "metadata": { + "description": "扩展元数据。", + "$ref": "#/components/schemas/JsonElement" + } + }, + "description": "新增或更新平台租户账务资料请求 DTO。" + }, + "UpsertPlatformTenantPaymentAppDto": { + "required": [ + "tenantId", + "provider" + ], + "type": "object", + "properties": { + "tenantId": { + "type": "string", + "description": "租户 ID。", + "format": "uuid" + }, + "provider": { + "maxLength": 80, + "minLength": 0, + "type": "string", + "description": "服务提供方。" + }, + "status": { + "description": "状态。", + "$ref": "#/components/schemas/TenantExternalProviderStatus" + }, + "displayName": { + "maxLength": 200, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "显示名称。" + }, + "secretRef": { + "maxLength": 300, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "密钥引用。" + }, + "priority": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "description": "优先级。", + "format": "int32" + }, + "configPublic": { + "description": "公开配置内容。", + "$ref": "#/components/schemas/JsonElement" + }, + "metadata": { + "description": "扩展元数据。", + "$ref": "#/components/schemas/JsonElement" + } + }, + "description": "新增或更新租户支付应用请求。" + }, + "UpsertPointExchangeItemDto": { + "required": [ + "itemKey", + "name" + ], + "type": "object", + "properties": { + "id": { + "type": [ + "null", + "string" + ], + "description": "ID。", + "format": "uuid" + }, + "regionId": { + "type": [ + "null", + "string" + ], + "description": "地区 ID。", + "format": "uuid" + }, + "itemKey": { + "maxLength": 100, + "minLength": 0, + "type": "string", + "description": "兑换项键。" + }, + "name": { + "maxLength": 200, + "minLength": 0, + "type": "string", + "description": "名称。" + }, + "description": { + "maxLength": 1000, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "说明。" + }, + "itemType": { + "description": "兑换项类型。", + "$ref": "#/components/schemas/PointExchangeItemType" + }, + "status": { + "description": "状态。", + "$ref": "#/components/schemas/PointExchangeItemStatus" + }, + "pointsCost": { + "maximum": 2147483647, + "minimum": 1, + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "description": "所需积分。", + "format": "int32" + }, + "stock": { + "maximum": 2147483647, + "minimum": 0, + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "description": "库存数量。", + "format": "int32" + }, + "days": { + "maximum": 3650, + "minimum": 0, + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "description": "天数。", + "format": "int32" + }, + "sortOrder": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "description": "排序值。", + "format": "int32" + }, + "startsAt": { + "type": [ + "null", + "string" + ], + "description": "开始时间。", + "format": "date-time" + }, + "endsAt": { + "type": [ + "null", + "string" + ], + "description": "结束时间。", + "format": "date-time" + }, + "fulfillmentPayload": { + "description": "履约载荷。", + "$ref": "#/components/schemas/JsonElement" + }, + "metadata": { + "description": "扩展元数据。", + "$ref": "#/components/schemas/JsonElement" + } + }, + "description": "新增或更新积分兑换Item请求 DTO。" + }, + "UpsertPointTaskDto": { + "required": [ + "taskKey", + "title" + ], + "type": "object", + "properties": { + "id": { + "type": [ + "null", + "string" + ], + "description": "ID。", + "format": "uuid" + }, + "taskKey": { + "maxLength": 100, + "minLength": 0, + "type": "string", + "description": "任务键。" + }, + "title": { + "maxLength": 200, + "minLength": 0, + "type": "string", + "description": "标题。" + }, + "description": { + "maxLength": 1000, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "说明。" + }, + "taskType": { + "description": "任务类型。", + "$ref": "#/components/schemas/PointActivityTaskType" + }, + "status": { + "description": "状态。", + "$ref": "#/components/schemas/PointActivityTaskStatus" + }, + "points": { + "maximum": 2147483647, + "minimum": 1, + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "description": "积分数量。", + "format": "int32" + }, + "maxClaimsPerUser": { + "maximum": 1000, + "minimum": 1, + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "description": "每用户最多领取次数。", + "format": "int32" + }, + "startsAt": { + "type": [ + "null", + "string" + ], + "description": "开始时间。", + "format": "date-time" + }, + "endsAt": { + "type": [ + "null", + "string" + ], + "description": "结束时间。", + "format": "date-time" + }, + "sortOrder": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "description": "排序值。", + "format": "int32" + }, + "rules": { + "description": "规则配置。", + "$ref": "#/components/schemas/JsonElement" + }, + "metadata": { + "description": "扩展元数据。", + "$ref": "#/components/schemas/JsonElement" + } + }, + "description": "新增或更新积分任务请求 DTO。" + }, + "UpsertPracticeBlueprintDto": { + "required": [ + "name" + ], + "type": "object", + "properties": { + "id": { + "type": [ + "null", + "string" + ], + "description": "ID。", + "format": "uuid" + }, + "regionId": { + "type": [ + "null", + "string" + ], + "description": "地区 ID。", + "format": "uuid" + }, + "entryId": { + "type": [ + "null", + "string" + ], + "description": "内容入口 ID。", + "format": "uuid" + }, + "nodeId": { + "type": [ + "null", + "string" + ], + "description": "节点 ID。", + "format": "uuid" + }, + "collectionId": { + "type": [ + "null", + "string" + ], + "description": "题集 ID。", + "format": "uuid" + }, + "legacyId": { + "maxLength": 64, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "历史系统 ID。" + }, + "name": { + "maxLength": 300, + "minLength": 0, + "type": "string", + "description": "名称。" + }, + "mode": { + "maxLength": 50, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "模式。" + }, + "assemblyType": { + "maxLength": 50, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "组卷方式。" + }, + "questionLimit": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "description": "题目数量上限。", + "format": "int32" + }, + "durationMinutes": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "description": "时长,单位为分钟。", + "format": "int32" + }, + "totalScore": { + "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$", + "type": [ + "null", + "number", + "string" + ], + "description": "总分。", + "format": "double" + }, + "passScore": { + "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$", + "type": [ + "null", + "number", + "string" + ], + "description": "及格分。", + "format": "double" + }, + "sections": { + "description": "分段配置。", + "$ref": "#/components/schemas/JsonElement" + }, + "rules": { + "description": "规则配置。", + "$ref": "#/components/schemas/JsonElement" + }, + "accessRules": { + "description": "访问规则。", + "$ref": "#/components/schemas/JsonElement" + }, + "status": { + "maxLength": 50, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "状态。" + }, + "order": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "description": "显示顺序。", + "format": "int32" + } + }, + "description": "新增或更新练习Blueprint请求 DTO。" + }, + "UpsertQuestionCollectionDto": { + "required": [ + "name" + ], + "type": "object", + "properties": { + "id": { + "type": [ + "null", + "string" + ], + "description": "ID。", + "format": "uuid" + }, + "regionId": { + "type": [ + "null", + "string" + ], + "description": "地区 ID。", + "format": "uuid" + }, + "entryId": { + "type": [ + "null", + "string" + ], + "description": "内容入口 ID。", + "format": "uuid" + }, + "nodeId": { + "type": [ + "null", + "string" + ], + "description": "节点 ID。", + "format": "uuid" + }, + "subjectId": { + "type": [ + "null", + "string" + ], + "description": "科目 ID。", + "format": "uuid" + }, + "categoryId": { + "type": [ + "null", + "string" + ], + "description": "分类 ID。", + "format": "uuid" + }, + "questionBankId": { + "type": [ + "null", + "string" + ], + "description": "题库 ID。", + "format": "uuid" + }, + "legacyId": { + "maxLength": 64, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "历史系统 ID。" + }, + "name": { + "maxLength": 300, + "minLength": 0, + "type": "string", + "description": "名称。" + }, + "collectionType": { + "maxLength": 50, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "题集类型。" + }, + "sourceType": { + "maxLength": 50, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "来源类型。" + }, + "filters": { + "description": "筛选条件。", + "$ref": "#/components/schemas/JsonElement" + }, + "totalScore": { + "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$", + "type": [ + "null", + "number", + "string" + ], + "description": "总分。", + "format": "double" + }, + "durationMinutes": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "description": "时长,单位为分钟。", + "format": "int32" + }, + "status": { + "maxLength": 50, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "状态。" + }, + "order": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "description": "显示顺序。", + "format": "int32" + }, + "accessRules": { + "description": "访问规则。", + "$ref": "#/components/schemas/JsonElement" + }, + "metadata": { + "description": "扩展元数据。", + "$ref": "#/components/schemas/JsonElement" + } + }, + "description": "新增或更新题目题集请求 DTO。" + }, + "UpsertReferralTeamDto": { + "required": [ + "memberUserId" + ], + "type": "object", + "properties": { + "memberUserId": { + "type": "string", + "description": "成员用户 ID。", + "format": "uuid" + }, + "leaderUserId": { + "type": [ + "null", + "string" + ], + "description": "上级成员用户 ID。", + "format": "uuid" + }, + "relationType": { + "maxLength": 50, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "关系类型。" + }, + "status": { + "maxLength": 50, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "状态。" + }, + "metadata": { + "oneOf": [ + { + "type": "null" + }, + { + "description": "扩展元数据。", + "$ref": "#/components/schemas/JsonElement" + } + ] + } + }, + "description": "新增或更新推荐团队请求 DTO。" + }, + "UpsertSaasFeatureDto": { + "required": [ + "id", + "code", + "name", + "category", + "description", + "referencePriceCents", + "currency", + "status", + "sortOrder" + ], + "type": "object", + "properties": { + "id": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "code": { + "type": "string" + }, + "name": { + "type": "string" + }, + "category": { + "type": "string" + }, + "description": { + "type": [ + "null", + "string" + ] + }, + "referencePriceCents": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "currency": { + "type": "string" + }, + "status": { + "$ref": "#/components/schemas/SaasFeatureStatus" + }, + "sortOrder": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + } + }, + "description": "新增或更新SaaS功能请求 DTO。" + }, + "UpsertSaasFeatureLimitDto": { + "required": [ + "id", + "metricCode", + "featureCode", + "name", + "unit", + "kind", + "warningPercent", + "isHardLimit" + ], + "type": "object", + "properties": { + "id": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "metricCode": { + "type": "string" + }, + "featureCode": { + "type": "string" + }, + "name": { + "type": "string" + }, + "unit": { + "type": "string" + }, + "kind": { + "$ref": "#/components/schemas/SaasFeatureLimitKind" + }, + "warningPercent": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "isHardLimit": { + "type": "boolean" + } + }, + "description": "新增或更新 SaaS 功能额度定义。" + }, + "UpsertSaasOfferingDto": { + "required": [ + "id", + "code", + "name", + "type", + "status", + "description", + "sortOrder" + ], + "type": "object", + "properties": { + "id": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "code": { + "type": "string" + }, + "name": { + "type": "string" + }, + "type": { + "$ref": "#/components/schemas/SaasOfferingType" + }, + "status": { + "$ref": "#/components/schemas/SaasOfferingStatus" + }, + "description": { + "type": [ + "null", + "string" + ] + }, + "sortOrder": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + } + }, + "description": "新增或更新SaaS套餐请求 DTO。" + }, + "UpsertSaasOfferingVersionDto": { + "required": [ + "id", + "offeringId", + "billingCycle", + "originalAmountCents", + "amountCents", + "currency", + "effectiveAt", + "featureCodes", + "limits", + "metadata" + ], + "type": "object", + "properties": { + "id": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "offeringId": { + "type": "string", + "format": "uuid" + }, + "billingCycle": { + "$ref": "#/components/schemas/PlatformBillingCycle" + }, + "originalAmountCents": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "amountCents": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "currency": { + "type": "string" + }, + "effectiveAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "featureCodes": { + "type": [ + "null", + "array" + ], + "items": { + "type": "string" + } + }, + "limits": { + "type": [ + "null", + "object" + ], + "additionalProperties": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int64" + } + }, + "metadata": { + "$ref": "#/components/schemas/JsonElement" + } + }, + "description": "新增或更新SaaS套餐版本请求 DTO。" + }, + "UpsertTenantAdminBadgeDto": { + "required": [ + "name" + ], + "type": "object", + "properties": { + "id": { + "type": [ + "null", + "string" + ], + "description": "ID。", + "format": "uuid" + }, + "legacyId": { + "type": [ + "null", + "string" + ], + "description": "历史系统 ID。" + }, + "name": { + "type": "string", + "description": "名称。" + }, + "description": { + "type": [ + "null", + "string" + ], + "description": "说明。" + }, + "category": { + "type": [ + "null", + "string" + ], + "description": "分类。" + }, + "iconUrl": { + "type": [ + "null", + "string" + ], + "description": "图标地址。" + }, + "level": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "description": "级别。", + "format": "int32" + }, + "unlockType": { + "type": [ + "null", + "string" + ], + "description": "解锁类型。" + }, + "conditionField": { + "type": [ + "null", + "string" + ], + "description": "条件字段。" + }, + "conditionOperator": { + "type": [ + "null", + "string" + ], + "description": "条件运算符。" + }, + "conditionValue": { + "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$", + "type": [ + "null", + "number", + "string" + ], + "description": "条件值。", + "format": "double" + }, + "conditionExtra": { + "description": "条件扩展配置。", + "$ref": "#/components/schemas/JsonElement" + }, + "order": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "description": "显示顺序。", + "format": "int32" + }, + "isActive": { + "type": [ + "null", + "boolean" + ], + "description": "是否启用。" + } + }, + "description": "新增或更新租户管理端徽章请求 DTO。" + }, + "UpsertTenantAdminClassDto": { + "required": [ + "name" + ], + "type": "object", + "properties": { + "id": { + "type": [ + "null", + "string" + ], + "description": "ID。", + "format": "uuid" + }, + "regionId": { + "type": [ + "null", + "string" + ], + "description": "地区 ID。", + "format": "uuid" + }, + "legacyId": { + "type": [ + "null", + "string" + ], + "description": "历史系统 ID。" + }, + "code": { + "type": [ + "null", + "string" + ], + "description": "编码。" + }, + "name": { + "type": "string", + "description": "名称。" + }, + "description": { + "type": [ + "null", + "string" + ], + "description": "说明。" + }, + "status": { + "type": [ + "null", + "string" + ], + "description": "状态。" + }, + "order": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "description": "显示顺序。", + "format": "int32" + }, + "metadata": { + "description": "扩展元数据。", + "$ref": "#/components/schemas/JsonElement" + } + }, + "description": "新增或更新租户管理端班级请求 DTO。" + }, + "UpsertTenantAdminClassMemberDto": { + "required": [ + "classId" + ], + "type": "object", + "properties": { + "classId": { + "type": "string", + "description": "班级 ID。", + "format": "uuid" + }, + "user": { + "description": "用户信息。", + "$ref": "#/components/schemas/TenantAdminUserLookupDto" + }, + "memberType": { + "type": [ + "null", + "string" + ], + "description": "成员类型。" + }, + "status": { + "type": [ + "null", + "string" + ], + "description": "状态。" + }, + "metadata": { + "description": "扩展元数据。", + "$ref": "#/components/schemas/JsonElement" + } + }, + "description": "新增或更新租户管理端班级成员请求 DTO。" + }, + "UpsertTenantAdminMemberDto": { + "type": "object", + "properties": { + "membershipId": { + "type": [ + "null", + "string" + ], + "description": "成员关系 ID。", + "format": "uuid" + }, + "user": { + "description": "用户信息。", + "$ref": "#/components/schemas/TenantAdminUserLookupDto" + }, + "role": { + "type": [ + "null", + "string" + ], + "description": "角色。" + }, + "status": { + "type": [ + "null", + "string" + ], + "description": "状态。" + }, + "primaryRole": { + "type": [ + "null", + "string" + ], + "description": "主要角色。" + } + }, + "description": "新增或更新租户管理端成员请求 DTO。" + }, + "UpsertTenantAdminNotificationDto": { + "required": [ + "userId", + "notificationType", + "title", + "message" + ], + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "用户 ID。", + "format": "uuid" + }, + "notificationType": { + "type": "string", + "description": "通知类型。" + }, + "severity": { + "type": [ + "null", + "string" + ], + "description": "严重级别。" + }, + "title": { + "type": "string", + "description": "标题。" + }, + "message": { + "type": "string", + "description": "消息内容。" + }, + "actionLabel": { + "type": [ + "null", + "string" + ], + "description": "操作按钮文案。" + }, + "actionPath": { + "type": [ + "null", + "string" + ], + "description": "操作路径。" + }, + "sourceType": { + "type": [ + "null", + "string" + ], + "description": "来源类型。" + }, + "sourceId": { + "type": [ + "null", + "string" + ], + "description": "来源 ID。", + "format": "uuid" + }, + "dedupeKey": { + "type": [ + "null", + "string" + ], + "description": "去重键。" + }, + "metadata": { + "description": "扩展元数据。", + "$ref": "#/components/schemas/JsonElement" + } + }, + "description": "新增或更新租户管理端通知请求 DTO。" + }, + "UpsertTenantAdminStudentDto": { + "type": "object", + "properties": { + "user": { + "description": "用户信息。", + "$ref": "#/components/schemas/TenantAdminUserLookupDto" + }, + "regionId": { + "type": [ + "null", + "string" + ], + "description": "地区 ID。", + "format": "uuid" + }, + "selectedSchoolId": { + "type": [ + "null", + "string" + ], + "description": "已选择院校 ID。", + "format": "uuid" + }, + "selectedMajorId": { + "type": [ + "null", + "string" + ], + "description": "已选择专业 ID。", + "format": "uuid" + }, + "avatarPreset": { + "type": [ + "null", + "string" + ], + "description": "头像预设。" + }, + "stats": { + "description": "统计数据。", + "$ref": "#/components/schemas/JsonElement" + }, + "progress": { + "description": "进度数据。", + "$ref": "#/components/schemas/JsonElement" + }, + "moduleSelections": { + "description": "模块选择数据。", + "$ref": "#/components/schemas/JsonElement" + }, + "rawProfile": { + "description": "原始用户资料。", + "$ref": "#/components/schemas/JsonElement" + } + }, + "description": "新增或更新租户管理端学生请求 DTO。" + }, + "UpsertTenantAdminStudentFollowupDto": { + "required": [ + "studentUserId", + "title" + ], + "type": "object", + "properties": { + "id": { + "type": [ + "null", + "string" + ], + "description": "ID。", + "format": "uuid" + }, + "studentUserId": { + "type": "string", + "description": "学生用户 ID。", + "format": "uuid" + }, + "assignedToUserId": { + "type": [ + "null", + "string" + ], + "description": "分配处理人用户 ID。", + "format": "uuid" + }, + "classId": { + "type": [ + "null", + "string" + ], + "description": "班级 ID。", + "format": "uuid" + }, + "title": { + "type": "string", + "description": "标题。" + }, + "description": { + "type": [ + "null", + "string" + ], + "description": "说明。" + }, + "followupType": { + "type": [ + "null", + "string" + ], + "description": "跟进类型。" + }, + "priority": { + "type": [ + "null", + "string" + ], + "description": "优先级。" + }, + "status": { + "type": [ + "null", + "string" + ], + "description": "状态。" + }, + "dueAt": { + "type": [ + "null", + "string" + ], + "description": "到期时间。", + "format": "date-time" + }, + "metadata": { + "description": "扩展元数据。", + "$ref": "#/components/schemas/JsonElement" + } + }, + "description": "新增或更新租户管理端学生跟进请求 DTO。" + }, + "UpsertTenantAdminStudentNoteDto": { + "required": [ + "studentUserId", + "content" + ], + "type": "object", + "properties": { + "id": { + "type": [ + "null", + "string" + ], + "description": "ID。", + "format": "uuid" + }, + "studentUserId": { + "type": "string", + "description": "学生用户 ID。", + "format": "uuid" + }, + "noteType": { + "type": [ + "null", + "string" + ], + "description": "备注类型。" + }, + "content": { + "type": "string", + "description": "内容。" + }, + "visibility": { + "type": [ + "null", + "string" + ], + "description": "可见性。" + }, + "isPinned": { + "type": [ + "null", + "boolean" + ], + "description": "是否置顶。" + }, + "metadata": { + "description": "扩展元数据。", + "$ref": "#/components/schemas/JsonElement" + } + }, + "description": "新增或更新租户管理端学生Note请求 DTO。" + }, + "UpsertTenantBrandingDto": { + "required": [ + "brandName" + ], + "type": "object", + "properties": { + "brandName": { + "type": "string", + "description": "品牌名称。" + }, + "shortName": { + "type": [ + "null", + "string" + ], + "description": "品牌简称。" + }, + "slogan": { + "type": [ + "null", + "string" + ], + "description": "品牌标语。" + }, + "organizationName": { + "type": [ + "null", + "string" + ], + "description": "机构名称。" + }, + "logoUrl": { + "type": [ + "null", + "string" + ], + "description": "Logo 地址。" + }, + "faviconUrl": { + "type": [ + "null", + "string" + ], + "description": "站点图标地址。" + }, + "serviceWechat": { + "type": [ + "null", + "string" + ], + "description": "客服微信。" + }, + "serviceAccountName": { + "type": [ + "null", + "string" + ], + "description": "客服账号名称。" + } + }, + "description": "新增或更新租户品牌请求 DTO。" + }, + "UpsertTenantCouponDto": { + "required": [ + "code" + ], + "type": "object", + "properties": { + "id": { + "type": [ + "null", + "string" + ], + "description": "ID。", + "format": "uuid" + }, + "code": { + "maxLength": 100, + "minLength": 0, + "type": "string", + "description": "编码。" + }, + "planId": { + "type": [ + "null", + "string" + ], + "description": "套餐 ID。", + "format": "uuid" + }, + "discountType": { + "description": "优惠类型。", + "$ref": "#/components/schemas/DiscountType" + }, + "discountValue": { + "maximum": 999999, + "minimum": 0.01, + "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$", + "type": [ + "number", + "string" + ], + "description": "优惠值。", + "format": "double" + }, + "validFrom": { + "type": [ + "null", + "string" + ], + "description": "有效期开始时间。", + "format": "date-time" + }, + "validTo": { + "type": [ + "null", + "string" + ], + "description": "有效期结束时间。", + "format": "date-time" + }, + "maxUses": { + "maximum": 2147483647, + "minimum": 1, + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "description": "最大使用次数。", + "format": "int32" + }, + "source": { + "maxLength": 50, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "来源。" + }, + "remark": { + "maxLength": 1000, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "备注。" + } + }, + "description": "新增或更新租户优惠券请求 DTO。" + }, + "UpsertTenantFeatureOverrideDto": { + "required": [ + "tenantId", + "featureCode", + "mode", + "expiresAt", + "reason" + ], + "type": "object", + "properties": { + "tenantId": { + "type": "string", + "format": "uuid" + }, + "featureCode": { + "type": "string" + }, + "mode": { + "$ref": "#/components/schemas/TenantFeatureOverrideMode" + }, + "expiresAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "reason": { + "type": "string" + } + }, + "description": "新增或更新租户功能覆盖规则请求 DTO。" + }, + "UpsertTenantIdentityProviderDto": { + "required": [ + "provider" + ], + "type": "object", + "properties": { + "provider": { + "type": "string", + "description": "服务提供方。" + }, + "status": { + "type": [ + "null", + "string" + ], + "description": "状态。" + }, + "displayName": { + "type": [ + "null", + "string" + ], + "description": "显示名称。" + }, + "secretRef": { + "type": [ + "null", + "string" + ], + "description": "密钥引用。" + }, + "priority": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "description": "优先级。", + "format": "int32" + }, + "configPublic": { + "description": "公开配置内容。", + "$ref": "#/components/schemas/JsonElement" + } + }, + "description": "新增或更新租户身份源Provider请求 DTO。" + }, + "UpsertTenantSecretDto": { + "required": [ + "purpose", + "provider", + "secretKey" + ], + "type": "object", + "properties": { + "purpose": { + "maxLength": 80, + "minLength": 0, + "type": "string", + "description": "用途。" + }, + "provider": { + "maxLength": 50, + "minLength": 0, + "type": "string", + "description": "服务提供方。" + }, + "secretKey": { + "maxLength": 120, + "minLength": 0, + "type": "string", + "description": "密钥键。" + }, + "secretRef": { + "maxLength": 300, + "minLength": 0, + "type": "string", + "description": "密钥引用。" + }, + "status": { + "description": "状态。", + "$ref": "#/components/schemas/TenantSecretStatus" + }, + "secretPayload": { + "description": "密钥载荷。", + "$ref": "#/components/schemas/JsonElement" + }, + "expiresAt": { + "type": [ + "null", + "string" + ], + "description": "过期时间。", + "format": "date-time" + } + }, + "description": "新增或更新租户Secret请求 DTO。" + }, + "UpsertTenantSettingsDto": { + "type": "object", + "properties": { + "featureFlags": { + "description": "前端功能开关。", + "$ref": "#/components/schemas/JsonElement" + }, + "adminFeatureFlags": { + "description": "管理端功能开关。", + "$ref": "#/components/schemas/JsonElement" + }, + "publicConfig": { + "description": "公开配置。", + "$ref": "#/components/schemas/JsonElement" + } + }, + "description": "新增或更新租户设置请求 DTO。" + }, + "UpsertTenantSupervisionRuleDto": { + "required": [ + "code", + "title" + ], + "type": "object", + "properties": { + "code": { + "maxLength": 100, + "minLength": 0, + "type": "string", + "description": "编码。" + }, + "title": { + "maxLength": 200, + "minLength": 0, + "type": "string", + "description": "标题。" + }, + "enabled": { + "type": "boolean", + "description": "是否启用。" + }, + "daysWithoutCheckIn": { + "maximum": 3650, + "minimum": 0, + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "description": "未签到天数。", + "format": "int32" + }, + "maxQuestionsAnsweredToday": { + "maximum": 2147483647, + "minimum": 0, + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "description": "当天最大答题数。", + "format": "int32" + }, + "followupType": { + "maxLength": 50, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "跟进类型。" + }, + "priority": { + "maxLength": 50, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "优先级。" + }, + "metadata": { + "description": "扩展元数据。", + "$ref": "#/components/schemas/JsonElement" + } + }, + "description": "新增或更新租户督导规则请求 DTO。" + }, + "UserStatus": { + "type": "integer" + }, + "VideoExplanationCatalogItem": { + "required": [ + "id", + "legacyId", + "subjectId", + "title", + "description", + "videoUrl", + "thumbnailUrl", + "durationSeconds", + "knowledgeTags", + "isGeneral", + "difficulty", + "order", + "isActive", + "metadata" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "legacyId": { + "type": [ + "null", + "string" + ] + }, + "subjectId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "title": { + "type": "string" + }, + "description": { + "type": [ + "null", + "string" + ] + }, + "videoUrl": { + "type": [ + "null", + "string" + ] + }, + "thumbnailUrl": { + "type": [ + "null", + "string" + ] + }, + "durationSeconds": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "format": "int32" + }, + "knowledgeTags": { + "$ref": "#/components/schemas/JsonElement" + }, + "isGeneral": { + "type": "boolean" + }, + "difficulty": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "format": "int32" + }, + "order": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "isActive": { + "type": "boolean" + }, + "metadata": { + "$ref": "#/components/schemas/JsonElement" + } + } + }, + "VideoManagementItem": { + "required": [ + "id", + "subjectId", + "legacyId", + "title", + "description", + "videoUrl", + "thumbnailUrl", + "durationSeconds", + "knowledgeTags", + "isGeneral", + "difficulty", + "order", + "isActive", + "metadata" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "subjectId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "legacyId": { + "type": [ + "null", + "string" + ] + }, + "title": { + "type": "string" + }, + "description": { + "type": [ + "null", + "string" + ] + }, + "videoUrl": { + "type": [ + "null", + "string" + ] + }, + "thumbnailUrl": { + "type": [ + "null", + "string" + ] + }, + "durationSeconds": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "format": "int32" + }, + "knowledgeTags": { + "$ref": "#/components/schemas/JsonElement" + }, + "isGeneral": { + "type": "boolean" + }, + "difficulty": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "format": "int32" + }, + "order": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "isActive": { + "type": "boolean" + }, + "metadata": { + "$ref": "#/components/schemas/JsonElement" + } + } + }, + "VideoPlaybackItem": { + "required": [ + "videoId", + "questionId", + "title", + "description", + "playUrl", + "thumbnailUrl", + "durationSeconds", + "progress", + "metadata" + ], + "type": "object", + "properties": { + "videoId": { + "type": "string", + "format": "uuid" + }, + "questionId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "title": { + "type": "string" + }, + "description": { + "type": [ + "null", + "string" + ] + }, + "playUrl": { + "type": [ + "null", + "string" + ] + }, + "thumbnailUrl": { + "type": [ + "null", + "string" + ] + }, + "durationSeconds": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "format": "int32" + }, + "progress": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/components/schemas/VideoProgressItem" + } + ] + }, + "metadata": { + "$ref": "#/components/schemas/JsonElement" + } + } + }, + "VideoPlayDto": { + "required": [ + "videoId" + ], + "type": "object", + "properties": { + "videoId": { + "type": "string", + "description": "视频 ID。", + "format": "uuid" + }, + "questionId": { + "type": [ + "null", + "string" + ], + "description": "题目 ID。", + "format": "uuid" + } + }, + "description": "视频Play请求 DTO。" + }, + "VideoProgressDto": { + "required": [ + "videoId" + ], + "type": "object", + "properties": { + "videoId": { + "type": "string", + "description": "视频 ID。", + "format": "uuid" + }, + "questionId": { + "type": [ + "null", + "string" + ], + "description": "题目 ID。", + "format": "uuid" + }, + "positionSeconds": { + "maximum": 2147483647, + "minimum": 0, + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "description": "播放位置,单位为秒。", + "format": "int32" + }, + "durationSeconds": { + "maximum": 2147483647, + "minimum": 0, + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "description": "时长,单位为秒。", + "format": "int32" + }, + "watchedSeconds": { + "maximum": 2147483647, + "minimum": 0, + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "description": "已观看时长,单位为秒。", + "format": "int32" + }, + "isCompleted": { + "type": [ + "null", + "boolean" + ], + "description": "是否已完成。" + }, + "metadata": { + "description": "扩展元数据。", + "$ref": "#/components/schemas/JsonElement" + } + }, + "description": "视频Progress请求 DTO。" + }, + "VideoProgressItem": { + "required": [ + "id", + "videoId", + "questionId", + "positionSeconds", + "durationSeconds", + "watchedSeconds", + "isCompleted", + "completedAt", + "lastPlayedAt", + "playCount", + "metadata" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "videoId": { + "type": "string", + "format": "uuid" + }, + "questionId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "positionSeconds": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "durationSeconds": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "format": "int32" + }, + "watchedSeconds": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "isCompleted": { + "type": "boolean" + }, + "completedAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "lastPlayedAt": { + "type": "string", + "format": "date-time" + }, + "playCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "metadata": { + "$ref": "#/components/schemas/JsonElement" + } + } + }, + "VocabularyUnit": { + "type": "object", + "properties": { + "regionId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "entryId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "contentNodeId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "legacyId": { + "type": [ + "null", + "string" + ] + }, + "name": { + "type": "string" + }, + "description": { + "type": [ + "null", + "string" + ] + }, + "wordCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "format": "int32" + }, + "sortOrder": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "isActive": { + "type": "boolean" + }, + "sourceHash": { + "type": [ + "null", + "string" + ] + }, + "metadata": { + "$ref": "#/components/schemas/JsonElement" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "tenantId": { + "type": "string", + "format": "uuid" + }, + "id": { + "type": "string", + "format": "uuid" + } + } + }, + "VocabularyUnitCatalogItem": { + "required": [ + "id", + "legacyId", + "regionId", + "entryId", + "contentNodeId", + "name", + "description", + "wordCount", + "order", + "metadata" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "legacyId": { + "type": [ + "null", + "string" + ] + }, + "regionId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "entryId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "contentNodeId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "name": { + "type": "string" + }, + "description": { + "type": [ + "null", + "string" + ] + }, + "wordCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "format": "int32" + }, + "order": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "metadata": { + "$ref": "#/components/schemas/JsonElement" + } + } + }, + "VocabularyWord": { + "type": "object", + "properties": { + "unitId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "entryId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "contentNodeId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "legacyId": { + "type": [ + "null", + "string" + ] + }, + "word": { + "type": "string" + }, + "phonetic": { + "type": [ + "null", + "string" + ] + }, + "meaning": { + "type": [ + "null", + "string" + ] + }, + "example": { + "type": [ + "null", + "string" + ] + }, + "exampleTranslation": { + "type": [ + "null", + "string" + ] + }, + "difficulty": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "format": "int32" + }, + "tags": { + "$ref": "#/components/schemas/JsonElement" + }, + "sortOrder": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "isActive": { + "type": "boolean" + }, + "sourceHash": { + "type": [ + "null", + "string" + ] + }, + "metadata": { + "$ref": "#/components/schemas/JsonElement" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "tenantId": { + "type": "string", + "format": "uuid" + }, + "id": { + "type": "string", + "format": "uuid" + } + } + }, + "VocabularyWordCatalogItem": { + "required": [ + "id", + "legacyId", + "unitId", + "entryId", + "contentNodeId", + "word", + "phonetic", + "meaning", + "example", + "exampleTranslation", + "difficulty", + "tags", + "order", + "metadata" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "legacyId": { + "type": [ + "null", + "string" + ] + }, + "unitId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "entryId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "contentNodeId": { + "type": [ + "null", + "string" + ], + "format": "uuid" + }, + "word": { + "type": "string" + }, + "phonetic": { + "type": [ + "null", + "string" + ] + }, + "meaning": { + "type": [ + "null", + "string" + ] + }, + "example": { + "type": [ + "null", + "string" + ] + }, + "exampleTranslation": { + "type": [ + "null", + "string" + ] + }, + "difficulty": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "format": "int32" + }, + "tags": { + "$ref": "#/components/schemas/JsonElement" + }, + "order": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "metadata": { + "$ref": "#/components/schemas/JsonElement" + } + } + }, + "WordDueLevel": { + "type": "integer" + }, + "WordProgressDto": { + "required": [ + "wordId" + ], + "type": "object", + "properties": { + "wordId": { + "type": "string", + "description": "单词 ID。", + "format": "uuid" + }, + "status": { + "maxLength": 50, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "状态。" + }, + "correctDelta": { + "maximum": 100, + "minimum": 0, + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "description": "答对数量变化。", + "format": "int32" + }, + "wrongDelta": { + "maximum": 100, + "minimum": 0, + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "null", + "integer", + "string" + ], + "description": "答错数量变化。", + "format": "int32" + }, + "nextReviewAt": { + "type": [ + "null", + "string" + ], + "description": "下次复习时间。", + "format": "date-time" + } + }, + "description": "单词Progress请求 DTO。" + }, + "WordProgressItem": { + "required": [ + "wordId", + "status", + "correctCount", + "wrongCount", + "lastReviewAt", + "nextReviewAt", + "reviewCount", + "correctStreak", + "lastResult", + "dueLevel", + "metadata" + ], + "type": "object", + "properties": { + "wordId": { + "type": "string", + "format": "uuid" + }, + "status": { + "$ref": "#/components/schemas/WordProgressStatus" + }, + "correctCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "wrongCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "lastReviewAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "nextReviewAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "reviewCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "correctStreak": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "lastResult": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/components/schemas/WordReviewResult" + } + ] + }, + "dueLevel": { + "$ref": "#/components/schemas/WordDueLevel" + }, + "metadata": { + "$ref": "#/components/schemas/JsonElement" + } + } + }, + "WordProgressStatus": { + "type": "integer" + }, + "WordReviewDto": { + "required": [ + "wordId" + ], + "type": "object", + "properties": { + "wordId": { + "type": "string", + "description": "单词 ID。", + "format": "uuid" + }, + "result": { + "maxLength": 50, + "minLength": 0, + "type": [ + "null", + "string" + ], + "description": "结果。" + }, + "nextReviewAt": { + "type": [ + "null", + "string" + ], + "description": "下次复习时间。", + "format": "date-time" + } + }, + "description": "单词Review请求 DTO。" + }, + "WordReviewPlan": { + "required": [ + "items", + "nextAction" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/WordReviewPlanItem" + } + }, + "nextAction": { + "$ref": "#/components/schemas/JsonElement" + } + } + }, + "WordReviewPlanItem": { + "required": [ + "wordId", + "status", + "nextReviewAt", + "correctCount", + "wrongCount", + "dueLevel" + ], + "type": "object", + "properties": { + "wordId": { + "type": "string", + "format": "uuid" + }, + "status": { + "$ref": "#/components/schemas/WordProgressStatus" + }, + "nextReviewAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + }, + "correctCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "wrongCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "dueLevel": { + "$ref": "#/components/schemas/WordDueLevel" + } + } + }, + "WordReviewResult": { + "type": "integer" + }, + "WordStatsItem": { + "required": [ + "total", + "newCount", + "learningCount", + "reviewingCount", + "masteredCount", + "dueCount", + "favoriteCount" + ], + "type": "object", + "properties": { + "total": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "newCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "learningCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "reviewingCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "masteredCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "dueCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "favoriteCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + } + } + }, + "WrongQuestionItem": { + "required": [ + "questionReferenceId", + "locator", + "wrongCount", + "lastWrongAt", + "resolvedAt" + ], + "type": "object", + "properties": { + "questionReferenceId": { + "type": "string", + "format": "uuid" + }, + "locator": { + "$ref": "#/components/schemas/QuestionLocator" + }, + "wrongCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "lastWrongAt": { + "type": "string", + "format": "date-time" + }, + "resolvedAt": { + "type": [ + "null", + "string" + ], + "format": "date-time" + } + } + }, + "WrongQuestionReviewPlan": { + "required": [ + "items", + "nextAction" + ], + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/WrongQuestionReviewPlanItem" + } + }, + "nextAction": { + "$ref": "#/components/schemas/JsonElement" + } + } + }, + "WrongQuestionReviewPlanItem": { + "required": [ + "questionReferenceId", + "locator", + "wrongCount", + "lastWrongAt" + ], + "type": "object", + "properties": { + "questionReferenceId": { + "type": "string", + "format": "uuid" + }, + "locator": { + "$ref": "#/components/schemas/QuestionLocator" + }, + "wrongCount": { + "pattern": "^-?(?:0|[1-9]\\d*)$", + "type": [ + "integer", + "string" + ], + "format": "int32" + }, + "lastWrongAt": { + "type": "string", + "format": "date-time" + } + } + } +} as const; diff --git a/Tiku.PlatformAdmin.Web/src/api/platform.ts b/Tiku.PlatformAdmin.Web/src/api/platform.ts new file mode 100644 index 0000000..53fb214 --- /dev/null +++ b/Tiku.PlatformAdmin.Web/src/api/platform.ts @@ -0,0 +1,13 @@ +import { apiRequest } from './http'; +import { platformOperations } from './platform-operations.generated'; +import type { HttpMethod, OperationInput, PlatformOperation } from './types'; + +export function platformOperation(method: HttpMethod, path: string): PlatformOperation { + const operation = platformOperations.find((item) => item.method === method && item.path === path); + if (!operation) throw new Error(`平台接口契约缺失:${method} ${path}`); + return operation; +} + +export function platformRequest(method: HttpMethod, path: string, input: OperationInput = {}, signal?: AbortSignal) { + return apiRequest(platformOperation(method, path), input, signal); +} diff --git a/Tiku.PlatformAdmin.Web/src/api/schema-utils.ts b/Tiku.PlatformAdmin.Web/src/api/schema-utils.ts new file mode 100644 index 0000000..d00df49 --- /dev/null +++ b/Tiku.PlatformAdmin.Web/src/api/schema-utils.ts @@ -0,0 +1,37 @@ +import { openApiSchemas } from './platform-operations.generated'; +import type { JsonSchema } from './types'; + +const schemas = openApiSchemas as unknown as Record; + +export function resolveSchema(schema: JsonSchema | null | undefined, seen = new Set()): JsonSchema { + if (!schema) return {}; + if (schema.$ref) { + const name = schema.$ref.split('/').at(-1) || ''; + if (seen.has(name)) return { type: 'object', description: schema.description }; + const nextSeen = new Set(seen).add(name); + return { ...resolveSchema(schemas[name], nextSeen), description: schema.description || schemas[name]?.description }; + } + const alternatives = schema.oneOf || schema.anyOf; + if (alternatives?.length) { + const meaningful = alternatives.find((item) => item.type !== 'null') || alternatives[0]; + return { ...schema, ...resolveSchema(meaningful, seen), oneOf: undefined, anyOf: undefined }; + } + return schema; +} + +export function schemaType(schema: JsonSchema): string { + const type = resolveSchema(schema).type; + if (Array.isArray(type)) return type.find((item) => item !== 'null') || 'string'; + return typeof type === 'string' ? type : 'string'; +} + +export function defaultForSchema(schema: JsonSchema): unknown { + const resolved = resolveSchema(schema); + if (resolved.default !== undefined) return resolved.default; + switch (schemaType(resolved)) { + case 'boolean': return false; + case 'array': return []; + case 'object': return {}; + default: return undefined; + } +} diff --git a/Tiku.PlatformAdmin.Web/src/api/schema.generated.d.ts b/Tiku.PlatformAdmin.Web/src/api/schema.generated.d.ts new file mode 100644 index 0000000..ca8f388 --- /dev/null +++ b/Tiku.PlatformAdmin.Web/src/api/schema.generated.d.ts @@ -0,0 +1,26144 @@ +/** + * This file was auto-generated by openapi-typescript. + * Do not make direct changes to the file. + */ + +export interface paths { + "/api/assets/{assetId}/download": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 获取资源下载地址 */ + get: { + parameters: { + query?: { + /** @description 租户编码。 */ + TenantCode?: string; + /** @description 有效期秒数。 */ + ExpiresInSeconds?: number | string; + }; + header?: never; + path: { + assetId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["AssetAccessResponseDto"]; + }; + }; + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProblemDetails"]; + }; + }; + /** @description Forbidden */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProblemDetails"]; + }; + }; + /** @description Not Found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProblemDetails"]; + }; + }; + /** @description Conflict */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProblemDetails"]; + }; + }; + /** @description Service Unavailable */ + 503: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProblemDetails"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/assets/{assetId}/preview": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 获取资源预览地址 */ + get: { + parameters: { + query?: { + /** @description 租户编码。 */ + TenantCode?: string; + /** @description 有效期秒数。 */ + ExpiresInSeconds?: number | string; + }; + header?: never; + path: { + assetId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["AssetAccessResponseDto"]; + }; + }; + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProblemDetails"]; + }; + }; + /** @description Forbidden */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProblemDetails"]; + }; + }; + /** @description Not Found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProblemDetails"]; + }; + }; + /** @description Conflict */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProblemDetails"]; + }; + }; + /** @description Service Unavailable */ + 503: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProblemDetails"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/auth/sms/send": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * 发送短信验证码 + * @description 发送登录用途短信验证码,并应用租户级短信限流。 + */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["SendSmsCodeDto"]; + "text/json": components["schemas"]["SendSmsCodeDto"]; + "application/*+json": components["schemas"]["SendSmsCodeDto"]; + }; + }; + responses: { + /** @description Accepted */ + 202: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["SmsSendResult"]; + }; + }; + /** @description Bad Request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProblemDetails"]; + }; + }; + /** @description Too Many Requests */ + 429: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProblemDetails"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/auth/login/password": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * 手机号密码登录 + * @description 使用本地手机号和密码登录,签发 JWT access token 与数据库 refresh/session。 + */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["PasswordLoginDto"]; + "text/json": components["schemas"]["PasswordLoginDto"]; + "application/*+json": components["schemas"]["PasswordLoginDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["AuthenticationResultDto"]; + }; + }; + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProblemDetails"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/auth/login/sms": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * 短信验证码登录 + * @description 校验已发送的登录用途短信验证码,成功后签发 JWT access token 与数据库 refresh/session。 + */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["SmsLoginDto"]; + "text/json": components["schemas"]["SmsLoginDto"]; + "application/*+json": components["schemas"]["SmsLoginDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["AuthenticationResultDto"]; + }; + }; + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProblemDetails"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/auth/oauth/wechat": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * 微信网页 OAuth 登录 + * @description 使用微信网页授权 code 换取 openid/unionid,upsert 用户身份并创建应用会话。 + */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["OAuthCodeDto"]; + "text/json": components["schemas"]["OAuthCodeDto"]; + "application/*+json": components["schemas"]["OAuthCodeDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["AuthenticationResultDto"]; + }; + }; + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProblemDetails"]; + }; + }; + /** @description Service Unavailable */ + 503: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProblemDetails"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/auth/oauth/wechat-miniapp": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * 微信小程序登录 + * @description 使用小程序 wx.login 返回的 code 换取 openid/session_key,upsert 用户身份并创建应用会话。 + */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["OAuthCodeDto"]; + "text/json": components["schemas"]["OAuthCodeDto"]; + "application/*+json": components["schemas"]["OAuthCodeDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["AuthenticationResultDto"]; + }; + }; + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProblemDetails"]; + }; + }; + /** @description Service Unavailable */ + 503: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProblemDetails"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/auth/refresh": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * 刷新登录会话 + * @description 使用 refresh token 轮换数据库 session,并签发新的 access/refresh token。 + */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["RefreshSessionDto"]; + "text/json": components["schemas"]["RefreshSessionDto"]; + "application/*+json": components["schemas"]["RefreshSessionDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["AuthTokenPair"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/auth/logout": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * 退出登录 + * @description 撤销 refresh token 对应的数据库 session;session 校验开启时,旧 access token 也会被拒绝。 + */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["RefreshSessionDto"]; + "text/json": components["schemas"]["RefreshSessionDto"]; + "application/*+json": components["schemas"]["RefreshSessionDto"]; + }; + }; + responses: { + /** @description No Content */ + 204: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": unknown; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/auth/logout-all": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * 退出全部登录会话 + * @description 撤销当前用户全部 refresh/session,会话校验开启时旧 access token 也会被拒绝。 + */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description No Content */ + 204: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": unknown; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/auth/password/change-required": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * 修改首次登录必改密码 + * @description 校验密码变更挑战令牌并设置新密码,成功后签发新的登录会话。 + */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["RequiredPasswordChangeDto"]; + "text/json": components["schemas"]["RequiredPasswordChangeDto"]; + "application/*+json": components["schemas"]["RequiredPasswordChangeDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["AuthenticationResultDto"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/backoffice/tenant/jobs": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询租户后台任务 */ + get: { + parameters: { + query?: { + jobType?: string; + limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "text/plain": components["schemas"]["BackgroundJobItem"][]; + "application/json": components["schemas"]["BackgroundJobItem"][]; + "text/json": components["schemas"]["BackgroundJobItem"][]; + }; + }; + }; + }; + put?: never; + /** 创建租户后台任务 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["CreateBackgroundJobDto"]; + "text/json": components["schemas"]["CreateBackgroundJobDto"]; + "application/*+json": components["schemas"]["CreateBackgroundJobDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "text/plain": components["schemas"]["BackgroundJobItem"]; + "application/json": components["schemas"]["BackgroundJobItem"]; + "text/json": components["schemas"]["BackgroundJobItem"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/browser-auth/sms/send": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 发送浏览器短信验证码 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["SendSmsCodeDto"]; + "text/json": components["schemas"]["SendSmsCodeDto"]; + "application/*+json": components["schemas"]["SendSmsCodeDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["SmsSendResult"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/browser-auth/login/password": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 浏览器手机号密码登录 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["PasswordLoginDto"]; + "text/json": components["schemas"]["PasswordLoginDto"]; + "application/*+json": components["schemas"]["PasswordLoginDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": unknown; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/browser-auth/login/sms": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 浏览器短信验证码登录 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["SmsLoginDto"]; + "text/json": components["schemas"]["SmsLoginDto"]; + "application/*+json": components["schemas"]["SmsLoginDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": unknown; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/browser-auth/oauth/wechat": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 浏览器微信网页 OAuth 登录 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["OAuthCodeDto"]; + "text/json": components["schemas"]["OAuthCodeDto"]; + "application/*+json": components["schemas"]["OAuthCodeDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": unknown; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/browser-auth/oauth/wechat-miniapp": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 浏览器微信小程序登录 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["OAuthCodeDto"]; + "text/json": components["schemas"]["OAuthCodeDto"]; + "application/*+json": components["schemas"]["OAuthCodeDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": unknown; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/browser-auth/refresh": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * 刷新浏览器登录会话 + * @description 读取浏览器 refresh cookie,轮换会话并重新写入认证 cookie。 + */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": unknown; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/browser-auth/logout": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * 退出浏览器登录 + * @description 撤销浏览器 refresh cookie 对应会话,并清理 access、refresh 与 CSRF cookie。 + */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": unknown; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/browser-auth/logout-all": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 退出全部浏览器登录会话 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": unknown; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/catalog/regions": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询可用地区 */ + get: { + parameters: { + query?: { + /** @description 租户编码。 */ + TenantCode?: string; + /** @description 地区 ID。 */ + RegionId?: string; + /** @description ModuleId。 */ + ModuleId?: string; + /** @description 父节点 ID;传 root 表示根节点。 */ + ParentId?: string; + /** @description 院校 ID。 */ + SchoolId?: string; + /** @description 专业 ID。 */ + MajorId?: string; + /** @description 科目 ID。 */ + SubjectId?: string; + /** @description 节点 ID。 */ + NodeId?: string; + /** @description 关键字。 */ + Keyword?: string; + /** @description 类型。 */ + Type?: string; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CatalogListOfRegionCatalogItem"]; + }; + }; + /** @description Not Found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProblemDetails"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/catalog/region-modules": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询地区功能模块 */ + get: { + parameters: { + query?: { + /** @description 租户编码。 */ + TenantCode?: string; + /** @description 地区 ID。 */ + RegionId?: string; + /** @description ModuleId。 */ + ModuleId?: string; + /** @description 父节点 ID;传 root 表示根节点。 */ + ParentId?: string; + /** @description 院校 ID。 */ + SchoolId?: string; + /** @description 专业 ID。 */ + MajorId?: string; + /** @description 科目 ID。 */ + SubjectId?: string; + /** @description 节点 ID。 */ + NodeId?: string; + /** @description 关键字。 */ + Keyword?: string; + /** @description 类型。 */ + Type?: string; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CatalogListOfRegionModuleCatalogItem"]; + }; + }; + /** @description Not Found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProblemDetails"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/catalog/module-nodes": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询模块导航节点 */ + get: { + parameters: { + query?: { + /** @description 租户编码。 */ + TenantCode?: string; + /** @description 地区 ID。 */ + RegionId?: string; + /** @description ModuleId。 */ + ModuleId?: string; + /** @description 父节点 ID;传 root 表示根节点。 */ + ParentId?: string; + /** @description 院校 ID。 */ + SchoolId?: string; + /** @description 专业 ID。 */ + MajorId?: string; + /** @description 科目 ID。 */ + SubjectId?: string; + /** @description 节点 ID。 */ + NodeId?: string; + /** @description 关键字。 */ + Keyword?: string; + /** @description 类型。 */ + Type?: string; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CatalogListOfModuleNodeCatalogItem"]; + }; + }; + /** @description Not Found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProblemDetails"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/catalog/schools": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询院校目录 */ + get: { + parameters: { + query?: { + /** @description 租户编码。 */ + TenantCode?: string; + /** @description 地区 ID。 */ + RegionId?: string; + /** @description ModuleId。 */ + ModuleId?: string; + /** @description 父节点 ID;传 root 表示根节点。 */ + ParentId?: string; + /** @description 院校 ID。 */ + SchoolId?: string; + /** @description 专业 ID。 */ + MajorId?: string; + /** @description 科目 ID。 */ + SubjectId?: string; + /** @description 节点 ID。 */ + NodeId?: string; + /** @description 关键字。 */ + Keyword?: string; + /** @description 类型。 */ + Type?: string; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CatalogListOfSchoolCatalogItem"]; + }; + }; + /** @description Not Found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProblemDetails"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/catalog/majors": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询专业目录 */ + get: { + parameters: { + query?: { + /** @description 租户编码。 */ + TenantCode?: string; + /** @description 地区 ID。 */ + RegionId?: string; + /** @description ModuleId。 */ + ModuleId?: string; + /** @description 父节点 ID;传 root 表示根节点。 */ + ParentId?: string; + /** @description 院校 ID。 */ + SchoolId?: string; + /** @description 专业 ID。 */ + MajorId?: string; + /** @description 科目 ID。 */ + SubjectId?: string; + /** @description 节点 ID。 */ + NodeId?: string; + /** @description 关键字。 */ + Keyword?: string; + /** @description 类型。 */ + Type?: string; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CatalogListOfMajorCatalogItem"]; + }; + }; + /** @description Not Found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProblemDetails"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/catalog/subjects": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询科目目录 */ + get: { + parameters: { + query?: { + /** @description 租户编码。 */ + TenantCode?: string; + /** @description 地区 ID。 */ + RegionId?: string; + /** @description ModuleId。 */ + ModuleId?: string; + /** @description 父节点 ID;传 root 表示根节点。 */ + ParentId?: string; + /** @description 院校 ID。 */ + SchoolId?: string; + /** @description 专业 ID。 */ + MajorId?: string; + /** @description 科目 ID。 */ + SubjectId?: string; + /** @description 节点 ID。 */ + NodeId?: string; + /** @description 关键字。 */ + Keyword?: string; + /** @description 类型。 */ + Type?: string; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CatalogListOfSubjectCatalogItem"]; + }; + }; + /** @description Not Found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProblemDetails"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/catalog/categories": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询题目分类 */ + get: { + parameters: { + query?: { + /** @description 租户编码。 */ + TenantCode?: string; + /** @description 地区 ID。 */ + RegionId?: string; + /** @description ModuleId。 */ + ModuleId?: string; + /** @description 父节点 ID;传 root 表示根节点。 */ + ParentId?: string; + /** @description 院校 ID。 */ + SchoolId?: string; + /** @description 专业 ID。 */ + MajorId?: string; + /** @description 科目 ID。 */ + SubjectId?: string; + /** @description 节点 ID。 */ + NodeId?: string; + /** @description 关键字。 */ + Keyword?: string; + /** @description 类型。 */ + Type?: string; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CatalogListOfCategoryCatalogItem"]; + }; + }; + /** @description Not Found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProblemDetails"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/catalog/question-categories": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询题目分类 */ + get: { + parameters: { + query?: { + /** @description 租户编码。 */ + TenantCode?: string; + /** @description 地区 ID。 */ + RegionId?: string; + /** @description ModuleId。 */ + ModuleId?: string; + /** @description 父节点 ID;传 root 表示根节点。 */ + ParentId?: string; + /** @description 院校 ID。 */ + SchoolId?: string; + /** @description 专业 ID。 */ + MajorId?: string; + /** @description 科目 ID。 */ + SubjectId?: string; + /** @description 节点 ID。 */ + NodeId?: string; + /** @description 关键字。 */ + Keyword?: string; + /** @description 类型。 */ + Type?: string; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CatalogListOfCategoryCatalogItem"]; + }; + }; + /** @description Not Found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProblemDetails"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/catalog/content-entries": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询内容入口 */ + get: { + parameters: { + query?: { + /** @description 租户编码。 */ + TenantCode?: string; + /** @description 地区 ID。 */ + RegionId?: string; + /** @description 内容入口 ID。 */ + EntryId?: string; + /** @description 节点 ID。 */ + NodeId?: string; + /** @description 题集 ID。 */ + CollectionId?: string; + /** @description 父节点 ID;传 root 表示根节点。 */ + ParentId?: string; + /** @description 入口类型。 */ + EntryType?: string; + /** @description 题集类型。 */ + CollectionType?: string; + /** @description 模式。 */ + Mode?: string; + /** @description 标记类型。 */ + MarkerType?: string; + /** @description 关键字。 */ + Keyword?: string; + /** @description 是否包含隐藏数据。 */ + IncludeHidden?: boolean; + /** @description 是否包含停用数据。 */ + IncludeInactive?: boolean; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CatalogListOfContentEntryCatalogItem"]; + }; + }; + /** @description Not Found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProblemDetails"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/catalog/content-nodes": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询内容导航节点 */ + get: { + parameters: { + query?: { + /** @description 租户编码。 */ + TenantCode?: string; + /** @description 地区 ID。 */ + RegionId?: string; + /** @description 内容入口 ID。 */ + EntryId?: string; + /** @description 节点 ID。 */ + NodeId?: string; + /** @description 题集 ID。 */ + CollectionId?: string; + /** @description 父节点 ID;传 root 表示根节点。 */ + ParentId?: string; + /** @description 入口类型。 */ + EntryType?: string; + /** @description 题集类型。 */ + CollectionType?: string; + /** @description 模式。 */ + Mode?: string; + /** @description 标记类型。 */ + MarkerType?: string; + /** @description 关键字。 */ + Keyword?: string; + /** @description 是否包含隐藏数据。 */ + IncludeHidden?: boolean; + /** @description 是否包含停用数据。 */ + IncludeInactive?: boolean; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CatalogListOfContentNodeCatalogItem"]; + }; + }; + /** @description Bad Request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProblemDetails"]; + }; + }; + /** @description Not Found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProblemDetails"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/catalog/question-collections": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询可用题集 */ + get: { + parameters: { + query?: { + /** @description 租户编码。 */ + TenantCode?: string; + /** @description 地区 ID。 */ + RegionId?: string; + /** @description 内容入口 ID。 */ + EntryId?: string; + /** @description 节点 ID。 */ + NodeId?: string; + /** @description 题集 ID。 */ + CollectionId?: string; + /** @description 父节点 ID;传 root 表示根节点。 */ + ParentId?: string; + /** @description 入口类型。 */ + EntryType?: string; + /** @description 题集类型。 */ + CollectionType?: string; + /** @description 模式。 */ + Mode?: string; + /** @description 标记类型。 */ + MarkerType?: string; + /** @description 关键字。 */ + Keyword?: string; + /** @description 是否包含隐藏数据。 */ + IncludeHidden?: boolean; + /** @description 是否包含停用数据。 */ + IncludeInactive?: boolean; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CatalogListOfQuestionCollectionCatalogItem"]; + }; + }; + /** @description Not Found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProblemDetails"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/catalog/question-collections/questions": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询题集内题目 */ + get: { + parameters: { + query?: { + /** @description 租户编码。 */ + TenantCode?: string; + /** @description 地区 ID。 */ + RegionId?: string; + /** @description 内容入口 ID。 */ + EntryId?: string; + /** @description 节点 ID。 */ + NodeId?: string; + /** @description 题集 ID。 */ + CollectionId?: string; + /** @description 父节点 ID;传 root 表示根节点。 */ + ParentId?: string; + /** @description 入口类型。 */ + EntryType?: string; + /** @description 题集类型。 */ + CollectionType?: string; + /** @description 模式。 */ + Mode?: string; + /** @description 标记类型。 */ + MarkerType?: string; + /** @description 关键字。 */ + Keyword?: string; + /** @description 是否包含隐藏数据。 */ + IncludeHidden?: boolean; + /** @description 是否包含停用数据。 */ + IncludeInactive?: boolean; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CatalogListOfCollectionQuestionCatalogItem"]; + }; + }; + /** @description Bad Request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProblemDetails"]; + }; + }; + /** @description Not Found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProblemDetails"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/catalog/practice-blueprints": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询练习蓝图 */ + get: { + parameters: { + query?: { + /** @description 租户编码。 */ + TenantCode?: string; + /** @description 地区 ID。 */ + RegionId?: string; + /** @description 内容入口 ID。 */ + EntryId?: string; + /** @description 节点 ID。 */ + NodeId?: string; + /** @description 题集 ID。 */ + CollectionId?: string; + /** @description 父节点 ID;传 root 表示根节点。 */ + ParentId?: string; + /** @description 入口类型。 */ + EntryType?: string; + /** @description 题集类型。 */ + CollectionType?: string; + /** @description 模式。 */ + Mode?: string; + /** @description 标记类型。 */ + MarkerType?: string; + /** @description 关键字。 */ + Keyword?: string; + /** @description 是否包含隐藏数据。 */ + IncludeHidden?: boolean; + /** @description 是否包含停用数据。 */ + IncludeInactive?: boolean; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CatalogListOfPracticeBlueprintCatalogItem"]; + }; + }; + /** @description Not Found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProblemDetails"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/catalog/question-banks": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询题库列表 */ + get: { + parameters: { + query?: { + /** @description 租户编码。 */ + TenantCode?: string; + /** @description 地区 ID。 */ + RegionId?: string; + /** @description 题库 ID。 */ + QuestionBankId?: string; + /** @description 科目 ID。 */ + SubjectId?: string; + /** @description 分类 ID。 */ + CategoryId?: string; + /** @description 节点 ID。 */ + NodeId?: string; + /** @description 内容入口 ID。 */ + EntryId?: string; + /** @description 内容节点 ID。 */ + ContentNodeId?: string; + /** @description 题集 ID。 */ + CollectionId?: string; + /** @description 来源。 */ + Source?: components["schemas"]["QuestionSource"]; + /** @description 类型。 */ + Type?: string; + /** @description 关键字。 */ + Keyword?: string; + /** @description 题目 ID 列表。 */ + QuestionIds?: string; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CatalogListOfQuestionBankCatalogItem"]; + }; + }; + /** @description Not Found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProblemDetails"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/catalog/questions": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * 查询已发布题目 + * @description 支持按题库、科目、分类、模块节点、内容入口、内容节点、题集或题目 ID 列表筛选。 + */ + get: { + parameters: { + query?: { + /** @description 租户编码。 */ + TenantCode?: string; + /** @description 地区 ID。 */ + RegionId?: string; + /** @description 题库 ID。 */ + QuestionBankId?: string; + /** @description 科目 ID。 */ + SubjectId?: string; + /** @description 分类 ID。 */ + CategoryId?: string; + /** @description 节点 ID。 */ + NodeId?: string; + /** @description 内容入口 ID。 */ + EntryId?: string; + /** @description 内容节点 ID。 */ + ContentNodeId?: string; + /** @description 题集 ID。 */ + CollectionId?: string; + /** @description 来源。 */ + Source?: components["schemas"]["QuestionSource"]; + /** @description 类型。 */ + Type?: string; + /** @description 关键字。 */ + Keyword?: string; + /** @description 题目 ID 列表。 */ + QuestionIds?: string; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CatalogListOfQuestionCatalogItem"]; + }; + }; + /** @description Not Found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProblemDetails"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/catalog/questions/{questionId}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询题目详情 */ + get: { + parameters: { + query?: { + /** @description 租户编码。 */ + TenantCode?: string; + /** @description 地区 ID。 */ + RegionId?: string; + /** @description 题库 ID。 */ + QuestionBankId?: string; + /** @description 科目 ID。 */ + SubjectId?: string; + /** @description 分类 ID。 */ + CategoryId?: string; + /** @description 节点 ID。 */ + NodeId?: string; + /** @description 内容入口 ID。 */ + EntryId?: string; + /** @description 内容节点 ID。 */ + ContentNodeId?: string; + /** @description 题集 ID。 */ + CollectionId?: string; + /** @description 来源。 */ + Source?: components["schemas"]["QuestionSource"]; + /** @description 类型。 */ + Type?: string; + /** @description 关键字。 */ + Keyword?: string; + /** @description 题目 ID 列表。 */ + QuestionIds?: string; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path: { + questionId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["QuestionCatalogItem"]; + }; + }; + /** @description Not Found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProblemDetails"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/catalog/questions/{questionId}/versions": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询题目版本 */ + get: { + parameters: { + query?: { + /** @description 租户编码。 */ + TenantCode?: string; + /** @description 地区 ID。 */ + RegionId?: string; + /** @description 题库 ID。 */ + QuestionBankId?: string; + /** @description 科目 ID。 */ + SubjectId?: string; + /** @description 分类 ID。 */ + CategoryId?: string; + /** @description 节点 ID。 */ + NodeId?: string; + /** @description 内容入口 ID。 */ + EntryId?: string; + /** @description 内容节点 ID。 */ + ContentNodeId?: string; + /** @description 题集 ID。 */ + CollectionId?: string; + /** @description 来源。 */ + Source?: components["schemas"]["QuestionSource"]; + /** @description 类型。 */ + Type?: string; + /** @description 关键字。 */ + Keyword?: string; + /** @description 题目 ID 列表。 */ + QuestionIds?: string; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path: { + questionId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CatalogListOfQuestionVersionCatalogItem"]; + }; + }; + /** @description Not Found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProblemDetails"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/catalog/vocabulary-units": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询词汇单元 */ + get: { + parameters: { + query?: { + /** @description 租户编码。 */ + TenantCode?: string; + /** @description 地区 ID。 */ + RegionId?: string; + /** @description 单元 ID。 */ + UnitId?: string; + /** @description 科目 ID。 */ + SubjectId?: string; + /** @description 章节 ID。 */ + ChapterId?: string; + /** @description 内容入口 ID。 */ + EntryId?: string; + /** @description 内容节点 ID。 */ + ContentNodeId?: string; + /** @description 关键字。 */ + Keyword?: string; + /** @description 是否包含正文内容。 */ + IncludeContent?: boolean; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CatalogListOfVocabularyUnitCatalogItem"]; + }; + }; + /** @description Not Found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProblemDetails"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/catalog/vocabulary-words": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询词汇单词 */ + get: { + parameters: { + query?: { + /** @description 租户编码。 */ + TenantCode?: string; + /** @description 地区 ID。 */ + RegionId?: string; + /** @description 单元 ID。 */ + UnitId?: string; + /** @description 科目 ID。 */ + SubjectId?: string; + /** @description 章节 ID。 */ + ChapterId?: string; + /** @description 内容入口 ID。 */ + EntryId?: string; + /** @description 内容节点 ID。 */ + ContentNodeId?: string; + /** @description 关键字。 */ + Keyword?: string; + /** @description 是否包含正文内容。 */ + IncludeContent?: boolean; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CatalogListOfVocabularyWordCatalogItem"]; + }; + }; + /** @description Not Found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProblemDetails"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/catalog/handbook-subjects": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询知识手册科目 */ + get: { + parameters: { + query?: { + /** @description 租户编码。 */ + TenantCode?: string; + /** @description 地区 ID。 */ + RegionId?: string; + /** @description 单元 ID。 */ + UnitId?: string; + /** @description 科目 ID。 */ + SubjectId?: string; + /** @description 章节 ID。 */ + ChapterId?: string; + /** @description 内容入口 ID。 */ + EntryId?: string; + /** @description 内容节点 ID。 */ + ContentNodeId?: string; + /** @description 关键字。 */ + Keyword?: string; + /** @description 是否包含正文内容。 */ + IncludeContent?: boolean; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CatalogListOfHandbookSubjectCatalogItem"]; + }; + }; + /** @description Not Found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProblemDetails"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/catalog/handbook-chapters": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询知识手册章节 */ + get: { + parameters: { + query?: { + /** @description 租户编码。 */ + TenantCode?: string; + /** @description 地区 ID。 */ + RegionId?: string; + /** @description 单元 ID。 */ + UnitId?: string; + /** @description 科目 ID。 */ + SubjectId?: string; + /** @description 章节 ID。 */ + ChapterId?: string; + /** @description 内容入口 ID。 */ + EntryId?: string; + /** @description 内容节点 ID。 */ + ContentNodeId?: string; + /** @description 关键字。 */ + Keyword?: string; + /** @description 是否包含正文内容。 */ + IncludeContent?: boolean; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CatalogListOfHandbookChapterCatalogItem"]; + }; + }; + /** @description Not Found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProblemDetails"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/catalog/handbook-entries": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询知识手册条目 */ + get: { + parameters: { + query?: { + /** @description 租户编码。 */ + TenantCode?: string; + /** @description 地区 ID。 */ + RegionId?: string; + /** @description 单元 ID。 */ + UnitId?: string; + /** @description 科目 ID。 */ + SubjectId?: string; + /** @description 章节 ID。 */ + ChapterId?: string; + /** @description 内容入口 ID。 */ + EntryId?: string; + /** @description 内容节点 ID。 */ + ContentNodeId?: string; + /** @description 关键字。 */ + Keyword?: string; + /** @description 是否包含正文内容。 */ + IncludeContent?: boolean; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CatalogListOfHandbookEntryCatalogItem"]; + }; + }; + /** @description Not Found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProblemDetails"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/catalog/content-assets": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询内容资源 */ + get: { + parameters: { + query?: { + /** @description 租户编码。 */ + TenantCode?: string; + /** @description 地区 ID。 */ + RegionId?: string; + /** @description 科目 ID。 */ + SubjectId?: string; + /** @description 分类 ID。 */ + CategoryId?: string; + /** @description 内容节点 ID。 */ + ContentNodeId?: string; + /** @description 题目 ID。 */ + QuestionId?: string; + /** @description 资产 ID。 */ + AssetId?: string; + /** @description 资产类型。 */ + AssetType?: string; + /** @description 分类。 */ + Category?: string; + /** @description 资产键。 */ + AssetKey?: string; + /** @description 关键字。 */ + Keyword?: string; + /** @description 是否包含锁定资源。 */ + IncludeLocked?: boolean; + /** @description 是否包含停用数据。 */ + IncludeInactive?: boolean; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CatalogListOfContentAssetCatalogItem"]; + }; + }; + /** @description Not Found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProblemDetails"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/catalog/images": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询图片资源 */ + get: { + parameters: { + query?: { + /** @description 租户编码。 */ + TenantCode?: string; + /** @description 地区 ID。 */ + RegionId?: string; + /** @description 科目 ID。 */ + SubjectId?: string; + /** @description 分类 ID。 */ + CategoryId?: string; + /** @description 内容节点 ID。 */ + ContentNodeId?: string; + /** @description 题目 ID。 */ + QuestionId?: string; + /** @description 资产 ID。 */ + AssetId?: string; + /** @description 资产类型。 */ + AssetType?: string; + /** @description 分类。 */ + Category?: string; + /** @description 资产键。 */ + AssetKey?: string; + /** @description 关键字。 */ + Keyword?: string; + /** @description 是否包含锁定资源。 */ + IncludeLocked?: boolean; + /** @description 是否包含停用数据。 */ + IncludeInactive?: boolean; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CatalogListOfImageAssetCatalogItem"]; + }; + }; + /** @description Not Found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProblemDetails"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/catalog/app-assets": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询应用资源 */ + get: { + parameters: { + query?: { + /** @description 租户编码。 */ + TenantCode?: string; + /** @description 地区 ID。 */ + RegionId?: string; + /** @description 科目 ID。 */ + SubjectId?: string; + /** @description 分类 ID。 */ + CategoryId?: string; + /** @description 内容节点 ID。 */ + ContentNodeId?: string; + /** @description 题目 ID。 */ + QuestionId?: string; + /** @description 资产 ID。 */ + AssetId?: string; + /** @description 资产类型。 */ + AssetType?: string; + /** @description 分类。 */ + Category?: string; + /** @description 资产键。 */ + AssetKey?: string; + /** @description 关键字。 */ + Keyword?: string; + /** @description 是否包含锁定资源。 */ + IncludeLocked?: boolean; + /** @description 是否包含停用数据。 */ + IncludeInactive?: boolean; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CatalogListOfAppAssetCatalogItem"]; + }; + }; + /** @description Not Found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProblemDetails"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/catalog/video-explanations": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询视频讲解 */ + get: { + parameters: { + query?: { + /** @description 租户编码。 */ + TenantCode?: string; + /** @description 地区 ID。 */ + RegionId?: string; + /** @description 科目 ID。 */ + SubjectId?: string; + /** @description 分类 ID。 */ + CategoryId?: string; + /** @description 内容节点 ID。 */ + ContentNodeId?: string; + /** @description 题目 ID。 */ + QuestionId?: string; + /** @description 资产 ID。 */ + AssetId?: string; + /** @description 资产类型。 */ + AssetType?: string; + /** @description 分类。 */ + Category?: string; + /** @description 资产键。 */ + AssetKey?: string; + /** @description 关键字。 */ + Keyword?: string; + /** @description 是否包含锁定资源。 */ + IncludeLocked?: boolean; + /** @description 是否包含停用数据。 */ + IncludeInactive?: boolean; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CatalogListOfVideoExplanationCatalogItem"]; + }; + }; + /** @description Not Found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProblemDetails"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/catalog/question-videos": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询题目关联视频 */ + get: { + parameters: { + query?: { + /** @description 租户编码。 */ + TenantCode?: string; + /** @description 地区 ID。 */ + RegionId?: string; + /** @description 科目 ID。 */ + SubjectId?: string; + /** @description 分类 ID。 */ + CategoryId?: string; + /** @description 内容节点 ID。 */ + ContentNodeId?: string; + /** @description 题目 ID。 */ + QuestionId?: string; + /** @description 资产 ID。 */ + AssetId?: string; + /** @description 资产类型。 */ + AssetType?: string; + /** @description 分类。 */ + Category?: string; + /** @description 资产键。 */ + AssetKey?: string; + /** @description 关键字。 */ + Keyword?: string; + /** @description 是否包含锁定资源。 */ + IncludeLocked?: boolean; + /** @description 是否包含停用数据。 */ + IncludeInactive?: boolean; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CatalogListOfQuestionVideoCatalogItem"]; + }; + }; + /** @description Not Found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProblemDetails"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/catalog/banners": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询首页横幅 */ + get: { + parameters: { + query?: { + /** @description 租户编码。 */ + TenantCode?: string; + /** @description 地区 ID。 */ + RegionId?: string; + /** @description ModuleId。 */ + ModuleId?: string; + /** @description 父节点 ID;传 root 表示根节点。 */ + ParentId?: string; + /** @description 院校 ID。 */ + SchoolId?: string; + /** @description 专业 ID。 */ + MajorId?: string; + /** @description 科目 ID。 */ + SubjectId?: string; + /** @description 节点 ID。 */ + NodeId?: string; + /** @description 关键字。 */ + Keyword?: string; + /** @description 类型。 */ + Type?: string; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CatalogListOfBannerCatalogItem"]; + }; + }; + /** @description Not Found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProblemDetails"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/catalog/faqs": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询常见问题 */ + get: { + parameters: { + query?: { + /** @description 租户编码。 */ + TenantCode?: string; + /** @description 地区 ID。 */ + RegionId?: string; + /** @description ModuleId。 */ + ModuleId?: string; + /** @description 父节点 ID;传 root 表示根节点。 */ + ParentId?: string; + /** @description 院校 ID。 */ + SchoolId?: string; + /** @description 专业 ID。 */ + MajorId?: string; + /** @description 科目 ID。 */ + SubjectId?: string; + /** @description 节点 ID。 */ + NodeId?: string; + /** @description 关键字。 */ + Keyword?: string; + /** @description 类型。 */ + Type?: string; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CatalogListOfFaqCatalogItem"]; + }; + }; + /** @description Not Found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProblemDetails"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/catalog/announcements": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询公告 */ + get: { + parameters: { + query?: { + /** @description 租户编码。 */ + TenantCode?: string; + /** @description 地区 ID。 */ + RegionId?: string; + /** @description ModuleId。 */ + ModuleId?: string; + /** @description 父节点 ID;传 root 表示根节点。 */ + ParentId?: string; + /** @description 院校 ID。 */ + SchoolId?: string; + /** @description 专业 ID。 */ + MajorId?: string; + /** @description 科目 ID。 */ + SubjectId?: string; + /** @description 节点 ID。 */ + NodeId?: string; + /** @description 关键字。 */ + Keyword?: string; + /** @description 类型。 */ + Type?: string; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CatalogListOfAnnouncementCatalogItem"]; + }; + }; + /** @description Not Found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProblemDetails"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/catalog/exam-dates": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询考试日期 */ + get: { + parameters: { + query?: { + /** @description 租户编码。 */ + TenantCode?: string; + /** @description 地区 ID。 */ + RegionId?: string; + /** @description ModuleId。 */ + ModuleId?: string; + /** @description 父节点 ID;传 root 表示根节点。 */ + ParentId?: string; + /** @description 院校 ID。 */ + SchoolId?: string; + /** @description 专业 ID。 */ + MajorId?: string; + /** @description 科目 ID。 */ + SubjectId?: string; + /** @description 节点 ID。 */ + NodeId?: string; + /** @description 关键字。 */ + Keyword?: string; + /** @description 类型。 */ + Type?: string; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CatalogListOfExamDateCatalogItem"]; + }; + }; + /** @description Not Found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProblemDetails"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/catalog/products": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询可购买产品 */ + get: { + parameters: { + query?: { + /** @description 租户编码。 */ + TenantCode?: string; + /** @description 地区 ID。 */ + RegionId?: string; + /** @description ModuleId。 */ + ModuleId?: string; + /** @description 父节点 ID;传 root 表示根节点。 */ + ParentId?: string; + /** @description 院校 ID。 */ + SchoolId?: string; + /** @description 专业 ID。 */ + MajorId?: string; + /** @description 科目 ID。 */ + SubjectId?: string; + /** @description 节点 ID。 */ + NodeId?: string; + /** @description 关键字。 */ + Keyword?: string; + /** @description 类型。 */ + Type?: string; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CatalogListOfProductCatalogItem"]; + }; + }; + /** @description Not Found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProblemDetails"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/catalog/svip-plans": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询 SVIP 套餐 */ + get: { + parameters: { + query?: { + /** @description 租户编码。 */ + TenantCode?: string; + /** @description 地区 ID。 */ + RegionId?: string; + /** @description ModuleId。 */ + ModuleId?: string; + /** @description 父节点 ID;传 root 表示根节点。 */ + ParentId?: string; + /** @description 院校 ID。 */ + SchoolId?: string; + /** @description 专业 ID。 */ + MajorId?: string; + /** @description 科目 ID。 */ + SubjectId?: string; + /** @description 节点 ID。 */ + NodeId?: string; + /** @description 关键字。 */ + Keyword?: string; + /** @description 类型。 */ + Type?: string; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CatalogListOfSvipPlanCatalogItem"]; + }; + }; + /** @description Not Found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProblemDetails"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/commerce/orders": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询当前用户订单 */ + get: { + parameters: { + query?: { + /** @description 返回数量上限。 */ + Limit?: number | string; + /** @description 状态。 */ + Status?: string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CommerceOrderList"]; + }; + }; + }; + }; + put?: never; + /** 创建学生端订单 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["CreateCommerceOrderDto"]; + "text/json": components["schemas"]["CreateCommerceOrderDto"]; + "application/*+json": components["schemas"]["CreateCommerceOrderDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CommerceOrderItem"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/commerce/orders/{orderNo}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询当前用户订单详情 */ + get: { + parameters: { + query?: never; + header?: never; + path: { + orderNo: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CommerceOrderItem"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/commerce/payments": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 创建订单支付 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["CreateCommercePaymentDto"]; + "text/json": components["schemas"]["CreateCommercePaymentDto"]; + "application/*+json": components["schemas"]["CreateCommercePaymentDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CommercePaymentItem"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/commerce/entitlements/current": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询当前用户权益 */ + get: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CurrentEntitlementItem"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/commerce/coupons/claim": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 领取优惠券 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["ClaimCommerceCouponDto"]; + "text/json": components["schemas"]["ClaimCommerceCouponDto"]; + "application/*+json": components["schemas"]["ClaimCommerceCouponDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CommerceCouponItem"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/commerce/coupons": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询当前用户优惠券 */ + get: { + parameters: { + query?: { + /** @description 返回数量上限。 */ + Limit?: number | string; + /** @description 状态。 */ + Status?: string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CommerceCouponList"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/commerce/coupons/check": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 校验优惠券并预览订单金额 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["CheckCommerceCouponDto"]; + "text/json": components["schemas"]["CheckCommerceCouponDto"]; + "application/*+json": components["schemas"]["CheckCommerceCouponDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CommerceCouponCheckResult"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/commerce/payments/notify/wechat-pay": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 微信支付回调 */ + post: { + parameters: { + query?: { + tenantCode?: string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["PaymentNotificationProcessResult"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/commerce/payments/notify/alipay": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 支付宝支付回调 */ + post: { + parameters: { + query?: { + tenantCode?: string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["PaymentNotificationProcessResult"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/commerce/refunds/notify/wechat_pay": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 微信退款结果回调 */ + post: { + parameters: { + query?: { + tenantCode?: string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["RefundNotificationDto"]; + "text/json": components["schemas"]["RefundNotificationDto"]; + "application/*+json": components["schemas"]["RefundNotificationDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CommerceRefundRequest"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/commerce/refunds/notify/alipay": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 支付宝退款结果回调 */ + post: { + parameters: { + query?: { + tenantCode?: string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["RefundNotificationDto"]; + "text/json": components["schemas"]["RefundNotificationDto"]; + "application/*+json": components["schemas"]["RefundNotificationDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CommerceRefundRequest"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/commission/settings": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询佣金配置 */ + get: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CommissionSettingsItem"]; + }; + }; + }; + }; + /** 保存佣金配置 */ + put: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["UpdateCommissionSettingsDto"]; + "text/json": components["schemas"]["UpdateCommissionSettingsDto"]; + "application/*+json": components["schemas"]["UpdateCommissionSettingsDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CommissionSettingsItem"]; + }; + }; + }; + }; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/commission/member-rate": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + /** 调整成员佣金比例 */ + put: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["UpdateMemberCommissionRateDto"]; + "text/json": components["schemas"]["UpdateMemberCommissionRateDto"]; + "application/*+json": components["schemas"]["UpdateMemberCommissionRateDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": unknown; + }; + }; + }; + }; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/commission/summary": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询佣金统计摘要 */ + get: { + parameters: { + query?: { + /** @description 开始日期,格式为 yyyy-MM-dd。 */ + StartDate?: string; + /** @description 结束日期,格式为 yyyy-MM-dd。 */ + EndDate?: string; + /** @description 推荐人用户 ID。 */ + ReferrerUserId?: string; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CommissionSummaryItem"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/commission/orders": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询佣金来源订单 */ + get: { + parameters: { + query?: { + /** @description 开始日期,格式为 yyyy-MM-dd。 */ + StartDate?: string; + /** @description 结束日期,格式为 yyyy-MM-dd。 */ + EndDate?: string; + /** @description 推荐人用户 ID。 */ + ReferrerUserId?: string; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CommissionListOfCommissionSourceItem"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/commission/settlements": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询佣金结算单 */ + get: { + parameters: { + query?: { + /** @description 状态。 */ + Status?: string; + /** @description 推荐人用户 ID。 */ + ReferrerUserId?: string; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CommissionListOfCommissionSettlementItemDto"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/commission/settlements/export": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 导出佣金结算单 */ + get: { + parameters: { + query?: { + /** @description 结算单 ID。 */ + SettlementId?: string; + /** @description 导出格式。 */ + Format?: string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CommissionExportItem"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/commission/settlements/generate": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 生成佣金结算单 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["GenerateCommissionSettlementDto"]; + "text/json": components["schemas"]["GenerateCommissionSettlementDto"]; + "application/*+json": components["schemas"]["GenerateCommissionSettlementDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CommissionSettlementItemDto"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/commission/settlements/status": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 更新佣金结算单状态 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["UpdateCommissionSettlementStatusDto"]; + "text/json": components["schemas"]["UpdateCommissionSettlementStatusDto"]; + "application/*+json": components["schemas"]["UpdateCommissionSettlementStatusDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CommissionSettlementItemDto"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/commission/settlements/proofs": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询佣金结算凭证 */ + get: { + parameters: { + query?: { + /** @description 结算单 ID。 */ + SettlementId?: string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CommissionListOfCommissionProofItem"]; + }; + }; + }; + }; + put?: never; + /** 创建佣金结算凭证 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["CreateCommissionProofDto"]; + "text/json": components["schemas"]["CreateCommissionProofDto"]; + "application/*+json": components["schemas"]["CreateCommissionProofDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CommissionProofItem"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/commission/settlements/proofs/status": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 更新佣金结算凭证状态 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["UpdateCommissionProofStatusDto"]; + "text/json": components["schemas"]["UpdateCommissionProofStatusDto"]; + "application/*+json": components["schemas"]["UpdateCommissionProofStatusDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CommissionProofItem"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/crm/config": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询 CRM 推送配置 */ + get: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CrmConfigItem"]; + }; + }; + }; + }; + /** 保存 CRM 推送配置 */ + put: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["UpsertCrmConfigDto"]; + "text/json": components["schemas"]["UpsertCrmConfigDto"]; + "application/*+json": components["schemas"]["UpsertCrmConfigDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CrmConfigItem"]; + }; + }; + }; + }; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/crm/queue": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询 CRM webhook 队列 */ + get: { + parameters: { + query?: { + /** @description 状态。 */ + Status?: string; + /** @description 队列任务 ID。 */ + QueueId?: string; + /** @description 来源。 */ + Source?: string; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CrmListOfCrmQueueItem"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/crm/dead-letters": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询 CRM 死信任务与汇总 */ + get: { + parameters: { + query?: { + /** @description 状态。 */ + Status?: string; + /** @description 队列任务 ID。 */ + QueueId?: string; + /** @description 来源。 */ + Source?: string; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CrmDeadLetterResult"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/crm/queue/logs": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询 CRM 队列执行日志 */ + get: { + parameters: { + query?: { + /** @description 队列任务 ID。 */ + QueueId?: string; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CrmListOfCrmQueueLogItem"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/crm/queue/action": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 重试或忽略 CRM 死信任务 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["CrmQueueActionDto"]; + "text/json": components["schemas"]["CrmQueueActionDto"]; + "application/*+json": components["schemas"]["CrmQueueActionDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CrmQueueItem"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/health": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * 健康检查 + * @description 用于本地、CI 和部署环境 smoke test 的轻量健康检查。 + */ + get: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HealthResponseDto"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/health/ready": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 依赖就绪检查 */ + get: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": unknown; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/learning/stats": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询学习统计 */ + get: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["LearningStatsItem"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/learning/trend": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询学习趋势 */ + get: { + parameters: { + query?: { + /** @description 返回数量上限。 */ + Limit?: number | string; + /** @description 状态。 */ + Status?: string; + /** @description 单元 ID。 */ + UnitId?: string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["LearningListOfLearningTrendItem"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/learning/leaderboard": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询学习排行榜 */ + get: { + parameters: { + query?: { + /** @description 返回数量上限。 */ + Limit?: number | string; + /** @description 状态。 */ + Status?: string; + /** @description 单元 ID。 */ + UnitId?: string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["LearningLeaderboardResult"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/learning/practice-sessions": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 创建练习会话 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["CreatePracticeSessionDto"]; + "text/json": components["schemas"]["CreatePracticeSessionDto"]; + "application/*+json": components["schemas"]["CreatePracticeSessionDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["PracticeSessionItem"]; + }; + }; + /** @description Conflict */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProblemDetails"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/learning/practice-sessions/detail": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 获取练习会话详情 */ + get: { + parameters: { + query?: { + /** @description 练习会话 ID。 */ + PracticeSessionId?: string; + /** @description 练习蓝图 ID。 */ + BlueprintId?: string; + /** @description 模式。 */ + Mode?: string; + /** @description 状态。 */ + Status?: string; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["PracticeSessionDetailItem"]; + }; + }; + /** @description Not Found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProblemDetails"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/learning/practice-sessions/submit": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 提交练习会话并生成报告 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["SubmitPracticeSessionDto"]; + "text/json": components["schemas"]["SubmitPracticeSessionDto"]; + "application/*+json": components["schemas"]["SubmitPracticeSessionDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["PracticeSessionReportItem"]; + }; + }; + /** @description Not Found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProblemDetails"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/learning/practice-sessions/report": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 获取练习会话报告 */ + get: { + parameters: { + query?: { + /** @description 练习会话 ID。 */ + PracticeSessionId?: string; + /** @description 练习蓝图 ID。 */ + BlueprintId?: string; + /** @description 模式。 */ + Mode?: string; + /** @description 状态。 */ + Status?: string; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["PracticeSessionReportItem"]; + }; + }; + /** @description Not Found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProblemDetails"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/learning/practice-reports": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询练习报告列表 */ + get: { + parameters: { + query?: { + /** @description 练习会话 ID。 */ + PracticeSessionId?: string; + /** @description 练习蓝图 ID。 */ + BlueprintId?: string; + /** @description 模式。 */ + Mode?: string; + /** @description 状态。 */ + Status?: string; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["LearningListOfPracticeSessionReportItem"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/learning/practice-sessions/history": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询练习历史 */ + get: { + parameters: { + query?: { + /** @description 练习会话 ID。 */ + PracticeSessionId?: string; + /** @description 练习蓝图 ID。 */ + BlueprintId?: string; + /** @description 模式。 */ + Mode?: string; + /** @description 状态。 */ + Status?: string; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["LearningListOfPracticeHistoryItem"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/learning/answers": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 提交题目答案 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["SubmitAnswerDto"]; + "text/json": components["schemas"]["SubmitAnswerDto"]; + "application/*+json": components["schemas"]["SubmitAnswerDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["AnswerRecordItem"]; + }; + }; + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProblemDetails"]; + }; + }; + /** @description Forbidden */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProblemDetails"]; + }; + }; + /** @description Not Found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProblemDetails"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/learning/favorites/questions": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询收藏题目 */ + get: { + parameters: { + query?: { + /** @description 返回数量上限。 */ + Limit?: number | string; + /** @description 状态。 */ + Status?: string; + /** @description 单元 ID。 */ + UnitId?: string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["LearningListOfFavoriteQuestionItem"]; + }; + }; + }; + }; + put?: never; + /** 收藏或取消收藏题目 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["QuestionActionDto"]; + "text/json": components["schemas"]["QuestionActionDto"]; + "application/*+json": components["schemas"]["QuestionActionDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["LearningActionResult"]; + }; + }; + /** @description Not Found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProblemDetails"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/learning/wrong-questions": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询错题列表 */ + get: { + parameters: { + query?: { + /** @description 返回数量上限。 */ + Limit?: number | string; + /** @description 状态。 */ + Status?: string; + /** @description 单元 ID。 */ + UnitId?: string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["LearningListOfWrongQuestionItem"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/learning/wrong-questions/review-plan": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 生成错题复习计划 */ + get: { + parameters: { + query?: { + /** @description 返回数量上限。 */ + Limit?: number | string; + /** @description 状态。 */ + Status?: string; + /** @description 单元 ID。 */ + UnitId?: string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["WrongQuestionReviewPlan"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/learning/wrong-questions/resolve": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 将错题标记为已解决 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["QuestionActionDto"]; + "text/json": components["schemas"]["QuestionActionDto"]; + "application/*+json": components["schemas"]["QuestionActionDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["LearningActionResult"]; + }; + }; + /** @description Not Found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProblemDetails"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/learning/vocabulary/progress": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询单词学习进度 */ + get: { + parameters: { + query?: { + /** @description 返回数量上限。 */ + Limit?: number | string; + /** @description 状态。 */ + Status?: string; + /** @description 单元 ID。 */ + UnitId?: string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["LearningListOfWordProgressItem"]; + }; + }; + }; + }; + put?: never; + /** 更新单词学习进度 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["WordProgressDto"]; + "text/json": components["schemas"]["WordProgressDto"]; + "application/*+json": components["schemas"]["WordProgressDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["WordProgressItem"]; + }; + }; + /** @description Not Found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProblemDetails"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/learning/vocabulary/review-plan": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 生成单词复习计划 */ + get: { + parameters: { + query?: { + /** @description 返回数量上限。 */ + Limit?: number | string; + /** @description 状态。 */ + Status?: string; + /** @description 单元 ID。 */ + UnitId?: string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["WordReviewPlan"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/learning/vocabulary/review": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 提交单词复习结果 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["WordReviewDto"]; + "text/json": components["schemas"]["WordReviewDto"]; + "application/*+json": components["schemas"]["WordReviewDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["WordProgressItem"]; + }; + }; + /** @description Not Found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProblemDetails"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/learning/vocabulary/stats": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询单词学习统计 */ + get: { + parameters: { + query?: { + /** @description 返回数量上限。 */ + Limit?: number | string; + /** @description 状态。 */ + Status?: string; + /** @description 单元 ID。 */ + UnitId?: string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["WordStatsItem"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/learning/vocabulary/favorites": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询收藏单词 */ + get: { + parameters: { + query?: { + /** @description 返回数量上限。 */ + Limit?: number | string; + /** @description 状态。 */ + Status?: string; + /** @description 单元 ID。 */ + UnitId?: string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["LearningListOfFavoriteWordItem"]; + }; + }; + }; + }; + put?: never; + /** 收藏或取消收藏单词 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["FavoriteWordDto"]; + "text/json": components["schemas"]["FavoriteWordDto"]; + "application/*+json": components["schemas"]["FavoriteWordDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["LearningActionResult"]; + }; + }; + /** @description Not Found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProblemDetails"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/me": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * 获取当前登录用户 + * @description 根据 Bearer Token 返回当前用户基础信息和活跃租户成员摘要。 + */ + get: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "text/plain": components["schemas"]["MeResponse"]; + "application/json": components["schemas"]["MeResponse"]; + "text/json": components["schemas"]["MeResponse"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/platform-admin/overview": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询平台经营概览 */ + get: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["PlatformOverview"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/platform-admin/tenants": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询平台租户列表 */ + get: { + parameters: { + query?: { + /** @description 状态。 */ + Status?: string; + /** @description 搜索关键字。 */ + Search?: string; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["PlatformTenantList"]; + }; + }; + }; + }; + put?: never; + /** 创建平台租户 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["CreatePlatformTenantDto"]; + "text/json": components["schemas"]["CreatePlatformTenantDto"]; + "application/*+json": components["schemas"]["CreatePlatformTenantDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["PlatformTenantProvisioningResult"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/platform-admin/tenants/detail": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询平台租户详情 */ + get: { + parameters: { + query?: { + tenantId?: string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["PlatformTenantDetail"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/platform-admin/tenants/status": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + /** 更新租户业务与账务状态 */ + patch: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["UpdatePlatformTenantStatusDto"]; + "text/json": components["schemas"]["UpdatePlatformTenantStatusDto"]; + "application/*+json": components["schemas"]["UpdatePlatformTenantStatusDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["PlatformTenantItem"]; + }; + }; + }; + }; + trace?: never; + }; + "/api/platform-admin/tenants/billing-profile": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + /** 保存租户账务与开票资料 */ + put: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["UpsertPlatformTenantBillingProfileDto"]; + "text/json": components["schemas"]["UpsertPlatformTenantBillingProfileDto"]; + "application/*+json": components["schemas"]["UpsertPlatformTenantBillingProfileDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["TenantBillingProfileItem"]; + }; + }; + }; + }; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/platform-admin/domains": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询租户域名状态 */ + get: { + parameters: { + query?: { + /** @description 状态。 */ + Status?: string; + /** @description 搜索关键字。 */ + Search?: string; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["PlatformDomainList"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/platform-admin/domains/{domainId}/recheck": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 重新触发租户域名 DNS/TLS 验证 */ + post: { + parameters: { + query?: never; + header?: never; + path: { + domainId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["PlatformDomainRecheckResult"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/platform-admin/staff": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询平台员工列表 */ + get: { + parameters: { + query?: { + /** @description 状态。 */ + Status?: string; + /** @description 搜索关键字。 */ + Search?: string; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["PlatformStaffList"]; + }; + }; + }; + }; + /** 创建或更新平台员工 */ + put: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["UpsertPlatformStaffDto"]; + "text/json": components["schemas"]["UpsertPlatformStaffDto"]; + "application/*+json": components["schemas"]["UpsertPlatformStaffDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["PlatformStaffItem"]; + }; + }; + }; + }; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/platform-admin/staff/status": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + /** 启用或禁用平台员工 */ + patch: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["UpdatePlatformStaffStatusDto"]; + "text/json": components["schemas"]["UpdatePlatformStaffStatusDto"]; + "application/*+json": components["schemas"]["UpdatePlatformStaffStatusDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["PlatformStaffItem"]; + }; + }; + }; + }; + trace?: never; + }; + "/api/platform-admin/audit-logs": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询平台审计日志 */ + get: { + parameters: { + query?: { + /** @description 状态。 */ + Status?: string; + /** @description 搜索关键字。 */ + Search?: string; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["PlatformAuditLogList"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/platform-admin/audit-alerts": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询平台审计告警 */ + get: { + parameters: { + query?: { + /** @description 状态。 */ + Status?: string; + /** @description 搜索关键字。 */ + Search?: string; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["PlatformAuditAlertList"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/platform-admin/audit-alerts/status": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 更新平台审计告警状态 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["UpdatePlatformAuditAlertStatusDto"]; + "text/json": components["schemas"]["UpdatePlatformAuditAlertStatusDto"]; + "application/*+json": components["schemas"]["UpdatePlatformAuditAlertStatusDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["PlatformAuditAlert"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/platform-admin/saas/dunning/channels": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询平台催缴通知渠道 */ + get: { + parameters: { + query?: { + /** @description 状态。 */ + Status?: string; + /** @description 搜索关键字。 */ + Search?: string; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["PlatformBillingDunningChannelList"]; + }; + }; + }; + }; + /** 创建或更新平台催缴通知渠道 */ + put: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["UpsertPlatformBillingDunningChannelDto"]; + "text/json": components["schemas"]["UpsertPlatformBillingDunningChannelDto"]; + "application/*+json": components["schemas"]["UpsertPlatformBillingDunningChannelDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["PlatformBillingDunningChannelItem"]; + }; + }; + }; + }; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/platform-admin/saas/dunning/channels/disable": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 禁用平台催缴通知渠道 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["DisablePlatformBillingDunningChannelDto"]; + "text/json": components["schemas"]["DisablePlatformBillingDunningChannelDto"]; + "application/*+json": components["schemas"]["DisablePlatformBillingDunningChannelDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["PlatformBillingDunningChannelItem"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/platform-admin/saas/dunning/events": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询平台催缴通知事件 */ + get: { + parameters: { + query?: { + /** @description 状态。 */ + Status?: string; + /** @description 搜索关键字。 */ + Search?: string; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["PlatformBillingDunningEventList"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/platform-admin/saas/dunning/events/detail": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询平台催缴通知事件详情 */ + get: { + parameters: { + query?: { + eventId?: string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["PlatformBillingDunningEventItem"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/platform-admin/saas/dunning/events/retry": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 重新标记平台催缴通知事件待发送 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["RetryPlatformBillingDunningEventDto"]; + "text/json": components["schemas"]["RetryPlatformBillingDunningEventDto"]; + "application/*+json": components["schemas"]["RetryPlatformBillingDunningEventDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["PlatformBillingDunningEventItem"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/backoffice/platform/ui-bootstrap": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * 查询平台后台菜单与权限 + * @description 返回当前平台管理员可见的后台菜单、权限和模块启用状态。 + */ + get: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "text/plain": components["schemas"]["BackofficeUiBootstrap"]; + "application/json": components["schemas"]["BackofficeUiBootstrap"]; + "text/json": components["schemas"]["BackofficeUiBootstrap"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/backoffice/platform/bootstrap": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询平台角色管理初始化数据 */ + get: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "text/plain": components["schemas"]["BackofficeBootstrap"]; + "application/json": components["schemas"]["BackofficeBootstrap"]; + "text/json": components["schemas"]["BackofficeBootstrap"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/backoffice/platform/roles": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 创建或更新平台后台角色 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["UpsertBackofficeRoleDto"]; + "text/json": components["schemas"]["UpsertBackofficeRoleDto"]; + "application/*+json": components["schemas"]["UpsertBackofficeRoleDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "text/plain": components["schemas"]["BackofficeRoleItem"]; + "application/json": components["schemas"]["BackofficeRoleItem"]; + "text/json": components["schemas"]["BackofficeRoleItem"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/backoffice/platform/roles/{roleId}/bindings": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + /** 替换平台后台角色权限绑定 */ + put: { + parameters: { + query?: never; + header?: never; + path: { + roleId: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["ReplaceRoleBindingsDto"]; + "text/json": components["schemas"]["ReplaceRoleBindingsDto"]; + "application/*+json": components["schemas"]["ReplaceRoleBindingsDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "text/plain": components["schemas"]["BackofficeRoleItem"]; + "application/json": components["schemas"]["BackofficeRoleItem"]; + "text/json": components["schemas"]["BackofficeRoleItem"]; + }; + }; + }; + }; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/backoffice/platform/users/{userId}/roles": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + /** 替换平台用户后台角色 */ + put: { + parameters: { + query?: never; + header?: never; + path: { + userId: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["ReplaceUserRolesDto"]; + "text/json": components["schemas"]["ReplaceUserRolesDto"]; + "application/*+json": components["schemas"]["ReplaceUserRolesDto"]; + }; + }; + responses: { + /** @description No Content */ + 204: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/platform-billing/callbacks/{provider}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * 处理平台账务支付回调 + * @description 接收平台账务支付渠道回调,按 provider 归一化后写入通知处理流程。 + */ + post: { + parameters: { + query?: never; + header?: never; + path: { + provider: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/platform-admin/payment-settings/apps": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询平台支付应用 */ + get: { + parameters: { + query?: { + status?: string; + limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["PlatformPaymentApp"][]; + }; + }; + }; + }; + /** 新增或更新平台支付应用 */ + put: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["UpsertPlatformPaymentAppDto"]; + "text/json": components["schemas"]["UpsertPlatformPaymentAppDto"]; + "application/*+json": components["schemas"]["UpsertPlatformPaymentAppDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["PlatformPaymentApp"]; + }; + }; + }; + }; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/platform-admin/payment-settings/channels": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询平台支付渠道 */ + get: { + parameters: { + query?: { + appId?: string; + status?: string; + limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["PlatformPaymentChannel"][]; + }; + }; + }; + }; + /** 新增或更新平台支付渠道 */ + put: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["UpsertPlatformPaymentChannelDto"]; + "text/json": components["schemas"]["UpsertPlatformPaymentChannelDto"]; + "application/*+json": components["schemas"]["UpsertPlatformPaymentChannelDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["PlatformPaymentChannel"]; + }; + }; + }; + }; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/platform-admin/payment-settings/channels/{id}/disable": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 禁用平台支付渠道 */ + post: { + parameters: { + query?: never; + header?: never; + path: { + id: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["PlatformPaymentChannel"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/platform-admin/payment-settings/events": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询平台支付事件 */ + get: { + parameters: { + query?: { + status?: string; + limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["PlatformBillingPaymentEvent"][]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/platform-admin/payment-settings/rebates/summary": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询平台返佣汇总 */ + get: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["PlatformRebateSummary"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/platform-admin/question-banks": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询平台公共题库 */ + get: { + parameters: { + query?: { + keyword?: string; + status?: string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["PlatformQuestionBankItem"][]; + }; + }; + }; + }; + /** 新增或更新平台公共题库 */ + put: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["UpsertPlatformQuestionBankCommand"]; + "text/json": components["schemas"]["UpsertPlatformQuestionBankCommand"]; + "application/*+json": components["schemas"]["UpsertPlatformQuestionBankCommand"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["PlatformQuestionBankItem"]; + }; + }; + }; + }; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/platform-admin/question-banks/{bankId}/archive": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 归档平台公共题库 */ + post: { + parameters: { + query?: never; + header?: never; + path: { + bankId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["PlatformQuestionBankItem"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/platform-admin/question-banks/{bankId}/nodes": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询公共题库内容结构 */ + get: { + parameters: { + query?: never; + header?: never; + path: { + bankId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["PlatformQuestionBankNodeItem"][]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/platform-admin/question-banks/nodes": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + /** 新增或更新公共题库内容节点 */ + put: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["UpsertPlatformQuestionBankNodeCommand"]; + "text/json": components["schemas"]["UpsertPlatformQuestionBankNodeCommand"]; + "application/*+json": components["schemas"]["UpsertPlatformQuestionBankNodeCommand"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["PlatformQuestionBankNodeItem"]; + }; + }; + }; + }; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/platform-admin/question-banks/nodes/batch": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 批量创建公共题库章节或试卷 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["BatchCreatePlatformQuestionBankNodesCommand"]; + "text/json": components["schemas"]["BatchCreatePlatformQuestionBankNodesCommand"]; + "application/*+json": components["schemas"]["BatchCreatePlatformQuestionBankNodesCommand"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["PlatformQuestionBankNodeItem"][]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/platform-admin/question-banks/nodes/{nodeId}/archive": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 归档公共题库内容节点 */ + post: { + parameters: { + query?: never; + header?: never; + path: { + nodeId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["PlatformQuestionBankNodeItem"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/platform-admin/question-banks/questions": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 分页查询公共题库题目 */ + get: { + parameters: { + query?: { + questionBankId?: string; + contentNodeId?: string; + keyword?: string; + type?: string; + difficulty?: number | string; + status?: string; + page?: number | string; + pageSize?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["PlatformQuestionPage"]; + }; + }; + }; + }; + /** 新增或更新公共题库题目并保留版本 */ + put: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["UpsertPlatformQuestionCommand"]; + "text/json": components["schemas"]["UpsertPlatformQuestionCommand"]; + "application/*+json": components["schemas"]["UpsertPlatformQuestionCommand"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["PlatformQuestionItem"]; + }; + }; + }; + }; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/platform-admin/question-banks/questions/archive": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 批量归档公共题库题目 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["ArchivePlatformQuestionsCommand"]; + "text/json": components["schemas"]["ArchivePlatformQuestionsCommand"]; + "application/*+json": components["schemas"]["ArchivePlatformQuestionsCommand"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": number | string; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/platform-admin/question-banks/imports/preview": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 预检公共题库 JSON 导入 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["PlatformQuestionImportCommand"]; + "text/json": components["schemas"]["PlatformQuestionImportCommand"]; + "application/*+json": components["schemas"]["PlatformQuestionImportCommand"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["PlatformQuestionImportResult"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/platform-admin/question-banks/imports": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 执行公共题库 JSON 导入 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["PlatformQuestionImportCommand"]; + "text/json": components["schemas"]["PlatformQuestionImportCommand"]; + "application/*+json": components["schemas"]["PlatformQuestionImportCommand"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["PlatformQuestionImportResult"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/platform-admin/question-banks/imports/{jobId}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询公共题库导入结果 */ + get: { + parameters: { + query?: never; + header?: never; + path: { + jobId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ContentImportJobDetail"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/platform-admin/question-banks/assets/upload-sign": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 签发公共题库图片上传地址 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["AssetUploadSignDto"]; + "text/json": components["schemas"]["AssetUploadSignDto"]; + "application/*+json": components["schemas"]["AssetUploadSignDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["AssetUploadSignResult"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/platform-admin/question-banks/assets/upload-confirm": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 确认公共题库图片上传结果 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["AssetUploadConfirmDto"]; + "text/json": components["schemas"]["AssetUploadConfirmDto"]; + "application/*+json": components["schemas"]["AssetUploadConfirmDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["AssetUploadConfirmResult"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/platform-admin/saas/catalog": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询平台 SaaS 商品目录 */ + get: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "text/plain": components["schemas"]["SaasCatalogSnapshot"]; + "application/json": components["schemas"]["SaasCatalogSnapshot"]; + "text/json": components["schemas"]["SaasCatalogSnapshot"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/platform-admin/saas/features": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + /** 新增或更新 SaaS 功能 */ + put: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["UpsertSaasFeatureDto"]; + "text/json": components["schemas"]["UpsertSaasFeatureDto"]; + "application/*+json": components["schemas"]["UpsertSaasFeatureDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "text/plain": components["schemas"]["SaasFeature"]; + "application/json": components["schemas"]["SaasFeature"]; + "text/json": components["schemas"]["SaasFeature"]; + }; + }; + }; + }; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/platform-admin/saas/feature-limits": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + /** 新增或更新 SaaS 功能限额 */ + put: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["UpsertSaasFeatureLimitDto"]; + "text/json": components["schemas"]["UpsertSaasFeatureLimitDto"]; + "application/*+json": components["schemas"]["UpsertSaasFeatureLimitDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "text/plain": components["schemas"]["SaasFeatureLimitDefinition"]; + "application/json": components["schemas"]["SaasFeatureLimitDefinition"]; + "text/json": components["schemas"]["SaasFeatureLimitDefinition"]; + }; + }; + }; + }; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/platform-admin/saas/offerings": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + /** 新增或更新 SaaS 套餐 */ + put: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["UpsertSaasOfferingDto"]; + "text/json": components["schemas"]["UpsertSaasOfferingDto"]; + "application/*+json": components["schemas"]["UpsertSaasOfferingDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "text/plain": components["schemas"]["SaasOffering"]; + "application/json": components["schemas"]["SaasOffering"]; + "text/json": components["schemas"]["SaasOffering"]; + }; + }; + }; + }; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/platform-admin/saas/offering-versions": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + /** 新增或更新 SaaS 套餐版本草稿 */ + put: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["UpsertSaasOfferingVersionDto"]; + "text/json": components["schemas"]["UpsertSaasOfferingVersionDto"]; + "application/*+json": components["schemas"]["UpsertSaasOfferingVersionDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "text/plain": components["schemas"]["SaasOfferingVersionItem"]; + "application/json": components["schemas"]["SaasOfferingVersionItem"]; + "text/json": components["schemas"]["SaasOfferingVersionItem"]; + }; + }; + }; + }; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/platform-admin/saas/offering-versions/{versionId}/publish": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 发布 SaaS 套餐版本 */ + post: { + parameters: { + query?: never; + header?: never; + path: { + versionId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "text/plain": components["schemas"]["SaasOfferingVersionItem"]; + "application/json": components["schemas"]["SaasOfferingVersionItem"]; + "text/json": components["schemas"]["SaasOfferingVersionItem"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/platform-admin/saas/offering-versions/{versionId}/clone": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 克隆 SaaS 套餐版本 */ + post: { + parameters: { + query?: never; + header?: never; + path: { + versionId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "text/plain": components["schemas"]["SaasOfferingVersionItem"]; + "application/json": components["schemas"]["SaasOfferingVersionItem"]; + "text/json": components["schemas"]["SaasOfferingVersionItem"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/platform-admin/saas/offering-versions/{versionId}/retire": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 下架 SaaS 套餐版本 */ + post: { + parameters: { + query?: never; + header?: never; + path: { + versionId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "text/plain": components["schemas"]["SaasOfferingVersionItem"]; + "application/json": components["schemas"]["SaasOfferingVersionItem"]; + "text/json": components["schemas"]["SaasOfferingVersionItem"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/platform-admin/saas/orders": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询平台 SaaS 订单 */ + get: { + parameters: { + query?: { + tenantId?: string; + status?: string; + limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "text/plain": components["schemas"]["PlatformBillingOrder"][]; + "application/json": components["schemas"]["PlatformBillingOrder"][]; + "text/json": components["schemas"]["PlatformBillingOrder"][]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/platform-admin/saas/payments": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询平台 SaaS 支付记录 */ + get: { + parameters: { + query?: { + tenantId?: string; + status?: string; + limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "text/plain": components["schemas"]["PlatformBillingPayment"][]; + "application/json": components["schemas"]["PlatformBillingPayment"][]; + "text/json": components["schemas"]["PlatformBillingPayment"][]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/platform-admin/saas/refunds": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询平台 SaaS 退款记录 */ + get: { + parameters: { + query?: { + tenantId?: string; + status?: string; + limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "text/plain": components["schemas"]["PlatformBillingRefund"][]; + "application/json": components["schemas"]["PlatformBillingRefund"][]; + "text/json": components["schemas"]["PlatformBillingRefund"][]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/platform-admin/saas/invoices": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询平台 SaaS 发票 */ + get: { + parameters: { + query?: { + tenantId?: string; + status?: string; + limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "text/plain": components["schemas"]["PlatformBillingInvoice"][]; + "application/json": components["schemas"]["PlatformBillingInvoice"][]; + "text/json": components["schemas"]["PlatformBillingInvoice"][]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/platform-admin/saas/usage": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询租户 SaaS 用量 */ + get: { + parameters: { + query?: { + tenantId?: string; + limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "text/plain": components["schemas"]["TenantFeatureUsage"][]; + "application/json": components["schemas"]["TenantFeatureUsage"][]; + "text/json": components["schemas"]["TenantFeatureUsage"][]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/platform-admin/saas/invoices/reminders": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询平台 SaaS 账单提醒 */ + get: { + parameters: { + query?: { + tenantId?: string; + status?: string; + limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "text/plain": components["schemas"]["PlatformBillingInvoiceReminder"][]; + "application/json": components["schemas"]["PlatformBillingInvoiceReminder"][]; + "text/json": components["schemas"]["PlatformBillingInvoiceReminder"][]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/platform-admin/saas/subscriptions": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询租户 SaaS 订阅 */ + get: { + parameters: { + query?: { + tenantId?: string; + status?: string; + limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "text/plain": components["schemas"]["TenantSaasSubscription"][]; + "application/json": components["schemas"]["TenantSaasSubscription"][]; + "text/json": components["schemas"]["TenantSaasSubscription"][]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/platform-admin/saas/payments/manual/confirm": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 确认平台手工支付 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["ConfirmManualPlatformPaymentDto"]; + "text/json": components["schemas"]["ConfirmManualPlatformPaymentDto"]; + "application/*+json": components["schemas"]["ConfirmManualPlatformPaymentDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "text/plain": components["schemas"]["PlatformBillingPayment"]; + "application/json": components["schemas"]["PlatformBillingPayment"]; + "text/json": components["schemas"]["PlatformBillingPayment"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/platform-admin/saas/tenant-feature-overrides": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + /** 新增或更新租户功能覆盖规则 */ + put: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["UpsertTenantFeatureOverrideDto"]; + "text/json": components["schemas"]["UpsertTenantFeatureOverrideDto"]; + "application/*+json": components["schemas"]["UpsertTenantFeatureOverrideDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "text/plain": components["schemas"]["TenantFeatureOverride"]; + "application/json": components["schemas"]["TenantFeatureOverride"]; + "text/json": components["schemas"]["TenantFeatureOverride"]; + }; + }; + }; + }; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/platform-admin/tenant-capabilities/crm/configs": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询租户 CRM 配置 */ + get: { + parameters: { + query?: { + /** @description 租户 ID。 */ + TenantId?: string; + /** @description 状态。 */ + Status?: string; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["PlatformTenantCapabilityListOfPlatformCrmConfigItem"]; + }; + }; + }; + }; + /** 新增或更新租户 CRM 配置 */ + put: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["UpsertPlatformCrmConfigDto"]; + "text/json": components["schemas"]["UpsertPlatformCrmConfigDto"]; + "application/*+json": components["schemas"]["UpsertPlatformCrmConfigDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["PlatformCrmConfigItem"]; + }; + }; + }; + }; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/platform-admin/tenant-capabilities/crm/leads": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询租户 CRM 线索队列 */ + get: { + parameters: { + query?: { + /** @description 租户 ID。 */ + TenantId?: string; + /** @description 状态。 */ + Status?: string; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["PlatformTenantCapabilityListOfCrmWebhookQueueItem"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/platform-admin/tenant-capabilities/crm/leads/retry": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 重试租户 CRM 线索推送 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["RetryPlatformCrmLeadDto"]; + "text/json": components["schemas"]["RetryPlatformCrmLeadDto"]; + "application/*+json": components["schemas"]["RetryPlatformCrmLeadDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CrmWebhookQueueItem"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/platform-admin/tenant-capabilities/crm/logs": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询租户 CRM 推送日志 */ + get: { + parameters: { + query?: { + /** @description 队列任务 ID。 */ + QueueId?: string; + TenantId?: string; + Status?: string; + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["PlatformTenantCapabilityListOfCrmWebhookLog"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/platform-admin/tenant-capabilities/sms/channels": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询租户短信渠道 */ + get: { + parameters: { + query?: { + /** @description 租户 ID。 */ + TenantId?: string; + /** @description 状态。 */ + Status?: string; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["PlatformTenantCapabilityListOfPlatformSmsChannelItem"]; + }; + }; + }; + }; + /** 新增或更新租户短信渠道 */ + put: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["UpsertPlatformSmsChannelDto"]; + "text/json": components["schemas"]["UpsertPlatformSmsChannelDto"]; + "application/*+json": components["schemas"]["UpsertPlatformSmsChannelDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["PlatformSmsChannelItem"]; + }; + }; + }; + }; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/platform-admin/tenant-capabilities/sms/channels/{id}/disable": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 禁用租户短信渠道 */ + post: { + parameters: { + query?: never; + header?: never; + path: { + id: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["PlatformSmsChannelItem"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/platform-admin/tenant-capabilities/sms/templates": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询租户短信模板 */ + get: { + parameters: { + query?: { + /** @description 租户 ID。 */ + TenantId?: string; + /** @description 状态。 */ + Status?: string; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["PlatformTenantCapabilityListOfPlatformSmsTemplateItem"]; + }; + }; + }; + }; + /** 新增或更新租户短信模板 */ + put: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["UpsertPlatformSmsTemplateDto"]; + "text/json": components["schemas"]["UpsertPlatformSmsTemplateDto"]; + "application/*+json": components["schemas"]["UpsertPlatformSmsTemplateDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["PlatformSmsTemplateItem"]; + }; + }; + }; + }; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/platform-admin/tenant-capabilities/sms/templates/{id}/submit-review": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 提交租户短信模板审核 */ + post: { + parameters: { + query?: never; + header?: never; + path: { + id: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["PlatformSmsTemplateItem"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/platform-admin/tenant-capabilities/sms/templates/{id}/disable": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 禁用租户短信模板 */ + post: { + parameters: { + query?: never; + header?: never; + path: { + id: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["PlatformSmsTemplateItem"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/platform-admin/tenant-capabilities/sms/logs": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询租户短信发送日志 */ + get: { + parameters: { + query?: { + /** @description 租户 ID。 */ + TenantId?: string; + /** @description 状态。 */ + Status?: string; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["PlatformTenantCapabilityListOfSmsSendLog"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/platform-admin/tenant-capabilities/payments/apps": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询租户支付应用 */ + get: { + parameters: { + query?: { + /** @description 租户 ID。 */ + TenantId?: string; + /** @description 状态。 */ + Status?: string; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["PlatformTenantCapabilityListOfTenantExternalProviderItem"]; + }; + }; + }; + }; + /** 新增或更新租户支付应用 */ + put: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["UpsertPlatformTenantPaymentAppDto"]; + "text/json": components["schemas"]["UpsertPlatformTenantPaymentAppDto"]; + "application/*+json": components["schemas"]["UpsertPlatformTenantPaymentAppDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["TenantExternalProviderItem"]; + }; + }; + }; + }; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/platform-admin/tenant-capabilities/payments/events": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询租户支付事件 */ + get: { + parameters: { + query?: { + /** @description 租户 ID。 */ + TenantId?: string; + /** @description 状态。 */ + Status?: string; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["PlatformTenantCapabilityListOfObject"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/points/summary": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询当前用户积分摘要 */ + get: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["PointSummaryItem"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/points/tasks": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询当前可领取积分任务 */ + get: { + parameters: { + query?: { + /** @description 返回数量上限。 */ + Limit?: number | string; + /** @description 状态。 */ + Status?: string; + /** @description 地区 ID。 */ + RegionId?: string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["PointListOfPointTaskItem"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/points/tasks/claim": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 领取积分任务奖励 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["ClaimPointTaskDto"]; + "text/json": components["schemas"]["ClaimPointTaskDto"]; + "application/*+json": components["schemas"]["ClaimPointTaskDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["PointClaimItem"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/points/exchange-items": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询积分兑换项 */ + get: { + parameters: { + query?: { + /** @description 返回数量上限。 */ + Limit?: number | string; + /** @description 状态。 */ + Status?: string; + /** @description 地区 ID。 */ + RegionId?: string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["PointListOfPointExchangeItemDto"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/points/exchange-orders": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询当前用户积分兑换订单 */ + get: { + parameters: { + query?: { + /** @description 返回数量上限。 */ + Limit?: number | string; + /** @description 状态。 */ + Status?: string; + /** @description 地区 ID。 */ + RegionId?: string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["PointListOfPointExchangeOrderItem"]; + }; + }; + }; + }; + put?: never; + /** 创建积分兑换订单 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["CreatePointExchangeOrderDto"]; + "text/json": components["schemas"]["CreatePointExchangeOrderDto"]; + "application/*+json": components["schemas"]["CreatePointExchangeOrderDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["PointExchangeOrderItem"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/profile/me": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 获取当前学生资料 */ + get: { + parameters: { + query?: { + /** @description 最近记录数量上限。 */ + RecentLimit?: number | string; + /** @description 返回数量上限。 */ + Limit?: number | string; + /** @description 状态。 */ + Status?: string; + /** @description 类型。 */ + Type?: string; + /** @description 分类。 */ + Category?: string; + /** @description 是否包含锁定资源。 */ + IncludeLocked?: boolean; + /** @description 来源类型。 */ + SourceType?: string; + /** @description 开始时间。 */ + From?: string; + /** @description 结束时间。 */ + To?: string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["StudentProfileItem"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + /** 更新当前学生资料 */ + patch: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["UpdateProfileDto"]; + "text/json": components["schemas"]["UpdateProfileDto"]; + "application/*+json": components["schemas"]["UpdateProfileDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["StudentProfileItem"]; + }; + }; + }; + }; + trace?: never; + }; + "/api/profile/exam-countdowns": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询考试倒计时 */ + get: { + parameters: { + query?: { + /** @description 最近记录数量上限。 */ + RecentLimit?: number | string; + /** @description 返回数量上限。 */ + Limit?: number | string; + /** @description 状态。 */ + Status?: string; + /** @description 类型。 */ + Type?: string; + /** @description 分类。 */ + Category?: string; + /** @description 是否包含锁定资源。 */ + IncludeLocked?: boolean; + /** @description 来源类型。 */ + SourceType?: string; + /** @description 开始时间。 */ + From?: string; + /** @description 结束时间。 */ + To?: string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ExamCountdownList"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/profile/notifications": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询用户通知 */ + get: { + parameters: { + query?: { + /** @description 最近记录数量上限。 */ + RecentLimit?: number | string; + /** @description 返回数量上限。 */ + Limit?: number | string; + /** @description 状态。 */ + Status?: string; + /** @description 类型。 */ + Type?: string; + /** @description 分类。 */ + Category?: string; + /** @description 是否包含锁定资源。 */ + IncludeLocked?: boolean; + /** @description 来源类型。 */ + SourceType?: string; + /** @description 开始时间。 */ + From?: string; + /** @description 结束时间。 */ + To?: string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProfileNotificationList"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/profile/notifications/status": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 更新通知状态 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["NotificationStatusDto"]; + "text/json": components["schemas"]["NotificationStatusDto"]; + "application/*+json": components["schemas"]["NotificationStatusDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProfileNotificationList"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/profile/badges": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询徽章列表 */ + get: { + parameters: { + query?: { + /** @description 最近记录数量上限。 */ + RecentLimit?: number | string; + /** @description 返回数量上限。 */ + Limit?: number | string; + /** @description 状态。 */ + Status?: string; + /** @description 类型。 */ + Type?: string; + /** @description 分类。 */ + Category?: string; + /** @description 是否包含锁定资源。 */ + IncludeLocked?: boolean; + /** @description 来源类型。 */ + SourceType?: string; + /** @description 开始时间。 */ + From?: string; + /** @description 结束时间。 */ + To?: string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["BadgeList"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/profile/feedbacks": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询反馈记录 */ + get: { + parameters: { + query?: { + /** @description 最近记录数量上限。 */ + RecentLimit?: number | string; + /** @description 返回数量上限。 */ + Limit?: number | string; + /** @description 状态。 */ + Status?: string; + /** @description 类型。 */ + Type?: string; + /** @description 分类。 */ + Category?: string; + /** @description 是否包含锁定资源。 */ + IncludeLocked?: boolean; + /** @description 来源类型。 */ + SourceType?: string; + /** @description 开始时间。 */ + From?: string; + /** @description 结束时间。 */ + To?: string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["FeedbackItem"][]; + }; + }; + }; + }; + put?: never; + /** 提交意见反馈 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["SubmitFeedbackDto"]; + "text/json": components["schemas"]["SubmitFeedbackDto"]; + "application/*+json": components["schemas"]["SubmitFeedbackDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["FeedbackItem"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/profile/check-in": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 每日签到 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CheckInResult"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/profile/score-events": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询积分流水 */ + get: { + parameters: { + query?: { + /** @description 最近记录数量上限。 */ + RecentLimit?: number | string; + /** @description 返回数量上限。 */ + Limit?: number | string; + /** @description 状态。 */ + Status?: string; + /** @description 类型。 */ + Type?: string; + /** @description 分类。 */ + Category?: string; + /** @description 是否包含锁定资源。 */ + IncludeLocked?: boolean; + /** @description 来源类型。 */ + SourceType?: string; + /** @description 开始时间。 */ + From?: string; + /** @description 结束时间。 */ + To?: string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProfileScoreEventList"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/questions/videos": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询单道题目的解析视频 */ + get: { + parameters: { + query?: { + /** @description 题目 ID。 */ + QuestionId?: string; + /** @description 题目 ID 列表。 */ + QuestionIds?: string[]; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CatalogListOfQuestionVideoCatalogItem"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/questions/videos/batch": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 批量查询题目解析视频 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["QuestionVideoQueryDto"]; + "text/json": components["schemas"]["QuestionVideoQueryDto"]; + "application/*+json": components["schemas"]["QuestionVideoQueryDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CatalogListOfQuestionVideoCatalogItem"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/referral/invite-code": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 生成或查询当前成员邀请码 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["ReferralInviteDto"]; + "text/json": components["schemas"]["ReferralInviteDto"]; + "application/*+json": components["schemas"]["ReferralInviteDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ReferralInviteItem"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/referral/resolve": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 解析推荐邀请码 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["ResolveReferralDto"]; + "text/json": components["schemas"]["ResolveReferralDto"]; + "application/*+json": components["schemas"]["ResolveReferralDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ReferralResolutionItem"]; + }; + }; + /** @description Not Found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProblemDetails"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/referral/track-event": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 记录推荐行为 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["TrackReferralEventDto"]; + "text/json": components["schemas"]["TrackReferralEventDto"]; + "application/*+json": components["schemas"]["TrackReferralEventDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ReferralTrackResult"]; + }; + }; + /** @description Not Found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProblemDetails"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/referral/bind": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 绑定当前用户推荐归属 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["BindReferralDto"]; + "text/json": components["schemas"]["BindReferralDto"]; + "application/*+json": components["schemas"]["BindReferralDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ReferralBindResult"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/referral/qrcode": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 生成或查询推广二维码 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["ReferralQrcodeDto"]; + "text/json": components["schemas"]["ReferralQrcodeDto"]; + "application/*+json": components["schemas"]["ReferralQrcodeDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ReferralQrcodeItem"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/referral/stats": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询推荐人个人统计 */ + get: { + parameters: { + query?: { + /** @description 推荐人用户 ID。 */ + ReferrerUserId?: string; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ReferralStatsItem"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/referral/sales-stats": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询销售推荐统计排行 */ + get: { + parameters: { + query?: { + /** @description 推荐人用户 ID。 */ + ReferrerUserId?: string; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ReferralListOfReferralStatsItem"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/referral/conversion-report": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询推荐转化报告 */ + get: { + parameters: { + query?: { + /** @description 推荐人用户 ID。 */ + ReferrerUserId?: string; + /** @description 开始日期,格式为 yyyy-MM-dd。 */ + StartDate?: string; + /** @description 结束日期,格式为 yyyy-MM-dd。 */ + EndDate?: string; + /** @description 天数。 */ + Days?: number | string; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ReferralConversionReport"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/referral/sales-clients": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询推荐人名下客户 */ + get: { + parameters: { + query?: { + /** @description 推荐人用户 ID。 */ + ReferrerUserId?: string; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ReferralListOfReferralLeadItem"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/referral/manual-bind": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 人工调整学生推荐归属 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["ManualBindReferralDto"]; + "text/json": components["schemas"]["ManualBindReferralDto"]; + "application/*+json": components["schemas"]["ManualBindReferralDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ReferralBindResult"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/referral/team": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询推荐团队成员 */ + get: { + parameters: { + query?: { + /** @description 上级成员用户 ID。 */ + LeaderUserId?: string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ReferralListOfReferralTeamItem"]; + }; + }; + }; + }; + /** 新增或更新推荐团队关系 */ + put: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["UpsertReferralTeamDto"]; + "text/json": components["schemas"]["UpsertReferralTeamDto"]; + "application/*+json": components["schemas"]["UpsertReferralTeamDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ReferralTeamItem"]; + }; + }; + }; + }; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/runtime/bootstrap": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 获取租户前端运行时配置 */ + get: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["TenantRuntimeBootstrap"]; + }; + }; + /** @description Not Modified */ + 304: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": unknown; + }; + }; + /** @description Not Found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProblemDetails"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/scoreline/fields": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询分数线字段配置 */ + get: { + parameters: { + query?: { + /** @description 租户编码。 */ + TenantCode?: string; + /** @description 地区 ID。 */ + RegionId?: string; + /** @description 院校 ID。 */ + SchoolId?: string; + /** @description 专业 ID。 */ + MajorId?: string; + /** @description 关键字。 */ + Keyword?: string; + /** @description 年份。 */ + Year?: number | string; + /** @description 页码。 */ + Page?: number | string; + /** @description 每页数量。 */ + PageSize?: number | string; + /** @description 返回数量上限。 */ + Limit?: number | string; + /** @description 版本化的不透明游标,仅用于游标分页接口。 */ + Cursor?: string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CatalogListOfScorelineFieldItem"]; + }; + }; + /** @description Not Found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProblemDetails"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/scoreline/records": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 分页查询分数线记录 */ + get: { + parameters: { + query?: { + /** @description 租户编码。 */ + TenantCode?: string; + /** @description 地区 ID。 */ + RegionId?: string; + /** @description 院校 ID。 */ + SchoolId?: string; + /** @description 专业 ID。 */ + MajorId?: string; + /** @description 关键字。 */ + Keyword?: string; + /** @description 年份。 */ + Year?: number | string; + /** @description 页码。 */ + Page?: number | string; + /** @description 每页数量。 */ + PageSize?: number | string; + /** @description 返回数量上限。 */ + Limit?: number | string; + /** @description 版本化的不透明游标,仅用于游标分页接口。 */ + Cursor?: string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ScorelineRecordPage"]; + }; + }; + /** @description Not Found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProblemDetails"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/scoreline/records/cursor": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 游标分页查询分数线记录 */ + get: { + parameters: { + query?: { + /** @description 租户编码。 */ + TenantCode?: string; + /** @description 地区 ID。 */ + RegionId?: string; + /** @description 院校 ID。 */ + SchoolId?: string; + /** @description 专业 ID。 */ + MajorId?: string; + /** @description 关键字。 */ + Keyword?: string; + /** @description 年份。 */ + Year?: number | string; + /** @description 页码。 */ + Page?: number | string; + /** @description 每页数量。 */ + PageSize?: number | string; + /** @description 返回数量上限。 */ + Limit?: number | string; + /** @description 版本化的不透明游标,仅用于游标分页接口。 */ + Cursor?: string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ScorelineRecordCursorPage"]; + }; + }; + /** @description Bad Request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProblemDetails"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/scoreline/trend": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询历年分数线趋势 */ + get: { + parameters: { + query?: { + /** @description 租户编码。 */ + TenantCode?: string; + /** @description 地区 ID。 */ + RegionId?: string; + /** @description 院校 ID。 */ + SchoolId?: string; + /** @description 专业 ID。 */ + MajorId?: string; + /** @description 关键字。 */ + Keyword?: string; + /** @description 年份。 */ + Year?: number | string; + /** @description 页码。 */ + Page?: number | string; + /** @description 每页数量。 */ + PageSize?: number | string; + /** @description 返回数量上限。 */ + Limit?: number | string; + /** @description 版本化的不透明游标,仅用于游标分页接口。 */ + Cursor?: string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CatalogListOfScorelineRecordItem"]; + }; + }; + /** @description Not Found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProblemDetails"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/scoreline/years": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询分数线可用年份 */ + get: { + parameters: { + query?: { + /** @description 租户编码。 */ + TenantCode?: string; + /** @description 地区 ID。 */ + RegionId?: string; + /** @description 院校 ID。 */ + SchoolId?: string; + /** @description 专业 ID。 */ + MajorId?: string; + /** @description 关键字。 */ + Keyword?: string; + /** @description 年份。 */ + Year?: number | string; + /** @description 页码。 */ + Page?: number | string; + /** @description 每页数量。 */ + PageSize?: number | string; + /** @description 返回数量上限。 */ + Limit?: number | string; + /** @description 版本化的不透明游标,仅用于游标分页接口。 */ + Cursor?: string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CatalogListOfint"]; + }; + }; + /** @description Not Found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProblemDetails"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/taxonomy/nodes": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询租户分类节点 */ + get: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["TaxonomyNodeItem"][]; + }; + }; + }; + }; + put?: never; + /** 创建租户分类节点 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["CreateTaxonomyNodeDto"]; + "text/json": components["schemas"]["CreateTaxonomyNodeDto"]; + "application/*+json": components["schemas"]["CreateTaxonomyNodeDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["TaxonomyNodeItem"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-admin/overview": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询租户后台运营概览 */ + get: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["TenantAdminOverviewItem"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-admin/classes": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询租户班级 */ + get: { + parameters: { + query?: { + /** @description 地区 ID。 */ + RegionId?: string; + /** @description 状态。 */ + Status?: string; + /** @description 关键字。 */ + Keyword?: string; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["TenantAdminClassList"]; + }; + }; + }; + }; + /** 新增或更新租户班级 */ + put: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["UpsertTenantAdminClassDto"]; + "text/json": components["schemas"]["UpsertTenantAdminClassDto"]; + "application/*+json": components["schemas"]["UpsertTenantAdminClassDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ContentManagementResultOfTenantAdminClassItem"]; + }; + }; + }; + }; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-admin/classes/disable": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 停用租户班级 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": string; + "text/json": string; + "application/*+json": string; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ContentManagementResultOfTenantAdminClassItem"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-admin/classes/members": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询班级成员 */ + get: { + parameters: { + query?: { + /** @description 班级 ID。 */ + ClassId?: string; + /** @description 成员类型。 */ + MemberType?: string; + /** @description 状态。 */ + Status?: string; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CatalogListOfTenantAdminClassMemberItem"]; + }; + }; + }; + }; + /** 新增或更新班级成员 */ + put: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["UpsertTenantAdminClassMemberDto"]; + "text/json": components["schemas"]["UpsertTenantAdminClassMemberDto"]; + "application/*+json": components["schemas"]["UpsertTenantAdminClassMemberDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ContentManagementResultOfTenantAdminClassMemberItem"]; + }; + }; + }; + }; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-admin/classes/members/remove": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 移除班级成员 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["RemoveTenantAdminClassMemberDto"]; + "text/json": components["schemas"]["RemoveTenantAdminClassMemberDto"]; + "application/*+json": components["schemas"]["RemoveTenantAdminClassMemberDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ContentManagementResultOfTenantAdminClassMemberItem"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-admin/students": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询租户学生 */ + get: { + parameters: { + query?: { + /** @description 地区 ID。 */ + RegionId?: string; + /** @description 班级 ID。 */ + ClassId?: string; + /** @description 状态。 */ + Status?: string; + /** @description 关键字。 */ + Keyword?: string; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["TenantAdminStudentList"]; + }; + }; + }; + }; + /** 新增或更新租户学生档案 */ + put: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["UpsertTenantAdminStudentDto"]; + "text/json": components["schemas"]["UpsertTenantAdminStudentDto"]; + "application/*+json": components["schemas"]["UpsertTenantAdminStudentDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ContentManagementResultOfTenantAdminStudentItem"]; + }; + }; + }; + }; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-admin/students/status": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 更新租户学生状态 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["UpdateTenantAdminStudentStatusDto"]; + "text/json": components["schemas"]["UpdateTenantAdminStudentStatusDto"]; + "application/*+json": components["schemas"]["UpdateTenantAdminStudentStatusDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ContentManagementResultOfTenantAdminStudentStatusItem"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-admin/students/import/preview": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 预览学生批量导入 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["TenantAdminStudentImportDto"]; + "text/json": components["schemas"]["TenantAdminStudentImportDto"]; + "application/*+json": components["schemas"]["TenantAdminStudentImportDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["TenantAdminStudentImportPreview"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-admin/students/import": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 提交学生批量导入 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["TenantAdminStudentImportDto"]; + "text/json": components["schemas"]["TenantAdminStudentImportDto"]; + "application/*+json": components["schemas"]["TenantAdminStudentImportDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["TenantAdminStudentImportResult"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-admin/students/bulk-assign-class": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 批量分班 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["TenantAdminBulkAssignClassDto"]; + "text/json": components["schemas"]["TenantAdminBulkAssignClassDto"]; + "application/*+json": components["schemas"]["TenantAdminBulkAssignClassDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["TenantAdminBulkOperationResult"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-admin/students/bulk-status": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 批量调整学生状态 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["TenantAdminBulkStatusDto"]; + "text/json": components["schemas"]["TenantAdminBulkStatusDto"]; + "application/*+json": components["schemas"]["TenantAdminBulkStatusDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["TenantAdminBulkOperationResult"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-admin/students/supervision/rules": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询学习督导规则 */ + get: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CatalogListOfTenantSupervisionRuleItem"]; + }; + }; + }; + }; + /** 新增或更新学习督导规则 */ + put: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["UpsertTenantSupervisionRuleDto"]; + "text/json": components["schemas"]["UpsertTenantSupervisionRuleDto"]; + "application/*+json": components["schemas"]["UpsertTenantSupervisionRuleDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ContentManagementResultOfTenantSupervisionRuleItem"]; + }; + }; + }; + }; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-admin/students/supervision/preview": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 预览学习风险学生 */ + get: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["TenantSupervisionPreview"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-admin/students/supervision/generate": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 批量生成学习督导跟进任务 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["TenantSupervisionGenerateDto"]; + "text/json": components["schemas"]["TenantSupervisionGenerateDto"]; + "application/*+json": components["schemas"]["TenantSupervisionGenerateDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["TenantSupervisionGenerateResult"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-admin/student-followups/report": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询学生跟进统计报表 */ + get: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["TenantFollowupReport"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-admin/feedbacks/report": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询反馈处理统计报表 */ + get: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["TenantFeedbackReport"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-admin/points/risk-report": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询积分风险统计报表 */ + get: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["TenantPointRiskReport"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-admin/student-notes": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询学生备注 */ + get: { + parameters: { + query?: { + /** @description 学生用户 ID。 */ + StudentUserId?: string; + /** @description 状态。 */ + Status?: string; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CatalogListOfTenantAdminStudentNoteItem"]; + }; + }; + }; + }; + /** 新增或更新学生备注 */ + put: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["UpsertTenantAdminStudentNoteDto"]; + "text/json": components["schemas"]["UpsertTenantAdminStudentNoteDto"]; + "application/*+json": components["schemas"]["UpsertTenantAdminStudentNoteDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ContentManagementResultOfTenantAdminStudentNoteItem"]; + }; + }; + }; + }; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-admin/student-followups": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询学生跟进 */ + get: { + parameters: { + query?: { + /** @description 学生用户 ID。 */ + StudentUserId?: string; + /** @description 状态。 */ + Status?: string; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CatalogListOfTenantAdminStudentFollowupItem"]; + }; + }; + }; + }; + /** 新增或更新学生跟进 */ + put: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["UpsertTenantAdminStudentFollowupDto"]; + "text/json": components["schemas"]["UpsertTenantAdminStudentFollowupDto"]; + "application/*+json": components["schemas"]["UpsertTenantAdminStudentFollowupDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ContentManagementResultOfTenantAdminStudentFollowupItem"]; + }; + }; + }; + }; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-admin/members": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询租户成员 */ + get: { + parameters: { + query?: { + /** @description 角色。 */ + Role?: string; + /** @description 状态。 */ + Status?: string; + /** @description 关键字。 */ + Keyword?: string; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CatalogListOfTenantAdminMemberItem"]; + }; + }; + }; + }; + /** 新增或更新租户成员 */ + put: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["UpsertTenantAdminMemberDto"]; + "text/json": components["schemas"]["UpsertTenantAdminMemberDto"]; + "application/*+json": components["schemas"]["UpsertTenantAdminMemberDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ContentManagementResultOfTenantAdminMemberItem"]; + }; + }; + }; + }; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-admin/members/disable": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 停用租户成员并撤销会话 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["DisableTenantAdminMemberDto"]; + "text/json": components["schemas"]["DisableTenantAdminMemberDto"]; + "application/*+json": components["schemas"]["DisableTenantAdminMemberDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ContentManagementResultOfTenantAdminMemberItem"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-admin/audit-logs": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询租户审计日志 */ + get: { + parameters: { + query?: { + /** @description 操作。 */ + Action?: string; + /** @description 目标类型。 */ + TargetType?: string; + /** @description 操作人用户 ID。 */ + ActorUserId?: string; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CatalogListOfTenantAdminAuditLogItem"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-admin/branding": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + /** 更新租户品牌信息 */ + put: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["UpsertTenantBrandingDto"]; + "text/json": components["schemas"]["UpsertTenantBrandingDto"]; + "application/*+json": components["schemas"]["UpsertTenantBrandingDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ContentManagementResultOfTenantBrandingItem"]; + }; + }; + }; + }; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-admin/settings": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + /** 更新租户公开设置与功能开关 */ + put: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["UpsertTenantSettingsDto"]; + "text/json": components["schemas"]["UpsertTenantSettingsDto"]; + "application/*+json": components["schemas"]["UpsertTenantSettingsDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ContentManagementResultOfTenantSettingsItem"]; + }; + }; + }; + }; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-admin/theme-templates": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询可用租户主题模板 */ + get: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CatalogListOfTenantThemeTemplateItem"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-admin/theme": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询租户当前主题与草稿 */ + get: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ContentManagementResultOfTenantThemeItem"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-admin/theme/preview": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 生成租户主题草稿 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["PreviewTenantThemeDto"]; + "text/json": components["schemas"]["PreviewTenantThemeDto"]; + "application/*+json": components["schemas"]["PreviewTenantThemeDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ContentManagementResultOfTenantThemeItem"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-admin/theme/publish": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 发布租户主题 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["PublishTenantThemeDto"]; + "text/json": components["schemas"]["PublishTenantThemeDto"]; + "application/*+json": components["schemas"]["PublishTenantThemeDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ContentManagementResultOfTenantThemeItem"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-admin/domains": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询租户域名 */ + get: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CatalogListOfTenantDomainItem"]; + }; + }; + }; + }; + put?: never; + /** 添加租户域名 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["CreateTenantDomainDto"]; + "text/json": components["schemas"]["CreateTenantDomainDto"]; + "application/*+json": components["schemas"]["CreateTenantDomainDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ContentManagementResultOfTenantDomainItem"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-admin/auth-providers": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询租户登录 Provider 公开配置 */ + get: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CatalogListOfTenantIdentityProviderItem"]; + }; + }; + }; + }; + /** 新增或更新租户登录 Provider */ + put: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["UpsertTenantIdentityProviderDto"]; + "text/json": components["schemas"]["UpsertTenantIdentityProviderDto"]; + "application/*+json": components["schemas"]["UpsertTenantIdentityProviderDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ContentManagementResultOfTenantIdentityProviderItem"]; + }; + }; + }; + }; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-admin/badges": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询租户勋章 */ + get: { + parameters: { + query?: { + /** @description 分类。 */ + Category?: string; + /** @description 是否包含停用数据。 */ + IncludeInactive?: boolean; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CatalogListOfTenantAdminBadgeItem"]; + }; + }; + }; + }; + /** 新增或更新租户勋章 */ + put: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["UpsertTenantAdminBadgeDto"]; + "text/json": components["schemas"]["UpsertTenantAdminBadgeDto"]; + "application/*+json": components["schemas"]["UpsertTenantAdminBadgeDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ContentManagementResultOfTenantAdminBadgeItem"]; + }; + }; + }; + }; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-admin/badge-grants": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询勋章发放记录 */ + get: { + parameters: { + query?: { + /** @description 用户 ID。 */ + UserId?: string; + /** @description 徽章 ID。 */ + BadgeId?: string; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CatalogListOfTenantAdminBadgeGrantItem"]; + }; + }; + }; + }; + put?: never; + /** 向租户成员发放勋章 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["GrantTenantAdminBadgeDto"]; + "text/json": components["schemas"]["GrantTenantAdminBadgeDto"]; + "application/*+json": components["schemas"]["GrantTenantAdminBadgeDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ContentManagementResultOfTenantAdminBadgeGrantItem"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-admin/notifications": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询用户站内通知 */ + get: { + parameters: { + query?: { + /** @description 用户 ID。 */ + UserId?: string; + /** @description 状态。 */ + Status?: string; + /** @description 通知类型。 */ + NotificationType?: string; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CatalogListOfTenantAdminNotificationItem"]; + }; + }; + }; + }; + /** 新增或更新用户站内通知 */ + put: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["UpsertTenantAdminNotificationDto"]; + "text/json": components["schemas"]["UpsertTenantAdminNotificationDto"]; + "application/*+json": components["schemas"]["UpsertTenantAdminNotificationDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ContentManagementResultOfTenantAdminNotificationItem"]; + }; + }; + }; + }; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-admin/feedbacks": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询用户反馈 */ + get: { + parameters: { + query?: { + /** @description 用户 ID。 */ + UserId?: string; + /** @description 状态。 */ + Status?: string; + /** @description 类型。 */ + Type?: string; + /** @description 关键字。 */ + Keyword?: string; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CatalogListOfTenantAdminFeedbackItem"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-admin/feedbacks/status": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 处理用户反馈 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["UpdateTenantAdminFeedbackDto"]; + "text/json": components["schemas"]["UpdateTenantAdminFeedbackDto"]; + "application/*+json": components["schemas"]["UpdateTenantAdminFeedbackDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ContentManagementResultOfTenantAdminFeedbackItem"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/backoffice/tenant/ui-bootstrap": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * 查询租户后台菜单与权限 + * @description 返回当前租户管理员可见的后台菜单、权限和模块启用状态。 + */ + get: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "text/plain": components["schemas"]["BackofficeUiBootstrap"]; + "application/json": components["schemas"]["BackofficeUiBootstrap"]; + "text/json": components["schemas"]["BackofficeUiBootstrap"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/backoffice/tenant/bootstrap": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询租户角色管理初始化数据 */ + get: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "text/plain": components["schemas"]["BackofficeBootstrap"]; + "application/json": components["schemas"]["BackofficeBootstrap"]; + "text/json": components["schemas"]["BackofficeBootstrap"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/backoffice/tenant/roles": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 创建或更新租户后台角色 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["UpsertBackofficeRoleDto"]; + "text/json": components["schemas"]["UpsertBackofficeRoleDto"]; + "application/*+json": components["schemas"]["UpsertBackofficeRoleDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "text/plain": components["schemas"]["BackofficeRoleItem"]; + "application/json": components["schemas"]["BackofficeRoleItem"]; + "text/json": components["schemas"]["BackofficeRoleItem"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/backoffice/tenant/roles/{roleId}/bindings": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + /** 替换租户后台角色权限绑定 */ + put: { + parameters: { + query?: never; + header?: never; + path: { + roleId: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["ReplaceRoleBindingsDto"]; + "text/json": components["schemas"]["ReplaceRoleBindingsDto"]; + "application/*+json": components["schemas"]["ReplaceRoleBindingsDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "text/plain": components["schemas"]["BackofficeRoleItem"]; + "application/json": components["schemas"]["BackofficeRoleItem"]; + "text/json": components["schemas"]["BackofficeRoleItem"]; + }; + }; + }; + }; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/backoffice/tenant/users/{userId}/roles": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + /** 替换租户用户后台角色 */ + put: { + parameters: { + query?: never; + header?: never; + path: { + userId: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["ReplaceUserRolesDto"]; + "text/json": components["schemas"]["ReplaceUserRolesDto"]; + "application/*+json": components["schemas"]["ReplaceUserRolesDto"]; + }; + }; + responses: { + /** @description No Content */ + 204: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-billing/catalog": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询租户可购买 SaaS 目录 */ + get: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "text/plain": components["schemas"]["TenantBillingCatalog"]; + "application/json": components["schemas"]["TenantBillingCatalog"]; + "text/json": components["schemas"]["TenantBillingCatalog"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-billing/quotes": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 创建租户账务报价 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["CreatePlatformBillingQuoteDto"]; + "text/json": components["schemas"]["CreatePlatformBillingQuoteDto"]; + "application/*+json": components["schemas"]["CreatePlatformBillingQuoteDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "text/plain": components["schemas"]["PlatformBillingQuoteView"]; + "application/json": components["schemas"]["PlatformBillingQuoteView"]; + "text/json": components["schemas"]["PlatformBillingQuoteView"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-billing/orders": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询租户账务订单 */ + get: { + parameters: { + query?: { + limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "text/plain": components["schemas"]["PlatformBillingOrderView"][]; + "application/json": components["schemas"]["PlatformBillingOrderView"][]; + "text/json": components["schemas"]["PlatformBillingOrderView"][]; + }; + }; + }; + }; + put?: never; + /** 创建租户账务订单 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["CreatePlatformBillingOrderDto"]; + "text/json": components["schemas"]["CreatePlatformBillingOrderDto"]; + "application/*+json": components["schemas"]["CreatePlatformBillingOrderDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "text/plain": components["schemas"]["PlatformBillingOrderView"]; + "application/json": components["schemas"]["PlatformBillingOrderView"]; + "text/json": components["schemas"]["PlatformBillingOrderView"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-billing/orders/{orderNo}/payments": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 创建租户账务订单支付 */ + post: { + parameters: { + query?: never; + header?: never; + path: { + orderNo: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["CreatePlatformBillingPaymentDto"]; + "text/json": components["schemas"]["CreatePlatformBillingPaymentDto"]; + "application/*+json": components["schemas"]["CreatePlatformBillingPaymentDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "text/plain": components["schemas"]["PlatformBillingPaymentView"]; + "application/json": components["schemas"]["PlatformBillingPaymentView"]; + "text/json": components["schemas"]["PlatformBillingPaymentView"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-billing/orders/{orderNo}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询租户账务订单详情 */ + get: { + parameters: { + query?: never; + header?: never; + path: { + orderNo: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "text/plain": components["schemas"]["PlatformBillingOrderView"]; + "application/json": components["schemas"]["PlatformBillingOrderView"]; + "text/json": components["schemas"]["PlatformBillingOrderView"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-billing/subscription": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询当前租户 SaaS 订阅 */ + get: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "text/plain": components["schemas"]["TenantSubscriptionView"]; + "application/json": components["schemas"]["TenantSubscriptionView"]; + "text/json": components["schemas"]["TenantSubscriptionView"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-billing/subscription/change": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 变更当前租户 SaaS 订阅 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["ChangeTenantSubscriptionDto"]; + "text/json": components["schemas"]["ChangeTenantSubscriptionDto"]; + "application/*+json": components["schemas"]["ChangeTenantSubscriptionDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "text/plain": components["schemas"]["PlatformBillingOrderView"]; + "application/json": components["schemas"]["PlatformBillingOrderView"]; + "text/json": components["schemas"]["PlatformBillingOrderView"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-billing/subscription/renew": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 续费当前租户 SaaS 订阅 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["IdempotentTenantBillingDto"]; + "text/json": components["schemas"]["IdempotentTenantBillingDto"]; + "application/*+json": components["schemas"]["IdempotentTenantBillingDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "text/plain": components["schemas"]["PlatformBillingOrderView"]; + "application/json": components["schemas"]["PlatformBillingOrderView"]; + "text/json": components["schemas"]["PlatformBillingOrderView"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-billing/subscription/cancel": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 取消当前租户 SaaS 订阅 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "text/plain": components["schemas"]["TenantSubscriptionView"]; + "application/json": components["schemas"]["TenantSubscriptionView"]; + "text/json": components["schemas"]["TenantSubscriptionView"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-billing/usage": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询当前租户功能用量 */ + get: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "text/plain": components["schemas"]["FeatureQuotaSnapshot"][]; + "application/json": components["schemas"]["FeatureQuotaSnapshot"][]; + "text/json": components["schemas"]["FeatureQuotaSnapshot"][]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-billing/invoices": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询当前租户发票 */ + get: { + parameters: { + query?: { + limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "text/plain": components["schemas"]["PlatformBillingInvoice"][]; + "application/json": components["schemas"]["PlatformBillingInvoice"][]; + "text/json": components["schemas"]["PlatformBillingInvoice"][]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-commerce/payment-accounts": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询租户支付账号 */ + get: { + parameters: { + query?: { + /** @description 服务提供方。 */ + Provider?: string; + /** @description 状态。 */ + Status?: string; + /** @description 返回数量上限。 */ + Limit?: number | string; + /** @description 用户 ID。 */ + UserId?: string; + /** @description 地区 ID。 */ + RegionId?: string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["TenantPaymentProviderItem"][]; + }; + }; + }; + }; + /** 新增或更新租户支付账号 */ + put: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["UpsertPaymentAccountDto"]; + "text/json": components["schemas"]["UpsertPaymentAccountDto"]; + "application/*+json": components["schemas"]["UpsertPaymentAccountDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["TenantPaymentProviderItem"]; + }; + }; + }; + }; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-commerce/secrets": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + /** 写入或轮换租户密钥 */ + put: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["UpsertTenantSecretDto"]; + "text/json": components["schemas"]["UpsertTenantSecretDto"]; + "application/*+json": components["schemas"]["UpsertTenantSecretDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["TenantSecretItem"]; + }; + }; + }; + }; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-commerce/orders": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询租户订单 */ + get: { + parameters: { + query?: { + /** @description 服务提供方。 */ + Provider?: string; + /** @description 状态。 */ + Status?: string; + /** @description 返回数量上限。 */ + Limit?: number | string; + /** @description 用户 ID。 */ + UserId?: string; + /** @description 地区 ID。 */ + RegionId?: string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["AdminOrderList"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-commerce/payments": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询租户支付记录 */ + get: { + parameters: { + query?: { + /** @description 服务提供方。 */ + Provider?: string; + /** @description 状态。 */ + Status?: string; + /** @description 返回数量上限。 */ + Limit?: number | string; + /** @description 用户 ID。 */ + UserId?: string; + /** @description 地区 ID。 */ + RegionId?: string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["AdminPaymentList"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-commerce/code-batches": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 创建兑换码批次 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["CreateCodeBatchDto"]; + "text/json": components["schemas"]["CreateCodeBatchDto"]; + "application/*+json": components["schemas"]["CreateCodeBatchDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CodeBatchItem"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-commerce/activation-codes": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询兑换码 */ + get: { + parameters: { + query?: { + /** @description 服务提供方。 */ + Provider?: string; + /** @description 状态。 */ + Status?: string; + /** @description 返回数量上限。 */ + Limit?: number | string; + /** @description 用户 ID。 */ + UserId?: string; + /** @description 地区 ID。 */ + RegionId?: string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ActivationCodeList"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-commerce/activation-codes/redeem": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 后台核销兑换码 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["RedeemActivationCodeDto"]; + "text/json": components["schemas"]["RedeemActivationCodeDto"]; + "application/*+json": components["schemas"]["RedeemActivationCodeDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ActivationCodeItem"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-commerce/point-activity-tasks": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询积分活动任务 */ + get: { + parameters: { + query?: { + /** @description 服务提供方。 */ + Provider?: string; + /** @description 状态。 */ + Status?: string; + /** @description 返回数量上限。 */ + Limit?: number | string; + /** @description 用户 ID。 */ + UserId?: string; + /** @description 地区 ID。 */ + RegionId?: string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["TenantPointTaskList"]; + }; + }; + }; + }; + /** 新增或更新积分活动任务 */ + put: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["UpsertPointTaskDto"]; + "text/json": components["schemas"]["UpsertPointTaskDto"]; + "application/*+json": components["schemas"]["UpsertPointTaskDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": unknown; + }; + }; + }; + }; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-commerce/point-activity-claims": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询积分任务领取记录 */ + get: { + parameters: { + query?: { + /** @description 服务提供方。 */ + Provider?: string; + /** @description 状态。 */ + Status?: string; + /** @description 返回数量上限。 */ + Limit?: number | string; + /** @description 用户 ID。 */ + UserId?: string; + /** @description 地区 ID。 */ + RegionId?: string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["TenantPointClaimList"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-commerce/point-exchange-items": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询积分兑换项 */ + get: { + parameters: { + query?: { + /** @description 服务提供方。 */ + Provider?: string; + /** @description 状态。 */ + Status?: string; + /** @description 返回数量上限。 */ + Limit?: number | string; + /** @description 用户 ID。 */ + UserId?: string; + /** @description 地区 ID。 */ + RegionId?: string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["TenantPointExchangeItemList"]; + }; + }; + }; + }; + /** 新增或更新积分兑换项 */ + put: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["UpsertPointExchangeItemDto"]; + "text/json": components["schemas"]["UpsertPointExchangeItemDto"]; + "application/*+json": components["schemas"]["UpsertPointExchangeItemDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": unknown; + }; + }; + }; + }; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-commerce/point-exchange-orders": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询积分兑换订单 */ + get: { + parameters: { + query?: { + /** @description 服务提供方。 */ + Provider?: string; + /** @description 状态。 */ + Status?: string; + /** @description 返回数量上限。 */ + Limit?: number | string; + /** @description 用户 ID。 */ + UserId?: string; + /** @description 地区 ID。 */ + RegionId?: string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["TenantPointExchangeOrderList"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-commerce/point-exchange-orders/status": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 更新积分兑换订单状态 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["UpdatePointExchangeOrderStatusDto"]; + "text/json": components["schemas"]["UpdatePointExchangeOrderStatusDto"]; + "application/*+json": components["schemas"]["UpdatePointExchangeOrderStatusDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": unknown; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-commerce/coupons": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询租户优惠券 */ + get: { + parameters: { + query?: { + /** @description 服务提供方。 */ + Provider?: string; + /** @description 状态。 */ + Status?: string; + /** @description 返回数量上限。 */ + Limit?: number | string; + /** @description 用户 ID。 */ + UserId?: string; + /** @description 地区 ID。 */ + RegionId?: string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["TenantCouponList"]; + }; + }; + }; + }; + /** 新增或更新租户优惠券 */ + put: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["UpsertTenantCouponDto"]; + "text/json": components["schemas"]["UpsertTenantCouponDto"]; + "application/*+json": components["schemas"]["UpsertTenantCouponDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": unknown; + }; + }; + }; + }; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-commerce/coupons/redemptions": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询优惠券领取和核销记录 */ + get: { + parameters: { + query?: { + /** @description 服务提供方。 */ + Provider?: string; + /** @description 状态。 */ + Status?: string; + /** @description 返回数量上限。 */ + Limit?: number | string; + /** @description 用户 ID。 */ + UserId?: string; + /** @description 地区 ID。 */ + RegionId?: string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["TenantCouponRedemptionList"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-commerce/coupons/report": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询优惠券基础报表 */ + get: { + parameters: { + query?: { + /** @description 服务提供方。 */ + Provider?: string; + /** @description 状态。 */ + Status?: string; + /** @description 返回数量上限。 */ + Limit?: number | string; + /** @description 用户 ID。 */ + UserId?: string; + /** @description 地区 ID。 */ + RegionId?: string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["TenantCouponReport"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-commerce/refunds": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询退款申请 */ + get: { + parameters: { + query?: { + /** @description 服务提供方。 */ + Provider?: string; + /** @description 状态。 */ + Status?: string; + /** @description 返回数量上限。 */ + Limit?: number | string; + /** @description 用户 ID。 */ + UserId?: string; + /** @description 地区 ID。 */ + RegionId?: string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["TenantRefundList"]; + }; + }; + }; + }; + put?: never; + /** 创建退款申请 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["CreateRefundRequestDto"]; + "text/json": components["schemas"]["CreateRefundRequestDto"]; + "application/*+json": components["schemas"]["CreateRefundRequestDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CommerceRefundRequest"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-commerce/refunds/status": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 更新退款状态 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["UpdateRefundStatusDto"]; + "text/json": components["schemas"]["UpdateRefundStatusDto"]; + "application/*+json": components["schemas"]["UpdateRefundStatusDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CommerceRefundRequest"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-commerce/refunds/{refundRequestId}/events": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询退款事件 */ + get: { + parameters: { + query?: never; + header?: never; + path: { + refundRequestId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["TenantRefundEventList"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-commerce/reconciliation/batches": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询对账批次 */ + get: { + parameters: { + query?: { + /** @description 服务提供方。 */ + Provider?: string; + /** @description 状态。 */ + Status?: string; + /** @description 返回数量上限。 */ + Limit?: number | string; + /** @description 用户 ID。 */ + UserId?: string; + /** @description 地区 ID。 */ + RegionId?: string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["TenantReconciliationBatchList"]; + }; + }; + }; + }; + put?: never; + /** 创建对账批次 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["CreateReconciliationBatchDto"]; + "text/json": components["schemas"]["CreateReconciliationBatchDto"]; + "application/*+json": components["schemas"]["CreateReconciliationBatchDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CommerceReconciliationBatch"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-commerce/reconciliation/issues": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询对账异常 */ + get: { + parameters: { + query?: { + /** @description 服务提供方。 */ + Provider?: string; + /** @description 状态。 */ + Status?: string; + /** @description 返回数量上限。 */ + Limit?: number | string; + /** @description 用户 ID。 */ + UserId?: string; + /** @description 地区 ID。 */ + RegionId?: string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["TenantReconciliationIssueList"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-commerce/reconciliation/items": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询对账明细 */ + get: { + parameters: { + query?: { + batchId?: string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["TenantReconciliationItemList"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-commerce/reconciliation/issues/events": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询对账工单事件 */ + get: { + parameters: { + query?: { + issueId?: string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["TenantReconciliationIssueEventList"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-commerce/reconciliation/issues/status": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 更新对账异常状态 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["UpdateReconciliationIssueDto"]; + "text/json": components["schemas"]["UpdateReconciliationIssueDto"]; + "application/*+json": components["schemas"]["UpdateReconciliationIssueDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CommerceReconciliationIssue"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-commerce/adjustment-vouchers": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询调账凭证 */ + get: { + parameters: { + query?: { + /** @description 服务提供方。 */ + Provider?: string; + /** @description 状态。 */ + Status?: string; + /** @description 返回数量上限。 */ + Limit?: number | string; + /** @description 用户 ID。 */ + UserId?: string; + /** @description 地区 ID。 */ + RegionId?: string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["TenantAdjustmentVoucherList"]; + }; + }; + }; + }; + put?: never; + /** 创建调账凭证 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["CreateAdjustmentVoucherDto"]; + "text/json": components["schemas"]["CreateAdjustmentVoucherDto"]; + "application/*+json": components["schemas"]["CreateAdjustmentVoucherDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CommerceAdjustmentVoucher"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-commerce/adjustment-vouchers/detail": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询调账凭证详情 */ + get: { + parameters: { + query?: { + voucherId?: string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CommerceAdjustmentVoucher"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-commerce/adjustment-vouchers/status": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 审核或关闭调账凭证 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["UpdateAdjustmentVoucherStatusDto"]; + "text/json": components["schemas"]["UpdateAdjustmentVoucherStatusDto"]; + "application/*+json": components["schemas"]["UpdateAdjustmentVoucherStatusDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CommerceAdjustmentVoucher"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-commerce/adjustment-vouchers/events": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询调账凭证事件 */ + get: { + parameters: { + query?: { + voucherId?: string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["TenantAdjustmentVoucherEventList"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-commerce/adjustment-vouchers/report": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询调账统计报告 */ + get: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["TenantAdjustmentReport"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-commerce/reconciliation/anomalies": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询对账异常汇总 */ + get: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["TenantCommerceAnomalySummary"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-commerce/reconciliation/preview": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 预览支付渠道账单对账 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["PreviewReconciliationImportDto"]; + "text/json": components["schemas"]["PreviewReconciliationImportDto"]; + "application/*+json": components["schemas"]["PreviewReconciliationImportDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ReconciliationImportPreview"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-commerce/reconciliation/import": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 导入支付渠道账单并创建对账批次 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["PreviewReconciliationImportDto"]; + "text/json": components["schemas"]["PreviewReconciliationImportDto"]; + "application/*+json": components["schemas"]["PreviewReconciliationImportDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CommerceReconciliationBatch"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-commerce/reconciliation/provider-bills/jobs": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询渠道账单下载任务 */ + get: { + parameters: { + query?: { + /** @description 服务提供方。 */ + Provider?: string; + /** @description 状态。 */ + Status?: string; + /** @description 返回数量上限。 */ + Limit?: number | string; + /** @description 用户 ID。 */ + UserId?: string; + /** @description 地区 ID。 */ + RegionId?: string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["BackgroundJobItem"][]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-commerce/reconciliation/provider-bills/request": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 创建渠道官方账单下载任务 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["RequestProviderBillJobDto"]; + "text/json": components["schemas"]["RequestProviderBillJobDto"]; + "application/*+json": components["schemas"]["RequestProviderBillJobDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["BackgroundJobItem"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-content/entries": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询租户内容入口 */ + get: { + parameters: { + query?: { + /** @description 地区 ID。 */ + RegionId?: string; + /** @description 内容入口 ID。 */ + EntryId?: string; + /** @description 节点 ID。 */ + NodeId?: string; + /** @description 题集 ID。 */ + CollectionId?: string; + /** @description 父节点 ID;传 root 表示根节点。 */ + ParentId?: string; + /** @description 入口类型。 */ + EntryType?: string; + /** @description 题集类型。 */ + CollectionType?: string; + /** @description 模式。 */ + Mode?: string; + /** @description 标记类型。 */ + MarkerType?: string; + /** @description 关键字。 */ + Keyword?: string; + /** @description 是否包含停用数据。 */ + IncludeInactive?: boolean; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CatalogListOfContentEntryManagementItem"]; + }; + }; + }; + }; + put?: never; + /** 创建或更新内容入口 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["UpsertContentEntryDto"]; + "text/json": components["schemas"]["UpsertContentEntryDto"]; + "application/*+json": components["schemas"]["UpsertContentEntryDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ContentManagementResultOfContentEntryManagementItem"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-content/nodes": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询租户内容节点 */ + get: { + parameters: { + query?: { + /** @description 地区 ID。 */ + RegionId?: string; + /** @description 内容入口 ID。 */ + EntryId?: string; + /** @description 节点 ID。 */ + NodeId?: string; + /** @description 题集 ID。 */ + CollectionId?: string; + /** @description 父节点 ID;传 root 表示根节点。 */ + ParentId?: string; + /** @description 入口类型。 */ + EntryType?: string; + /** @description 题集类型。 */ + CollectionType?: string; + /** @description 模式。 */ + Mode?: string; + /** @description 标记类型。 */ + MarkerType?: string; + /** @description 关键字。 */ + Keyword?: string; + /** @description 是否包含停用数据。 */ + IncludeInactive?: boolean; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CatalogListOfContentNodeManagementItem"]; + }; + }; + }; + }; + put?: never; + /** 创建或更新内容节点 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["UpsertContentNodeDto"]; + "text/json": components["schemas"]["UpsertContentNodeDto"]; + "application/*+json": components["schemas"]["UpsertContentNodeDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ContentManagementResultOfContentNodeManagementItem"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-content/question-collections": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询租户题集 */ + get: { + parameters: { + query?: { + /** @description 地区 ID。 */ + RegionId?: string; + /** @description 内容入口 ID。 */ + EntryId?: string; + /** @description 节点 ID。 */ + NodeId?: string; + /** @description 题集 ID。 */ + CollectionId?: string; + /** @description 父节点 ID;传 root 表示根节点。 */ + ParentId?: string; + /** @description 入口类型。 */ + EntryType?: string; + /** @description 题集类型。 */ + CollectionType?: string; + /** @description 模式。 */ + Mode?: string; + /** @description 标记类型。 */ + MarkerType?: string; + /** @description 关键字。 */ + Keyword?: string; + /** @description 是否包含停用数据。 */ + IncludeInactive?: boolean; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CatalogListOfQuestionCollectionManagementItem"]; + }; + }; + }; + }; + put?: never; + /** 创建或更新题集 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["UpsertQuestionCollectionDto"]; + "text/json": components["schemas"]["UpsertQuestionCollectionDto"]; + "application/*+json": components["schemas"]["UpsertQuestionCollectionDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ContentManagementResultOfQuestionCollectionManagementItem"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-content/question-collections/items/replace": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 替换题集题目 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["ReplaceCollectionItemsDto"]; + "text/json": components["schemas"]["ReplaceCollectionItemsDto"]; + "application/*+json": components["schemas"]["ReplaceCollectionItemsDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CollectionItemsReplaceResult"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-content/practice-blueprints": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询练习蓝图 */ + get: { + parameters: { + query?: { + /** @description 地区 ID。 */ + RegionId?: string; + /** @description 内容入口 ID。 */ + EntryId?: string; + /** @description 节点 ID。 */ + NodeId?: string; + /** @description 题集 ID。 */ + CollectionId?: string; + /** @description 父节点 ID;传 root 表示根节点。 */ + ParentId?: string; + /** @description 入口类型。 */ + EntryType?: string; + /** @description 题集类型。 */ + CollectionType?: string; + /** @description 模式。 */ + Mode?: string; + /** @description 标记类型。 */ + MarkerType?: string; + /** @description 关键字。 */ + Keyword?: string; + /** @description 是否包含停用数据。 */ + IncludeInactive?: boolean; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CatalogListOfPracticeBlueprintManagementItem"]; + }; + }; + }; + }; + put?: never; + /** 创建或更新练习蓝图 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["UpsertPracticeBlueprintDto"]; + "text/json": components["schemas"]["UpsertPracticeBlueprintDto"]; + "application/*+json": components["schemas"]["UpsertPracticeBlueprintDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ContentManagementResultOfPracticeBlueprintManagementItem"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-content/imports/field-mapping": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询导入字段映射 */ + get: { + parameters: { + query?: { + /** @description 导入Type。 */ + ImportType?: string; + /** @description 导出格式。 */ + Format?: string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ImportFieldMappingItem"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-content/imports/templates": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 获取内容导入模板 */ + get: { + parameters: { + query?: { + /** @description 导入Type。 */ + ImportType?: string; + /** @description 导出格式。 */ + Format?: string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ImportTemplateItem"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-content/assets": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询租户内容资产 */ + get: { + parameters: { + query?: { + /** @description 地区 ID。 */ + RegionId?: string; + /** @description 科目 ID。 */ + SubjectId?: string; + /** @description 分类 ID。 */ + CategoryId?: string; + /** @description 内容节点 ID。 */ + ContentNodeId?: string; + /** @description 资产类型。 */ + AssetType?: string; + /** @description 分类。 */ + Category?: string; + /** @description 上传状态。 */ + UploadStatus?: string; + /** @description 安全扫描状态。 */ + SecurityScanStatus?: string; + /** @description 关键字。 */ + Keyword?: string; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CatalogListOfContentAssetManagementItem"]; + }; + }; + }; + }; + /** 新增或更新内容资产 */ + put: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["UpsertAssetDto"]; + "text/json": components["schemas"]["UpsertAssetDto"]; + "application/*+json": components["schemas"]["UpsertAssetDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ContentManagementResultOfContentAssetManagementItem"]; + }; + }; + }; + }; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-content/assets/access-events": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询资产访问审计事件 */ + get: { + parameters: { + query?: { + /** @description 资产 ID。 */ + AssetId?: string; + /** @description 用户 ID。 */ + UserId?: string; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CatalogListOfContentAssetAccessEventItem"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-content/assets/security-scan-events": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询资产安全扫描事件 */ + get: { + parameters: { + query?: { + /** @description 资产 ID。 */ + AssetId?: string; + /** @description 用户 ID。 */ + UserId?: string; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CatalogListOfContentAssetSecurityScanEventItem"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-content/assets/uploads/sign": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 创建资产上传签名 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["AssetUploadSignDto"]; + "text/json": components["schemas"]["AssetUploadSignDto"]; + "application/*+json": components["schemas"]["AssetUploadSignDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["AssetUploadSignResult"]; + }; + }; + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProblemDetails"]; + }; + }; + /** @description Forbidden */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProblemDetails"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-content/assets/uploads/confirm": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 确认资产上传完成 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["AssetUploadConfirmDto"]; + "text/json": components["schemas"]["AssetUploadConfirmDto"]; + "application/*+json": components["schemas"]["AssetUploadConfirmDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["AssetUploadConfirmResult"]; + }; + }; + /** @description Not Found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProblemDetails"]; + }; + }; + /** @description Conflict */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProblemDetails"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-content/assets/{assetId}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post?: never; + /** 归档内容资产 */ + delete: { + parameters: { + query?: never; + header?: never; + path: { + assetId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ContentManagementResultOfContentAssetManagementItem"]; + }; + }; + /** @description Not Found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProblemDetails"]; + }; + }; + }; + }; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-content/assets/sign-download": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 签发管理侧资产下载地址 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["AssetAccessSignDto"]; + "text/json": components["schemas"]["AssetAccessSignDto"]; + "application/*+json": components["schemas"]["AssetAccessSignDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["AssetManagementSignedAccessResult"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-content/assets/sign-preview": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 签发管理侧资产预览地址 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["AssetAccessSignDto"]; + "text/json": components["schemas"]["AssetAccessSignDto"]; + "application/*+json": components["schemas"]["AssetAccessSignDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["AssetManagementSignedAccessResult"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-content/import-jobs": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询内容导入任务 */ + get: { + parameters: { + query?: { + /** @description 状态。 */ + Status?: string; + /** @description 导入Type。 */ + ImportType?: string; + /** @description 来源格式。 */ + SourceFormat?: string; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CatalogListOfContentImportJobItem"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-content/import-jobs/{jobId}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询内容导入任务详情 */ + get: { + parameters: { + query?: never; + header?: never; + path: { + jobId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ContentImportJobDetail"]; + }; + }; + /** @description Not Found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProblemDetails"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-content/questions": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 创建题目及首个版本 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["DirectQuestionWriteDto"]; + "text/json": components["schemas"]["DirectQuestionWriteDto"]; + "application/*+json": components["schemas"]["DirectQuestionWriteDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ContentManagementResultOfQuestionManagementItem"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + /** 更新题目并可选择创建新版本 */ + patch: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["DirectQuestionWriteDto"]; + "text/json": components["schemas"]["DirectQuestionWriteDto"]; + "application/*+json": components["schemas"]["DirectQuestionWriteDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ContentManagementResultOfQuestionManagementItem"]; + }; + }; + }; + }; + trace?: never; + }; + "/api/tenant-content/vocabulary-units": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询管理侧词汇单元 */ + get: { + parameters: { + query?: { + /** @description 地区 ID。 */ + RegionId?: string; + /** @description 内容入口 ID。 */ + EntryId?: string; + /** @description 内容节点 ID。 */ + ContentNodeId?: string; + /** @description 父节点 ID。 */ + ParentId?: string; + /** @description 科目 ID。 */ + SubjectId?: string; + /** @description 章节 ID。 */ + ChapterId?: string; + /** @description 单元 ID。 */ + UnitId?: string; + /** @description 院校 ID。 */ + SchoolId?: string; + /** @description 专业 ID。 */ + MajorId?: string; + /** @description 题目 ID。 */ + QuestionId?: string; + /** @description 状态。 */ + Status?: string; + /** @description 关键字。 */ + Keyword?: string; + /** @description 年份。 */ + Year?: number | string; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CatalogListOfVocabularyUnit"]; + }; + }; + }; + }; + /** 新增或更新词汇单元 */ + put: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["DirectVocabularyUnitDto"]; + "text/json": components["schemas"]["DirectVocabularyUnitDto"]; + "application/*+json": components["schemas"]["DirectVocabularyUnitDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ContentManagementResultOfVocabularyUnit"]; + }; + }; + }; + }; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-content/vocabulary-words": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询管理侧词汇 */ + get: { + parameters: { + query?: { + /** @description 地区 ID。 */ + RegionId?: string; + /** @description 内容入口 ID。 */ + EntryId?: string; + /** @description 内容节点 ID。 */ + ContentNodeId?: string; + /** @description 父节点 ID。 */ + ParentId?: string; + /** @description 科目 ID。 */ + SubjectId?: string; + /** @description 章节 ID。 */ + ChapterId?: string; + /** @description 单元 ID。 */ + UnitId?: string; + /** @description 院校 ID。 */ + SchoolId?: string; + /** @description 专业 ID。 */ + MajorId?: string; + /** @description 题目 ID。 */ + QuestionId?: string; + /** @description 状态。 */ + Status?: string; + /** @description 关键字。 */ + Keyword?: string; + /** @description 年份。 */ + Year?: number | string; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CatalogListOfVocabularyWord"]; + }; + }; + }; + }; + /** 新增或更新词汇 */ + put: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["DirectVocabularyWordDto"]; + "text/json": components["schemas"]["DirectVocabularyWordDto"]; + "application/*+json": components["schemas"]["DirectVocabularyWordDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ContentManagementResultOfVocabularyWord"]; + }; + }; + }; + }; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-content/handbook-subjects": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询管理侧知识手册科目 */ + get: { + parameters: { + query?: { + /** @description 地区 ID。 */ + RegionId?: string; + /** @description 内容入口 ID。 */ + EntryId?: string; + /** @description 内容节点 ID。 */ + ContentNodeId?: string; + /** @description 父节点 ID。 */ + ParentId?: string; + /** @description 科目 ID。 */ + SubjectId?: string; + /** @description 章节 ID。 */ + ChapterId?: string; + /** @description 单元 ID。 */ + UnitId?: string; + /** @description 院校 ID。 */ + SchoolId?: string; + /** @description 专业 ID。 */ + MajorId?: string; + /** @description 题目 ID。 */ + QuestionId?: string; + /** @description 状态。 */ + Status?: string; + /** @description 关键字。 */ + Keyword?: string; + /** @description 年份。 */ + Year?: number | string; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CatalogListOfHandbookSubject"]; + }; + }; + }; + }; + /** 新增或更新知识手册科目 */ + put: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["DirectHandbookSubjectDto"]; + "text/json": components["schemas"]["DirectHandbookSubjectDto"]; + "application/*+json": components["schemas"]["DirectHandbookSubjectDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ContentManagementResultOfHandbookSubject"]; + }; + }; + }; + }; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-content/handbook-chapters": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询管理侧知识手册章节 */ + get: { + parameters: { + query?: { + /** @description 地区 ID。 */ + RegionId?: string; + /** @description 内容入口 ID。 */ + EntryId?: string; + /** @description 内容节点 ID。 */ + ContentNodeId?: string; + /** @description 父节点 ID。 */ + ParentId?: string; + /** @description 科目 ID。 */ + SubjectId?: string; + /** @description 章节 ID。 */ + ChapterId?: string; + /** @description 单元 ID。 */ + UnitId?: string; + /** @description 院校 ID。 */ + SchoolId?: string; + /** @description 专业 ID。 */ + MajorId?: string; + /** @description 题目 ID。 */ + QuestionId?: string; + /** @description 状态。 */ + Status?: string; + /** @description 关键字。 */ + Keyword?: string; + /** @description 年份。 */ + Year?: number | string; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CatalogListOfHandbookChapter"]; + }; + }; + }; + }; + /** 新增或更新知识手册章节 */ + put: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["DirectHandbookChapterDto"]; + "text/json": components["schemas"]["DirectHandbookChapterDto"]; + "application/*+json": components["schemas"]["DirectHandbookChapterDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ContentManagementResultOfHandbookChapter"]; + }; + }; + }; + }; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-content/handbook-entries": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询管理侧知识手册条目 */ + get: { + parameters: { + query?: { + /** @description 地区 ID。 */ + RegionId?: string; + /** @description 内容入口 ID。 */ + EntryId?: string; + /** @description 内容节点 ID。 */ + ContentNodeId?: string; + /** @description 父节点 ID。 */ + ParentId?: string; + /** @description 科目 ID。 */ + SubjectId?: string; + /** @description 章节 ID。 */ + ChapterId?: string; + /** @description 单元 ID。 */ + UnitId?: string; + /** @description 院校 ID。 */ + SchoolId?: string; + /** @description 专业 ID。 */ + MajorId?: string; + /** @description 题目 ID。 */ + QuestionId?: string; + /** @description 状态。 */ + Status?: string; + /** @description 关键字。 */ + Keyword?: string; + /** @description 年份。 */ + Year?: number | string; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CatalogListOfHandbookEntry"]; + }; + }; + }; + }; + /** 新增或更新知识手册条目 */ + put: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["DirectHandbookEntryDto"]; + "text/json": components["schemas"]["DirectHandbookEntryDto"]; + "application/*+json": components["schemas"]["DirectHandbookEntryDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ContentManagementResultOfHandbookEntry"]; + }; + }; + }; + }; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-content/scoreline/schools": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询管理侧分数线院校 */ + get: { + parameters: { + query?: { + /** @description 地区 ID。 */ + RegionId?: string; + /** @description 内容入口 ID。 */ + EntryId?: string; + /** @description 内容节点 ID。 */ + ContentNodeId?: string; + /** @description 父节点 ID。 */ + ParentId?: string; + /** @description 科目 ID。 */ + SubjectId?: string; + /** @description 章节 ID。 */ + ChapterId?: string; + /** @description 单元 ID。 */ + UnitId?: string; + /** @description 院校 ID。 */ + SchoolId?: string; + /** @description 专业 ID。 */ + MajorId?: string; + /** @description 题目 ID。 */ + QuestionId?: string; + /** @description 状态。 */ + Status?: string; + /** @description 关键字。 */ + Keyword?: string; + /** @description 年份。 */ + Year?: number | string; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CatalogListOfSchool"]; + }; + }; + }; + }; + /** 新增或更新分数线院校 */ + put: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["DirectSchoolDto"]; + "text/json": components["schemas"]["DirectSchoolDto"]; + "application/*+json": components["schemas"]["DirectSchoolDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ContentManagementResultOfSchool"]; + }; + }; + }; + }; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-content/scoreline/majors": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询管理侧分数线专业 */ + get: { + parameters: { + query?: { + /** @description 地区 ID。 */ + RegionId?: string; + /** @description 内容入口 ID。 */ + EntryId?: string; + /** @description 内容节点 ID。 */ + ContentNodeId?: string; + /** @description 父节点 ID。 */ + ParentId?: string; + /** @description 科目 ID。 */ + SubjectId?: string; + /** @description 章节 ID。 */ + ChapterId?: string; + /** @description 单元 ID。 */ + UnitId?: string; + /** @description 院校 ID。 */ + SchoolId?: string; + /** @description 专业 ID。 */ + MajorId?: string; + /** @description 题目 ID。 */ + QuestionId?: string; + /** @description 状态。 */ + Status?: string; + /** @description 关键字。 */ + Keyword?: string; + /** @description 年份。 */ + Year?: number | string; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CatalogListOfMajor"]; + }; + }; + }; + }; + /** 新增或更新分数线专业 */ + put: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["DirectMajorDto"]; + "text/json": components["schemas"]["DirectMajorDto"]; + "application/*+json": components["schemas"]["DirectMajorDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ContentManagementResultOfMajor"]; + }; + }; + }; + }; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-content/scoreline/fields": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询管理侧分数线字段 */ + get: { + parameters: { + query?: { + /** @description 地区 ID。 */ + RegionId?: string; + /** @description 内容入口 ID。 */ + EntryId?: string; + /** @description 内容节点 ID。 */ + ContentNodeId?: string; + /** @description 父节点 ID。 */ + ParentId?: string; + /** @description 科目 ID。 */ + SubjectId?: string; + /** @description 章节 ID。 */ + ChapterId?: string; + /** @description 单元 ID。 */ + UnitId?: string; + /** @description 院校 ID。 */ + SchoolId?: string; + /** @description 专业 ID。 */ + MajorId?: string; + /** @description 题目 ID。 */ + QuestionId?: string; + /** @description 状态。 */ + Status?: string; + /** @description 关键字。 */ + Keyword?: string; + /** @description 年份。 */ + Year?: number | string; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CatalogListOfScorelineField"]; + }; + }; + }; + }; + /** 新增或更新动态分数线字段 */ + put: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["DirectScorelineFieldDto"]; + "text/json": components["schemas"]["DirectScorelineFieldDto"]; + "application/*+json": components["schemas"]["DirectScorelineFieldDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ContentManagementResultOfScorelineField"]; + }; + }; + }; + }; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-content/scoreline/records": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询管理侧分数线记录 */ + get: { + parameters: { + query?: { + /** @description 地区 ID。 */ + RegionId?: string; + /** @description 内容入口 ID。 */ + EntryId?: string; + /** @description 内容节点 ID。 */ + ContentNodeId?: string; + /** @description 父节点 ID。 */ + ParentId?: string; + /** @description 科目 ID。 */ + SubjectId?: string; + /** @description 章节 ID。 */ + ChapterId?: string; + /** @description 单元 ID。 */ + UnitId?: string; + /** @description 院校 ID。 */ + SchoolId?: string; + /** @description 专业 ID。 */ + MajorId?: string; + /** @description 题目 ID。 */ + QuestionId?: string; + /** @description 状态。 */ + Status?: string; + /** @description 关键字。 */ + Keyword?: string; + /** @description 年份。 */ + Year?: number | string; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CatalogListOfScorelineRecord"]; + }; + }; + }; + }; + /** 新增或更新分数线记录 */ + put: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["DirectScorelineRecordDto"]; + "text/json": components["schemas"]["DirectScorelineRecordDto"]; + "application/*+json": components["schemas"]["DirectScorelineRecordDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ContentManagementResultOfScorelineRecord"]; + }; + }; + }; + }; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-content/scoreline/years": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询分数线年份 */ + get: { + parameters: { + query?: { + /** @description 地区 ID。 */ + RegionId?: string; + /** @description 内容入口 ID。 */ + EntryId?: string; + /** @description 内容节点 ID。 */ + ContentNodeId?: string; + /** @description 父节点 ID。 */ + ParentId?: string; + /** @description 科目 ID。 */ + SubjectId?: string; + /** @description 章节 ID。 */ + ChapterId?: string; + /** @description 单元 ID。 */ + UnitId?: string; + /** @description 院校 ID。 */ + SchoolId?: string; + /** @description 专业 ID。 */ + MajorId?: string; + /** @description 题目 ID。 */ + QuestionId?: string; + /** @description 状态。 */ + Status?: string; + /** @description 关键字。 */ + Keyword?: string; + /** @description 年份。 */ + Year?: number | string; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CatalogListOfint"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-content/scoreline/trend": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询分数线趋势摘要 */ + get: { + parameters: { + query?: { + /** @description 地区 ID。 */ + RegionId?: string; + /** @description 内容入口 ID。 */ + EntryId?: string; + /** @description 内容节点 ID。 */ + ContentNodeId?: string; + /** @description 父节点 ID。 */ + ParentId?: string; + /** @description 科目 ID。 */ + SubjectId?: string; + /** @description 章节 ID。 */ + ChapterId?: string; + /** @description 单元 ID。 */ + UnitId?: string; + /** @description 院校 ID。 */ + SchoolId?: string; + /** @description 专业 ID。 */ + MajorId?: string; + /** @description 题目 ID。 */ + QuestionId?: string; + /** @description 状态。 */ + Status?: string; + /** @description 关键字。 */ + Keyword?: string; + /** @description 年份。 */ + Year?: number | string; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CatalogListOfScorelineTrendItem"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-content/videos": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询租户视频解析 */ + get: { + parameters: { + query?: { + /** @description 地区 ID。 */ + RegionId?: string; + /** @description 内容入口 ID。 */ + EntryId?: string; + /** @description 内容节点 ID。 */ + ContentNodeId?: string; + /** @description 父节点 ID。 */ + ParentId?: string; + /** @description 科目 ID。 */ + SubjectId?: string; + /** @description 章节 ID。 */ + ChapterId?: string; + /** @description 单元 ID。 */ + UnitId?: string; + /** @description 院校 ID。 */ + SchoolId?: string; + /** @description 专业 ID。 */ + MajorId?: string; + /** @description 题目 ID。 */ + QuestionId?: string; + /** @description 状态。 */ + Status?: string; + /** @description 关键字。 */ + Keyword?: string; + /** @description 年份。 */ + Year?: number | string; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CatalogListOfVideoManagementItem"]; + }; + }; + }; + }; + /** 新增或更新视频解析 */ + put: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["DirectVideoDto"]; + "text/json": components["schemas"]["DirectVideoDto"]; + "application/*+json": components["schemas"]["DirectVideoDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ContentManagementResultOfVideoManagementItem"]; + }; + }; + }; + }; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-content/question-videos": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 绑定题目与解析视频 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["DirectQuestionVideoDto"]; + "text/json": components["schemas"]["DirectQuestionVideoDto"]; + "application/*+json": components["schemas"]["DirectQuestionVideoDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ContentManagementResultOfQuestionVideoManagementItem"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-content/operations/{kind}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询运营内容 */ + get: { + parameters: { + query?: { + /** @description 地区 ID。 */ + RegionId?: string; + /** @description 内容入口 ID。 */ + EntryId?: string; + /** @description 内容节点 ID。 */ + ContentNodeId?: string; + /** @description 父节点 ID。 */ + ParentId?: string; + /** @description 科目 ID。 */ + SubjectId?: string; + /** @description 章节 ID。 */ + ChapterId?: string; + /** @description 单元 ID。 */ + UnitId?: string; + /** @description 院校 ID。 */ + SchoolId?: string; + /** @description 专业 ID。 */ + MajorId?: string; + /** @description 题目 ID。 */ + QuestionId?: string; + /** @description 状态。 */ + Status?: string; + /** @description 关键字。 */ + Keyword?: string; + /** @description 年份。 */ + Year?: number | string; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path: { + kind: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CatalogListOfOperationContentItem"]; + }; + }; + }; + }; + /** 新增或更新运营内容 */ + put: { + parameters: { + query?: never; + header?: never; + path: { + kind: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["DirectOperationContentDto"]; + "text/json": components["schemas"]["DirectOperationContentDto"]; + "application/*+json": components["schemas"]["DirectOperationContentDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ContentManagementResultOfOperationContentItem"]; + }; + }; + }; + }; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-content/imports/preview/{importType}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 预览内容导入数据 */ + post: { + parameters: { + query?: never; + header?: never; + path: { + importType: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["DirectImportDto"]; + "text/json": components["schemas"]["DirectImportDto"]; + "application/*+json": components["schemas"]["DirectImportDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["SimpleImportResult"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-content/imports/{importType}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 执行或排队内容导入 */ + post: { + parameters: { + query?: never; + header?: never; + path: { + importType: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["DirectImportDto"]; + "text/json": components["schemas"]["DirectImportDto"]; + "application/*+json": components["schemas"]["DirectImportDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["SimpleImportResult"]; + }; + }; + /** @description Accepted */ + 202: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["BackgroundJobItem"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-content/imports/detail": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询内容导入任务详情 */ + get: { + parameters: { + query?: { + /** @description 任务 ID。 */ + JobId?: string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ContentImportJobDetail"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-content/imports/issues": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询内容导入问题明细 */ + get: { + parameters: { + query?: { + /** @description 任务 ID。 */ + JobId?: string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CatalogListOfContentImportIssueModel"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-content/imports/post-check": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询内容导入后检查状态 */ + get: { + parameters: { + query?: { + /** @description 任务 ID。 */ + JobId?: string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ImportPostCheckResult"]; + }; + }; + }; + }; + put?: never; + /** 执行内容导入后完整性检查 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["DirectImportJobDto"]; + "text/json": components["schemas"]["DirectImportJobDto"]; + "application/*+json": components["schemas"]["DirectImportJobDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ImportPostCheckResult"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-admin/frontend-config": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询租户前端配置 */ + get: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["TenantFrontendConfigItem"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-admin/frontend-config/draft": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + /** 保存租户前端配置草稿 */ + put: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["SaveTenantFrontendConfigDraftDto"]; + "text/json": components["schemas"]["SaveTenantFrontendConfigDraftDto"]; + "application/*+json": components["schemas"]["SaveTenantFrontendConfigDraftDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["TenantFrontendConfigItem"]; + }; + }; + }; + }; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-admin/frontend-config/publish": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 发布租户前端配置 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["PublishTenantFrontendConfigDto"]; + "text/json": components["schemas"]["PublishTenantFrontendConfigDto"]; + "application/*+json": components["schemas"]["PublishTenantFrontendConfigDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["TenantFrontendConfigItem"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant-onboarding/status": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 查询租户开通引导状态 */ + get: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "text/plain": components["schemas"]["TenantOnboardingStatus"]; + "application/json": components["schemas"]["TenantOnboardingStatus"]; + "text/json": components["schemas"]["TenantOnboardingStatus"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant/resolve": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * 解析当前租户 + * @description 根据访问域名、host 参数、x-tenant-code 或 tenantCode 查询启用中的租户及公开品牌配置。 + */ + get: { + parameters: { + query?: { + /** @description 访问域名。 */ + Host?: string; + /** @description 租户编码。 */ + TenantCode?: string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["TenantResolveResponseDto"]; + }; + }; + /** @description Not Found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProblemDetails"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenant/current-public": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * 获取公开租户配置 + * @description 公开页面使用的租户品牌、功能开关和 public config。和 resolve 返回结构一致。 + */ + get: { + parameters: { + query?: { + /** @description 访问域名。 */ + Host?: string; + /** @description 租户编码。 */ + TenantCode?: string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["TenantResolveResponseDto"]; + }; + }; + /** @description Not Found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProblemDetails"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tenants/current": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * 查询当前租户 + * @description 返回当前请求租户及当前用户在该租户内的成员角色。 + */ + get: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "text/plain": components["schemas"]["CurrentTenantResponse"]; + "application/json": components["schemas"]["CurrentTenantResponse"]; + "text/json": components["schemas"]["CurrentTenantResponse"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/videos/search": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** 搜索通用解析视频 */ + get: { + parameters: { + query?: { + /** @description 关键字。 */ + Keyword?: string; + /** @description 科目 ID。 */ + SubjectId?: string; + /** @description 返回数量上限。 */ + Limit?: number | string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CatalogListOfVideoExplanationCatalogItem"]; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/videos/play": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 申请视频播放信息 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["VideoPlayDto"]; + "text/json": components["schemas"]["VideoPlayDto"]; + "application/*+json": components["schemas"]["VideoPlayDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["VideoPlaybackItem"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/videos/progress": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** 上报视频播放进度 */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["VideoProgressDto"]; + "text/json": components["schemas"]["VideoProgressDto"]; + "application/*+json": components["schemas"]["VideoProgressDto"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["VideoProgressItem"]; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; +} +export type webhooks = Record; +export interface components { + schemas: { + ActivationCodeItem: { + /** Format: uuid */ + id: string; + /** Format: uuid */ + batchId: null | string; + code: string; + /** Format: int32 */ + days: number | string; + isUsed: boolean; + /** Format: uuid */ + usedBy: null | string; + /** Format: date-time */ + usedAt: null | string; + saleType: null | string; + soldTo: null | string; + remark: null | string; + /** Format: date-time */ + createdAt: string; + }; + ActivationCodeList: { + items: components["schemas"]["ActivationCodeItem"][]; + }; + AdminOrderList: { + items: components["schemas"]["CommerceOrderItem"][]; + }; + AdminPaymentList: { + items: components["schemas"]["CommercePaymentItem"][]; + }; + AnnouncementCatalogItem: { + /** Format: uuid */ + id: string; + legacyId: null | string; + content: null | string; + link: null | string; + backgroundColor: null | string; + /** Format: int32 */ + order: number | string; + isActive: boolean; + }; + AnswerRecordItem: { + /** Format: uuid */ + id: string; + /** Format: uuid */ + sessionQuestionId: string; + /** Format: uuid */ + practiceSessionId: string; + selectedOptions: components["schemas"]["JsonElement"]; + answerText: null | string; + isCorrect: null | boolean; + /** Format: date-time */ + answeredAt: string; + }; + AppAssetCatalogItem: { + /** Format: uuid */ + id: string; + legacyId: null | string; + assetKey: string; + fileName: null | string; + description: null | string; + metadata: components["schemas"]["JsonElement"]; + }; + ArchivePlatformQuestionsCommand: { + questionIds: string[]; + }; + AssetAccessActorRole: number; + AssetAccessDisposition: number; + /** @description 资产访问Principal请求 DTO。 */ + AssetAccessPrincipalDto: { + /** Format: uuid */ + userId: null | string; + isMember: boolean; + hasSvip: boolean; + }; + /** @description 资产访问签名响应。 */ + AssetAccessResponseDto: { + item: components["schemas"]["ContentAssetAccessSummaryDto"]; + access: components["schemas"]["AssetAccessPrincipalDto"]; + url: components["schemas"]["SignedStorageUrlDto"]; + watermark: components["schemas"]["JsonElement"]; + }; + AssetAccessResult: number; + /** @description 创建资产访问签名请求。 */ + AssetAccessSignDto: { + /** + * Format: uuid + * @description 资产 ID。 + */ + assetId: string; + /** + * Format: int32 + * @description 有效期秒数。 + */ + expiresInSeconds?: null | number | string; + }; + AssetAccessType: number; + AssetManagementSignedAccessResult: { + item: components["schemas"]["ContentAssetManagementItem"]; + url: components["schemas"]["ObjectStorageSignedUrl"]; + }; + AssetPreviewStatus: number; + AssetSecurityRiskLevel: number; + AssetSecurityScanStatus: number; + AssetStorageProvider: number; + /** @description 确认资产上传请求。 */ + AssetUploadConfirmDto: { + /** + * Format: uuid + * @description 资产 ID。 + */ + assetId: string; + /** @description MIME 类型。 */ + mimeType?: null | string; + /** + * Format: int64 + * @description 文件大小,单位为字节。 + */ + fileSizeBytes?: null | number | string; + /** @description SHA-256 校验值。 */ + checksumSha256?: null | string; + }; + AssetUploadConfirmResult: { + item: components["schemas"]["ContentAssetManagementItem"]; + metadata: components["schemas"]["ObjectStorageMetadata"]; + }; + /** @description 创建资产上传签名请求。 */ + AssetUploadSignDto: { + /** + * Format: uuid + * @description 资产 ID。 + */ + assetId?: null | string; + /** + * Format: uuid + * @description 地区 ID。 + */ + regionId?: null | string; + /** + * Format: uuid + * @description 科目 ID。 + */ + subjectId?: null | string; + /** + * Format: uuid + * @description 分类 ID。 + */ + categoryId?: null | string; + /** + * Format: uuid + * @description 内容节点 ID。 + */ + contentNodeId?: null | string; + /** @description 资产键。 */ + assetKey?: null | string; + /** @description 标题。 */ + title?: null | string; + /** @description 分类。 */ + category?: null | string; + /** @description 说明。 */ + description?: null | string; + /** @description 文件名。 */ + fileName: string; + /** @description MIME 类型。 */ + mimeType: string; + /** + * Format: int64 + * @description 文件大小,单位为字节。 + */ + fileSizeBytes?: null | number | string; + /** @description SHA-256 校验值。 */ + checksumSha256?: null | string; + /** @description 资产类型。 */ + assetType?: null | string; + /** @description 可见性。 */ + visibility?: null | string; + /** @description 是否公开。 */ + isPublic?: null | boolean; + /** @description 服务提供方。 */ + provider?: null | string; + /** @description 存储桶。 */ + bucket?: null | string; + /** @description 对象存储键。 */ + objectKey?: null | string; + /** + * Format: int32 + * @description 有效期秒数。 + */ + expiresInSeconds?: null | number | string; + /** @description 扩展元数据。 */ + metadata?: components["schemas"]["JsonElement"]; + }; + AssetUploadSignResult: { + item: components["schemas"]["ContentAssetManagementItem"]; + upload: components["schemas"]["ObjectStorageSignedUrl"]; + }; + AssetUploadStatus: number; + /** @description Authenticated用户请求 DTO。 */ + AuthenticatedUserDto: { + /** + * Format: uuid + * @description 用户 ID。 + */ + userId?: string; + /** @description 手机号。 */ + phone?: null | string; + /** @description 邮箱。 */ + email?: null | string; + /** @description 名称。 */ + name?: null | string; + /** @description 认证域。 */ + realm?: components["schemas"]["AuthRealm"]; + tenant?: null | components["schemas"]["TenantMembershipSummary"]; + /** @description 访问令牌和刷新令牌。 */ + tokens?: components["schemas"]["AuthTokenPair"]; + }; + /** @description 登录认证结果。 */ + AuthenticationResultDto: { + /** @description 状态。 */ + status?: components["schemas"]["AuthenticationStatus"]; + user?: null | components["schemas"]["AuthenticatedUserDto"]; + /** @description 挑战令牌。 */ + challengeToken?: null | string; + /** + * Format: date-time + * @description 挑战令牌过期时间。 + */ + challengeExpiresAt?: null | string; + }; + AuthenticationStatus: number; + AuthRealm: number; + /** @description 认证令牌对。 */ + AuthTokenPair: { + /** @description 用于访问 API 的 JWT access token。 */ + accessToken: string; + /** @description 用于刷新会话的 refresh token,服务端只保存哈希。 */ + refreshToken: string; + /** + * Format: date-time + * @description access token 过期时间。 + */ + accessTokenExpiresAt: string; + /** + * Format: date-time + * @description refresh token 过期时间。 + */ + refreshTokenExpiresAt: string; + }; + BackendPermissionArea: number; + BackendRoleStatus: number; + BackgroundJobItem: { + /** Format: uuid */ + id: string; + /** Format: uuid */ + tenantId: string; + jobType: string; + status: components["schemas"]["BackgroundJobStatus"]; + /** Format: int32 */ + retryCount: number | string; + /** Format: int32 */ + maxRetries: number | string; + /** Format: date-time */ + runAfter: null | string; + /** Format: date-time */ + startedAt: null | string; + /** Format: date-time */ + completedAt: null | string; + lastError: null | string; + /** Format: uuid */ + outputAssetId: null | string; + result: components["schemas"]["JsonElement"]; + }; + BackgroundJobStatus: number; + BackofficeBootstrap: { + permissions: components["schemas"]["BackofficePermissionItem"][]; + menus: components["schemas"]["BackofficeMenuItem"][]; + roles: components["schemas"]["BackofficeRoleItem"][]; + }; + BackofficeMenuItem: { + /** Format: uuid */ + id: string; + code: string; + parentCode: null | string; + title: string; + area: components["schemas"]["BackendPermissionArea"]; + path: null | string; + icon: null | string; + permissionCode: null | string; + /** Format: int32 */ + sortOrder: number | string; + isActive: boolean; + }; + BackofficePermissionItem: { + /** Format: uuid */ + id: string; + code: string; + name: string; + area: components["schemas"]["BackendPermissionArea"]; + permissionModuleCode: string; + description: null | string; + /** Format: int32 */ + sortOrder: number | string; + }; + BackofficeRoleItem: { + /** Format: uuid */ + id: string; + code: string; + name: string; + status: components["schemas"]["BackendRoleStatus"]; + isSystem: boolean; + description: null | string; + permissionCodes: string[]; + menuCodes: string[]; + dataScope?: unknown; + }; + BackofficeUiBootstrap: { + permissionCodes: string[]; + menus: components["schemas"]["BackofficeMenuItem"][]; + enabledFeatures: string[]; + quotas: components["schemas"]["FeatureQuotaSnapshot"][]; + }; + BadgeItem: { + /** Format: uuid */ + id: string; + name: string; + description: null | string; + category: null | string; + iconUrl: null | string; + /** Format: int32 */ + level: null | number | string; + unlockType: null | string; + conditionExtra: components["schemas"]["JsonElement"]; + isUnlocked: boolean; + /** Format: date-time */ + grantedAt: null | string; + note: null | string; + /** Format: int32 */ + order: number | string; + }; + BadgeList: { + items: components["schemas"]["BadgeItem"][]; + /** Format: int32 */ + total: number | string; + /** Format: int32 */ + unlocked: number | string; + includeLocked: boolean; + }; + BannerCatalogItem: { + /** Format: uuid */ + id: string; + legacyId: null | string; + /** Format: uuid */ + regionId: null | string; + title: null | string; + subtitle: null | string; + content: null | string; + buttonText: null | string; + buttonLink: null | string; + backgroundColor: null | string; + borderColor: null | string; + /** Format: int32 */ + order: number | string; + isActive: boolean; + }; + BatchCreatePlatformQuestionBankNodesCommand: { + /** Format: uuid */ + questionBankId: string; + /** Format: uuid */ + parentId: null | string; + nodeType: components["schemas"]["ContentNodeType"]; + names: string[]; + }; + BillingStatus: number; + /** @description 绑定推荐请求 DTO。 */ + BindReferralDto: { + /** @description 推荐码。 */ + refCode: string; + /** @description 来源。 */ + source?: null | string; + metadata?: null | components["schemas"]["JsonElement"]; + }; + CatalogListOfAnnouncementCatalogItem: { + items: components["schemas"]["AnnouncementCatalogItem"][]; + }; + CatalogListOfAppAssetCatalogItem: { + items: components["schemas"]["AppAssetCatalogItem"][]; + }; + CatalogListOfBannerCatalogItem: { + items: components["schemas"]["BannerCatalogItem"][]; + }; + CatalogListOfCategoryCatalogItem: { + items: components["schemas"]["CategoryCatalogItem"][]; + }; + CatalogListOfCollectionQuestionCatalogItem: { + items: components["schemas"]["CollectionQuestionCatalogItem"][]; + }; + CatalogListOfContentAssetAccessEventItem: { + items: components["schemas"]["ContentAssetAccessEventItem"][]; + }; + CatalogListOfContentAssetCatalogItem: { + items: components["schemas"]["ContentAssetCatalogItem"][]; + }; + CatalogListOfContentAssetManagementItem: { + items: components["schemas"]["ContentAssetManagementItem"][]; + }; + CatalogListOfContentAssetSecurityScanEventItem: { + items: components["schemas"]["ContentAssetSecurityScanEventItem"][]; + }; + CatalogListOfContentEntryCatalogItem: { + items: components["schemas"]["ContentEntryCatalogItem"][]; + }; + CatalogListOfContentEntryManagementItem: { + items: components["schemas"]["ContentEntryManagementItem"][]; + }; + CatalogListOfContentImportIssueModel: { + items: components["schemas"]["ContentImportIssueModel"][]; + }; + CatalogListOfContentImportJobItem: { + items: components["schemas"]["ContentImportJobItem"][]; + }; + CatalogListOfContentNodeCatalogItem: { + items: components["schemas"]["ContentNodeCatalogItem"][]; + }; + CatalogListOfContentNodeManagementItem: { + items: components["schemas"]["ContentNodeManagementItem"][]; + }; + CatalogListOfExamDateCatalogItem: { + items: components["schemas"]["ExamDateCatalogItem"][]; + }; + CatalogListOfFaqCatalogItem: { + items: components["schemas"]["FaqCatalogItem"][]; + }; + CatalogListOfHandbookChapter: { + items: components["schemas"]["HandbookChapter"][]; + }; + CatalogListOfHandbookChapterCatalogItem: { + items: components["schemas"]["HandbookChapterCatalogItem"][]; + }; + CatalogListOfHandbookEntry: { + items: components["schemas"]["HandbookEntry"][]; + }; + CatalogListOfHandbookEntryCatalogItem: { + items: components["schemas"]["HandbookEntryCatalogItem"][]; + }; + CatalogListOfHandbookSubject: { + items: components["schemas"]["HandbookSubject"][]; + }; + CatalogListOfHandbookSubjectCatalogItem: { + items: components["schemas"]["HandbookSubjectCatalogItem"][]; + }; + CatalogListOfImageAssetCatalogItem: { + items: components["schemas"]["ImageAssetCatalogItem"][]; + }; + CatalogListOfint: { + items: (number | string)[]; + }; + CatalogListOfMajor: { + items: components["schemas"]["Major"][]; + }; + CatalogListOfMajorCatalogItem: { + items: components["schemas"]["MajorCatalogItem"][]; + }; + CatalogListOfModuleNodeCatalogItem: { + items: components["schemas"]["ModuleNodeCatalogItem"][]; + }; + CatalogListOfOperationContentItem: { + items: components["schemas"]["OperationContentItem"][]; + }; + CatalogListOfPracticeBlueprintCatalogItem: { + items: components["schemas"]["PracticeBlueprintCatalogItem"][]; + }; + CatalogListOfPracticeBlueprintManagementItem: { + items: components["schemas"]["PracticeBlueprintManagementItem"][]; + }; + CatalogListOfProductCatalogItem: { + items: components["schemas"]["ProductCatalogItem"][]; + }; + CatalogListOfQuestionBankCatalogItem: { + items: components["schemas"]["QuestionBankCatalogItem"][]; + }; + CatalogListOfQuestionCatalogItem: { + items: components["schemas"]["QuestionCatalogItem"][]; + }; + CatalogListOfQuestionCollectionCatalogItem: { + items: components["schemas"]["QuestionCollectionCatalogItem"][]; + }; + CatalogListOfQuestionCollectionManagementItem: { + items: components["schemas"]["QuestionCollectionManagementItem"][]; + }; + CatalogListOfQuestionVersionCatalogItem: { + items: components["schemas"]["QuestionVersionCatalogItem"][]; + }; + CatalogListOfQuestionVideoCatalogItem: { + items: components["schemas"]["QuestionVideoCatalogItem"][]; + }; + CatalogListOfRegionCatalogItem: { + items: components["schemas"]["RegionCatalogItem"][]; + }; + CatalogListOfRegionModuleCatalogItem: { + items: components["schemas"]["RegionModuleCatalogItem"][]; + }; + CatalogListOfSchool: { + items: components["schemas"]["School"][]; + }; + CatalogListOfSchoolCatalogItem: { + items: components["schemas"]["SchoolCatalogItem"][]; + }; + CatalogListOfScorelineField: { + items: components["schemas"]["ScorelineField"][]; + }; + CatalogListOfScorelineFieldItem: { + items: components["schemas"]["ScorelineFieldItem"][]; + }; + CatalogListOfScorelineRecord: { + items: components["schemas"]["ScorelineRecord"][]; + }; + CatalogListOfScorelineRecordItem: { + items: components["schemas"]["ScorelineRecordItem"][]; + }; + CatalogListOfScorelineTrendItem: { + items: components["schemas"]["ScorelineTrendItem"][]; + }; + CatalogListOfSubjectCatalogItem: { + items: components["schemas"]["SubjectCatalogItem"][]; + }; + CatalogListOfSvipPlanCatalogItem: { + items: components["schemas"]["SvipPlanCatalogItem"][]; + }; + CatalogListOfTenantAdminAuditLogItem: { + items: components["schemas"]["TenantAdminAuditLogItem"][]; + }; + CatalogListOfTenantAdminBadgeGrantItem: { + items: components["schemas"]["TenantAdminBadgeGrantItem"][]; + }; + CatalogListOfTenantAdminBadgeItem: { + items: components["schemas"]["TenantAdminBadgeItem"][]; + }; + CatalogListOfTenantAdminClassMemberItem: { + items: components["schemas"]["TenantAdminClassMemberItem"][]; + }; + CatalogListOfTenantAdminFeedbackItem: { + items: components["schemas"]["TenantAdminFeedbackItem"][]; + }; + CatalogListOfTenantAdminMemberItem: { + items: components["schemas"]["TenantAdminMemberItem"][]; + }; + CatalogListOfTenantAdminNotificationItem: { + items: components["schemas"]["TenantAdminNotificationItem"][]; + }; + CatalogListOfTenantAdminStudentFollowupItem: { + items: components["schemas"]["TenantAdminStudentFollowupItem"][]; + }; + CatalogListOfTenantAdminStudentNoteItem: { + items: components["schemas"]["TenantAdminStudentNoteItem"][]; + }; + CatalogListOfTenantDomainItem: { + items: components["schemas"]["TenantDomainItem"][]; + }; + CatalogListOfTenantIdentityProviderItem: { + items: components["schemas"]["TenantIdentityProviderItem"][]; + }; + CatalogListOfTenantSupervisionRuleItem: { + items: components["schemas"]["TenantSupervisionRuleItem"][]; + }; + CatalogListOfTenantThemeTemplateItem: { + items: components["schemas"]["TenantThemeTemplateItem"][]; + }; + CatalogListOfVideoExplanationCatalogItem: { + items: components["schemas"]["VideoExplanationCatalogItem"][]; + }; + CatalogListOfVideoManagementItem: { + items: components["schemas"]["VideoManagementItem"][]; + }; + CatalogListOfVocabularyUnit: { + items: components["schemas"]["VocabularyUnit"][]; + }; + CatalogListOfVocabularyUnitCatalogItem: { + items: components["schemas"]["VocabularyUnitCatalogItem"][]; + }; + CatalogListOfVocabularyWord: { + items: components["schemas"]["VocabularyWord"][]; + }; + CatalogListOfVocabularyWordCatalogItem: { + items: components["schemas"]["VocabularyWordCatalogItem"][]; + }; + CategoryCatalogItem: { + /** Format: uuid */ + id: string; + legacyId: null | string; + /** Format: uuid */ + subjectId: null | string; + /** Format: uuid */ + nodeId: null | string; + name: string; + categoryType: null | components["schemas"]["CategoryType"]; + /** Format: int32 */ + order: number | string; + /** Format: int32 */ + svipQuestionLimit: null | number | string; + }; + CategoryType: number; + /** @description 变更租户订阅请求 DTO。 */ + ChangeTenantSubscriptionDto: { + /** Format: uuid */ + baseOfferingVersionId: string; + addOnOfferingVersionIds: null | string[]; + idempotencyKey: string; + }; + /** @description 校验交易优惠券请求 DTO。 */ + CheckCommerceCouponDto: { + /** @description 优惠券码。 */ + couponCode?: null | string; + /** + * Format: uuid + * @description 优惠券领取记录 ID。 + */ + couponRedemptionId?: null | string; + /** + * Format: uuid + * @description 套餐 ID。 + */ + planId: string; + /** + * Format: int32 + * @description 数量。 + */ + quantity?: number | string; + /** + * Format: uuid + * @description 地区 ID。 + */ + regionId?: null | string; + }; + CheckInResult: { + /** Format: date */ + checkInDate: string; + alreadyCheckedIn: boolean; + /** Format: int32 */ + points: number | string; + /** Format: int32 */ + balanceAfter: number | string; + /** Format: uuid */ + claimId: null | string; + /** Format: uuid */ + scoreEventId: null | string; + }; + /** @description 领取交易优惠券请求 DTO。 */ + ClaimCommerceCouponDto: { + /** @description 优惠券码。 */ + couponCode: string; + }; + /** @description 领取积分任务请求 DTO。 */ + ClaimPointTaskDto: { + /** @description 任务键。 */ + taskKey: string; + /** @description 来源类型。 */ + sourceType?: null | string; + /** + * Format: uuid + * @description 来源 ID。 + */ + sourceId?: null | string; + }; + CodeBatchItem: { + /** Format: uuid */ + id: string; + name: string; + /** Format: int32 */ + totalCount: number | string; + /** Format: int32 */ + days: number | string; + /** Format: uuid */ + regionId: null | string; + saleType: null | string; + channel: null | string; + /** Format: int32 */ + defaultUnitPriceCents: number | string; + /** Format: int32 */ + costPriceCents: number | string; + /** Format: date-time */ + issuedAt: null | string; + remark: null | string; + /** Format: date-time */ + createdAt: string; + }; + CollectionItemsReplaceResult: { + /** Format: uuid */ + collectionId: string; + /** Format: int32 */ + questionCount: number | string; + items: components["schemas"]["QuestionCollectionItemManagementItem"][]; + }; + CollectionQuestionCatalogItem: { + /** Format: uuid */ + id: string; + legacyId: null | string; + /** Format: uuid */ + entryId: null | string; + /** Format: uuid */ + contentNodeId: null | string; + /** Format: uuid */ + primaryCollectionId: null | string; + /** Format: uuid */ + subjectId: null | string; + /** Format: uuid */ + categoryId: null | string; + /** Format: uuid */ + nodeId: null | string; + type: string; + typeLabel: null | string; + /** Format: int32 */ + difficulty: null | number | string; + tags: components["schemas"]["JsonElement"]; + examMarkers: components["schemas"]["JsonElement"]; + mediaUrl: null | string; + hasVideoExplanation: boolean; + sectionKey: null | string; + /** Format: double */ + score: null | number | string; + /** Format: int32 */ + order: number | string; + /** Format: uuid */ + versionId: null | string; + content: null | string; + options: components["schemas"]["JsonElement"]; + /** Format: int32 */ + correctOptionIndex: null | number | string; + correctOptionIndices: components["schemas"]["JsonElement"]; + answerText: null | string; + explanation: null | string; + subQuestions: components["schemas"]["JsonElement"]; + codeLang: null | string; + codeTemplate: null | string; + }; + /** @description 题集题目请求 DTO。 */ + CollectionQuestionDto: { + /** + * Format: uuid + * @description 题目 ID。 + */ + questionId: string; + /** @description 来源。 */ + source: components["schemas"]["QuestionSource"]; + /** @description 分段键。 */ + sectionKey?: null | string; + /** + * Format: int32 + * @description 显示顺序。 + */ + order?: null | number | string; + /** + * Format: double + * @description 分数。 + */ + score?: null | number | string; + /** @description 是否必填。 */ + required?: null | boolean; + /** @description 扩展元数据。 */ + metadata?: components["schemas"]["JsonElement"]; + }; + CommerceAdjustmentDirection: number; + CommerceAdjustmentVoucher: { + /** Format: uuid */ + issueId?: null | string; + /** Format: uuid */ + batchId?: null | string; + /** Format: uuid */ + itemId?: null | string; + /** Format: uuid */ + orderId?: null | string; + /** Format: uuid */ + paymentId?: null | string; + /** Format: uuid */ + refundRequestId?: null | string; + /** Format: uuid */ + createdBy?: null | string; + /** Format: uuid */ + reviewedBy?: null | string; + voucherNo?: string; + status?: components["schemas"]["CommerceAdjustmentVoucherStatus"]; + direction?: components["schemas"]["CommerceAdjustmentDirection"]; + /** Format: int32 */ + amountCents?: number | string; + currency?: string; + reason?: string; + proofAssetKey?: null | string; + /** Format: date-time */ + reviewedAt?: null | string; + /** Format: date-time */ + closedAt?: null | string; + metadata?: components["schemas"]["JsonElement"]; + /** Format: date-time */ + createdAt?: string; + /** Format: date-time */ + updatedAt?: string; + /** Format: uuid */ + tenantId?: string; + /** Format: uuid */ + id?: string; + }; + CommerceAdjustmentVoucherEvent: { + /** Format: uuid */ + tenantId?: string; + /** Format: uuid */ + voucherId?: string; + fromStatus?: null | components["schemas"]["CommerceAdjustmentVoucherStatus"]; + toStatus?: components["schemas"]["CommerceAdjustmentVoucherStatus"]; + /** Format: uuid */ + actorUserId?: null | string; + note?: null | string; + details?: components["schemas"]["JsonElement"]; + /** Format: date-time */ + createdAt?: string; + /** Format: uuid */ + id?: string; + }; + CommerceAdjustmentVoucherStatus: number; + CommerceCouponCheckResult: { + valid: boolean; + reasonCode: null | string; + /** Format: uuid */ + couponId: null | string; + /** Format: uuid */ + couponRedemptionId: null | string; + couponCode: null | string; + /** Format: int32 */ + originalAmountCents: number | string; + /** Format: int32 */ + discountCents: number | string; + /** Format: int32 */ + payableAmountCents: number | string; + payablePrice: string; + }; + CommerceCouponItem: { + /** Format: uuid */ + id: string; + /** Format: uuid */ + couponId: null | string; + couponCode: string; + status: string; + /** Format: uuid */ + planId: null | string; + /** Format: uuid */ + regionId: null | string; + discountType: null | string; + /** Format: double */ + discountValue: null | number | string; + /** Format: int32 */ + discountPreviewCents: null | number | string; + discountPreview: null | string; + /** Format: date-time */ + validFrom: null | string; + /** Format: date-time */ + validTo: null | string; + /** Format: date-time */ + claimedAt: null | string; + /** Format: date-time */ + usedAt: null | string; + }; + CommerceCouponList: { + items: components["schemas"]["CommerceCouponItem"][]; + }; + CommerceOrderItem: { + /** Format: uuid */ + id: string; + orderNo: string; + status: string; + /** Format: uuid */ + planId: null | string; + /** Format: uuid */ + regionId: null | string; + productType: null | string; + productName: null | string; + /** Format: int32 */ + amountCents: number | string; + price: string; + payMethod: null | string; + payProvider: null | string; + tradeNo: null | string; + /** Format: int32 */ + days: null | number | string; + /** Format: date-time */ + paidAt: null | string; + /** Format: date-time */ + createdAt: string; + rawPayload: components["schemas"]["JsonElement"]; + }; + CommerceOrderList: { + items: components["schemas"]["CommerceOrderItem"][]; + }; + CommercePaymentItem: { + /** Format: uuid */ + id: string; + /** Format: uuid */ + orderId: string; + orderNo: string; + provider: string; + method: null | string; + status: string; + /** Format: int32 */ + amountCents: number | string; + price: string; + providerTradeNo: null | string; + /** Format: date-time */ + paidAt: null | string; + clientPayload: components["schemas"]["JsonElement"]; + rawPayload: components["schemas"]["JsonElement"]; + }; + CommerceReconciliationBatch: { + /** Format: uuid */ + createdBy?: null | string; + provider?: string; + /** Format: date */ + billDate?: string; + billType?: components["schemas"]["ReconciliationBillType"]; + source?: components["schemas"]["ReconciliationSource"]; + sourceName?: null | string; + sourceHash?: string; + status?: components["schemas"]["ReconciliationBatchStatus"]; + /** Format: int32 */ + totalCount?: number | string; + /** Format: int32 */ + matchedCount?: number | string; + /** Format: int32 */ + mismatchCount?: number | string; + /** Format: int32 */ + missingLocalCount?: number | string; + /** Format: int32 */ + missingProviderCount?: number | string; + /** Format: int32 */ + duplicateCount?: number | string; + /** Format: int32 */ + ignoredCount?: number | string; + /** Format: int32 */ + amountCents?: number | string; + /** Format: int32 */ + refundAmountCents?: number | string; + /** Format: int32 */ + feeCents?: number | string; + /** Format: date-time */ + completedAt?: null | string; + error?: null | string; + metadata?: components["schemas"]["JsonElement"]; + /** Format: date-time */ + createdAt?: string; + /** Format: date-time */ + updatedAt?: string; + /** Format: uuid */ + tenantId?: string; + /** Format: uuid */ + id?: string; + }; + CommerceReconciliationIssue: { + /** Format: uuid */ + batchId?: null | string; + /** Format: uuid */ + itemId?: null | string; + /** Format: uuid */ + orderId?: null | string; + /** Format: uuid */ + paymentId?: null | string; + /** Format: uuid */ + refundRequestId?: null | string; + /** Format: uuid */ + assignedTo?: null | string; + /** Format: uuid */ + createdBy?: null | string; + /** Format: uuid */ + resolvedBy?: null | string; + issueNo?: string; + provider?: string; + transactionType?: components["schemas"]["ReconciliationTransactionType"]; + issueCode?: null | string; + matchStatus?: components["schemas"]["ReconciliationIssueMatchStatus"]; + severity?: components["schemas"]["NotificationSeverity"]; + status?: components["schemas"]["ReconciliationIssueStatus"]; + resolutionType?: components["schemas"]["ReconciliationResolutionType"]; + orderNo?: null | string; + refundNo?: null | string; + providerTradeNo?: null | string; + providerRefundNo?: null | string; + /** Format: int32 */ + amountCents?: number | string; + /** Format: int32 */ + refundAmountCents?: number | string; + /** Format: date-time */ + resolvedAt?: null | string; + /** Format: date-time */ + dueAt?: null | string; + summary?: null | string; + resolutionNote?: null | string; + metadata?: components["schemas"]["JsonElement"]; + /** Format: date-time */ + createdAt?: string; + /** Format: date-time */ + updatedAt?: string; + /** Format: uuid */ + tenantId?: string; + /** Format: uuid */ + id?: string; + }; + CommerceReconciliationIssueEvent: { + /** Format: uuid */ + tenantId?: string; + /** Format: uuid */ + issueId?: string; + fromStatus?: null | components["schemas"]["ReconciliationIssueStatus"]; + toStatus?: null | components["schemas"]["ReconciliationIssueStatus"]; + eventType?: string; + /** Format: uuid */ + actorUserId?: null | string; + note?: null | string; + details?: components["schemas"]["JsonElement"]; + /** Format: date-time */ + createdAt?: string; + /** Format: uuid */ + id?: string; + }; + CommerceReconciliationItem: { + /** Format: uuid */ + tenantId?: string; + /** Format: uuid */ + batchId?: string; + /** Format: uuid */ + orderId?: null | string; + /** Format: uuid */ + paymentId?: null | string; + /** Format: uuid */ + refundRequestId?: null | string; + /** Format: int32 */ + rowNo?: number | string; + provider?: string; + transactionType?: components["schemas"]["ReconciliationTransactionType"]; + providerTradeNo?: null | string; + providerRefundNo?: null | string; + orderNo?: null | string; + refundNo?: null | string; + /** Format: int32 */ + amountCents?: number | string; + /** Format: int32 */ + refundAmountCents?: number | string; + /** Format: int32 */ + feeCents?: number | string; + /** Format: date-time */ + paidAt?: null | string; + /** Format: date-time */ + refundedAt?: null | string; + providerStatus?: null | string; + localStatus?: null | string; + matchStatus?: components["schemas"]["ReconciliationMatchStatus"]; + severity?: components["schemas"]["NotificationSeverity"]; + issueCode?: null | string; + details?: components["schemas"]["JsonElement"]; + /** Format: date-time */ + createdAt?: string; + /** Format: uuid */ + id?: string; + }; + CommerceRefundEvent: { + /** Format: uuid */ + tenantId?: string; + /** Format: uuid */ + refundRequestId?: string; + fromStatus?: null | components["schemas"]["CommerceRefundStatus"]; + toStatus?: components["schemas"]["CommerceRefundStatus"]; + eventType?: string; + /** Format: uuid */ + actorUserId?: null | string; + details?: components["schemas"]["JsonElement"]; + /** Format: date-time */ + createdAt?: string; + /** Format: uuid */ + id?: string; + }; + CommerceRefundRequest: { + /** Format: uuid */ + orderId?: string; + /** Format: uuid */ + paymentId?: null | string; + /** Format: uuid */ + requestedBy?: null | string; + /** Format: uuid */ + reviewedBy?: null | string; + /** Format: uuid */ + processedBy?: null | string; + refundNo?: string; + provider?: null | string; + providerRefundNo?: null | string; + status?: components["schemas"]["CommerceRefundStatus"]; + /** Format: int32 */ + amountCents?: number | string; + reason?: null | string; + entitlementAction?: components["schemas"]["RefundEntitlementAction"]; + /** Format: date-time */ + requestedAt?: string; + /** Format: date-time */ + reviewedAt?: null | string; + /** Format: date-time */ + processedAt?: null | string; + /** Format: date-time */ + succeededAt?: null | string; + /** Format: date-time */ + failedAt?: null | string; + /** Format: date-time */ + cancelledAt?: null | string; + failureReason?: null | string; + metadata?: components["schemas"]["JsonElement"]; + /** Format: date-time */ + createdAt?: string; + /** Format: date-time */ + updatedAt?: string; + /** Format: uuid */ + tenantId?: string; + /** Format: uuid */ + id?: string; + }; + CommerceRefundStatus: number; + CommissionExportItem: { + /** Format: uuid */ + settlementId: string; + filename: string; + format: string; + mimeType: string; + /** Format: int32 */ + rowCount: number | string; + contentBase64: string; + sha256: string; + /** Format: int32 */ + sizeBytes: number | string; + }; + CommissionListOfCommissionProofItem: { + items: components["schemas"]["CommissionProofItem"][]; + }; + CommissionListOfCommissionSettlementItemDto: { + items: components["schemas"]["CommissionSettlementItemDto"][]; + }; + CommissionListOfCommissionSourceItem: { + items: components["schemas"]["CommissionSourceItem"][]; + }; + CommissionProofItem: { + /** Format: uuid */ + id: string; + /** Format: uuid */ + settlementId: string; + proofType: string; + status: string; + title: null | string; + /** Format: uuid */ + assetId: null | string; + externalUrl: null | string; + /** Format: int32 */ + amountCents: null | number | string; + paymentMethod: null | string; + paymentAccount: null | string; + /** Format: date-time */ + paidAt: null | string; + /** Format: date-time */ + reviewedAt: null | string; + }; + CommissionSettingsItem: { + /** Format: double */ + defaultRate: number | string; + /** Format: int32 */ + minSettlementCents: number | string; + settlementCycle: string; + config: components["schemas"]["JsonElement"]; + }; + CommissionSettlementItemDto: { + /** Format: uuid */ + id: string; + settlementNo: string; + /** Format: uuid */ + referrerUserId: string; + status: string; + /** Format: date */ + periodStart: string; + /** Format: date */ + periodEnd: string; + /** Format: int32 */ + sourceCount: number | string; + /** Format: int32 */ + paidUserCount: number | string; + /** Format: int32 */ + grossAmountCents: number | string; + /** Format: int32 */ + commissionAmountCents: number | string; + /** Format: date-time */ + reviewedAt: null | string; + /** Format: date-time */ + paidAt: null | string; + }; + CommissionSourceItem: { + sourceType: string; + /** Format: uuid */ + sourceId: string; + sourceNo: null | string; + /** Format: uuid */ + referrerUserId: string; + /** Format: uuid */ + studentUserId: null | string; + /** Format: int32 */ + grossAmountCents: number | string; + /** Format: double */ + commissionRate: number | string; + /** Format: int32 */ + commissionAmountCents: number | string; + rateSource: string; + /** Format: uuid */ + settlementId: null | string; + }; + CommissionSummaryItem: { + /** Format: int32 */ + sourceCount: number | string; + /** Format: int32 */ + paidUserCount: number | string; + /** Format: int32 */ + grossAmountCents: number | string; + /** Format: int32 */ + commissionAmountCents: number | string; + }; + /** @description 确认人工平台支付请求 DTO。 */ + ConfirmManualPlatformPaymentDto: { + /** Format: uuid */ + paymentId: string; + providerTradeNo: null | string; + /** Format: date-time */ + paidAt: null | string; + reason: string; + }; + ContentAssetAccessEventItem: { + /** Format: uuid */ + id: string; + /** Format: uuid */ + assetId: null | string; + /** Format: uuid */ + userId: null | string; + actorRole: components["schemas"]["AssetAccessActorRole"]; + accessType: components["schemas"]["AssetAccessType"]; + visibility: null | string; + assetType: null | string; + storageProvider: null | string; + disposition: null | components["schemas"]["AssetAccessDisposition"]; + /** Format: int32 */ + expiresInSeconds: null | number | string; + signatureMode: null | string; + result: components["schemas"]["AssetAccessResult"]; + denyCode: null | string; + ipAddress: null | string; + userAgent: null | string; + metadata: components["schemas"]["JsonElement"]; + /** Format: date-time */ + createdAt: string; + }; + /** @description 内容资产访问摘要。 */ + ContentAssetAccessSummaryDto: { + /** Format: uuid */ + id: string; + assetType: components["schemas"]["ContentAssetType"]; + title: null | string; + fileName: null | string; + previewUrl: null | string; + uploadStatus: components["schemas"]["AssetUploadStatus"]; + securityScanStatus: components["schemas"]["AssetSecurityScanStatus"]; + previewStatus: components["schemas"]["AssetPreviewStatus"]; + visibility: components["schemas"]["ContentVisibility"]; + }; + ContentAssetCatalogItem: { + /** Format: uuid */ + id: string; + legacyId: null | string; + /** Format: uuid */ + regionId: null | string; + /** Format: uuid */ + subjectId: null | string; + /** Format: uuid */ + categoryId: null | string; + /** Format: uuid */ + contentNodeId: null | string; + assetKey: null | string; + title: null | string; + category: null | string; + description: null | string; + fileName: null | string; + cdnUrl: null | string; + isPublic: boolean; + assetType: components["schemas"]["ContentAssetType"]; + storageProvider: components["schemas"]["AssetStorageProvider"]; + bucket: null | string; + objectKey: null | string; + mimeType: null | string; + /** Format: int64 */ + fileSizeBytes: null | number | string; + checksumSha256: null | string; + visibility: components["schemas"]["ContentVisibility"]; + previewUrl: null | string; + status: components["schemas"]["ContentStatus"]; + /** Format: int32 */ + order: number | string; + uploadStatus: components["schemas"]["AssetUploadStatus"]; + /** Format: date-time */ + verifiedAt: null | string; + previewStatus: components["schemas"]["AssetPreviewStatus"]; + securityScanStatus: components["schemas"]["AssetSecurityScanStatus"]; + metadata: components["schemas"]["JsonElement"]; + }; + ContentAssetManagementItem: { + /** Format: uuid */ + id: string; + legacyId: null | string; + /** Format: uuid */ + regionId: null | string; + /** Format: uuid */ + subjectId: null | string; + /** Format: uuid */ + categoryId: null | string; + /** Format: uuid */ + contentNodeId: null | string; + assetKey: null | string; + title: null | string; + category: null | string; + description: null | string; + fileName: null | string; + cdnUrl: null | string; + isPublic: boolean; + assetType: components["schemas"]["ContentAssetType"]; + storageProvider: components["schemas"]["AssetStorageProvider"]; + bucket: null | string; + objectKey: null | string; + mimeType: null | string; + /** Format: int64 */ + fileSizeBytes: null | number | string; + checksumSha256: null | string; + visibility: components["schemas"]["ContentVisibility"]; + status: components["schemas"]["ContentStatus"]; + /** Format: int32 */ + order: number | string; + uploadStatus: components["schemas"]["AssetUploadStatus"]; + /** Format: date-time */ + verifiedAt: null | string; + /** Format: int64 */ + verifiedSizeBytes: null | number | string; + verifiedChecksumSha256: null | string; + previewStatus: components["schemas"]["AssetPreviewStatus"]; + securityScanStatus: components["schemas"]["AssetSecurityScanStatus"]; + metadata: components["schemas"]["JsonElement"]; + /** Format: date-time */ + createdAt: string; + /** Format: date-time */ + updatedAt: null | string; + }; + ContentAssetSecurityScanEventItem: { + /** Format: uuid */ + id: string; + /** Format: uuid */ + assetId: null | string; + provider: string; + scanStatus: components["schemas"]["AssetSecurityScanStatus"]; + riskLevel: components["schemas"]["AssetSecurityRiskLevel"]; + issueCodes: string[]; + details: components["schemas"]["JsonElement"]; + /** Format: date-time */ + createdAt: string; + }; + ContentAssetType: number; + ContentEntryCatalogItem: { + /** Format: uuid */ + id: string; + /** Format: uuid */ + regionId: null | string; + legacyId: null | string; + entryKey: string; + name: string; + entryType: components["schemas"]["ContentEntryType"]; + icon: null | string; + route: null | string; + description: null | string; + visibility: components["schemas"]["ContentVisibility"]; + accessRules: components["schemas"]["JsonElement"]; + layoutConfig: components["schemas"]["JsonElement"]; + /** Format: int32 */ + order: number | string; + }; + ContentEntryManagementItem: { + /** Format: uuid */ + id: string; + /** Format: uuid */ + regionId: null | string; + legacyId: null | string; + entryKey: string; + name: string; + entryType: components["schemas"]["ContentEntryType"]; + icon: null | string; + route: null | string; + description: null | string; + visibility: components["schemas"]["ContentVisibility"]; + accessRules: components["schemas"]["JsonElement"]; + layoutConfig: components["schemas"]["JsonElement"]; + /** Format: int32 */ + order: number | string; + isActive: boolean; + /** Format: date-time */ + createdAt: string; + /** Format: date-time */ + updatedAt: null | string; + }; + ContentEntryType: number; + ContentImportIssueModel: { + /** Format: uuid */ + id: string; + /** Format: uuid */ + jobId: string; + /** Format: uuid */ + itemId: null | string; + /** Format: int32 */ + rowNo: null | number | string; + severity: components["schemas"]["ImportIssueSeverity"]; + code: string; + fieldPath: null | string; + message: string; + details: components["schemas"]["JsonElement"]; + }; + ContentImportItemModel: { + /** Format: uuid */ + id: string; + /** Format: uuid */ + jobId: string; + /** Format: int32 */ + rowNo: number | string; + externalId: null | string; + status: components["schemas"]["ContentImportItemStatus"]; + targetType: null | string; + /** Format: uuid */ + targetId: null | string; + sourcePayload: components["schemas"]["JsonElement"]; + normalizedPayload: components["schemas"]["JsonElement"]; + contentHash: null | string; + /** Format: int32 */ + issuesCount: number | string; + }; + ContentImportItemStatus: number; + ContentImportJobDetail: { + job: components["schemas"]["ContentImportJobItem"]; + items: components["schemas"]["ContentImportItemModel"][]; + issues: components["schemas"]["ContentImportIssueModel"][]; + }; + ContentImportJobItem: { + /** Format: uuid */ + id: string; + /** Format: uuid */ + targetRegionId: null | string; + /** Format: uuid */ + targetSubjectId: null | string; + /** Format: uuid */ + targetCategoryId: null | string; + /** Format: uuid */ + targetContentNodeId: null | string; + /** Format: uuid */ + targetQuestionBankId: null | string; + importType: components["schemas"]["ContentImportType"]; + sourceFormat: components["schemas"]["ImportSourceFormat"]; + status: components["schemas"]["ContentImportStatus"]; + sourceName: null | string; + sourceHash: null | string; + dryRun: boolean; + /** Format: int32 */ + totalCount: number | string; + /** Format: int32 */ + validCount: number | string; + /** Format: int32 */ + errorCount: number | string; + /** Format: int32 */ + warningCount: number | string; + /** Format: int32 */ + insertedCount: number | string; + /** Format: int32 */ + updatedCount: number | string; + /** Format: int32 */ + skippedCount: number | string; + summary: components["schemas"]["JsonElement"]; + errorMessage: null | string; + /** Format: date-time */ + startedAt: null | string; + /** Format: date-time */ + finishedAt: null | string; + /** Format: date-time */ + createdAt: string; + /** Format: date-time */ + updatedAt: null | string; + }; + ContentImportStatus: number; + ContentImportType: number; + ContentManagementResultOfContentAssetManagementItem: { + item: null | components["schemas"]["ContentAssetManagementItem"]; + }; + ContentManagementResultOfContentEntryManagementItem: { + item: null | components["schemas"]["ContentEntryManagementItem"]; + }; + ContentManagementResultOfContentNodeManagementItem: { + item: null | components["schemas"]["ContentNodeManagementItem"]; + }; + ContentManagementResultOfHandbookChapter: { + item: null | components["schemas"]["HandbookChapter"]; + }; + ContentManagementResultOfHandbookEntry: { + item: null | components["schemas"]["HandbookEntry"]; + }; + ContentManagementResultOfHandbookSubject: { + item: null | components["schemas"]["HandbookSubject"]; + }; + ContentManagementResultOfMajor: { + item: null | components["schemas"]["Major"]; + }; + ContentManagementResultOfOperationContentItem: { + item: null | components["schemas"]["OperationContentItem"]; + }; + ContentManagementResultOfPracticeBlueprintManagementItem: { + item: null | components["schemas"]["PracticeBlueprintManagementItem"]; + }; + ContentManagementResultOfQuestionCollectionManagementItem: { + item: null | components["schemas"]["QuestionCollectionManagementItem"]; + }; + ContentManagementResultOfQuestionManagementItem: { + item: null | components["schemas"]["QuestionManagementItem"]; + }; + ContentManagementResultOfQuestionVideoManagementItem: { + item: null | components["schemas"]["QuestionVideoManagementItem"]; + }; + ContentManagementResultOfSchool: { + item: null | components["schemas"]["School"]; + }; + ContentManagementResultOfScorelineField: { + item: null | components["schemas"]["ScorelineField"]; + }; + ContentManagementResultOfScorelineRecord: { + item: null | components["schemas"]["ScorelineRecord"]; + }; + ContentManagementResultOfTenantAdminBadgeGrantItem: { + item: null | components["schemas"]["TenantAdminBadgeGrantItem"]; + }; + ContentManagementResultOfTenantAdminBadgeItem: { + item: null | components["schemas"]["TenantAdminBadgeItem"]; + }; + ContentManagementResultOfTenantAdminClassItem: { + item: null | components["schemas"]["TenantAdminClassItem"]; + }; + ContentManagementResultOfTenantAdminClassMemberItem: { + item: null | components["schemas"]["TenantAdminClassMemberItem"]; + }; + ContentManagementResultOfTenantAdminFeedbackItem: { + item: null | components["schemas"]["TenantAdminFeedbackItem"]; + }; + ContentManagementResultOfTenantAdminMemberItem: { + item: null | components["schemas"]["TenantAdminMemberItem"]; + }; + ContentManagementResultOfTenantAdminNotificationItem: { + item: null | components["schemas"]["TenantAdminNotificationItem"]; + }; + ContentManagementResultOfTenantAdminStudentFollowupItem: { + item: null | components["schemas"]["TenantAdminStudentFollowupItem"]; + }; + ContentManagementResultOfTenantAdminStudentItem: { + item: null | components["schemas"]["TenantAdminStudentItem"]; + }; + ContentManagementResultOfTenantAdminStudentNoteItem: { + item: null | components["schemas"]["TenantAdminStudentNoteItem"]; + }; + ContentManagementResultOfTenantAdminStudentStatusItem: { + item: null | components["schemas"]["TenantAdminStudentStatusItem"]; + }; + ContentManagementResultOfTenantBrandingItem: { + item: null | components["schemas"]["TenantBrandingItem"]; + }; + ContentManagementResultOfTenantDomainItem: { + item: null | components["schemas"]["TenantDomainItem"]; + }; + ContentManagementResultOfTenantIdentityProviderItem: { + item: null | components["schemas"]["TenantIdentityProviderItem"]; + }; + ContentManagementResultOfTenantSettingsItem: { + item: null | components["schemas"]["TenantSettingsItem"]; + }; + ContentManagementResultOfTenantSupervisionRuleItem: { + item: null | components["schemas"]["TenantSupervisionRuleItem"]; + }; + ContentManagementResultOfTenantThemeItem: { + item: null | components["schemas"]["TenantThemeItem"]; + }; + ContentManagementResultOfVideoManagementItem: { + item: null | components["schemas"]["VideoManagementItem"]; + }; + ContentManagementResultOfVocabularyUnit: { + item: null | components["schemas"]["VocabularyUnit"]; + }; + ContentManagementResultOfVocabularyWord: { + item: null | components["schemas"]["VocabularyWord"]; + }; + ContentMarkerType: number; + ContentNodeCatalogItem: { + /** Format: uuid */ + id: string; + /** Format: uuid */ + entryId: string; + /** Format: uuid */ + regionId: null | string; + /** Format: uuid */ + parentId: null | string; + legacyId: null | string; + nodeKey: null | string; + name: string; + nodeType: components["schemas"]["ContentNodeType"]; + markerType: null | components["schemas"]["ContentMarkerType"]; + markerConfig: components["schemas"]["JsonElement"]; + path: null | string; + /** Format: int32 */ + depth: number | string; + /** Format: int32 */ + order: number | string; + isSelectable: boolean; + isLeaf: boolean; + accessRules: components["schemas"]["JsonElement"]; + metadata: components["schemas"]["JsonElement"]; + }; + ContentNodeManagementItem: { + /** Format: uuid */ + id: string; + /** Format: uuid */ + entryId: string; + /** Format: uuid */ + regionId: null | string; + /** Format: uuid */ + parentId: null | string; + legacyId: null | string; + nodeKey: null | string; + name: string; + nodeType: components["schemas"]["ContentNodeType"]; + markerType: null | components["schemas"]["ContentMarkerType"]; + markerConfig: components["schemas"]["JsonElement"]; + path: null | string; + /** Format: int32 */ + depth: number | string; + /** Format: int32 */ + order: number | string; + isActive: boolean; + isSelectable: boolean; + isLeaf: boolean; + accessRules: components["schemas"]["JsonElement"]; + metadata: components["schemas"]["JsonElement"]; + /** Format: date-time */ + createdAt: string; + /** Format: date-time */ + updatedAt: null | string; + }; + ContentNodeType: number; + ContentStatus: number; + ContentVisibility: number; + Coupon: { + /** Format: uuid */ + planId?: null | string; + legacyId?: null | string; + code?: string; + discountType?: null | components["schemas"]["DiscountType"]; + /** Format: double */ + discountValue?: null | number | string; + /** Format: date-time */ + validFrom?: null | string; + /** Format: date-time */ + validTo?: null | string; + /** Format: int32 */ + maxUses?: null | number | string; + /** Format: int32 */ + usedCount?: number | string; + source?: null | string; + remark?: null | string; + /** Format: date-time */ + createdAt?: string; + /** Format: date-time */ + updatedAt?: string; + /** Format: uuid */ + tenantId?: string; + /** Format: uuid */ + id?: string; + }; + CouponRedemption: { + /** Format: uuid */ + couponId?: null | string; + /** Format: uuid */ + userId?: null | string; + /** Format: uuid */ + planId?: null | string; + /** Format: uuid */ + orderId?: null | string; + /** Format: uuid */ + regionId?: null | string; + legacyId?: null | string; + couponCode?: null | string; + status?: components["schemas"]["CouponRedemptionStatus"]; + /** Format: int32 */ + discountAppliedCents?: null | number | string; + source?: null | string; + remark?: null | string; + /** Format: date-time */ + claimedAt?: null | string; + /** Format: date-time */ + usedAt?: null | string; + /** Format: date-time */ + createdAt?: string; + /** Format: date-time */ + updatedAt?: string; + /** Format: uuid */ + tenantId?: string; + /** Format: uuid */ + id?: string; + }; + CouponRedemptionStatus: number; + /** @description 创建调账凭证请求 DTO。 */ + CreateAdjustmentVoucherDto: { + /** + * Format: uuid + * @description 工单 ID。 + */ + issueId?: null | string; + /** + * Format: uuid + * @description 批次 ID。 + */ + batchId?: null | string; + /** + * Format: uuid + * @description 兑换项 ID。 + */ + itemId?: null | string; + /** + * Format: uuid + * @description 订单 ID。 + */ + orderId?: null | string; + /** + * Format: uuid + * @description 支付记录 ID。 + */ + paymentId?: null | string; + /** + * Format: uuid + * @description 退款申请 ID。 + */ + refundRequestId?: null | string; + /** @description 方向。 */ + direction?: components["schemas"]["CommerceAdjustmentDirection"]; + /** + * Format: int32 + * @description 金额,单位为分。 + */ + amountCents?: number | string; + /** @description 币种。 */ + currency?: null | string; + /** @description 原因。 */ + reason: string; + /** @description 证明资产键。 */ + proofAssetKey?: null | string; + /** @description 扩展元数据。 */ + metadata?: components["schemas"]["JsonElement"]; + }; + /** @description 创建租户后台任务请求。 */ + CreateBackgroundJobDto: { + /** @description 任务类型。 */ + jobType?: string; + /** @description 任务载荷。 */ + payload?: components["schemas"]["JsonElement"]; + /** + * Format: date-time + * @description 计划运行时间。 + */ + runAfter?: null | string; + /** + * Format: int32 + * @description 最大重试次数。 + */ + maxRetries?: number | string; + }; + /** @description 创建编码批次请求 DTO。 */ + CreateCodeBatchDto: { + /** @description 名称。 */ + name: string; + /** + * Format: int32 + * @description 总数量。 + */ + totalCount?: number | string; + /** + * Format: int32 + * @description 天数。 + */ + days?: number | string; + /** + * Format: uuid + * @description 地区 ID。 + */ + regionId?: null | string; + /** @description 售卖类型。 */ + saleType?: null | string; + /** @description 渠道。 */ + channel?: null | string; + /** + * Format: int32 + * @description 默认单价,单位为分。 + */ + defaultUnitPriceCents?: null | number | string; + /** + * Format: int32 + * @description 成本价,单位为分。 + */ + costPriceCents?: null | number | string; + /** @description 备注。 */ + remark?: null | string; + }; + /** @description 创建交易订单请求 DTO。 */ + CreateCommerceOrderDto: { + /** + * Format: uuid + * @description 套餐 ID。 + */ + planId: string; + /** + * Format: int32 + * @description 数量。 + */ + quantity?: number | string; + /** @description 支付方式。 */ + payMethod?: null | string; + /** @description 支付渠道。 */ + payProvider?: null | string; + /** + * Format: uuid + * @description 地区 ID。 + */ + regionId?: null | string; + /** @description 优惠券码。 */ + couponCode?: null | string; + /** + * Format: uuid + * @description 优惠券领取记录 ID。 + */ + couponRedemptionId?: null | string; + }; + /** @description 创建交易支付请求 DTO。 */ + CreateCommercePaymentDto: { + /** @description 订单号。 */ + orderNo: string; + /** @description 服务提供方。 */ + provider: string; + /** @description 方式。 */ + method: string; + /** @description 微信或支付渠道 openid。 */ + openId?: null | string; + /** @description 支付完成返回地址。 */ + returnUrl?: null | string; + /** @description 支付取消返回地址。 */ + quitUrl?: null | string; + }; + /** @description 创建佣金结算凭证请求。 */ + CreateCommissionProofDto: { + /** + * Format: uuid + * @description 结算单 ID。 + */ + settlementId: string; + /** @description 凭证类型。 */ + proofType?: null | string; + /** @description 标题。 */ + title?: null | string; + /** @description 说明。 */ + description?: null | string; + /** + * Format: uuid + * @description 资产 ID。 + */ + assetId?: null | string; + /** @description 外部链接。 */ + externalUrl?: null | string; + /** + * Format: int32 + * @description 金额,单位为分。 + */ + amountCents?: null | number | string; + /** @description 支付方式。 */ + paymentMethod?: null | string; + /** @description 收款账号。 */ + paymentAccount?: null | string; + /** + * Format: date-time + * @description 支付时间。 + */ + paidAt?: null | string; + metadata?: null | components["schemas"]["JsonElement"]; + }; + /** @description 创建平台账务订单请求 DTO。 */ + CreatePlatformBillingOrderDto: { + /** Format: uuid */ + quoteId: string; + idempotencyKey: string; + }; + /** @description 创建平台账务支付请求 DTO。 */ + CreatePlatformBillingPaymentDto: { + provider: string; + method: string; + idempotencyKey: string; + openId: null | string; + returnUrl: null | string; + quitUrl: null | string; + }; + /** @description 创建平台账务报价请求 DTO。 */ + CreatePlatformBillingQuoteDto: { + /** Format: uuid */ + baseOfferingVersionId: string; + addOnOfferingVersionIds: null | string[]; + purpose: components["schemas"]["PlatformBillingOrderPurpose"]; + idempotencyKey: string; + }; + /** @description 创建平台租户请求 DTO。 */ + CreatePlatformTenantDto: { + /** @description 短编码。 */ + slug: string; + /** @description 名称。 */ + name: string; + /** @description 法定名称。 */ + legalName?: null | string; + /** @description 状态。 */ + status?: components["schemas"]["TenantStatus"]; + /** @description 账务状态。 */ + billingStatus?: components["schemas"]["BillingStatus"]; + /** @description 扩展元数据。 */ + metadata?: components["schemas"]["JsonElement"]; + /** @description 租户负责人邮箱。 */ + ownerEmail?: null | string; + /** @description 租户负责人手机号。 */ + ownerPhone?: null | string; + /** @description 租户负责人姓名。 */ + ownerName: string; + /** @description 临时密码。 */ + temporaryPassword: string; + }; + /** @description 创建积分兑换订单请求 DTO。 */ + CreatePointExchangeOrderDto: { + /** + * Format: uuid + * @description 兑换项 ID。 + */ + itemId: string; + }; + /** @description 创建练习会话请求 DTO。 */ + CreatePracticeSessionDto: { + /** @description 模式。 */ + mode?: null | string; + /** @description 目标类型。 */ + targetType?: null | string; + /** + * Format: uuid + * @description 目标 ID。 + */ + targetId?: null | string; + /** + * Format: uuid + * @description 练习蓝图 ID。 + */ + blueprintId?: null | string; + /** + * Format: uuid + * @description 题集 ID。 + */ + collectionId?: null | string; + /** + * Format: uuid + * @description 内容入口 ID。 + */ + entryId?: null | string; + /** + * Format: uuid + * @description 内容节点 ID。 + */ + contentNodeId?: null | string; + /** + * Format: int32 + * @description 题目数量上限。 + */ + questionLimit?: null | number | string; + /** + * Format: int32 + * @description 时长,单位为分钟。 + */ + durationMinutes?: null | number | string; + /** + * Format: double + * @description 总分。 + */ + totalScore?: null | number | string; + /** @description 扩展元数据。 */ + metadata?: components["schemas"]["JsonElement"]; + }; + /** @description 创建对账批次请求 DTO。 */ + CreateReconciliationBatchDto: { + /** @description 服务提供方。 */ + provider: string; + /** + * Format: date + * @description 账单日期。 + */ + billDate?: string; + /** @description 账单类型。 */ + billType?: components["schemas"]["ReconciliationBillType"]; + /** @description 来源。 */ + source?: components["schemas"]["ReconciliationSource"]; + /** @description 来源名称。 */ + sourceName?: null | string; + /** @description 来源哈希。 */ + sourceHash: string; + /** @description 扩展元数据。 */ + metadata?: components["schemas"]["JsonElement"]; + }; + /** @description 创建退款Request请求 DTO。 */ + CreateRefundRequestDto: { + /** + * Format: uuid + * @description 订单 ID。 + */ + orderId: string; + /** + * Format: uuid + * @description 支付记录 ID。 + */ + paymentId?: null | string; + /** + * Format: int32 + * @description 金额,单位为分。 + */ + amountCents?: number | string; + /** @description 原因。 */ + reason?: null | string; + /** @description 权益动作。 */ + entitlementAction?: components["schemas"]["RefundEntitlementAction"]; + /** @description 扩展元数据。 */ + metadata?: components["schemas"]["JsonElement"]; + }; + /** @description 创建分类节点请求 DTO。 */ + CreateTaxonomyNodeDto: { + /** + * Format: uuid + * @description 父节点 ID。 + */ + parentId?: null | string; + parentSource?: null | components["schemas"]["QuestionSource"]; + /** @description 节点Type。 */ + nodeType: components["schemas"]["TaxonomyNodeType"]; + /** @description 编码。 */ + code: string; + /** @description 名称。 */ + name: string; + /** + * Format: int32 + * @description 排序值。 + */ + sortOrder?: number | string; + /** @description 扩展元数据。 */ + metadata?: components["schemas"]["JsonElement"]; + }; + /** @description 创建租户域名请求 DTO。 */ + CreateTenantDomainDto: { + /** @description 访问域名。 */ + host: string; + /** @description 域名类型。 */ + domainType?: null | string; + /** @description 是否主域名。 */ + isPrimary?: boolean; + }; + CrmConfigItem: { + /** Format: uuid */ + id: string; + enabled: boolean; + url: null | string; + secretRef: null | string; + assignmentMode: string; + assignmentPool: components["schemas"]["JsonElement"]; + formName: null | string; + examType: null | string; + /** Format: int32 */ + timeoutSeconds: null | number | string; + /** Format: int32 */ + delaySeconds: null | number | string; + /** Format: date-time */ + updatedAt: string; + }; + CrmDeadLetterResult: { + summary: components["schemas"]["CrmDeadLetterSummary"]; + items: components["schemas"]["CrmQueueItem"][]; + }; + CrmDeadLetterSummary: { + /** Format: int32 */ + failed: number | string; + /** Format: int32 */ + discarded: number | string; + /** Format: int32 */ + total: number | string; + /** Format: date-time */ + oldestOpenAt: null | string; + }; + CrmListOfCrmQueueItem: { + items: components["schemas"]["CrmQueueItem"][]; + }; + CrmListOfCrmQueueLogItem: { + items: components["schemas"]["CrmQueueLogItem"][]; + }; + /** @description CRM队列Action请求 DTO。 */ + CrmQueueActionDto: { + /** + * Format: uuid + * @description 队列任务 ID。 + */ + queueId: string; + /** @description 操作。 */ + action?: null | string; + /** @description 备注。 */ + note?: null | string; + metadata?: null | components["schemas"]["JsonElement"]; + }; + CrmQueueItem: { + /** Format: uuid */ + id: string; + status: string; + /** Format: int32 */ + attempts: number | string; + leadId: null | string; + recordId: null | string; + source: null | string; + provider: null | string; + lastError: null | string; + /** Format: date-time */ + scheduledAt: null | string; + /** Format: date-time */ + nextAttemptAt: null | string; + payload: components["schemas"]["JsonElement"]; + }; + CrmQueueLogItem: { + /** Format: uuid */ + id: string; + /** Format: uuid */ + queueId: null | string; + recordId: null | string; + leadId: null | string; + /** Format: int32 */ + httpCode: null | number | string; + outcome: string; + errorMessage: null | string; + operation: null | string; + requestPayload: components["schemas"]["JsonElement"]; + responseSummary: null | string; + /** Format: date-time */ + createdAt: string; + }; + CrmQueuePreviewItem: { + /** Format: uuid */ + id: string; + status: string; + source: null | string; + }; + CrmWebhookLog: { + legacyId?: null | string; + recordId?: null | string; + leadId?: null | string; + /** Format: int32 */ + httpCode?: null | number | string; + outcome?: null | string; + errorMessage?: null | string; + requestBody?: null | string; + requestPayload?: components["schemas"]["JsonElement"]; + responseSummary?: null | string; + /** Format: date-time */ + signedAt?: null | string; + /** Format: int32 */ + attempt?: null | number | string; + /** Format: date-time */ + createdAt?: string; + /** Format: date-time */ + updatedAt?: string; + /** Format: uuid */ + tenantId?: string; + /** Format: uuid */ + id?: string; + }; + CrmWebhookQueueItem: { + legacyId?: null | string; + recordId?: null | string; + leadId?: null | string; + source?: null | string; + provider?: null | string; + status?: components["schemas"]["CrmWebhookQueueStatus"]; + /** Format: date-time */ + scheduledAt?: null | string; + /** Format: int32 */ + attempts?: number | string; + /** Format: date-time */ + nextAttemptAt?: null | string; + /** Format: date-time */ + lastAttemptAt?: null | string; + lastError?: null | string; + /** Format: int32 */ + lastHttpCode?: null | number | string; + lastResponseSummary?: null | string; + /** Format: date-time */ + sentAt?: null | string; + idempotencyKey?: null | string; + targetUrl?: null | string; + payload?: components["schemas"]["JsonElement"]; + /** Format: date-time */ + createdAt?: string; + /** Format: date-time */ + updatedAt?: string; + /** Format: uuid */ + tenantId?: string; + /** Format: uuid */ + id?: string; + }; + CrmWebhookQueueStatus: number; + CurrentEntitlementItem: { + isActive: boolean; + entitlementType: string; + /** Format: date-time */ + startsAt: null | string; + /** Format: date-time */ + expiresAt: null | string; + status: string; + /** Format: int32 */ + daysLeft: null | number | string; + }; + /** @description 当前请求租户和当前用户在该租户内的权限摘要。 */ + CurrentTenantResponse: { + /** + * Format: uuid + * @description 租户 ID。 + */ + tenantId: string; + /** @description 租户名称。 */ + tenantName: string; + /** @description 租户编码。 */ + tenantSlug: string; + /** @description 租户状态。 */ + status: components["schemas"]["TenantStatus"]; + /** @description 当前用户在租户内的角色。 */ + role: components["schemas"]["TenantRole"]; + }; + /** @description 管理侧知识手册章节写入请求。 */ + DirectHandbookChapterDto: { + /** + * Format: uuid + * @description ID。 + */ + id?: null | string; + /** + * Format: uuid + * @description 科目 ID。 + */ + subjectId?: null | string; + /** + * Format: uuid + * @description 内容入口 ID。 + */ + entryId?: null | string; + /** + * Format: uuid + * @description 内容节点 ID。 + */ + contentNodeId?: null | string; + /** @description 历史系统 ID。 */ + legacyId?: null | string; + /** @description 名称。 */ + name: string; + /** @description 说明。 */ + description?: null | string; + /** + * Format: int32 + * @description 显示顺序。 + */ + order?: null | number | string; + /** @description 是否启用。 */ + isActive?: null | boolean; + /** @description 扩展元数据。 */ + metadata?: components["schemas"]["JsonElement"]; + }; + /** @description 管理侧知识手册条目写入请求。 */ + DirectHandbookEntryDto: { + /** + * Format: uuid + * @description ID。 + */ + id?: null | string; + /** + * Format: uuid + * @description 章节 ID。 + */ + chapterId?: null | string; + /** + * Format: uuid + * @description 内容入口 ID。 + */ + entryId?: null | string; + /** + * Format: uuid + * @description 内容节点 ID。 + */ + contentNodeId?: null | string; + /** @description 历史系统 ID。 */ + legacyId?: null | string; + /** @description 标题。 */ + title: string; + /** @description 摘要。 */ + summary?: null | string; + /** @description 内容。 */ + content?: null | string; + /** @description 标签列表。 */ + tags?: components["schemas"]["JsonElement"]; + /** + * Format: int32 + * @description 显示顺序。 + */ + order?: null | number | string; + /** @description 是否启用。 */ + isActive?: null | boolean; + /** @description 扩展元数据。 */ + metadata?: components["schemas"]["JsonElement"]; + }; + /** @description 管理侧知识手册科目写入请求。 */ + DirectHandbookSubjectDto: { + /** + * Format: uuid + * @description ID。 + */ + id?: null | string; + /** + * Format: uuid + * @description 地区 ID。 + */ + regionId?: null | string; + /** + * Format: uuid + * @description 院校 ID。 + */ + schoolId?: null | string; + /** + * Format: uuid + * @description 专业 ID。 + */ + majorId?: null | string; + /** + * Format: uuid + * @description 内容入口 ID。 + */ + entryId?: null | string; + /** + * Format: uuid + * @description 内容节点 ID。 + */ + contentNodeId?: null | string; + /** @description 历史系统 ID。 */ + legacyId?: null | string; + /** @description 名称。 */ + name: string; + /** @description 类型。 */ + type?: null | string; + /** @description 图标。 */ + icon?: null | string; + /** @description 颜色。 */ + color?: null | string; + /** @description 说明。 */ + description?: null | string; + /** + * Format: int32 + * @description 显示顺序。 + */ + order?: null | number | string; + /** @description 是否启用。 */ + isActive?: null | boolean; + /** @description 扩展元数据。 */ + metadata?: components["schemas"]["JsonElement"]; + }; + /** @description 管理侧内容导入请求。 */ + DirectImportDto: { + /** @description 来源格式。 */ + sourceFormat?: null | string; + /** @description 来源名称。 */ + sourceName?: null | string; + /** + * Format: uuid + * @description 地区 ID。 + */ + regionId?: null | string; + /** + * Format: uuid + * @description 内容入口 ID。 + */ + entryId?: null | string; + /** + * Format: uuid + * @description 内容节点 ID。 + */ + contentNodeId?: null | string; + /** + * Format: uuid + * @description 科目 ID。 + */ + subjectId?: null | string; + /** + * Format: uuid + * @description 分类 ID。 + */ + categoryId?: null | string; + /** + * Format: uuid + * @description 题库 ID。 + */ + questionBankId?: null | string; + /** + * Format: uuid + * @description 题集 ID。 + */ + collectionId?: null | string; + /** @description 是否异步执行。 */ + async?: null | boolean; + /** @description 数据项列表。 */ + items?: null | unknown[]; + /** @description 单元数据列表。 */ + units?: null | unknown[]; + /** @description 单词数据列表。 */ + words?: null | unknown[]; + /** @description 科目数据列表。 */ + subjects?: null | unknown[]; + /** @description 条目数据列表。 */ + entries?: null | unknown[]; + /** @description 字段数据列表。 */ + fields?: null | unknown[]; + /** @description 院校数据列表。 */ + schools?: null | unknown[]; + /** @description 专业数据列表。 */ + majors?: null | unknown[]; + /** @description 记录数据列表。 */ + records?: null | unknown[]; + /** @description 视频数据列表。 */ + videos?: null | unknown[]; + }; + /** @description 管理侧内容导入任务查询请求。 */ + DirectImportJobDto: { + /** + * Format: uuid + * @description 任务 ID。 + */ + jobId?: string; + }; + /** @description 管理侧专业写入请求。 */ + DirectMajorDto: { + /** + * Format: uuid + * @description ID。 + */ + id?: null | string; + /** + * Format: uuid + * @description 地区 ID。 + */ + regionId?: null | string; + /** + * Format: uuid + * @description 院校 ID。 + */ + schoolId?: null | string; + /** @description 历史系统 ID。 */ + legacyId?: null | string; + /** @description 名称。 */ + name: string; + /** @description 说明。 */ + description?: null | string; + /** @description 备考建议。 */ + studyTips?: null | string; + /** + * Format: int32 + * @description 显示顺序。 + */ + order?: null | number | string; + /** @description 是否启用。 */ + isActive?: null | boolean; + }; + /** @description 管理侧运营内容写入请求。 */ + DirectOperationContentDto: { + /** + * Format: uuid + * @description ID。 + */ + id?: null | string; + /** + * Format: uuid + * @description 地区 ID。 + */ + regionId?: null | string; + /** + * Format: uuid + * @description 院校 ID。 + */ + schoolId?: null | string; + /** @description 历史系统 ID。 */ + legacyId?: null | string; + /** @description 标题。 */ + title?: null | string; + /** @description 副标题。 */ + subtitle?: null | string; + /** @description 内容。 */ + content?: null | string; + /** @description 问题。 */ + question?: null | string; + /** @description 答案。 */ + answer?: null | string; + /** @description 链接地址。 */ + link?: null | string; + /** @description 按钮文案。 */ + buttonText?: null | string; + /** @description 按钮链接。 */ + buttonLink?: null | string; + /** @description 背景颜色。 */ + backgroundColor?: null | string; + /** @description 边框颜色。 */ + borderColor?: null | string; + /** @description 考试名称。 */ + examName?: null | string; + /** + * Format: date-time + * @description 考试时间。 + */ + examAt?: null | string; + /** @description 考试类型。 */ + examType?: null | string; + /** @description 说明。 */ + description?: null | string; + /** + * Format: int32 + * @description 显示顺序。 + */ + order?: null | number | string; + /** @description 是否启用。 */ + isActive?: null | boolean; + /** @description 扩展元数据。 */ + metadata?: components["schemas"]["JsonElement"]; + }; + /** @description 管理侧题目视频绑定请求。 */ + DirectQuestionVideoDto: { + /** + * Format: uuid + * @description 题目 ID。 + */ + questionId?: string; + /** + * Format: uuid + * @description 视频 ID。 + */ + videoId?: string; + /** @description 历史系统 ID。 */ + legacyId?: null | string; + /** @description 视频类型。 */ + videoType?: null | string; + /** + * Format: int32 + * @description 显示顺序。 + */ + order?: null | number | string; + /** @description 扩展元数据。 */ + metadata?: components["schemas"]["JsonElement"]; + }; + /** @description 管理侧题目写入请求。 */ + DirectQuestionWriteDto: { + /** + * Format: uuid + * @description 题目 ID。 + */ + questionId?: null | string; + /** + * Format: uuid + * @description 题库 ID。 + */ + questionBankId?: null | string; + /** + * Format: uuid + * @description 科目 ID。 + */ + subjectId?: null | string; + /** + * Format: uuid + * @description 分类 ID。 + */ + categoryId?: null | string; + /** + * Format: uuid + * @description 节点 ID。 + */ + nodeId?: null | string; + /** + * Format: uuid + * @description 内容入口 ID。 + */ + entryId?: null | string; + /** + * Format: uuid + * @description 内容节点 ID。 + */ + contentNodeId?: null | string; + /** + * Format: uuid + * @description 主题集 ID。 + */ + primaryCollectionId?: null | string; + /** @description 历史系统 ID。 */ + legacyId?: null | string; + /** @description 类型。 */ + type?: null | string; + /** @description 类型显示名。 */ + typeLabel?: null | string; + /** + * Format: int32 + * @description 难度。 + */ + difficulty?: null | number | string; + /** @description 标签列表。 */ + tags?: components["schemas"]["JsonElement"]; + /** @description 内容。 */ + content?: null | string; + /** @description 选项配置。 */ + options?: components["schemas"]["JsonElement"]; + /** + * Format: int32 + * @description 正确选项索引。 + */ + correctOptionIndex?: null | number | string; + /** @description 正确选项索引列表。 */ + correctOptionIndices?: components["schemas"]["JsonElement"]; + /** @description 文字答案。 */ + answerText?: null | string; + /** @description 解析。 */ + explanation?: null | string; + /** @description 子题列表。 */ + subQuestions?: components["schemas"]["JsonElement"]; + /** @description 代码语言。 */ + codeLang?: null | string; + /** @description 代码模板。 */ + codeTemplate?: null | string; + /** @description 媒体地址。 */ + mediaUrl?: null | string; + /** @description 状态。 */ + status?: null | string; + /** @description 考试标记配置。 */ + examMarkers?: components["schemas"]["JsonElement"]; + /** @description 来源哈希。 */ + sourceHash?: null | string; + /** @description 是否创建题目版本。 */ + createVersion?: null | boolean; + }; + /** @description 管理侧院校写入请求。 */ + DirectSchoolDto: { + /** + * Format: uuid + * @description ID。 + */ + id?: null | string; + /** + * Format: uuid + * @description 地区 ID。 + */ + regionId?: null | string; + /** @description 历史系统 ID。 */ + legacyId?: null | string; + /** @description 名称。 */ + name: string; + /** @description 专业考试日期。 */ + professionalExamDate?: null | string; + /** @description 扩展元数据。 */ + metadata?: components["schemas"]["JsonElement"]; + }; + /** @description 管理侧分数线字段写入请求。 */ + DirectScorelineFieldDto: { + /** + * Format: uuid + * @description ID。 + */ + id?: null | string; + /** + * Format: uuid + * @description 地区 ID。 + */ + regionId?: null | string; + /** @description 历史系统 ID。 */ + legacyId?: null | string; + /** @description 字段键。 */ + fieldKey: string; + /** @description 字段名称。 */ + fieldName: string; + /** @description 字段类型。 */ + fieldType?: null | string; + /** @description 单位。 */ + unit?: null | string; + /** @description 是否可筛选。 */ + isFilter?: null | boolean; + /** @description 是否必填。 */ + isRequired?: null | boolean; + /** @description 是否可见。 */ + isVisible?: null | boolean; + /** @description 是否参与趋势展示。 */ + isTrend?: null | boolean; + /** @description 选项配置。 */ + options?: components["schemas"]["JsonElement"]; + /** @description 占位提示。 */ + placeholder?: null | string; + /** @description 说明。 */ + description?: null | string; + /** + * Format: int32 + * @description 显示顺序。 + */ + order?: null | number | string; + }; + /** @description 管理侧分数线记录写入请求。 */ + DirectScorelineRecordDto: { + /** + * Format: uuid + * @description ID。 + */ + id?: null | string; + /** + * Format: uuid + * @description 地区 ID。 + */ + regionId?: null | string; + /** + * Format: uuid + * @description 院校 ID。 + */ + schoolId?: null | string; + /** + * Format: uuid + * @description 专业 ID。 + */ + majorId?: null | string; + /** @description 历史系统 ID。 */ + legacyId?: null | string; + /** + * Format: int32 + * @description 年份。 + */ + year?: number | string; + /** @description 院校名称。 */ + schoolName?: null | string; + /** @description 专业名称。 */ + majorName?: null | string; + /** @description 动态字段值。 */ + fieldValues?: components["schemas"]["JsonElement"]; + }; + /** @description 管理侧视频写入请求。 */ + DirectVideoDto: { + /** + * Format: uuid + * @description ID。 + */ + id?: null | string; + /** + * Format: uuid + * @description 科目 ID。 + */ + subjectId?: null | string; + /** @description 历史系统 ID。 */ + legacyId?: null | string; + /** @description 标题。 */ + title: string; + /** @description 说明。 */ + description?: null | string; + /** @description 视频地址。 */ + videoUrl?: null | string; + /** @description 缩略图地址。 */ + thumbnailUrl?: null | string; + /** + * Format: int32 + * @description 时长,单位为秒。 + */ + durationSeconds?: null | number | string; + /** @description 知识标签。 */ + knowledgeTags?: components["schemas"]["JsonElement"]; + /** @description 是否通用视频。 */ + isGeneral?: null | boolean; + /** + * Format: int32 + * @description 难度。 + */ + difficulty?: null | number | string; + /** + * Format: int32 + * @description 显示顺序。 + */ + order?: null | number | string; + /** @description 是否启用。 */ + isActive?: null | boolean; + /** @description 扩展元数据。 */ + metadata?: components["schemas"]["JsonElement"]; + }; + /** @description 管理侧词汇单元写入请求。 */ + DirectVocabularyUnitDto: { + /** + * Format: uuid + * @description ID。 + */ + id?: null | string; + /** + * Format: uuid + * @description 地区 ID。 + */ + regionId?: null | string; + /** + * Format: uuid + * @description 内容入口 ID。 + */ + entryId?: null | string; + /** + * Format: uuid + * @description 内容节点 ID。 + */ + contentNodeId?: null | string; + /** @description 历史系统 ID。 */ + legacyId?: null | string; + /** @description 名称。 */ + name: string; + /** @description 说明。 */ + description?: null | string; + /** + * Format: int32 + * @description 单词数量。 + */ + wordCount?: null | number | string; + /** + * Format: int32 + * @description 显示顺序。 + */ + order?: null | number | string; + /** @description 是否启用。 */ + isActive?: null | boolean; + /** @description 扩展元数据。 */ + metadata?: components["schemas"]["JsonElement"]; + }; + /** @description 管理侧词汇单词写入请求。 */ + DirectVocabularyWordDto: { + /** + * Format: uuid + * @description ID。 + */ + id?: null | string; + /** + * Format: uuid + * @description 单元 ID。 + */ + unitId?: null | string; + /** + * Format: uuid + * @description 内容入口 ID。 + */ + entryId?: null | string; + /** + * Format: uuid + * @description 内容节点 ID。 + */ + contentNodeId?: null | string; + /** @description 历史系统 ID。 */ + legacyId?: null | string; + /** @description 单词。 */ + word: string; + /** @description 音标。 */ + phonetic?: null | string; + /** @description 释义。 */ + meaning?: null | string; + /** @description 例句。 */ + example?: null | string; + /** @description 例句翻译。 */ + exampleTranslation?: null | string; + /** + * Format: int32 + * @description 难度。 + */ + difficulty?: null | number | string; + /** @description 标签列表。 */ + tags?: components["schemas"]["JsonElement"]; + /** + * Format: int32 + * @description 显示顺序。 + */ + order?: null | number | string; + /** @description 是否启用。 */ + isActive?: null | boolean; + /** @description 扩展元数据。 */ + metadata?: components["schemas"]["JsonElement"]; + }; + /** @description 禁用平台DunningChannel请求 DTO。 */ + DisablePlatformBillingDunningChannelDto: { + /** + * Format: uuid + * @description 通知渠道 ID。 + */ + channelId: string; + /** @description 原因。 */ + reason?: null | string; + }; + /** @description 禁用租户管理端成员请求 DTO。 */ + DisableTenantAdminMemberDto: { + /** + * Format: uuid + * @description 成员关系 ID。 + */ + membershipId: string; + }; + DiscountType: number; + ExamCountdownItem: { + /** Format: uuid */ + id: string; + legacyId: null | string; + /** Format: uuid */ + regionId: null | string; + /** Format: uuid */ + schoolId: null | string; + examName: string; + /** Format: date-time */ + examAt: null | string; + examType: null | string; + description: null | string; + metadata: components["schemas"]["JsonElement"]; + /** Format: int32 */ + order: number | string; + isActive: boolean; + /** Format: int32 */ + daysLeft: null | number | string; + }; + ExamCountdownList: { + items: components["schemas"]["ExamCountdownItem"][]; + /** Format: uuid */ + regionId: null | string; + /** Format: uuid */ + schoolId: null | string; + }; + ExamDateCatalogItem: { + /** Format: uuid */ + id: string; + legacyId: null | string; + /** Format: uuid */ + regionId: null | string; + /** Format: uuid */ + schoolId: null | string; + examName: string; + /** Format: date-time */ + examAt: null | string; + examType: null | string; + description: null | string; + metadata: components["schemas"]["JsonElement"]; + /** Format: int32 */ + order: number | string; + isActive: boolean; + /** Format: int32 */ + daysLeft: null | number | string; + }; + FaqCatalogItem: { + /** Format: uuid */ + id: string; + legacyId: null | string; + /** Format: uuid */ + regionId: null | string; + question: null | string; + answer: null | string; + /** Format: int32 */ + order: number | string; + isActive: boolean; + }; + FavoriteQuestionItem: { + /** Format: uuid */ + questionReferenceId: string; + locator: components["schemas"]["QuestionLocator"]; + /** Format: date-time */ + createdAt: string; + }; + /** @description 收藏单词请求 DTO。 */ + FavoriteWordDto: { + /** + * Format: uuid + * @description 单词 ID。 + */ + wordId: string; + /** @description 是否收藏。 */ + favorite?: null | boolean; + /** @description 备注。 */ + note?: null | string; + }; + FavoriteWordItem: { + /** Format: uuid */ + wordId: string; + note: null | string; + /** Format: date-time */ + favoritedAt: null | string; + }; + FeatureQuotaSnapshot: { + metricCode: string; + /** Format: int64 */ + usedValue: number | string; + /** Format: int64 */ + limitValue: number | string; + /** Format: int32 */ + usedPercent: number | string; + warning: boolean; + exceeded: boolean; + /** Format: date-time */ + periodStart: string; + /** Format: date-time */ + periodEnd: string; + }; + FeedbackItem: { + /** Format: uuid */ + id: string; + /** Format: uuid */ + questionId: null | string; + type: null | string; + title: null | string; + category: null | string; + description: null | string; + status: string; + priority: string; + contact: null | string; + attachments: components["schemas"]["JsonElement"]; + metadata: components["schemas"]["JsonElement"]; + /** Format: date-time */ + createdAt: string; + /** Format: date-time */ + updatedAt: string; + }; + /** @description 生成佣金结算单请求 DTO。 */ + GenerateCommissionSettlementDto: { + /** @description 开始日期,格式为 yyyy-MM-dd。 */ + startDate: string; + /** @description 结束日期,格式为 yyyy-MM-dd。 */ + endDate: string; + /** + * Format: uuid + * @description 推荐人用户 ID。 + */ + referrerUserId: string; + /** @description 状态。 */ + status?: null | string; + /** @description 备注。 */ + remark?: null | string; + metadata?: null | components["schemas"]["JsonElement"]; + }; + /** @description 授予租户管理端徽章请求 DTO。 */ + GrantTenantAdminBadgeDto: { + /** + * Format: uuid + * @description 用户 ID。 + */ + userId: string; + /** + * Format: uuid + * @description 徽章 ID。 + */ + badgeId: string; + /** @description 历史系统 ID。 */ + legacyId?: null | string; + /** @description 备注。 */ + note?: null | string; + /** + * Format: date-time + * @description 授予时间。 + */ + grantedAt?: null | string; + /** @description 扩展元数据。 */ + metadata?: components["schemas"]["JsonElement"]; + }; + HandbookChapter: { + /** Format: uuid */ + subjectId?: null | string; + /** Format: uuid */ + entryId?: null | string; + /** Format: uuid */ + contentNodeId?: null | string; + legacyId?: null | string; + name?: string; + description?: null | string; + /** Format: int32 */ + sortOrder?: number | string; + isActive?: boolean; + sourceHash?: null | string; + metadata?: components["schemas"]["JsonElement"]; + /** Format: date-time */ + createdAt?: string; + /** Format: date-time */ + updatedAt?: string; + /** Format: uuid */ + tenantId?: string; + /** Format: uuid */ + id?: string; + }; + HandbookChapterCatalogItem: { + /** Format: uuid */ + id: string; + legacyId: null | string; + /** Format: uuid */ + subjectId: null | string; + /** Format: uuid */ + entryId: null | string; + /** Format: uuid */ + contentNodeId: null | string; + name: string; + description: null | string; + /** Format: int32 */ + order: number | string; + metadata: components["schemas"]["JsonElement"]; + }; + HandbookEntry: { + /** Format: uuid */ + chapterId?: null | string; + /** Format: uuid */ + entryId?: null | string; + /** Format: uuid */ + contentNodeId?: null | string; + legacyId?: null | string; + title?: string; + summary?: null | string; + content?: null | string; + tags?: components["schemas"]["JsonElement"]; + /** Format: int32 */ + sortOrder?: number | string; + isActive?: boolean; + sourceHash?: null | string; + metadata?: components["schemas"]["JsonElement"]; + /** Format: date-time */ + createdAt?: string; + /** Format: date-time */ + updatedAt?: string; + /** Format: uuid */ + tenantId?: string; + /** Format: uuid */ + id?: string; + }; + HandbookEntryCatalogItem: { + /** Format: uuid */ + id: string; + legacyId: null | string; + /** Format: uuid */ + chapterId: null | string; + /** Format: uuid */ + entryId: null | string; + /** Format: uuid */ + contentNodeId: null | string; + title: string; + summary: null | string; + content: null | string; + tags: components["schemas"]["JsonElement"]; + /** Format: int32 */ + order: number | string; + metadata: components["schemas"]["JsonElement"]; + }; + HandbookSubject: { + /** Format: uuid */ + regionId?: null | string; + /** Format: uuid */ + schoolId?: null | string; + /** Format: uuid */ + majorId?: null | string; + /** Format: uuid */ + entryId?: null | string; + /** Format: uuid */ + contentNodeId?: null | string; + legacyId?: null | string; + name?: string; + type?: null | components["schemas"]["HandbookSubjectType"]; + icon?: null | string; + color?: null | string; + description?: null | string; + majorLegacyIds?: components["schemas"]["JsonElement"]; + /** Format: int32 */ + sortOrder?: number | string; + isActive?: boolean; + sourceHash?: null | string; + metadata?: components["schemas"]["JsonElement"]; + /** Format: date-time */ + createdAt?: string; + /** Format: date-time */ + updatedAt?: string; + /** Format: uuid */ + tenantId?: string; + /** Format: uuid */ + id?: string; + }; + HandbookSubjectCatalogItem: { + /** Format: uuid */ + id: string; + legacyId: null | string; + /** Format: uuid */ + regionId: null | string; + /** Format: uuid */ + schoolId: null | string; + /** Format: uuid */ + majorId: null | string; + /** Format: uuid */ + entryId: null | string; + /** Format: uuid */ + contentNodeId: null | string; + name: string; + type: null | components["schemas"]["HandbookSubjectType"]; + icon: null | string; + color: null | string; + description: null | string; + /** Format: int32 */ + order: number | string; + metadata: components["schemas"]["JsonElement"]; + }; + HandbookSubjectType: number; + /** @description 健康检查响应。 */ + HealthResponseDto: { + /** @description 服务状态,例如 ok。 */ + status: string; + /** @description 服务名称。 */ + service: string; + /** + * Format: date-time + * @description 检查时间。 + */ + checkedAt: string; + }; + /** @description Idempotent租户账务请求 DTO。 */ + IdempotentTenantBillingDto: { + idempotencyKey: string; + }; + ImageAssetCatalogItem: { + /** Format: uuid */ + id: string; + legacyId: null | string; + title: null | string; + category: null | string; + fileName: null | string; + isPublic: boolean; + cdnUrl: null | string; + metadata: components["schemas"]["JsonElement"]; + }; + ImportFieldMappingItem: { + importType: string; + title: string; + description: string; + fields: components["schemas"]["ImportFieldSpec"][]; + requiredFields: string[]; + }; + ImportFieldSpec: { + field: string; + label: string; + required: boolean; + aliases: string[]; + description: string; + example: components["schemas"]["JsonElement"]; + }; + ImportIssueSeverity: number; + ImportPostCheckResult: { + /** Format: uuid */ + jobId: string; + status: string; + counts: components["schemas"]["JsonElement"]; + issues: components["schemas"]["ContentImportIssueModel"][]; + }; + ImportSourceFormat: number; + ImportTemplateItem: { + importType: string; + format: string; + fileName: string; + mimeType: string; + contentBase64: string; + contentPreview: string; + fields: components["schemas"]["ImportFieldSpec"][]; + }; + JsonElement: unknown; + LearningActionResult: { + ok: boolean; + isFavorite?: null | boolean; + }; + LearningLeaderboardItem: { + /** Format: uuid */ + userId: string; + displayName: null | string; + /** Format: int32 */ + answerCount: number | string; + /** Format: int32 */ + correctCount: number | string; + /** Format: int32 */ + wrongCount: number | string; + /** Format: double */ + accuracy: number | string; + }; + LearningLeaderboardResult: { + metric: string; + period: string; + items: components["schemas"]["LearningLeaderboardItem"][]; + currentUser: null | components["schemas"]["LearningLeaderboardItem"]; + /** Format: date-time */ + generatedAt: string; + }; + LearningListOfFavoriteQuestionItem: { + items: components["schemas"]["FavoriteQuestionItem"][]; + }; + LearningListOfFavoriteWordItem: { + items: components["schemas"]["FavoriteWordItem"][]; + }; + LearningListOfLearningTrendItem: { + items: components["schemas"]["LearningTrendItem"][]; + }; + LearningListOfPracticeHistoryItem: { + items: components["schemas"]["PracticeHistoryItem"][]; + }; + LearningListOfPracticeSessionReportItem: { + items: components["schemas"]["PracticeSessionReportItem"][]; + }; + LearningListOfWordProgressItem: { + items: components["schemas"]["WordProgressItem"][]; + }; + LearningListOfWrongQuestionItem: { + items: components["schemas"]["WrongQuestionItem"][]; + }; + LearningStatsItem: { + /** Format: int32 */ + answerCount: number | string; + /** Format: int32 */ + correctCount: number | string; + /** Format: int32 */ + wrongCount: number | string; + /** Format: int32 */ + favoriteQuestionCount: number | string; + /** Format: int32 */ + favoriteWordCount: number | string; + /** Format: int32 */ + wordProgressCount: number | string; + /** Format: int32 */ + practiceSessionCount: number | string; + /** Format: int32 */ + practiceReportCount: number | string; + }; + LearningTrendItem: { + /** Format: date */ + date: string; + /** Format: int32 */ + answerCount: number | string; + /** Format: int32 */ + correctCount: number | string; + /** Format: int32 */ + wrongCount: number | string; + }; + Major: { + /** Format: uuid */ + regionId?: null | string; + /** Format: uuid */ + schoolId?: null | string; + legacyId?: null | string; + name?: string; + description?: null | string; + studyTips?: null | string; + /** Format: int32 */ + sortOrder?: number | string; + isActive?: boolean; + /** Format: date-time */ + createdAt?: string; + /** Format: date-time */ + updatedAt?: string; + /** Format: uuid */ + tenantId?: string; + /** Format: uuid */ + id?: string; + }; + MajorCatalogItem: { + /** Format: uuid */ + id: string; + legacyId: null | string; + /** Format: uuid */ + regionId: null | string; + /** Format: uuid */ + schoolId: null | string; + name: string; + description: null | string; + studyTips: null | string; + /** Format: int32 */ + order: number | string; + }; + /** @description 人工绑定推荐请求 DTO。 */ + ManualBindReferralDto: { + /** + * Format: uuid + * @description 学生用户 ID。 + */ + studentUserId: string; + /** + * Format: uuid + * @description 推荐人用户 ID。 + */ + referrerUserId: string; + /** @description 来源。 */ + source?: null | string; + /** @description 是否强制执行。 */ + force?: boolean; + metadata?: null | components["schemas"]["JsonElement"]; + }; + MembershipStatus: number; + /** @description 当前用户基础信息和租户成员摘要。 */ + MeResponse: { + /** + * Format: uuid + * @description 用户 ID。 + */ + userId: string; + /** @description 手机号。 */ + phone: null | string; + /** @description 邮箱。 */ + email: null | string; + /** @description 用户显示名称。 */ + name: null | string; + /** @description 当前用户拥有的活跃租户成员列表。 */ + tenants: components["schemas"]["TenantMembershipResponse"][]; + }; + ModuleNodeCatalogItem: { + /** Format: uuid */ + id: string; + legacyId: null | string; + /** Format: uuid */ + regionId: null | string; + /** Format: uuid */ + moduleId: null | string; + /** Format: uuid */ + parentId: null | string; + legacyParentId: null | string; + type: components["schemas"]["ModuleNodeType"]; + name: string; + path: null | string; + /** Format: int32 */ + order: number | string; + metadata: components["schemas"]["JsonElement"]; + }; + ModuleNodeType: number; + NotificationSeverity: number; + NotificationStatus: number; + /** @description 通知状态请求 DTO。 */ + NotificationStatusDto: { + /** @description 通知 ID 列表。 */ + notificationIds: string[]; + /** @description 状态。 */ + status?: null | string; + }; + /** @description O认证编码请求 DTO。 */ + OAuthCodeDto: { + realm: null | components["schemas"]["AuthRealm"]; + /** @description 租户编码。 */ + tenantCode?: null | string; + /** @description 编码。 */ + code: string; + /** @description 公开用户资料。 */ + profile?: null | Record; + /** @description 语言。 */ + lang?: null | string; + }; + ObjectStorageMetadata: { + provider: string; + bucket: null | string; + objectKey: null | string; + exists: boolean; + /** Format: int64 */ + sizeBytes: null | number | string; + mimeType: null | string; + checksumSha256: null | string; + eTag: null | string; + lastModified: null | string; + rawHeaders: { + [key: string]: string; + }; + verificationSource: string; + }; + ObjectStorageSignedUrl: { + provider: string; + bucket: null | string; + objectKey: null | string; + method: string; + /** Format: uri */ + url: string; + headers: { + [key: string]: string; + }; + /** Format: date-time */ + expiresAt: string; + expiresIn: string; + signatureMode: string; + }; + OperationContentItem: { + /** Format: uuid */ + id: string; + kind: string; + /** Format: uuid */ + regionId: null | string; + /** Format: uuid */ + schoolId: null | string; + legacyId: null | string; + title: null | string; + content: null | string; + question: null | string; + answer: null | string; + /** Format: date-time */ + examAt: null | string; + examType: null | string; + /** Format: int32 */ + order: number | string; + isActive: boolean; + metadata: components["schemas"]["JsonElement"]; + }; + /** @description PasswordLogin请求 DTO。 */ + PasswordLoginDto: { + realm: null | components["schemas"]["AuthRealm"]; + /** @description 租户编码。 */ + tenantCode?: null | string; + /** @description 账号标识。 */ + identifier?: null | string; + /** @description 兼容手机号字段;新客户端应使用 identifier。 */ + phone?: null | string; + /** @description 密码。 */ + password: string; + }; + PaymentNotificationProcessResult: { + provider: string; + eventId: string; + orderNo: string; + status: string; + idempotent: boolean; + }; + PlatformAlertSeverity: number; + PlatformAuditAlert: { + /** Format: uuid */ + ruleId?: string; + /** Format: uuid */ + auditLogId?: string; + /** Format: uuid */ + tenantId?: null | string; + /** Format: uuid */ + acknowledgedBy?: null | string; + /** Format: uuid */ + resolvedBy?: null | string; + severity?: components["schemas"]["PlatformAlertSeverity"]; + status?: components["schemas"]["PlatformAuditAlertStatus"]; + action?: string; + targetType?: null | string; + targetId?: null | string; + title?: string; + summary?: null | string; + details?: components["schemas"]["JsonElement"]; + /** Format: date-time */ + firstSeenAt?: string; + /** Format: date-time */ + lastSeenAt?: string; + /** Format: date-time */ + acknowledgedAt?: null | string; + /** Format: date-time */ + resolvedAt?: null | string; + resolutionNote?: null | string; + /** Format: date-time */ + createdAt?: string; + /** Format: date-time */ + updatedAt?: string; + /** Format: uuid */ + id?: string; + }; + PlatformAuditAlertList: { + items: components["schemas"]["PlatformAuditAlert"][]; + }; + PlatformAuditAlertStatus: number; + PlatformAuditLogItem: { + /** Format: uuid */ + id: string; + /** Format: uuid */ + tenantId: null | string; + /** Format: uuid */ + actorUserId: null | string; + action: string; + targetType: null | string; + targetId: null | string; + details: components["schemas"]["JsonElement"]; + ipAddress: null | string; + userAgent: null | string; + /** Format: date-time */ + createdAt: string; + }; + PlatformAuditLogList: { + items: components["schemas"]["PlatformAuditLogItem"][]; + }; + PlatformBillingCycle: number; + PlatformBillingDunningChannelItem: { + /** Format: uuid */ + id: string; + channelCode: string; + name: string; + description: null | string; + enabled: boolean; + provider: components["schemas"]["PlatformBillingDunningProvider"]; + webhookUrlMasked: string; + secretRef: null | string; + reminderTypes: string[]; + reminderChannels: string[]; + /** Format: int32 */ + minReminderLevel: number | string; + tenantIds: string[]; + /** Format: int32 */ + timeoutSeconds: number | string; + metadata: components["schemas"]["JsonElement"]; + /** Format: date-time */ + createdAt: string; + /** Format: date-time */ + updatedAt: string; + }; + PlatformBillingDunningChannelList: { + items: components["schemas"]["PlatformBillingDunningChannelItem"][]; + }; + PlatformBillingDunningEventItem: { + /** Format: uuid */ + id: string; + /** Format: uuid */ + tenantId: string; + /** Format: uuid */ + channelId: string; + /** Format: uuid */ + reminderId: string; + /** Format: uuid */ + invoiceId: string; + provider: components["schemas"]["PlatformBillingDunningProvider"]; + status: components["schemas"]["PlatformBillingDunningNotificationStatus"]; + /** Format: int32 */ + attempts: number | string; + /** Format: date-time */ + scheduledAt: string; + /** Format: date-time */ + nextAttemptAt: null | string; + /** Format: date-time */ + lastAttemptAt: null | string; + /** Format: date-time */ + sentAt: null | string; + lastError: null | string; + /** Format: int32 */ + lastHttpCode: null | number | string; + lastResponseSummary: null | string; + requestPayload: components["schemas"]["JsonElement"]; + metadata: components["schemas"]["JsonElement"]; + /** Format: date-time */ + createdAt: string; + /** Format: date-time */ + updatedAt: string; + }; + PlatformBillingDunningEventList: { + items: components["schemas"]["PlatformBillingDunningEventItem"][]; + }; + PlatformBillingDunningNotificationStatus: number; + PlatformBillingDunningProvider: number; + PlatformBillingInvoice: { + /** Format: uuid */ + orderId?: null | string; + invoiceNo?: string; + status?: components["schemas"]["PlatformBillingInvoiceStatus"]; + /** Format: int32 */ + totalAmountCents?: number | string; + currency?: string; + /** Format: date */ + dueDate?: null | string; + /** Format: date-time */ + issuedAt?: null | string; + /** Format: date-time */ + paidAt?: null | string; + billingProfileSnapshot?: components["schemas"]["JsonElement"]; + /** Format: date-time */ + createdAt?: string; + /** Format: date-time */ + updatedAt?: string; + /** Format: uuid */ + tenantId?: string; + /** Format: uuid */ + id?: string; + }; + PlatformBillingInvoiceReminder: { + /** Format: uuid */ + invoiceId?: string; + /** Format: uuid */ + createdBy?: null | string; + reminderType?: components["schemas"]["PlatformBillingInvoiceReminderType"]; + channel?: components["schemas"]["PlatformBillingInvoiceReminderChannel"]; + status?: components["schemas"]["PlatformBillingInvoiceReminderStatus"]; + /** Format: date */ + reminderDate?: string; + /** Format: int32 */ + reminderLevel?: number | string; + /** Format: date */ + dueDate?: null | string; + /** Format: int32 */ + balanceCentsSnapshot?: number | string; + message?: null | string; + metadata?: components["schemas"]["JsonElement"]; + /** Format: date-time */ + sentAt?: null | string; + /** Format: date-time */ + acknowledgedAt?: null | string; + /** Format: date-time */ + createdAt?: string; + /** Format: date-time */ + updatedAt?: string; + /** Format: uuid */ + tenantId?: string; + /** Format: uuid */ + id?: string; + }; + PlatformBillingInvoiceReminderChannel: number; + PlatformBillingInvoiceReminderStatus: number; + PlatformBillingInvoiceReminderType: number; + PlatformBillingInvoiceStatus: number; + PlatformBillingItemType: number; + PlatformBillingOrder: { + /** Format: uuid */ + quoteId?: string; + orderNo?: string; + idempotencyKey?: string; + purpose?: components["schemas"]["PlatformBillingOrderPurpose"]; + status?: components["schemas"]["PlatformBillingOrderStatus"]; + /** Format: int32 */ + originalAmountCents?: number | string; + /** Format: int32 */ + discountAmountCents?: number | string; + /** Format: int32 */ + totalAmountCents?: number | string; + currency?: string; + /** Format: date-time */ + expiresAt?: string; + /** Format: date-time */ + paidAt?: null | string; + /** Format: date-time */ + cancelledAt?: null | string; + snapshot?: components["schemas"]["JsonElement"]; + /** Format: date-time */ + createdAt?: string; + /** Format: date-time */ + updatedAt?: string; + /** Format: uuid */ + tenantId?: string; + /** Format: uuid */ + id?: string; + }; + PlatformBillingOrderPurpose: number; + PlatformBillingOrderStatus: number; + PlatformBillingOrderView: { + /** Format: uuid */ + id: string; + orderNo: string; + purpose: components["schemas"]["PlatformBillingOrderPurpose"]; + status: components["schemas"]["PlatformBillingOrderStatus"]; + /** Format: int32 */ + totalAmountCents: number | string; + currency: string; + /** Format: date-time */ + expiresAt: string; + /** Format: date-time */ + paidAt: null | string; + items: components["schemas"]["PlatformBillingQuoteItemView"][]; + }; + PlatformBillingPayment: { + /** Format: uuid */ + orderId?: string; + paymentNo?: string; + idempotencyKey?: string; + provider?: string; + method?: string; + status?: components["schemas"]["PlatformBillingPaymentStatus"]; + /** Format: int32 */ + amountCents?: number | string; + providerTradeNo?: null | string; + /** Format: date-time */ + paidAt?: null | string; + clientPayload?: components["schemas"]["JsonElement"]; + /** Format: date-time */ + createdAt?: string; + /** Format: date-time */ + updatedAt?: string; + /** Format: uuid */ + tenantId?: string; + /** Format: uuid */ + id?: string; + }; + PlatformBillingPaymentEvent: { + /** Format: uuid */ + tenantId?: string; + /** Format: uuid */ + paymentId?: string; + provider?: string; + providerEventId?: string; + eventType?: string; + payload?: components["schemas"]["JsonElement"]; + /** Format: date-time */ + createdAt?: string; + /** Format: uuid */ + id?: string; + }; + PlatformBillingPaymentStatus: number; + PlatformBillingPaymentView: { + /** Format: uuid */ + id: string; + paymentNo: string; + provider: string; + method: string; + status: components["schemas"]["PlatformBillingPaymentStatus"]; + /** Format: int32 */ + amountCents: number | string; + clientPayload: components["schemas"]["JsonElement"]; + }; + PlatformBillingQuoteItemView: { + /** Format: uuid */ + offeringVersionId: string; + offeringCode: string; + offeringName: string; + itemType: components["schemas"]["PlatformBillingItemType"]; + /** Format: int32 */ + unitAmountCents: number | string; + /** Format: int32 */ + amountCents: number | string; + }; + PlatformBillingQuoteStatus: number; + PlatformBillingQuoteView: { + /** Format: uuid */ + id: string; + quoteNo: string; + status: components["schemas"]["PlatformBillingQuoteStatus"]; + purpose: components["schemas"]["PlatformBillingOrderPurpose"]; + /** Format: int32 */ + originalAmountCents: number | string; + /** Format: int32 */ + discountAmountCents: number | string; + /** Format: int32 */ + totalAmountCents: number | string; + currency: string; + /** Format: date-time */ + expiresAt: string; + items: components["schemas"]["PlatformBillingQuoteItemView"][]; + featureCodes: string[]; + limits: { + [key: string]: number | string; + }; + }; + PlatformBillingRefund: { + /** Format: uuid */ + orderId?: string; + /** Format: uuid */ + paymentId?: null | string; + refundNo?: string; + status?: components["schemas"]["PlatformBillingRefundStatus"]; + /** Format: int32 */ + amountCents?: number | string; + reason?: string; + providerRefundNo?: null | string; + /** Format: date-time */ + completedAt?: null | string; + /** Format: date-time */ + createdAt?: string; + /** Format: date-time */ + updatedAt?: string; + /** Format: uuid */ + tenantId?: string; + /** Format: uuid */ + id?: string; + }; + PlatformBillingRefundStatus: number; + PlatformCrmConfigItem: { + /** Format: uuid */ + id: string; + /** Format: uuid */ + tenantId: string; + tenantName: string; + enabled: boolean; + url: null | string; + secretRef: null | string; + formName: null | string; + examType: null | string; + /** Format: int32 */ + timeoutSeconds: null | number | string; + /** Format: int32 */ + delaySeconds: null | number | string; + assignmentMode: components["schemas"]["ReferralAssignmentMode"]; + assignmentPool: components["schemas"]["JsonElement"]; + assignmentConfig: components["schemas"]["JsonElement"]; + /** Format: date-time */ + updatedAt: string; + }; + PlatformDomainList: { + items: components["schemas"]["PlatformTenantDomainItem"][]; + }; + PlatformDomainRecheckResult: { + /** Format: uuid */ + domainId: string; + status: components["schemas"]["TenantDomainStatus"]; + /** Format: date-time */ + lastCheckedAt: string; + }; + PlatformOverview: { + /** Format: int32 */ + tenantCount: number | string; + /** Format: int32 */ + activeTenantCount: number | string; + /** Format: int32 */ + suspendedTenantCount: number | string; + /** Format: int32 */ + orderCount: number | string; + /** Format: int32 */ + paidOrderCount: number | string; + /** Format: int32 */ + revenueCents: number | string; + /** Format: int32 */ + questionBankCount: number | string; + /** Format: int32 */ + questionCount: number | string; + /** Format: int32 */ + learningActiveUserCount: number | string; + }; + PlatformPaymentApp: { + appCode?: string; + appName?: string; + status?: components["schemas"]["PlatformPaymentAppStatus"]; + settlementMode?: string; + description?: null | string; + metadata?: components["schemas"]["JsonElement"]; + /** Format: date-time */ + createdAt?: string; + /** Format: date-time */ + updatedAt?: string; + /** Format: uuid */ + id?: string; + }; + PlatformPaymentAppStatus: number; + PlatformPaymentChannel: { + /** Format: uuid */ + appId?: string; + provider?: string; + mode?: string; + status?: components["schemas"]["PlatformPaymentChannelStatus"]; + displayName?: string; + secretRef?: null | string; + callbackPath?: null | string; + /** Format: int32 */ + priority?: number | string; + configPublic?: components["schemas"]["JsonElement"]; + metadata?: components["schemas"]["JsonElement"]; + /** Format: date-time */ + createdAt?: string; + /** Format: date-time */ + updatedAt?: string; + /** Format: uuid */ + id?: string; + }; + PlatformPaymentChannelStatus: number; + PlatformQuestionBankItem: { + /** Format: uuid */ + id: string; + /** Format: uuid */ + contentEntryId: null | string; + name: string; + status: components["schemas"]["QuestionBankStatus"]; + /** Format: int32 */ + nodeCount: number | string; + /** Format: int32 */ + questionCount: number | string; + metadata: components["schemas"]["JsonElement"]; + /** Format: date-time */ + createdAt: string; + /** Format: date-time */ + updatedAt: null | string; + }; + PlatformQuestionBankNodeItem: { + /** Format: uuid */ + id: string; + /** Format: uuid */ + questionBankId: string; + /** Format: uuid */ + entryId: string; + /** Format: uuid */ + parentId: null | string; + nodeKey: null | string; + name: string; + nodeType: components["schemas"]["ContentNodeType"]; + /** Format: int32 */ + depth: number | string; + /** Format: int32 */ + sortOrder: number | string; + isActive: boolean; + isSelectable: boolean; + isLeaf: boolean; + /** Format: int32 */ + questionCount: number | string; + metadata: components["schemas"]["JsonElement"]; + }; + PlatformQuestionImportCommand: { + /** Format: uuid */ + questionBankId: string; + /** Format: uuid */ + contentNodeId: null | string; + format: string; + sourceName: null | string; + payload: components["schemas"]["JsonElement"]; + }; + PlatformQuestionImportResult: { + detail: components["schemas"]["ContentImportJobDetail"]; + /** Format: int32 */ + createdNodeCount: number | string; + /** Format: int32 */ + insertedQuestionCount: number | string; + /** Format: int32 */ + updatedQuestionCount: number | string; + /** Format: int32 */ + skippedQuestionCount: number | string; + }; + PlatformQuestionItem: { + /** Format: uuid */ + id: string; + /** Format: uuid */ + versionId: null | string; + /** Format: uuid */ + questionBankId: string; + /** Format: uuid */ + entryId: string; + /** Format: uuid */ + contentNodeId: string; + legacyId: null | string; + type: string; + typeLabel: null | string; + /** Format: int32 */ + difficulty: null | number | string; + tags: components["schemas"]["JsonElement"]; + content: null | string; + options: components["schemas"]["JsonElement"]; + /** Format: int32 */ + correctOptionIndex: null | number | string; + correctOptionIndices: components["schemas"]["JsonElement"]; + answerText: null | string; + explanation: null | string; + subQuestions: components["schemas"]["JsonElement"]; + codeLang: null | string; + codeTemplate: null | string; + mediaUrl: null | string; + status: components["schemas"]["QuestionStatus"]; + /** Format: int32 */ + versionNo: number | string; + /** Format: date-time */ + createdAt: string; + /** Format: date-time */ + updatedAt: null | string; + }; + PlatformQuestionPage: { + items: components["schemas"]["PlatformQuestionItem"][]; + /** Format: int32 */ + total: number | string; + /** Format: int32 */ + page: number | string; + /** Format: int32 */ + pageSize: number | string; + }; + PlatformRebateSummary: { + /** Format: int32 */ + grossAmountCents: number | string; + /** Format: int32 */ + commissionAmountCents: number | string; + /** Format: int32 */ + pendingSettlementCents: number | string; + /** Format: int32 */ + paidSettlementCents: number | string; + /** Format: int32 */ + exceptionCount: number | string; + }; + PlatformSmsChannelItem: { + /** Format: uuid */ + id: string; + /** Format: uuid */ + tenantId: string; + tenantName: string; + provider: string; + name: string; + signature: string; + scene: string; + status: components["schemas"]["TenantExternalProviderStatus"]; + secretRef: null | string; + /** Format: int32 */ + priority: number | string; + /** Format: int32 */ + monthlyQuota: number | string; + /** Format: int32 */ + sentThisMonth: number | string; + configPublic: components["schemas"]["JsonElement"]; + metadata: components["schemas"]["JsonElement"]; + /** Format: date-time */ + updatedAt: string; + }; + PlatformSmsTemplateItem: { + /** Format: uuid */ + id: string; + /** Format: uuid */ + tenantId: string; + tenantName: string; + /** Format: uuid */ + channelId: string; + channelName: string; + code: string; + name: string; + type: components["schemas"]["SmsTemplateType"]; + auditStatus: components["schemas"]["SmsTemplateAuditStatus"]; + status: components["schemas"]["SmsTemplateStatus"]; + providerTemplateCode: null | string; + content: string; + remark: null | string; + /** Format: int32 */ + sentCount: number | string; + /** Format: int32 */ + failedCount: number | string; + /** Format: date-time */ + updatedAt: string; + }; + PlatformStaffItem: { + /** Format: uuid */ + userId: string; + name: null | string; + phoneMasked: null | string; + email: null | string; + status: components["schemas"]["UserStatus"]; + roleCodes: string[]; + /** Format: date-time */ + createdAt: string; + /** Format: date-time */ + updatedAt: string; + }; + PlatformStaffList: { + items: components["schemas"]["PlatformStaffItem"][]; + }; + PlatformTenantCapabilityListOfCrmWebhookLog: { + items: components["schemas"]["CrmWebhookLog"][]; + }; + PlatformTenantCapabilityListOfCrmWebhookQueueItem: { + items: components["schemas"]["CrmWebhookQueueItem"][]; + }; + PlatformTenantCapabilityListOfObject: { + items: unknown[]; + }; + PlatformTenantCapabilityListOfPlatformCrmConfigItem: { + items: components["schemas"]["PlatformCrmConfigItem"][]; + }; + PlatformTenantCapabilityListOfPlatformSmsChannelItem: { + items: components["schemas"]["PlatformSmsChannelItem"][]; + }; + PlatformTenantCapabilityListOfPlatformSmsTemplateItem: { + items: components["schemas"]["PlatformSmsTemplateItem"][]; + }; + PlatformTenantCapabilityListOfSmsSendLog: { + items: components["schemas"]["SmsSendLog"][]; + }; + PlatformTenantCapabilityListOfTenantExternalProviderItem: { + items: components["schemas"]["TenantExternalProviderItem"][]; + }; + PlatformTenantDetail: { + tenant: components["schemas"]["PlatformTenantItem"]; + domains: components["schemas"]["PlatformTenantDomainItem"][]; + subscriptions: components["schemas"]["PlatformTenantSubscriptionItem"][]; + billingProfile: null | components["schemas"]["TenantBillingProfileItem"]; + }; + PlatformTenantDomainItem: { + /** Format: uuid */ + id: string; + /** Format: uuid */ + tenantId: string; + host: string; + domainType: components["schemas"]["TenantDomainType"]; + status: components["schemas"]["TenantDomainStatus"]; + isPrimary: boolean; + /** Format: date-time */ + verifiedAt: null | string; + /** Format: date-time */ + dnsVerifiedAt: null | string; + /** Format: date-time */ + tlsReadyAt: null | string; + /** Format: date-time */ + lastCheckedAt: null | string; + lastFailureReason: null | string; + }; + PlatformTenantItem: { + /** Format: uuid */ + id: string; + slug: string; + name: string; + legalName: null | string; + status: components["schemas"]["TenantStatus"]; + mode: components["schemas"]["TenantMode"]; + billingStatus: components["schemas"]["BillingStatus"]; + /** Format: date-time */ + subscriptionExpiresAt: null | string; + /** Format: int32 */ + domainCount: number | string; + /** Format: date-time */ + createdAt: string; + /** Format: date-time */ + updatedAt: string; + }; + PlatformTenantList: { + items: components["schemas"]["PlatformTenantItem"][]; + }; + PlatformTenantProvisioningResult: { + tenant: components["schemas"]["PlatformTenantItem"]; + /** Format: uuid */ + ownerUserId: string; + ownerIdentifier: string; + mustChangePassword: boolean; + }; + PlatformTenantSubscriptionItem: { + /** Format: uuid */ + id: string; + /** Format: uuid */ + tenantId: string; + /** Format: uuid */ + baseOfferingVersionId: string; + status: components["schemas"]["TenantSaasSubscriptionStatus"]; + /** Format: date-time */ + startsAt: string; + /** Format: date-time */ + currentPeriodStart: string; + /** Format: date-time */ + currentPeriodEnd: string; + cancelAtPeriodEnd: boolean; + metadata: components["schemas"]["JsonElement"]; + }; + PointActivityClaim: { + /** Format: uuid */ + taskId?: string; + /** Format: uuid */ + userId?: string; + taskKey?: string; + /** Format: int32 */ + points?: number | string; + status?: components["schemas"]["PointActivityClaimStatus"]; + sourceType?: null | string; + /** Format: uuid */ + sourceId?: null | string; + /** Format: date-time */ + claimedAt?: string; + metadata?: components["schemas"]["JsonElement"]; + /** Format: date-time */ + createdAt?: string; + /** Format: date-time */ + updatedAt?: string; + /** Format: uuid */ + tenantId?: string; + /** Format: uuid */ + id?: string; + }; + PointActivityClaimStatus: number; + PointActivityTask: { + taskKey?: string; + title?: string; + description?: null | string; + taskType?: components["schemas"]["PointActivityTaskType"]; + status?: components["schemas"]["PointActivityTaskStatus"]; + /** Format: int32 */ + points?: number | string; + /** Format: int32 */ + maxClaimsPerUser?: number | string; + /** Format: date-time */ + startsAt?: null | string; + /** Format: date-time */ + endsAt?: null | string; + /** Format: int32 */ + sortOrder?: number | string; + rules?: components["schemas"]["JsonElement"]; + metadata?: components["schemas"]["JsonElement"]; + /** Format: date-time */ + createdAt?: string; + /** Format: date-time */ + updatedAt?: string; + /** Format: uuid */ + tenantId?: string; + /** Format: uuid */ + id?: string; + }; + PointActivityTaskStatus: number; + PointActivityTaskType: number; + PointClaimItem: { + /** Format: uuid */ + id: string; + /** Format: uuid */ + taskId: string; + taskKey: string; + /** Format: int32 */ + points: number | string; + status: string; + sourceType: null | string; + /** Format: uuid */ + sourceId: null | string; + /** Format: date-time */ + claimedAt: string; + metadata: components["schemas"]["JsonElement"]; + }; + PointExchangeItem: { + /** Format: uuid */ + regionId?: null | string; + itemKey?: string; + name?: string; + description?: null | string; + itemType?: components["schemas"]["PointExchangeItemType"]; + status?: components["schemas"]["PointExchangeItemStatus"]; + /** Format: int32 */ + pointsCost?: number | string; + /** Format: int32 */ + stock?: null | number | string; + /** Format: int32 */ + days?: null | number | string; + /** Format: int32 */ + sortOrder?: number | string; + /** Format: date-time */ + startsAt?: null | string; + /** Format: date-time */ + endsAt?: null | string; + fulfillmentPayload?: components["schemas"]["JsonElement"]; + metadata?: components["schemas"]["JsonElement"]; + /** Format: date-time */ + createdAt?: string; + /** Format: date-time */ + updatedAt?: string; + /** Format: uuid */ + tenantId?: string; + /** Format: uuid */ + id?: string; + }; + PointExchangeItemDto: { + /** Format: uuid */ + id: string; + /** Format: uuid */ + regionId: null | string; + itemKey: string; + name: string; + description: null | string; + itemType: string; + status: string; + /** Format: int32 */ + pointsCost: number | string; + /** Format: int32 */ + stock: null | number | string; + /** Format: int32 */ + days: null | number | string; + canExchange: boolean; + /** Format: int32 */ + sortOrder: number | string; + fulfillmentPayload: components["schemas"]["JsonElement"]; + metadata: components["schemas"]["JsonElement"]; + }; + PointExchangeItemStatus: number; + PointExchangeItemType: number; + PointExchangeOrder: { + /** Format: uuid */ + itemId?: string; + /** Format: uuid */ + userId?: string; + orderNo?: string; + itemName?: string; + itemType?: components["schemas"]["PointExchangeItemType"]; + status?: components["schemas"]["PointExchangeOrderStatus"]; + /** Format: int32 */ + pointsCost?: number | string; + /** Format: date-time */ + orderedAt?: string; + /** Format: date-time */ + completedAt?: null | string; + /** Format: date-time */ + cancelledAt?: null | string; + fulfillmentSnapshot?: components["schemas"]["JsonElement"]; + metadata?: components["schemas"]["JsonElement"]; + /** Format: date-time */ + createdAt?: string; + /** Format: date-time */ + updatedAt?: string; + /** Format: uuid */ + tenantId?: string; + /** Format: uuid */ + id?: string; + }; + PointExchangeOrderItem: { + /** Format: uuid */ + id: string; + /** Format: uuid */ + itemId: string; + orderNo: string; + itemName: string; + itemType: string; + status: string; + /** Format: int32 */ + pointsCost: number | string; + /** Format: date-time */ + orderedAt: string; + /** Format: date-time */ + completedAt: null | string; + fulfillmentSnapshot: components["schemas"]["JsonElement"]; + metadata: components["schemas"]["JsonElement"]; + }; + PointExchangeOrderStatus: number; + PointListOfPointExchangeItemDto: { + items: components["schemas"]["PointExchangeItemDto"][]; + }; + PointListOfPointExchangeOrderItem: { + items: components["schemas"]["PointExchangeOrderItem"][]; + }; + PointListOfPointTaskItem: { + items: components["schemas"]["PointTaskItem"][]; + }; + PointSummaryItem: { + /** Format: int32 */ + earnedPoints: number | string; + /** Format: int32 */ + spentPoints: number | string; + /** Format: int32 */ + balancePoints: number | string; + }; + PointTaskItem: { + /** Format: uuid */ + id: string; + taskKey: string; + title: string; + description: null | string; + taskType: string; + status: string; + /** Format: int32 */ + points: number | string; + /** Format: int32 */ + maxClaimsPerUser: number | string; + /** Format: int32 */ + claimedCount: number | string; + canClaim: boolean; + /** Format: date-time */ + startsAt: null | string; + /** Format: date-time */ + endsAt: null | string; + /** Format: int32 */ + sortOrder: number | string; + rules: components["schemas"]["JsonElement"]; + metadata: components["schemas"]["JsonElement"]; + }; + PracticeAccessMode: number; + PracticeAssemblyType: number; + PracticeBlueprintCatalogItem: { + /** Format: uuid */ + id: string; + /** Format: uuid */ + regionId: null | string; + /** Format: uuid */ + entryId: null | string; + /** Format: uuid */ + nodeId: null | string; + /** Format: uuid */ + collectionId: null | string; + legacyId: null | string; + name: string; + mode: components["schemas"]["PracticeMode"]; + assemblyType: components["schemas"]["PracticeAssemblyType"]; + /** Format: int32 */ + questionLimit: null | number | string; + /** Format: int32 */ + durationMinutes: null | number | string; + /** Format: double */ + totalScore: null | number | string; + /** Format: double */ + passScore: null | number | string; + sections: components["schemas"]["JsonElement"]; + rules: components["schemas"]["JsonElement"]; + accessRules: components["schemas"]["JsonElement"]; + status: components["schemas"]["ContentStatus"]; + /** Format: int32 */ + order: number | string; + }; + PracticeBlueprintManagementItem: { + /** Format: uuid */ + id: string; + /** Format: uuid */ + regionId: null | string; + /** Format: uuid */ + entryId: null | string; + /** Format: uuid */ + nodeId: null | string; + /** Format: uuid */ + collectionId: null | string; + legacyId: null | string; + name: string; + mode: components["schemas"]["PracticeMode"]; + assemblyType: components["schemas"]["PracticeAssemblyType"]; + /** Format: int32 */ + questionLimit: null | number | string; + /** Format: int32 */ + durationMinutes: null | number | string; + /** Format: double */ + totalScore: null | number | string; + /** Format: double */ + passScore: null | number | string; + sections: components["schemas"]["JsonElement"]; + rules: components["schemas"]["JsonElement"]; + accessRules: components["schemas"]["JsonElement"]; + status: components["schemas"]["ContentStatus"]; + /** Format: int32 */ + order: number | string; + /** Format: date-time */ + createdAt: string; + /** Format: date-time */ + updatedAt: null | string; + }; + PracticeHistoryItem: { + /** Format: uuid */ + id: string; + mode: string; + targetType: null | string; + /** Format: uuid */ + targetId: null | string; + /** Format: uuid */ + blueprintId: null | string; + /** Format: uuid */ + collectionId: null | string; + /** Format: uuid */ + entryId: null | string; + /** Format: uuid */ + contentNodeId: null | string; + /** Format: int32 */ + questionCount: number | string; + /** Format: int32 */ + answeredCount: number | string; + /** Format: int32 */ + correctCount: number | string; + /** Format: int32 */ + wrongCount: number | string; + /** Format: date-time */ + startedAt: string; + /** Format: date-time */ + finishedAt: null | string; + /** Format: date-time */ + expiresAt: null | string; + status: string; + /** Format: uuid */ + reportId: null | string; + /** Format: double */ + score: null | number | string; + /** Format: double */ + reportTotalScore: null | number | string; + /** Format: double */ + accuracy: null | number | string; + }; + PracticeMode: number; + PracticeSessionDetailItem: { + session: components["schemas"]["PracticeSessionItem"]; + questions: components["schemas"]["PracticeSessionQuestionItem"][]; + answersBySessionQuestion: { + [key: string]: components["schemas"]["AnswerRecordItem"]; + }; + }; + PracticeSessionItem: { + /** Format: uuid */ + id: string; + mode: string; + targetType: null | string; + /** Format: uuid */ + targetId: null | string; + /** Format: uuid */ + blueprintId: null | string; + /** Format: uuid */ + collectionId: null | string; + /** Format: uuid */ + entryId: null | string; + /** Format: uuid */ + contentNodeId: null | string; + /** Format: int32 */ + questionCount: number | string; + /** Format: int32 */ + durationMinutes: null | number | string; + /** Format: double */ + totalScore: null | number | string; + accessMode: components["schemas"]["PracticeAccessMode"]; + /** Format: uuid */ + accessEntitlementId: null | string; + /** Format: int32 */ + consumedFreeQuota: number | string; + accessSnapshot: components["schemas"]["JsonElement"]; + /** Format: date-time */ + startedAt: string; + /** Format: date-time */ + finishedAt: null | string; + /** Format: date-time */ + expiresAt: null | string; + metadata: components["schemas"]["JsonElement"]; + status: string; + }; + PracticeSessionQuestionItem: { + /** Format: uuid */ + sessionQuestionId: string; + /** Format: uuid */ + questionReferenceId: string; + locator: components["schemas"]["QuestionLocator"]; + /** Format: uuid */ + questionId: string; + type: string; + typeLabel: null | string; + /** Format: int32 */ + difficulty: null | number | string; + tags: components["schemas"]["JsonElement"]; + /** Format: uuid */ + versionId: null | string; + content: null | string; + options: components["schemas"]["JsonElement"]; + explanation: null | string; + }; + PracticeSessionReportItem: { + /** Format: uuid */ + id: string; + /** Format: uuid */ + practiceSessionId: string; + /** Format: uuid */ + blueprintId: null | string; + /** Format: uuid */ + collectionId: null | string; + mode: string; + /** Format: int32 */ + totalQuestions: number | string; + /** Format: int32 */ + answeredCount: number | string; + /** Format: int32 */ + correctCount: number | string; + /** Format: int32 */ + wrongCount: number | string; + /** Format: int32 */ + unansweredCount: number | string; + /** Format: double */ + score: number | string; + /** Format: double */ + totalScore: number | string; + /** Format: double */ + accuracy: number | string; + /** Format: int32 */ + durationSeconds: number | string; + /** Format: date-time */ + startedAt: null | string; + /** Format: date-time */ + submittedAt: string; + sectionStats: components["schemas"]["JsonElement"]; + questionResults: components["schemas"]["JsonElement"]; + wrongQuestionIds: components["schemas"]["JsonElement"]; + metadata: components["schemas"]["JsonElement"]; + }; + /** @description 预览对账导入请求 DTO。 */ + PreviewReconciliationImportDto: { + /** @description 服务提供方。 */ + provider: string; + /** + * Format: date + * @description 账单日期。 + */ + billDate?: string; + /** @description 账单类型。 */ + billType?: components["schemas"]["ReconciliationBillType"]; + /** @description 来源名称。 */ + sourceName: string; + /** @description 数据行列表。 */ + rows?: components["schemas"]["JsonElement"]; + }; + /** @description 预览租户主题请求 DTO。 */ + PreviewTenantThemeDto: { + /** @description 模板编码。 */ + templateCode: string; + /** @description 主题配置。 */ + theme?: components["schemas"]["JsonElement"]; + /** @description 公开资源配置。 */ + publicAssets?: components["schemas"]["JsonElement"]; + }; + ProblemDetails: { + type?: null | string; + title?: null | string; + /** Format: int32 */ + status?: null | number | string; + detail?: null | string; + instance?: null | string; + }; + ProductCatalogItem: { + /** Format: uuid */ + id: string; + legacyId: null | string; + /** Format: uuid */ + regionId: null | string; + title: string; + /** Format: double */ + price: null | number | string; + priceLabel: null | string; + link: null | string; + type: components["schemas"]["ProductType"]; + tags: components["schemas"]["JsonElement"]; + cover: null | string; + previewIframe: null | string; + detailImages: components["schemas"]["JsonElement"]; + /** Format: int32 */ + order: number | string; + isActive: boolean; + }; + ProductType: number; + ProfileNotificationItem: { + /** Format: uuid */ + id: string; + notificationType: string; + status: string; + severity: string; + title: string; + message: string; + actionLabel: null | string; + actionPath: null | string; + sourceType: null | string; + /** Format: uuid */ + sourceId: null | string; + metadata: components["schemas"]["JsonElement"]; + /** Format: date-time */ + readAt: null | string; + /** Format: date-time */ + createdAt: string; + }; + ProfileNotificationList: { + items: components["schemas"]["ProfileNotificationItem"][]; + summary: { + [key: string]: number | string; + }; + }; + ProfileScoreEventItem: { + /** Format: uuid */ + id: string; + eventType: string; + /** Format: int32 */ + points: number | string; + /** Format: int32 */ + balanceAfter: number | string; + sourceType: null | string; + /** Format: uuid */ + sourceId: null | string; + metadata: components["schemas"]["JsonElement"]; + /** Format: date-time */ + createdAt: string; + }; + ProfileScoreEventList: { + items: components["schemas"]["ProfileScoreEventItem"][]; + }; + /** @description 可公开给客户端的租户品牌信息。 */ + PublicTenantBrandingDto: { + /** @description 品牌名称。 */ + brandName: null | string; + /** @description 品牌短名称。 */ + shortName: null | string; + /** @description 品牌标语。 */ + slogan: null | string; + /** @description Logo 地址。 */ + logoUrl: null | string; + /** @description Favicon 地址。 */ + faviconUrl: null | string; + /** @description 客服微信。 */ + serviceWechat: null | string; + /** @description 公众号或服务号名称。 */ + serviceAccountName: null | string; + /** @description 公开主题配置。 */ + theme: components["schemas"]["JsonElement"]; + /** @description 公开资源配置。 */ + publicAssets: components["schemas"]["JsonElement"]; + }; + /** @description 可公开给客户端的租户基础信息。 */ + PublicTenantDto: { + /** + * Format: uuid + * @description 租户 ID。 + */ + id: string; + /** @description 租户编码。 */ + slug: string; + /** @description 租户名称。 */ + name: string; + /** @description 租户状态。 */ + status: components["schemas"]["TenantStatus"]; + /** @description 租户模式。 */ + mode: components["schemas"]["TenantMode"]; + /** @description 当前匹配到的访问域名。 */ + host: null | string; + }; + /** @description 发布租户前端配置请求。 */ + PublishTenantFrontendConfigDto: { + /** + * Format: int32 + * @description 期望配置版本。 + */ + expectedVersion?: number | string; + }; + /** @description 发布租户主题请求 DTO。 */ + PublishTenantThemeDto: { + /** @description 是否使用草稿配置。 */ + useDraft?: null | boolean; + /** @description 模板编码。 */ + templateCode?: null | string; + /** @description 主题配置。 */ + theme?: components["schemas"]["JsonElement"]; + /** @description 公开资源配置。 */ + publicAssets?: components["schemas"]["JsonElement"]; + }; + /** @description 题目Action请求 DTO。 */ + QuestionActionDto: { + /** + * Format: uuid + * @description 题目 ID。 + */ + questionId: string; + /** @description 来源。 */ + source: components["schemas"]["QuestionSource"]; + /** @description 是否收藏。 */ + favorite?: null | boolean; + }; + QuestionBankCatalogItem: { + /** Format: uuid */ + id: string; + /** Format: uuid */ + regionId: null | string; + name: string; + source: components["schemas"]["QuestionSource"]; + status: components["schemas"]["QuestionBankStatus"]; + metadata: components["schemas"]["JsonElement"]; + }; + QuestionBankStatus: number; + QuestionCatalogItem: { + /** Format: uuid */ + id: string; + /** Format: uuid */ + questionBankId: null | string; + /** Format: uuid */ + subjectId: null | string; + /** Format: uuid */ + categoryId: null | string; + /** Format: uuid */ + nodeId: null | string; + /** Format: uuid */ + entryId: null | string; + /** Format: uuid */ + contentNodeId: null | string; + /** Format: uuid */ + primaryCollectionId: null | string; + legacyId: null | string; + legacySubjectId: null | string; + legacyCategoryId: null | string; + legacyNodeId: null | string; + type: string; + typeLabel: null | string; + /** Format: int32 */ + difficulty: null | number | string; + tags: components["schemas"]["JsonElement"]; + examMarkers: components["schemas"]["JsonElement"]; + mediaUrl: null | string; + hasVideoExplanation: boolean; + status: components["schemas"]["QuestionStatus"]; + /** Format: uuid */ + versionId: null | string; + /** Format: int32 */ + versionNo: null | number | string; + content: null | string; + options: components["schemas"]["JsonElement"]; + /** Format: int32 */ + correctOptionIndex: null | number | string; + correctOptionIndices: components["schemas"]["JsonElement"]; + answerText: null | string; + explanation: null | string; + subQuestions: components["schemas"]["JsonElement"]; + codeLang: null | string; + codeTemplate: null | string; + locator: components["schemas"]["QuestionLocator"]; + }; + QuestionCollectionCatalogItem: { + /** Format: uuid */ + id: string; + /** Format: uuid */ + regionId: null | string; + /** Format: uuid */ + entryId: null | string; + /** Format: uuid */ + nodeId: null | string; + /** Format: uuid */ + subjectId: null | string; + /** Format: uuid */ + categoryId: null | string; + /** Format: uuid */ + questionBankId: null | string; + legacyId: null | string; + name: string; + collectionType: components["schemas"]["QuestionCollectionType"]; + sourceType: components["schemas"]["QuestionCollectionSourceType"]; + filters: components["schemas"]["JsonElement"]; + /** Format: int32 */ + questionCount: number | string; + /** Format: double */ + totalScore: null | number | string; + /** Format: int32 */ + durationMinutes: null | number | string; + status: components["schemas"]["ContentStatus"]; + /** Format: int32 */ + order: number | string; + accessRules: components["schemas"]["JsonElement"]; + metadata: components["schemas"]["JsonElement"]; + }; + QuestionCollectionItemManagementItem: { + /** Format: uuid */ + id: string; + /** Format: uuid */ + collectionId: string; + /** Format: uuid */ + questionId: string; + locator: components["schemas"]["QuestionLocator"]; + sectionKey: null | string; + /** Format: int32 */ + order: number | string; + /** Format: double */ + score: null | number | string; + required: boolean; + metadata: components["schemas"]["JsonElement"]; + }; + QuestionCollectionManagementItem: { + /** Format: uuid */ + id: string; + /** Format: uuid */ + regionId: null | string; + /** Format: uuid */ + entryId: null | string; + /** Format: uuid */ + nodeId: null | string; + /** Format: uuid */ + subjectId: null | string; + /** Format: uuid */ + categoryId: null | string; + /** Format: uuid */ + questionBankId: null | string; + legacyId: null | string; + name: string; + collectionType: components["schemas"]["QuestionCollectionType"]; + sourceType: components["schemas"]["QuestionCollectionSourceType"]; + filters: components["schemas"]["JsonElement"]; + /** Format: int32 */ + questionCount: number | string; + /** Format: double */ + totalScore: null | number | string; + /** Format: int32 */ + durationMinutes: null | number | string; + status: components["schemas"]["ContentStatus"]; + /** Format: int32 */ + order: number | string; + accessRules: components["schemas"]["JsonElement"]; + metadata: components["schemas"]["JsonElement"]; + /** Format: date-time */ + createdAt: string; + /** Format: date-time */ + updatedAt: null | string; + }; + QuestionCollectionSourceType: number; + QuestionCollectionType: number; + QuestionLocator: { + source: components["schemas"]["QuestionSource"]; + /** Format: uuid */ + questionId: string; + }; + QuestionManagementItem: { + /** Format: uuid */ + id: string; + /** Format: uuid */ + versionId: null | string; + /** Format: uuid */ + questionBankId: null | string; + /** Format: uuid */ + subjectId: null | string; + /** Format: uuid */ + categoryId: null | string; + /** Format: uuid */ + nodeId: null | string; + /** Format: uuid */ + entryId: null | string; + /** Format: uuid */ + contentNodeId: null | string; + /** Format: uuid */ + primaryCollectionId: null | string; + legacyId: null | string; + type: string; + typeLabel: null | string; + /** Format: int32 */ + difficulty: null | number | string; + tags: components["schemas"]["JsonElement"]; + content: null | string; + options: components["schemas"]["JsonElement"]; + /** Format: int32 */ + correctOptionIndex: null | number | string; + correctOptionIndices: components["schemas"]["JsonElement"]; + answerText: null | string; + explanation: null | string; + subQuestions: components["schemas"]["JsonElement"]; + codeLang: null | string; + codeTemplate: null | string; + mediaUrl: null | string; + hasVideoExplanation: boolean; + status: components["schemas"]["QuestionStatus"]; + }; + QuestionSource: number; + QuestionStatus: number; + QuestionVersionCatalogItem: { + /** Format: uuid */ + id: string; + /** Format: uuid */ + questionId: string; + /** Format: int32 */ + versionNo: number | string; + content: null | string; + options: components["schemas"]["JsonElement"]; + /** Format: int32 */ + correctOptionIndex: null | number | string; + correctOptionIndices: components["schemas"]["JsonElement"]; + answerText: null | string; + explanation: null | string; + subQuestions: components["schemas"]["JsonElement"]; + codeLang: null | string; + codeTemplate: null | string; + /** Format: date-time */ + createdAt: string; + }; + QuestionVideoCatalogItem: { + /** Format: uuid */ + id: string; + legacyId: null | string; + /** Format: uuid */ + questionId: null | string; + /** Format: uuid */ + videoId: null | string; + videoType: components["schemas"]["QuestionVideoType"]; + /** Format: int32 */ + order: number | string; + metadata: components["schemas"]["JsonElement"]; + video: null | components["schemas"]["VideoExplanationCatalogItem"]; + }; + QuestionVideoManagementItem: { + /** Format: uuid */ + id: string; + /** Format: uuid */ + questionId: null | string; + /** Format: uuid */ + videoId: null | string; + legacyId: null | string; + videoType: components["schemas"]["QuestionVideoType"]; + /** Format: int32 */ + order: number | string; + metadata: components["schemas"]["JsonElement"]; + }; + /** @description 题目视频查询参数。 */ + QuestionVideoQueryDto: { + /** + * Format: uuid + * @description 题目 ID。 + */ + questionId?: null | string; + /** @description 题目 ID 列表。 */ + questionIds?: null | string[]; + /** + * Format: int32 + * @description 返回数量上限。 + */ + limit?: null | number | string; + }; + QuestionVideoType: number; + RecentPracticeItem: { + /** Format: uuid */ + id: string; + practiceType: null | string; + targetName: null | string; + /** Format: int32 */ + progress: number | string; + /** Format: date-time */ + lastAccessAt: null | string; + /** Format: date-time */ + lastPracticeAt: null | string; + }; + ReconciliationBatchStatus: number; + ReconciliationBillType: number; + ReconciliationImportPreview: { + /** Format: int32 */ + totalCount: number | string; + /** Format: int32 */ + paymentCount: number | string; + /** Format: int32 */ + refundCount: number | string; + /** Format: int32 */ + invalidCount: number | string; + /** Format: int32 */ + amountCents: number | string; + /** Format: int32 */ + refundAmountCents: number | string; + sourceHash: string; + }; + ReconciliationIssueMatchStatus: number; + ReconciliationIssueStatus: number; + ReconciliationMatchStatus: number; + ReconciliationResolutionType: number; + ReconciliationSource: number; + ReconciliationTransactionType: number; + /** @description 核销激活码编码请求 DTO。 */ + RedeemActivationCodeDto: { + /** @description 编码。 */ + code: string; + /** + * Format: uuid + * @description 用户 ID。 + */ + userId: string; + /** + * Format: uuid + * @description 地区 ID。 + */ + regionId?: null | string; + }; + ReferralAssignmentMode: number; + ReferralBindResult: { + lead: components["schemas"]["ReferralLeadItem"]; + crmQueue: null | components["schemas"]["CrmQueuePreviewItem"]; + }; + ReferralConversionReport: { + /** Format: date */ + startDate: string; + /** Format: date */ + endDate: string; + /** Format: int32 */ + leadCount: number | string; + /** Format: int32 */ + paidLeadCount: number | string; + /** Format: int32 */ + paidAmountCents: number | string; + /** Format: double */ + conversionRate: number | string; + topReferrers: components["schemas"]["ReferralStatsItem"][]; + recentUnconvertedLeads: components["schemas"]["ReferralLeadItem"][]; + }; + /** @description 推荐邀请码请求 DTO。 */ + ReferralInviteDto: { + /** @description 渠道。 */ + channel?: null | string; + /** @description 落地页路径。 */ + landingPath?: null | string; + }; + ReferralInviteItem: { + inviteCode: string; + }; + ReferralLeadItem: { + /** Format: uuid */ + id: string; + /** Format: uuid */ + studentUserId: string; + /** Format: uuid */ + referrerUserId: null | string; + refCode: null | string; + status: string; + /** Format: date-time */ + boundAt: string; + changed: boolean; + }; + ReferralListOfReferralLeadItem: { + items: components["schemas"]["ReferralLeadItem"][]; + }; + ReferralListOfReferralStatsItem: { + items: components["schemas"]["ReferralStatsItem"][]; + }; + ReferralListOfReferralTeamItem: { + items: components["schemas"]["ReferralTeamItem"][]; + }; + /** @description 推荐二维码请求 DTO。 */ + ReferralQrcodeDto: { + /** @description 页码。 */ + page?: null | string; + /** @description 场景参数。 */ + scene?: null | string; + /** @description 服务提供方。 */ + provider?: null | string; + /** @description 二维码地址。 */ + qrcodeUrl?: null | string; + metadata?: null | components["schemas"]["JsonElement"]; + }; + ReferralQrcodeItem: { + /** Format: uuid */ + id: string; + refCode: string; + scene: string; + page: string; + provider: string; + qrcodeUrl: null | string; + status: string; + metadata: components["schemas"]["JsonElement"]; + }; + ReferralResolutionItem: { + valid: boolean; + /** Format: uuid */ + inviterId: null | string; + inviteCode: null | string; + role: null | string; + name: null | string; + }; + ReferralStatsItem: { + /** Format: uuid */ + referrerUserId: string; + name: null | string; + role: string; + inviteCode: null | string; + /** Format: int32 */ + leadCount: number | string; + /** Format: int32 */ + paidLeadCount: number | string; + /** Format: int32 */ + paidAmountCents: number | string; + /** Format: int32 */ + trackCount: number | string; + /** Format: double */ + conversionRate: number | string; + }; + ReferralTeamItem: { + /** Format: uuid */ + id: string; + /** Format: uuid */ + memberUserId: string; + /** Format: uuid */ + leaderUserId: null | string; + relationType: string; + status: string; + metadata: components["schemas"]["JsonElement"]; + }; + ReferralTrackItem: { + /** Format: uuid */ + id: string; + eventType: string; + refCode: null | string; + /** Format: uuid */ + referrerUserId: null | string; + /** Format: uuid */ + targetUserId: null | string; + source: null | string; + /** Format: date-time */ + createdAt: string; + }; + ReferralTrackResult: { + item: components["schemas"]["ReferralTrackItem"]; + lead: null | components["schemas"]["ReferralLeadItem"]; + crmQueue: null | components["schemas"]["CrmQueuePreviewItem"]; + }; + /** @description 刷新会话请求 DTO。 */ + RefreshSessionDto: { + /** @description 刷新令牌。 */ + refreshToken: string; + }; + RefundEntitlementAction: number; + /** @description 退款通知请求 DTO。 */ + RefundNotificationDto: { + /** @description 退款单号。 */ + refundNo: string; + /** @description 渠道退款单号。 */ + providerRefundNo?: null | string; + /** @description 状态。 */ + status?: components["schemas"]["CommerceRefundStatus"]; + /** @description 事件 ID。 */ + eventId?: null | string; + /** @description 任务载荷。 */ + payload?: components["schemas"]["JsonElement"]; + }; + RegionCatalogItem: { + /** Format: uuid */ + id: string; + legacyId: null | string; + name: string; + code: null | string; + shortName: null | string; + fullName: null | string; + icon: null | string; + pinyin: null | string; + /** Format: int32 */ + order: number | string; + isHot: boolean; + }; + RegionModuleCatalogItem: { + /** Format: uuid */ + id: string; + legacyId: null | string; + /** Format: uuid */ + regionId: null | string; + name: string; + type: null | string; + icon: null | string; + color: null | string; + textColor: null | string; + description: null | string; + route: null | string; + /** Format: int32 */ + order: number | string; + isPrimarySchoolModule: boolean; + }; + /** @description 移除租户管理端班级成员请求 DTO。 */ + RemoveTenantAdminClassMemberDto: { + /** + * Format: uuid + * @description 班级成员 ID。 + */ + classMemberId: string; + }; + /** @description 替换题集Items请求 DTO。 */ + ReplaceCollectionItemsDto: { + /** + * Format: uuid + * @description 题集 ID。 + */ + collectionId: string; + /** @description 题目列表。 */ + questions?: components["schemas"]["CollectionQuestionDto"][]; + }; + /** @description 替换角色权限绑定请求。 */ + ReplaceRoleBindingsDto: { + /** @description 权限编码列表。 */ + permissionCodes?: string[]; + /** @description 菜单编码列表。 */ + menuCodes?: string[]; + }; + /** @description 替换用户角色请求。 */ + ReplaceUserRolesDto: { + /** @description 角色 ID 列表。 */ + roleIds?: string[]; + }; + ReportPriority: number; + ReportStatus: number; + ReportType: number; + /** @description RequestProviderBill任务请求 DTO。 */ + RequestProviderBillJobDto: { + /** @description 服务提供方。 */ + provider: string; + /** + * Format: date + * @description 账单日期。 + */ + billDate?: string; + /** @description 账单类型。 */ + billType?: components["schemas"]["ReconciliationBillType"]; + /** + * Format: date-time + * @description 计划运行时间。 + */ + runAfter?: null | string; + }; + /** @description 首次登录必改密码请求。 */ + RequiredPasswordChangeDto: { + /** @description 挑战令牌。 */ + challengeToken: string; + /** @description 新密码。 */ + newPassword: string; + }; + /** @description 解析推荐请求 DTO。 */ + ResolveReferralDto: { + /** @description 编码。 */ + code?: null | string; + /** @description 租户编码。 */ + tenantCode?: null | string; + }; + /** @description 重试平台Dunning事件请求 DTO。 */ + RetryPlatformBillingDunningEventDto: { + /** + * Format: uuid + * @description 事件 ID。 + */ + eventId: string; + /** @description 原因。 */ + reason?: null | string; + }; + /** @description 重试租户 CRM 线索推送请求。 */ + RetryPlatformCrmLeadDto: { + /** + * Format: uuid + * @description 队列任务 ID。 + */ + queueId: string; + /** @description 备注。 */ + note?: null | string; + }; + SaasCatalogSnapshot: { + features: components["schemas"]["SaasFeature"][]; + limitDefinitions: components["schemas"]["SaasFeatureLimitDefinition"][]; + offerings: components["schemas"]["SaasOffering"][]; + versions: components["schemas"]["SaasOfferingVersionItem"][]; + }; + SaasFeature: { + code?: string; + name?: string; + category?: string; + description?: null | string; + /** Format: int32 */ + referencePriceCents?: number | string; + currency?: string; + status?: components["schemas"]["SaasFeatureStatus"]; + isCore?: boolean; + /** Format: int32 */ + sortOrder?: number | string; + /** Format: date-time */ + createdAt?: string; + /** Format: date-time */ + updatedAt?: string; + /** Format: uuid */ + id?: string; + }; + SaasFeatureLimitDefinition: { + metricCode?: string; + featureCode?: string; + name?: string; + unit?: string; + kind?: components["schemas"]["SaasFeatureLimitKind"]; + /** Format: int32 */ + warningPercent?: number | string; + isHardLimit?: boolean; + /** Format: date-time */ + createdAt?: string; + /** Format: date-time */ + updatedAt?: string; + /** Format: uuid */ + id?: string; + }; + SaasFeatureLimitKind: number; + SaasFeatureStatus: number; + SaasOffering: { + code?: string; + name?: string; + type?: components["schemas"]["SaasOfferingType"]; + status?: components["schemas"]["SaasOfferingStatus"]; + description?: null | string; + /** Format: int32 */ + sortOrder?: number | string; + /** Format: date-time */ + createdAt?: string; + /** Format: date-time */ + updatedAt?: string; + /** Format: uuid */ + id?: string; + }; + SaasOfferingStatus: number; + SaasOfferingType: number; + SaasOfferingVersionItem: { + /** Format: uuid */ + id: string; + /** Format: uuid */ + offeringId: string; + offeringCode: string; + offeringName: string; + offeringType: components["schemas"]["SaasOfferingType"]; + /** Format: int32 */ + version: number | string; + status: components["schemas"]["SaasOfferingVersionStatus"]; + billingCycle: components["schemas"]["PlatformBillingCycle"]; + /** Format: int32 */ + originalAmountCents: number | string; + /** Format: int32 */ + amountCents: number | string; + currency: string; + /** Format: date-time */ + effectiveAt: null | string; + /** Format: date-time */ + publishedAt: null | string; + featureCodes: string[]; + limits: { + [key: string]: number | string; + }; + }; + SaasOfferingVersionStatus: number; + /** @description 保存租户前端配置草稿请求。 */ + SaveTenantFrontendConfigDraftDto: { + /** @description 品牌配置。 */ + branding?: components["schemas"]["JsonElement"]; + /** @description 主题配置。 */ + theme?: components["schemas"]["JsonElement"]; + /** @description 功能配置。 */ + features?: components["schemas"]["JsonElement"]; + /** @description 导航配置。 */ + navigation?: components["schemas"]["JsonElement"]; + /** @description 首页模块配置。 */ + homeModules?: components["schemas"]["JsonElement"]; + }; + School: { + /** Format: uuid */ + regionId?: null | string; + /** Format: uuid */ + moduleId?: null | string; + legacyId?: null | string; + name?: string; + professionalExamDate?: null | string; + metadata?: components["schemas"]["JsonElement"]; + /** Format: date-time */ + createdAt?: string; + /** Format: date-time */ + updatedAt?: string; + /** Format: uuid */ + tenantId?: string; + /** Format: uuid */ + id?: string; + }; + SchoolCatalogItem: { + /** Format: uuid */ + id: string; + legacyId: null | string; + /** Format: uuid */ + regionId: null | string; + /** Format: uuid */ + moduleId: null | string; + name: string; + professionalExamDate: null | string; + metadata: components["schemas"]["JsonElement"]; + }; + ScorelineField: { + /** Format: uuid */ + regionId?: null | string; + legacyId?: null | string; + fieldKey?: string; + fieldName?: string; + fieldType?: string; + unit?: null | string; + isFilter?: boolean; + isRequired?: boolean; + isVisible?: boolean; + isTrend?: boolean; + options?: components["schemas"]["JsonElement"]; + placeholder?: null | string; + description?: null | string; + /** Format: int32 */ + sortOrder?: number | string; + /** Format: date-time */ + createdAt?: string; + /** Format: date-time */ + updatedAt?: string; + /** Format: uuid */ + tenantId?: string; + /** Format: uuid */ + id?: string; + }; + ScorelineFieldItem: { + /** Format: uuid */ + id: string; + legacyId: null | string; + /** Format: uuid */ + regionId: null | string; + fieldKey: string; + fieldName: string; + fieldType: string; + unit: null | string; + isFilter: boolean; + isRequired: boolean; + isVisible: boolean; + isTrend: boolean; + options: components["schemas"]["JsonElement"]; + placeholder: null | string; + description: null | string; + /** Format: int32 */ + sortOrder: number | string; + }; + ScorelineRecord: { + /** Format: uuid */ + regionId?: null | string; + /** Format: uuid */ + schoolId?: null | string; + /** Format: uuid */ + majorId?: null | string; + legacyId?: null | string; + /** Format: int32 */ + year?: number | string; + schoolName?: null | string; + majorName?: null | string; + fieldValues?: components["schemas"]["JsonElement"]; + /** Format: date-time */ + createdAt?: string; + /** Format: date-time */ + updatedAt?: string; + /** Format: uuid */ + tenantId?: string; + /** Format: uuid */ + id?: string; + }; + ScorelineRecordCursorPage: { + /** Format: int32 */ + pageSize: number | string; + hasMore: boolean; + nextCursor: null | string; + items: components["schemas"]["ScorelineRecordItem"][]; + }; + ScorelineRecordItem: { + /** Format: uuid */ + id: string; + legacyId: null | string; + /** Format: uuid */ + regionId: null | string; + /** Format: uuid */ + schoolId: null | string; + /** Format: uuid */ + majorId: null | string; + /** Format: int32 */ + year: number | string; + schoolName: null | string; + majorName: null | string; + fieldValues: components["schemas"]["JsonElement"]; + }; + ScorelineRecordPage: { + /** Format: int32 */ + page: number | string; + /** Format: int32 */ + pageSize: number | string; + /** Format: int32 */ + total: number | string; + items: components["schemas"]["ScorelineRecordItem"][]; + }; + ScorelineTrendItem: { + /** Format: int32 */ + year: number | string; + /** Format: int32 */ + schoolCount: number | string; + /** Format: int32 */ + majorCount: number | string; + }; + /** @description 发送短信验证码请求。 */ + SendSmsCodeDto: { + realm: null | components["schemas"]["AuthRealm"]; + /** @description 租户编码。 */ + tenantCode?: null | string; + /** @description 手机号。 */ + phone: string; + /** @description 设备 ID。 */ + deviceId?: null | string; + }; + /** @description SignedStorageUrl请求 DTO。 */ + SignedStorageUrlDto: { + provider: string; + bucket: null | string; + objectKey: null | string; + method: string; + url: string; + headers: { + [key: string]: string; + }; + /** Format: date-time */ + expiresAt: string; + /** Format: int32 */ + expiresInSeconds: number | string; + signatureMode: string; + }; + SimpleImportResult: { + job: components["schemas"]["ContentImportJobItem"]; + items: components["schemas"]["ContentImportItemModel"][]; + issues: components["schemas"]["ContentImportIssueModel"][]; + }; + /** @description SmsLogin请求 DTO。 */ + SmsLoginDto: { + realm: null | components["schemas"]["AuthRealm"]; + /** @description 租户编码。 */ + tenantCode?: null | string; + /** @description 手机号。 */ + phone: string; + /** @description 编码。 */ + code: string; + }; + SmsSendLog: { + /** Format: uuid */ + tenantId?: string; + /** Format: uuid */ + channelId?: null | string; + /** Format: uuid */ + templateId?: null | string; + provider?: string; + scene?: string; + phoneMasked?: null | string; + status?: components["schemas"]["SmsSendLogStatus"]; + providerMessageId?: null | string; + errorCode?: null | string; + errorMessage?: null | string; + /** Format: date-time */ + sentAt?: null | string; + metadata?: components["schemas"]["JsonElement"]; + /** Format: date-time */ + createdAt?: string; + /** Format: uuid */ + id?: string; + }; + SmsSendLogStatus: number; + SmsSendResult: { + /** Format: uuid */ + verificationId: string; + /** Format: date-time */ + expiresAt: string; + }; + SmsTemplateAuditStatus: number; + SmsTemplateStatus: number; + SmsTemplateType: number; + StudentFollowupPriority: number; + StudentFollowupStatus: number; + StudentFollowupType: number; + StudentMembershipItem: { + isSvip: boolean; + /** Format: date-time */ + expiresAt: null | string; + }; + StudentNoteType: number; + StudentNoteVisibility: number; + StudentProfileItem: { + /** Format: uuid */ + profileId: string; + /** Format: uuid */ + userId: string; + username: null | string; + phone: null | string; + email: null | string; + name: null | string; + avatarPreset: string; + avatarDisplayUrl: string; + primaryRole: string; + /** Format: int32 */ + score: number | string; + /** Format: uuid */ + regionId: null | string; + regionName: null | string; + /** Format: uuid */ + selectedSchoolId: null | string; + selectedSchoolName: null | string; + /** Format: uuid */ + selectedMajorId: null | string; + selectedMajorName: null | string; + /** Format: int32 */ + questionsAnsweredToday: number | string; + /** Format: int32 */ + masteredWordsCount: number | string; + /** Format: date */ + lastCheckInDate: null | string; + stats: components["schemas"]["JsonElement"]; + progress: components["schemas"]["JsonElement"]; + moduleSelections: components["schemas"]["JsonElement"]; + recentActivities: components["schemas"]["JsonElement"]; + recentPractices: components["schemas"]["RecentPracticeItem"][]; + membership: components["schemas"]["StudentMembershipItem"]; + }; + SubjectCatalogItem: { + /** Format: uuid */ + id: string; + legacyId: null | string; + /** Format: uuid */ + regionId: null | string; + /** Format: uuid */ + moduleId: null | string; + /** Format: uuid */ + schoolId: null | string; + /** Format: uuid */ + majorId: null | string; + /** Format: uuid */ + nodeId: null | string; + name: string; + type: null | components["schemas"]["SubjectType"]; + icon: null | string; + description: null | string; + stats: components["schemas"]["JsonElement"]; + /** Format: int32 */ + order: number | string; + }; + SubjectType: number; + /** @description 提交答案请求 DTO。 */ + SubmitAnswerDto: { + /** + * Format: uuid + * @description 会话题目 ID。 + */ + sessionQuestionId: string; + /** @description 已选选项。 */ + selectedOptions?: null | string[]; + /** @description 文字答案。 */ + answerText?: null | string; + /** @description 主观题自评是否正确。 */ + selfJudgedCorrect?: null | boolean; + }; + /** @description 提交反馈请求 DTO。 */ + SubmitFeedbackDto: { + /** + * Format: uuid + * @description 题目 ID。 + */ + questionId?: null | string; + /** @description 类型。 */ + type?: null | string; + /** @description 分类。 */ + category?: null | string; + /** @description 标题。 */ + title?: null | string; + /** @description 说明。 */ + description: string; + /** @description 优先级。 */ + priority?: null | string; + /** @description 联系方式。 */ + contact?: null | string; + /** @description 附件列表。 */ + attachments?: components["schemas"]["JsonElement"]; + /** @description 扩展元数据。 */ + metadata?: components["schemas"]["JsonElement"]; + }; + /** @description 提交练习会话请求 DTO。 */ + SubmitPracticeSessionDto: { + /** + * Format: uuid + * @description 练习会话 ID。 + */ + practiceSessionId: string; + }; + SvipPlanCatalogItem: { + /** Format: uuid */ + id: string; + legacyId: null | string; + /** Format: uuid */ + regionId: null | string; + name: string; + /** Format: int32 */ + priceCents: number | string; + /** Format: double */ + price: number | string; + /** Format: int32 */ + originalPriceCents: null | number | string; + /** Format: double */ + originalPrice: null | number | string; + /** Format: int32 */ + days: number | string; + description: null | string; + perDayLabel: null | string; + badge: null | string; + recommended: boolean; + couponOnly: boolean; + vpProductId: null | string; + vpEnabled: boolean; + /** Format: int32 */ + order: number | string; + isActive: boolean; + }; + TaxonomyNodeItem: { + /** Format: uuid */ + id: string; + source: components["schemas"]["QuestionSource"]; + /** Format: uuid */ + parentId: null | string; + parentSource: null | components["schemas"]["QuestionSource"]; + nodeType: components["schemas"]["TaxonomyNodeType"]; + code: string; + name: string; + path: null | string; + /** Format: int32 */ + depth: number | string; + /** Format: int32 */ + sortOrder: number | string; + metadata: components["schemas"]["JsonElement"]; + }; + TaxonomyNodeType: number; + TenantAdjustmentReport: { + /** Format: int32 */ + draftCount: number | string; + /** Format: int32 */ + pendingReviewCount: number | string; + /** Format: int32 */ + approvedCount: number | string; + /** Format: int32 */ + closedCount: number | string; + /** Format: int32 */ + increaseRevenueCents: number | string; + /** Format: int32 */ + decreaseRevenueCents: number | string; + }; + TenantAdjustmentVoucherEventList: { + items: components["schemas"]["CommerceAdjustmentVoucherEvent"][]; + }; + TenantAdjustmentVoucherList: { + items: components["schemas"]["CommerceAdjustmentVoucher"][]; + }; + TenantAdminAuditLogItem: { + /** Format: uuid */ + id: string; + /** Format: uuid */ + actorUserId: null | string; + action: string; + targetType: null | string; + targetId: null | string; + details: components["schemas"]["JsonElement"]; + ipAddress: null | string; + userAgent: null | string; + actorName: null | string; + actorPhone: null | string; + /** Format: date-time */ + createdAt: string; + }; + TenantAdminBadgeGrantItem: { + /** Format: uuid */ + id: string; + legacyId: null | string; + /** Format: uuid */ + userId: null | string; + userName: null | string; + userPhone: null | string; + /** Format: uuid */ + badgeId: null | string; + badgeName: null | string; + badgeCategory: null | string; + iconUrl: null | string; + /** Format: int32 */ + level: null | number | string; + /** Format: uuid */ + grantedBy: null | string; + grantedByName: null | string; + note: null | string; + /** Format: date-time */ + grantedAt: null | string; + /** Format: date-time */ + createdAt: string; + /** Format: date-time */ + updatedAt: string; + }; + TenantAdminBadgeItem: { + /** Format: uuid */ + id: string; + legacyId: null | string; + name: string; + description: null | string; + category: null | string; + iconUrl: null | string; + /** Format: int32 */ + level: null | number | string; + unlockType: null | string; + conditionField: null | string; + conditionOperator: null | string; + /** Format: double */ + conditionValue: null | number | string; + conditionExtra: components["schemas"]["JsonElement"]; + /** Format: int32 */ + order: number | string; + isActive: boolean; + /** Format: date-time */ + createdAt: string; + /** Format: date-time */ + updatedAt: string; + }; + /** @description 租户管理端批量分配班级请求 DTO。 */ + TenantAdminBulkAssignClassDto: { + /** + * Format: uuid + * @description 班级 ID。 + */ + classId: string; + /** @description 用户 ID 列表。 */ + userIds: string[]; + }; + TenantAdminBulkOperationResult: { + /** Format: int32 */ + requestedCount: number | string; + /** Format: int32 */ + succeededCount: number | string; + /** Format: int32 */ + failedCount: number | string; + failedUserIds: string[]; + }; + /** @description 租户管理端批量状态请求 DTO。 */ + TenantAdminBulkStatusDto: { + /** @description 用户 ID 列表。 */ + userIds: string[]; + /** @description 状态。 */ + status?: null | string; + /** @description 原因。 */ + reason?: null | string; + }; + TenantAdminClassItem: { + /** Format: uuid */ + id: string; + /** Format: uuid */ + regionId: null | string; + regionName: null | string; + legacyId: null | string; + code: null | string; + name: string; + description: null | string; + status: components["schemas"]["TenantRecordStatus"]; + /** Format: int32 */ + order: number | string; + metadata: components["schemas"]["JsonElement"]; + /** Format: int32 */ + studentCount: number | string; + /** Format: int32 */ + staffCount: number | string; + /** Format: date-time */ + createdAt: string; + /** Format: date-time */ + updatedAt: string; + }; + TenantAdminClassList: { + items: components["schemas"]["TenantAdminClassItem"][]; + scoped: boolean; + }; + TenantAdminClassMemberItem: { + /** Format: uuid */ + id: string; + /** Format: uuid */ + classId: string; + /** Format: uuid */ + userId: string; + memberType: components["schemas"]["TenantClassMemberType"]; + status: components["schemas"]["TenantClassMemberStatus"]; + /** Format: date-time */ + joinedAt: string; + /** Format: date-time */ + leftAt: null | string; + metadata: components["schemas"]["JsonElement"]; + user: components["schemas"]["TenantAdminUserSummary"]; + }; + TenantAdminFeedbackItem: { + /** Format: uuid */ + id: string; + /** Format: uuid */ + userId: null | string; + userName: null | string; + userPhone: null | string; + /** Format: uuid */ + questionId: null | string; + type: null | components["schemas"]["ReportType"]; + title: null | string; + category: null | string; + description: null | string; + status: components["schemas"]["ReportStatus"]; + priority: components["schemas"]["ReportPriority"]; + /** Format: uuid */ + handledBy: null | string; + /** Format: date-time */ + handledAt: null | string; + resolution: null | string; + contact: null | string; + attachments: components["schemas"]["JsonElement"]; + metadata: components["schemas"]["JsonElement"]; + /** Format: date-time */ + createdAt: string; + /** Format: date-time */ + updatedAt: string; + }; + TenantAdminMemberItem: { + /** Format: uuid */ + membershipId: string; + /** Format: uuid */ + userId: string; + role: components["schemas"]["TenantRole"]; + status: components["schemas"]["MembershipStatus"]; + legacyRole: null | string; + user: components["schemas"]["TenantAdminUserSummary"]; + /** Format: date-time */ + createdAt: string; + /** Format: date-time */ + updatedAt: string; + }; + TenantAdminNotificationItem: { + /** Format: uuid */ + id: string; + /** Format: uuid */ + userId: string; + notificationType: string; + status: components["schemas"]["NotificationStatus"]; + severity: components["schemas"]["NotificationSeverity"]; + title: string; + message: string; + actionLabel: null | string; + actionPath: null | string; + sourceType: null | string; + /** Format: uuid */ + sourceId: null | string; + dedupeKey: null | string; + metadata: components["schemas"]["JsonElement"]; + /** Format: uuid */ + createdBy: null | string; + /** Format: date-time */ + readAt: null | string; + /** Format: date-time */ + createdAt: string; + /** Format: date-time */ + updatedAt: string; + }; + TenantAdminOverviewItem: { + /** Format: int32 */ + studentCount: number | string; + /** Format: int32 */ + classCount: number | string; + /** Format: int32 */ + staffCount: number | string; + /** Format: int32 */ + activePracticeCount: number | string; + /** Format: int32 */ + todayPracticeCount: number | string; + /** Format: int32 */ + pendingFollowupCount: number | string; + /** Format: int32 */ + unreadNotificationCount: number | string; + /** Format: int32 */ + paidOrderCount: number | string; + /** Format: int32 */ + revenueCents: number | string; + /** Format: int32 */ + pendingRefundCount: number | string; + /** Format: int32 */ + openReconciliationIssueCount: number | string; + /** Format: date-time */ + generatedAt: string; + }; + TenantAdminStudentClassSummary: { + /** Format: uuid */ + classId: string; + className: string; + classCode: null | string; + memberType: components["schemas"]["TenantClassMemberType"]; + /** Format: date-time */ + joinedAt: string; + }; + TenantAdminStudentFollowupItem: { + /** Format: uuid */ + id: string; + /** Format: uuid */ + studentUserId: string; + /** Format: uuid */ + assignedToUserId: null | string; + /** Format: uuid */ + classId: null | string; + title: string; + description: null | string; + followupType: components["schemas"]["StudentFollowupType"]; + priority: components["schemas"]["StudentFollowupPriority"]; + status: components["schemas"]["StudentFollowupStatus"]; + /** Format: date-time */ + dueAt: null | string; + /** Format: date-time */ + completedAt: null | string; + /** Format: uuid */ + completedBy: null | string; + metadata: components["schemas"]["JsonElement"]; + /** Format: uuid */ + createdBy: null | string; + /** Format: uuid */ + updatedBy: null | string; + /** Format: date-time */ + createdAt: string; + /** Format: date-time */ + updatedAt: string; + }; + /** @description 租户管理端学生导入请求 DTO。 */ + TenantAdminStudentImportDto: { + /** @description 数据行列表。 */ + rows: components["schemas"]["TenantAdminStudentImportRowDto"][]; + }; + TenantAdminStudentImportPreview: { + /** Format: int32 */ + totalCount: number | string; + /** Format: int32 */ + validCount: number | string; + /** Format: int32 */ + invalidCount: number | string; + items: components["schemas"]["TenantAdminStudentImportPreviewItem"][]; + }; + TenantAdminStudentImportPreviewItem: { + /** Format: int32 */ + rowNo: number | string; + valid: boolean; + reason: null | string; + phone: null | string; + email: null | string; + name: null | string; + /** Format: uuid */ + regionId: null | string; + /** Format: uuid */ + classId: null | string; + }; + TenantAdminStudentImportResult: { + /** Format: int32 */ + totalCount: number | string; + /** Format: int32 */ + createdOrUpdatedCount: number | string; + /** Format: int32 */ + classAssignedCount: number | string; + invalidItems: components["schemas"]["TenantAdminStudentImportPreviewItem"][]; + }; + /** @description 租户管理端学生导入行请求 DTO。 */ + TenantAdminStudentImportRowDto: { + /** @description 用户信息。 */ + user?: components["schemas"]["TenantAdminUserLookupDto"]; + /** + * Format: uuid + * @description 地区 ID。 + */ + regionId?: null | string; + /** + * Format: uuid + * @description 班级 ID。 + */ + classId?: null | string; + /** @description 头像预设。 */ + avatarPreset?: null | string; + /** @description 原始用户资料。 */ + rawProfile?: components["schemas"]["JsonElement"]; + }; + TenantAdminStudentItem: { + /** Format: uuid */ + membershipId: string; + /** Format: uuid */ + userId: string; + status: components["schemas"]["MembershipStatus"]; + user: components["schemas"]["TenantAdminUserSummary"]; + /** Format: uuid */ + profileId: null | string; + avatarPreset: string; + /** Format: uuid */ + regionId: null | string; + regionName: null | string; + /** Format: uuid */ + selectedSchoolId: null | string; + selectedSchoolName: null | string; + /** Format: uuid */ + selectedMajorId: null | string; + selectedMajorName: null | string; + stats: components["schemas"]["JsonElement"]; + progress: components["schemas"]["JsonElement"]; + moduleSelections: components["schemas"]["JsonElement"]; + classes: components["schemas"]["TenantAdminStudentClassSummary"][]; + /** Format: date-time */ + createdAt: string; + /** Format: date-time */ + updatedAt: string; + }; + TenantAdminStudentList: { + items: components["schemas"]["TenantAdminStudentItem"][]; + scoped: boolean; + }; + TenantAdminStudentNoteItem: { + /** Format: uuid */ + id: string; + /** Format: uuid */ + studentUserId: string; + noteType: components["schemas"]["StudentNoteType"]; + content: string; + visibility: components["schemas"]["StudentNoteVisibility"]; + isPinned: boolean; + metadata: components["schemas"]["JsonElement"]; + /** Format: uuid */ + createdBy: null | string; + /** Format: uuid */ + updatedBy: null | string; + /** Format: date-time */ + createdAt: string; + /** Format: date-time */ + updatedAt: string; + }; + TenantAdminStudentStatusItem: { + /** Format: uuid */ + membershipId: string; + /** Format: uuid */ + userId: string; + role: components["schemas"]["TenantRole"]; + status: components["schemas"]["MembershipStatus"]; + /** Format: date-time */ + updatedAt: string; + }; + /** @description 租户管理端用户查找请求 DTO。 */ + TenantAdminUserLookupDto: { + /** + * Format: uuid + * @description 用户 ID。 + */ + userId?: null | string; + /** @description 用户名。 */ + username?: null | string; + /** @description 邮箱。 */ + email?: null | string; + /** @description 手机号。 */ + phone?: null | string; + /** @description 名称。 */ + name?: null | string; + /** @description 头像地址。 */ + avatarUrl?: null | string; + }; + TenantAdminUserSummary: { + /** Format: uuid */ + id: string; + username: null | string; + email: null | string; + phone: null | string; + name: null | string; + avatarUrl: null | string; + primaryRole: string; + }; + TenantBillingCatalog: { + features: components["schemas"]["SaasFeature"][]; + basePlans: components["schemas"]["SaasOfferingVersionItem"][]; + addOns: components["schemas"]["SaasOfferingVersionItem"][]; + }; + TenantBillingInvoiceTitleType: number; + TenantBillingProfileItem: { + /** Format: uuid */ + tenantId: string; + billingName: null | string; + taxId: null | string; + contactName: null | string; + contactPhoneMasked: null | string; + contactEmail: null | string; + billingAddress: null | string; + invoiceTitle: null | string; + invoiceType: null | components["schemas"]["TenantBillingInvoiceTitleType"]; + bankName: null | string; + bankAccountMasked: null | string; + metadata: components["schemas"]["JsonElement"]; + }; + TenantBrandingItem: { + /** Format: uuid */ + tenantId: string; + brandName: string; + shortName: null | string; + slogan: null | string; + organizationName: null | string; + logoUrl: null | string; + faviconUrl: null | string; + serviceWechat: null | string; + serviceAccountName: null | string; + theme: components["schemas"]["JsonElement"]; + publicAssets: components["schemas"]["JsonElement"]; + /** Format: date-time */ + updatedAt: string; + }; + TenantClassMemberStatus: number; + TenantClassMemberType: number; + TenantCommerceAnomalySummary: { + /** Format: int32 */ + openRefundCount: number | string; + /** Format: int32 */ + processingRefundCount: number | string; + /** Format: int32 */ + openReconciliationIssueCount: number | string; + /** Format: int32 */ + failedReconciliationBatchCount: number | string; + /** Format: int32 */ + pendingPaymentCount: number | string; + /** Format: int32 */ + paymentMismatchCount: number | string; + }; + TenantCouponList: { + items: components["schemas"]["Coupon"][]; + }; + TenantCouponRedemptionList: { + items: components["schemas"]["CouponRedemption"][]; + }; + TenantCouponReport: { + /** Format: int32 */ + couponCount: number | string; + /** Format: int32 */ + claimedCount: number | string; + /** Format: int32 */ + usedCount: number | string; + /** Format: int32 */ + discountAppliedCents: number | string; + }; + TenantDomainItem: { + /** Format: uuid */ + id: string; + host: string; + domainType: components["schemas"]["TenantDomainType"]; + status: components["schemas"]["TenantDomainStatus"]; + isPrimary: boolean; + verificationToken: null | string; + /** Format: date-time */ + verifiedAt: null | string; + /** Format: date-time */ + lastCheckedAt: null | string; + /** Format: date-time */ + dnsVerifiedAt: null | string; + /** Format: date-time */ + tlsReadyAt: null | string; + lastFailureReason: null | string; + /** Format: date-time */ + createdAt: string; + /** Format: date-time */ + updatedAt: string; + }; + TenantDomainStatus: number; + TenantDomainType: number; + TenantExternalProviderCapability: number; + TenantExternalProviderItem: { + /** Format: uuid */ + id: string; + capability: components["schemas"]["TenantExternalProviderCapability"]; + provider: string; + status: components["schemas"]["TenantExternalProviderStatus"]; + displayName: null | string; + secretRef: null | string; + /** Format: int32 */ + priority: number | string; + configPublic: components["schemas"]["JsonElement"]; + metadata: components["schemas"]["JsonElement"]; + /** Format: date-time */ + createdAt: string; + /** Format: date-time */ + updatedAt: string; + }; + TenantExternalProviderStatus: number; + TenantFeatureOverride: { + featureCode?: string; + mode?: components["schemas"]["TenantFeatureOverrideMode"]; + /** Format: date-time */ + expiresAt?: null | string; + reason?: string; + /** Format: date-time */ + createdAt?: string; + /** Format: date-time */ + updatedAt?: string; + /** Format: uuid */ + tenantId?: string; + /** Format: uuid */ + id?: string; + }; + TenantFeatureOverrideMode: number; + TenantFeatureUsage: { + metricCode?: string; + /** Format: date-time */ + periodStart?: string; + /** Format: date-time */ + periodEnd?: string; + /** Format: int64 */ + usedValue?: number | string; + /** Format: int64 */ + limitValueSnapshot?: number | string; + warningIssued?: boolean; + /** Format: int64 */ + version?: number | string; + /** Format: date-time */ + createdAt?: string; + /** Format: date-time */ + updatedAt?: string; + /** Format: uuid */ + tenantId?: string; + /** Format: uuid */ + id?: string; + }; + TenantFeedbackReport: { + /** Format: int32 */ + pendingCount: number | string; + /** Format: int32 */ + acceptedCount: number | string; + /** Format: int32 */ + rejectedCount: number | string; + /** Format: int32 */ + resolvedCount: number | string; + /** Format: int32 */ + closedCount: number | string; + }; + TenantFollowupReport: { + /** Format: int32 */ + openCount: number | string; + /** Format: int32 */ + inProgressCount: number | string; + /** Format: int32 */ + doneCount: number | string; + /** Format: int32 */ + overdueCount: number | string; + }; + TenantFrontendConfigDraft: { + branding: components["schemas"]["JsonElement"]; + theme: components["schemas"]["JsonElement"]; + features: components["schemas"]["JsonElement"]; + navigation: components["schemas"]["JsonElement"]; + homeModules: components["schemas"]["JsonElement"]; + }; + TenantFrontendConfigItem: { + /** Format: int32 */ + schemaVersion: number | string; + /** Format: int32 */ + configVersion: number | string; + published: components["schemas"]["TenantFrontendConfigDraft"]; + draft: components["schemas"]["TenantFrontendConfigDraft"]; + /** Format: date-time */ + publishedAt: null | string; + }; + TenantIdentityProviderItem: { + /** Format: uuid */ + id: string; + provider: string; + status: components["schemas"]["TenantExternalProviderStatus"]; + displayName: null | string; + secretRef: null | string; + /** Format: int32 */ + priority: number | string; + configPublic: components["schemas"]["JsonElement"]; + /** Format: date-time */ + createdAt: string; + /** Format: date-time */ + updatedAt: string; + }; + /** @description 用户在某个租户内的成员摘要。 */ + TenantMembershipResponse: { + /** + * Format: uuid + * @description 租户 ID。 + */ + tenantId: string; + /** @description 租户名称。 */ + tenantName: string; + /** @description 租户编码。 */ + tenantSlug: string; + /** @description 当前用户在该租户内的角色。 */ + role: components["schemas"]["TenantRole"]; + /** @description 租户成员状态。 */ + status: components["schemas"]["MembershipStatus"]; + }; + /** @description 当前登录租户成员摘要。 */ + TenantMembershipSummary: { + /** + * Format: uuid + * @description 租户 ID。 + */ + tenantId: string; + /** @description 租户名称。 */ + tenantName: string; + /** @description 当前用户在租户内的角色。 */ + role: components["schemas"]["TenantRole"]; + /** @description 租户成员状态。 */ + status: components["schemas"]["MembershipStatus"]; + }; + TenantMode: number; + TenantOnboardingStatus: { + /** Format: uuid */ + tenantId: string; + readyForStudentTraffic: boolean; + /** Format: int32 */ + completedRequiredSteps: number | string; + /** Format: int32 */ + requiredSteps: number | string; + steps: components["schemas"]["TenantOnboardingStep"][]; + }; + TenantOnboardingStep: { + code: string; + required: boolean; + completed: boolean; + detail: null | string; + }; + TenantPaymentProviderItem: { + /** Format: uuid */ + id: string; + provider: string; + mode: string; + displayName: null | string; + status: components["schemas"]["TenantExternalProviderStatus"]; + secretRef: null | string; + /** Format: int32 */ + priority: number | string; + configPublic: components["schemas"]["JsonElement"]; + /** Format: date-time */ + createdAt: string; + /** Format: date-time */ + updatedAt: string; + }; + TenantPointClaimList: { + items: components["schemas"]["PointActivityClaim"][]; + }; + TenantPointExchangeItemList: { + items: components["schemas"]["PointExchangeItem"][]; + }; + TenantPointExchangeOrderList: { + items: components["schemas"]["PointExchangeOrder"][]; + }; + TenantPointRiskReport: { + /** Format: int32 */ + negativeScoreUserCount: number | string; + /** Format: int32 */ + highPointClaimUserCount: number | string; + /** Format: int32 */ + cancelledExchangeOrderCount: number | string; + }; + TenantPointTaskList: { + items: components["schemas"]["PointActivityTask"][]; + }; + TenantReconciliationBatchList: { + items: components["schemas"]["CommerceReconciliationBatch"][]; + }; + TenantReconciliationIssueEventList: { + items: components["schemas"]["CommerceReconciliationIssueEvent"][]; + }; + TenantReconciliationIssueList: { + items: components["schemas"]["CommerceReconciliationIssue"][]; + }; + TenantReconciliationItemList: { + items: components["schemas"]["CommerceReconciliationItem"][]; + }; + TenantRecordStatus: number; + TenantRefundEventList: { + items: components["schemas"]["CommerceRefundEvent"][]; + }; + TenantRefundList: { + items: components["schemas"]["CommerceRefundRequest"][]; + }; + /** @description 租户解析响应。 */ + TenantResolveResponseDto: { + /** @description 公开租户基础信息。 */ + tenant: components["schemas"]["PublicTenantDto"]; + /** @description 公开品牌配置。 */ + branding: components["schemas"]["PublicTenantBrandingDto"]; + /** @description 面向前端公开的功能开关。 */ + features: components["schemas"]["JsonElement"]; + /** @description 面向管理端公开的功能开关。 */ + adminFeatures: components["schemas"]["JsonElement"]; + /** @description 可公开的租户配置,不包含密钥或内部配置。 */ + publicConfig: components["schemas"]["JsonElement"]; + }; + TenantRole: number; + TenantRuntimeBootstrap: { + /** Format: int32 */ + schemaVersion: number | string; + /** Format: int32 */ + configVersion: number | string; + tenantCode: string; + tenantName: string; + branding: components["schemas"]["JsonElement"]; + theme: components["schemas"]["JsonElement"]; + features: components["schemas"]["JsonElement"]; + navigation: components["schemas"]["JsonElement"]; + homeModules: components["schemas"]["JsonElement"]; + enabledFeatures: string[]; + loginMethods: string[]; + }; + TenantSaasSubscription: { + /** Format: uuid */ + baseOfferingVersionId?: string; + /** Format: uuid */ + scheduledBaseOfferingVersionId?: null | string; + status?: components["schemas"]["TenantSaasSubscriptionStatus"]; + /** Format: date-time */ + startsAt?: string; + /** Format: date-time */ + currentPeriodStart?: string; + /** Format: date-time */ + currentPeriodEnd?: string; + cancelAtPeriodEnd?: boolean; + /** Format: date-time */ + cancelledAt?: null | string; + /** Format: int64 */ + lifecycleVersion?: number | string; + metadata?: components["schemas"]["JsonElement"]; + /** Format: date-time */ + createdAt?: string; + /** Format: date-time */ + updatedAt?: string; + /** Format: uuid */ + tenantId?: string; + /** Format: uuid */ + id?: string; + }; + TenantSaasSubscriptionStatus: number; + TenantSecretItem: { + /** Format: uuid */ + id: string; + purpose: string; + provider: string; + secretKey: string; + secretRef: string; + status: string; + /** Format: date-time */ + rotatedAt: null | string; + /** Format: date-time */ + expiresAt: null | string; + /** Format: date-time */ + updatedAt: string; + }; + TenantSecretStatus: number; + TenantSettingsItem: { + /** Format: uuid */ + tenantId: string; + featureFlags: components["schemas"]["JsonElement"]; + adminFeatureFlags: components["schemas"]["JsonElement"]; + publicConfig: components["schemas"]["JsonElement"]; + /** Format: date-time */ + updatedAt: string; + }; + TenantStatus: number; + TenantSubscriptionView: { + /** Format: uuid */ + id: string; + status: components["schemas"]["TenantSaasSubscriptionStatus"]; + /** Format: date-time */ + startsAt: string; + /** Format: date-time */ + currentPeriodStart: string; + /** Format: date-time */ + currentPeriodEnd: string; + cancelAtPeriodEnd: boolean; + /** Format: uuid */ + baseOfferingVersionId: string; + /** Format: uuid */ + scheduledBaseOfferingVersionId: null | string; + featureCodes: string[]; + }; + /** @description 租户督导生成请求 DTO。 */ + TenantSupervisionGenerateDto: { + /** @description 用户 ID 列表。 */ + userIds?: null | string[]; + /** + * Format: uuid + * @description 分配处理人用户 ID。 + */ + assignedToUserId?: null | string; + /** + * Format: date-time + * @description 到期时间。 + */ + dueAt?: null | string; + }; + TenantSupervisionGenerateResult: { + /** Format: int32 */ + createdCount: number | string; + }; + TenantSupervisionPreview: { + items: components["schemas"]["TenantSupervisionRiskStudentItem"][]; + }; + TenantSupervisionRiskStudentItem: { + /** Format: uuid */ + userId: string; + name: null | string; + phoneMasked: null | string; + /** Format: uuid */ + regionId: null | string; + ruleCodes: string[]; + reasons: string[]; + }; + TenantSupervisionRuleItem: { + code: string; + title: string; + enabled: boolean; + /** Format: int32 */ + daysWithoutCheckIn: null | number | string; + /** Format: int32 */ + maxQuestionsAnsweredToday: null | number | string; + followupType: string; + priority: string; + metadata: components["schemas"]["JsonElement"]; + }; + TenantThemeConfigStatus: number; + TenantThemeItem: { + /** Format: uuid */ + tenantId: string; + activeTemplateCode: null | string; + activeTheme: components["schemas"]["JsonElement"]; + activePublicAssets: components["schemas"]["JsonElement"]; + draftTemplateCode: null | string; + draftTheme: components["schemas"]["JsonElement"]; + draftPublicAssets: components["schemas"]["JsonElement"]; + status: components["schemas"]["TenantThemeConfigStatus"]; + /** Format: date-time */ + publishedAt: null | string; + /** Format: uuid */ + publishedBy: null | string; + /** Format: uuid */ + draftUpdatedBy: null | string; + /** Format: date-time */ + updatedAt: string; + }; + TenantThemeTemplateItem: { + code: string; + name: string; + description: null | string; + previewImageUrl: null | string; + theme: components["schemas"]["JsonElement"]; + publicAssets: components["schemas"]["JsonElement"]; + /** Format: int32 */ + order: number | string; + }; + /** @description 记录推荐事件请求 DTO。 */ + TrackReferralEventDto: { + /** @description 推荐码。 */ + refCode: string; + /** @description 事件类型。 */ + eventType?: null | string; + /** @description 来源。 */ + source?: null | string; + /** + * Format: uuid + * @description 目标用户 ID。 + */ + targetUserId?: null | string; + metadata?: null | components["schemas"]["JsonElement"]; + /** @description 租户编码。 */ + tenantCode?: null | string; + }; + /** @description 更新调账凭证状态请求 DTO。 */ + UpdateAdjustmentVoucherStatusDto: { + /** + * Format: uuid + * @description 凭证 ID。 + */ + voucherId: string; + /** @description 状态。 */ + status?: components["schemas"]["CommerceAdjustmentVoucherStatus"]; + /** @description 备注。 */ + note?: null | string; + }; + /** @description 更新佣金结算凭证状态请求。 */ + UpdateCommissionProofStatusDto: { + /** + * Format: uuid + * @description 凭证 ID。 + */ + proofId: string; + /** @description 状态。 */ + status?: null | string; + /** @description 审核备注。 */ + reviewNote?: null | string; + metadata?: null | components["schemas"]["JsonElement"]; + }; + /** @description 保存佣金配置请求。 */ + UpdateCommissionSettingsDto: { + /** + * Format: double + * @description 默认佣金比例。 + */ + defaultRate?: null | number | string; + /** + * Format: int32 + * @description 最低结算金额,单位为分。 + */ + minSettlementCents?: null | number | string; + /** @description 结算周期。 */ + settlementCycle?: null | string; + config?: null | components["schemas"]["JsonElement"]; + }; + /** @description 更新佣金结算单状态请求 DTO。 */ + UpdateCommissionSettlementStatusDto: { + /** + * Format: uuid + * @description 结算单 ID。 + */ + settlementId: string; + /** @description 状态。 */ + status?: null | string; + /** @description 审核备注。 */ + reviewNote?: null | string; + /** @description 支付方式。 */ + paymentMethod?: null | string; + /** @description 收款账号。 */ + paymentAccount?: null | string; + metadata?: null | components["schemas"]["JsonElement"]; + }; + /** @description 调整成员佣金比例请求。 */ + UpdateMemberCommissionRateDto: { + /** + * Format: uuid + * @description 用户 ID。 + */ + userId: string; + /** + * Format: double + * @description 成员佣金比例。 + */ + commissionRate?: null | number | string; + commissionConfig?: null | components["schemas"]["JsonElement"]; + }; + /** @description 更新平台审计Alert状态请求 DTO。 */ + UpdatePlatformAuditAlertStatusDto: { + /** + * Format: uuid + * @description 告警 ID。 + */ + alertId: string; + /** @description 状态。 */ + status?: components["schemas"]["PlatformAuditAlertStatus"]; + /** @description 处理备注。 */ + resolutionNote?: null | string; + }; + /** @description 更新平台Staff状态请求 DTO。 */ + UpdatePlatformStaffStatusDto: { + /** + * Format: uuid + * @description 用户 ID。 + */ + userId: string; + /** @description 状态。 */ + status?: components["schemas"]["UserStatus"]; + /** @description 原因。 */ + reason?: null | string; + }; + /** @description 更新平台租户状态请求 DTO。 */ + UpdatePlatformTenantStatusDto: { + /** + * Format: uuid + * @description 租户 ID。 + */ + tenantId: string; + /** @description 状态。 */ + status?: components["schemas"]["TenantStatus"]; + /** @description 账务状态。 */ + billingStatus?: components["schemas"]["BillingStatus"]; + /** @description 原因。 */ + reason?: null | string; + }; + /** @description 更新积分兑换订单状态请求 DTO。 */ + UpdatePointExchangeOrderStatusDto: { + /** + * Format: uuid + * @description 订单 ID。 + */ + orderId: string; + /** @description 状态。 */ + status?: components["schemas"]["PointExchangeOrderStatus"]; + }; + /** @description 更新资料请求 DTO。 */ + UpdateProfileDto: { + /** @description 名称。 */ + name?: null | string; + /** @description 头像预设。 */ + avatarPreset?: null | string; + /** + * Format: uuid + * @description 地区 ID。 + */ + regionId?: null | string; + /** + * Format: uuid + * @description 已选择院校 ID。 + */ + selectedSchoolId?: null | string; + /** + * Format: uuid + * @description 已选择专业 ID。 + */ + selectedMajorId?: null | string; + stats?: null | components["schemas"]["JsonElement"]; + progress?: null | components["schemas"]["JsonElement"]; + moduleSelections?: null | components["schemas"]["JsonElement"]; + recentActivities?: null | components["schemas"]["JsonElement"]; + }; + /** @description 更新对账Issue请求 DTO。 */ + UpdateReconciliationIssueDto: { + /** + * Format: uuid + * @description 工单 ID。 + */ + issueId: string; + /** @description 状态。 */ + status?: components["schemas"]["ReconciliationIssueStatus"]; + /** @description 处理类型。 */ + resolutionType?: components["schemas"]["ReconciliationResolutionType"]; + /** @description 备注。 */ + note?: null | string; + /** + * Format: uuid + * @description 分配处理人。 + */ + assignedTo?: null | string; + }; + /** @description 更新退款状态请求 DTO。 */ + UpdateRefundStatusDto: { + /** + * Format: uuid + * @description 退款申请 ID。 + */ + refundRequestId: string; + /** @description 状态。 */ + status?: components["schemas"]["CommerceRefundStatus"]; + /** @description 原因。 */ + reason?: null | string; + /** @description 渠道退款单号。 */ + providerRefundNo?: null | string; + }; + /** @description 更新租户管理端反馈请求 DTO。 */ + UpdateTenantAdminFeedbackDto: { + /** + * Format: uuid + * @description 反馈 ID。 + */ + feedbackId: string; + /** @description 状态。 */ + status?: null | string; + /** @description 优先级。 */ + priority?: null | string; + /** @description 处理结果。 */ + resolution?: null | string; + /** @description 备注。 */ + note?: null | string; + /** @description 扩展元数据。 */ + metadata?: components["schemas"]["JsonElement"]; + }; + /** @description 更新租户管理端学生状态请求 DTO。 */ + UpdateTenantAdminStudentStatusDto: { + /** + * Format: uuid + * @description 用户 ID。 + */ + userId: string; + /** @description 状态。 */ + status?: null | string; + /** @description 原因。 */ + reason?: null | string; + }; + /** @description 新增或更新内容资产请求。 */ + UpsertAssetDto: { + /** + * Format: uuid + * @description 资产 ID。 + */ + assetId?: null | string; + /** + * Format: uuid + * @description 地区 ID。 + */ + regionId?: null | string; + /** + * Format: uuid + * @description 科目 ID。 + */ + subjectId?: null | string; + /** + * Format: uuid + * @description 分类 ID。 + */ + categoryId?: null | string; + /** + * Format: uuid + * @description 内容节点 ID。 + */ + contentNodeId?: null | string; + /** @description 历史系统 ID。 */ + legacyId?: null | string; + /** @description 资产键。 */ + assetKey?: null | string; + /** @description 标题。 */ + title?: null | string; + /** @description 分类。 */ + category?: null | string; + /** @description 说明。 */ + description?: null | string; + /** @description 文件名。 */ + fileName?: null | string; + /** @description CDN 地址。 */ + cdnUrl?: null | string; + /** @description 是否公开。 */ + isPublic?: null | boolean; + /** @description 资产类型。 */ + assetType?: null | string; + /** @description 可见性。 */ + visibility?: null | string; + /** @description 状态。 */ + status?: null | string; + /** @description 服务提供方。 */ + provider?: null | string; + /** @description 存储桶。 */ + bucket?: null | string; + /** @description 对象存储键。 */ + objectKey?: null | string; + /** @description MIME 类型。 */ + mimeType?: null | string; + /** + * Format: int64 + * @description 文件大小,单位为字节。 + */ + fileSizeBytes?: null | number | string; + /** @description SHA-256 校验值。 */ + checksumSha256?: null | string; + /** @description 预览地址。 */ + previewUrl?: null | string; + /** @description 预览对象存储键。 */ + previewObjectKey?: null | string; + /** + * Format: int32 + * @description 显示顺序。 + */ + order?: null | number | string; + /** @description 访问规则。 */ + accessRules?: components["schemas"]["JsonElement"]; + /** @description 扩展元数据。 */ + metadata?: components["schemas"]["JsonElement"]; + }; + /** @description 创建或更新后台角色请求。 */ + UpsertBackofficeRoleDto: { + /** + * Format: uuid + * @description ID。 + */ + id?: null | string; + /** @description 编码。 */ + code?: string; + /** @description 名称。 */ + name?: string; + /** @description 状态。 */ + status?: components["schemas"]["BackendRoleStatus"]; + /** @description 说明。 */ + description?: null | string; + dataScope?: null | components["schemas"]["JsonElement"]; + }; + /** @description 新增或更新内容条目请求 DTO。 */ + UpsertContentEntryDto: { + /** + * Format: uuid + * @description ID。 + */ + id?: null | string; + /** + * Format: uuid + * @description 地区 ID。 + */ + regionId?: null | string; + /** @description 历史系统 ID。 */ + legacyId?: null | string; + /** @description 入口键。 */ + entryKey?: null | string; + /** @description 名称。 */ + name: string; + /** @description 入口类型。 */ + entryType?: null | string; + /** @description 图标。 */ + icon?: null | string; + /** @description 路由地址。 */ + route?: null | string; + /** @description 说明。 */ + description?: null | string; + /** @description 可见性。 */ + visibility?: null | string; + /** @description 访问规则。 */ + accessRules?: components["schemas"]["JsonElement"]; + /** @description 布局配置。 */ + layoutConfig?: components["schemas"]["JsonElement"]; + /** + * Format: int32 + * @description 显示顺序。 + */ + order?: null | number | string; + /** @description 是否启用。 */ + isActive?: null | boolean; + }; + /** @description 新增或更新内容节点请求 DTO。 */ + UpsertContentNodeDto: { + /** + * Format: uuid + * @description ID。 + */ + id?: null | string; + /** + * Format: uuid + * @description 内容入口 ID。 + */ + entryId: string; + /** + * Format: uuid + * @description 地区 ID。 + */ + regionId?: null | string; + /** + * Format: uuid + * @description 父节点 ID。 + */ + parentId?: null | string; + /** @description 历史系统 ID。 */ + legacyId?: null | string; + /** @description 节点键。 */ + nodeKey?: null | string; + /** @description 名称。 */ + name: string; + /** @description 节点Type。 */ + nodeType?: null | string; + /** @description 标记类型。 */ + markerType?: null | string; + /** @description 标记配置。 */ + markerConfig?: components["schemas"]["JsonElement"]; + /** + * Format: int32 + * @description 显示顺序。 + */ + order?: null | number | string; + /** @description 是否启用。 */ + isActive?: null | boolean; + /** @description 是否可选择。 */ + isSelectable?: null | boolean; + /** @description 是否叶子节点。 */ + isLeaf?: null | boolean; + /** @description 访问规则。 */ + accessRules?: components["schemas"]["JsonElement"]; + /** @description 扩展元数据。 */ + metadata?: components["schemas"]["JsonElement"]; + }; + /** @description 新增或更新CRM配置请求 DTO。 */ + UpsertCrmConfigDto: { + /** @description 是否启用。 */ + enabled?: boolean; + /** @description 访问地址。 */ + url?: null | string; + /** @description 密钥引用。 */ + secretRef?: null | string; + /** @description 密钥内容。 */ + secret?: null | string; + /** @description 表单名称。 */ + formName?: null | string; + /** @description 考试类型。 */ + examType?: null | string; + /** + * Format: int32 + * @description 超时时长,单位为秒。 + */ + timeoutSeconds?: null | number | string; + /** + * Format: int32 + * @description 延迟秒数。 + */ + delaySeconds?: null | number | string; + /** @description 分配模式。 */ + assignmentMode?: null | string; + assignmentPool?: null | components["schemas"]["JsonElement"]; + assignmentConfig?: null | components["schemas"]["JsonElement"]; + }; + /** @description 新增或更新支付账号请求 DTO。 */ + UpsertPaymentAccountDto: { + /** @description 服务提供方。 */ + provider: string; + /** @description 模式。 */ + mode?: null | string; + /** @description 显示名称。 */ + displayName?: null | string; + /** @description 状态。 */ + status?: components["schemas"]["TenantExternalProviderStatus"]; + /** @description 密钥引用。 */ + secretRef?: null | string; + /** + * Format: int32 + * @description 优先级。 + */ + priority?: null | number | string; + /** @description 公开配置内容。 */ + configPublic?: components["schemas"]["JsonElement"]; + }; + /** @description 新增或更新平台DunningChannel请求 DTO。 */ + UpsertPlatformBillingDunningChannelDto: { + /** + * Format: uuid + * @description 通知渠道 ID。 + */ + channelId?: null | string; + /** @description 渠道编码。 */ + channelCode: string; + /** @description 名称。 */ + name: string; + /** @description 说明。 */ + description?: null | string; + /** @description 是否启用。 */ + enabled?: boolean; + /** @description 服务提供方。 */ + provider?: components["schemas"]["PlatformBillingDunningProvider"]; + /** @description Webhook 地址。 */ + webhookUrl: string; + /** @description 密钥引用。 */ + secretRef?: null | string; + /** @description 提醒类型列表。 */ + reminderTypes?: string[]; + /** @description 提醒渠道列表。 */ + reminderChannels?: string[]; + /** + * Format: int32 + * @description 最低提醒级别。 + */ + minReminderLevel?: number | string; + /** @description 租户 ID 列表。 */ + tenantIds?: string[]; + /** + * Format: int32 + * @description 超时时长,单位为秒。 + */ + timeoutSeconds?: number | string; + /** @description 扩展元数据。 */ + metadata?: components["schemas"]["JsonElement"]; + }; + /** @description 新增或更新租户 CRM 配置请求。 */ + UpsertPlatformCrmConfigDto: { + /** + * Format: uuid + * @description ID。 + */ + id?: null | string; + /** + * Format: uuid + * @description 租户 ID。 + */ + tenantId: string; + /** @description 是否启用。 */ + enabled?: boolean; + /** @description 回调地址。 */ + url?: null | string; + /** @description 密钥引用。 */ + secretRef?: null | string; + /** @description 表单名称。 */ + formName?: null | string; + /** @description 考试类型。 */ + examType?: null | string; + /** + * Format: int32 + * @description 超时时长,单位为秒。 + */ + timeoutSeconds?: null | number | string; + /** + * Format: int32 + * @description 延迟秒数。 + */ + delaySeconds?: null | number | string; + /** @description 分配模式。 */ + assignmentMode?: null | string; + assignmentPool?: null | components["schemas"]["JsonElement"]; + assignmentConfig?: null | components["schemas"]["JsonElement"]; + }; + /** @description 新增或更新平台支付应用请求。 */ + UpsertPlatformPaymentAppDto: { + /** + * Format: uuid + * @description ID。 + */ + id?: null | string; + /** @description 支付应用编码。 */ + appCode: string; + /** @description 支付应用名称。 */ + appName: string; + /** @description 状态。 */ + status?: components["schemas"]["PlatformPaymentAppStatus"]; + /** @description 结算模式。 */ + settlementMode?: string; + /** @description 说明。 */ + description?: null | string; + /** @description 扩展元数据。 */ + metadata?: components["schemas"]["JsonElement"]; + }; + /** @description 新增或更新平台支付渠道请求。 */ + UpsertPlatformPaymentChannelDto: { + /** + * Format: uuid + * @description ID。 + */ + id?: null | string; + /** + * Format: uuid + * @description 支付应用 ID。 + */ + appId: string; + /** @description 服务提供方。 */ + provider: string; + /** @description 模式。 */ + mode?: string; + /** @description 状态。 */ + status?: components["schemas"]["PlatformPaymentChannelStatus"]; + /** @description 显示名称。 */ + displayName: string; + /** @description 密钥引用。 */ + secretRef?: null | string; + /** @description 回调路径。 */ + callbackPath?: null | string; + /** + * Format: int32 + * @description 优先级。 + */ + priority?: null | number | string; + /** @description 公开配置内容。 */ + configPublic?: components["schemas"]["JsonElement"]; + /** @description 扩展元数据。 */ + metadata?: components["schemas"]["JsonElement"]; + }; + UpsertPlatformQuestionBankCommand: { + /** Format: uuid */ + id: null | string; + name: string; + metadata: components["schemas"]["JsonElement"]; + }; + UpsertPlatformQuestionBankNodeCommand: { + /** Format: uuid */ + id: null | string; + /** Format: uuid */ + questionBankId: string; + /** Format: uuid */ + parentId: null | string; + nodeKey: null | string; + name: string; + nodeType: components["schemas"]["ContentNodeType"]; + /** Format: int32 */ + sortOrder: number | string; + isSelectable: boolean; + metadata: components["schemas"]["JsonElement"]; + }; + UpsertPlatformQuestionCommand: { + /** Format: uuid */ + id: null | string; + /** Format: uuid */ + questionBankId: string; + /** Format: uuid */ + contentNodeId: string; + legacyId: null | string; + type: null | string; + typeLabel: null | string; + /** Format: int32 */ + difficulty: null | number | string; + tags: components["schemas"]["JsonElement"]; + content: null | string; + options: components["schemas"]["JsonElement"]; + /** Format: int32 */ + correctOptionIndex: null | number | string; + correctOptionIndices: components["schemas"]["JsonElement"]; + answerText: null | string; + explanation: null | string; + subQuestions: components["schemas"]["JsonElement"]; + codeLang: null | string; + codeTemplate: null | string; + mediaUrl: null | string; + status: null | string; + examMarkers: components["schemas"]["JsonElement"]; + sourceHash: null | string; + }; + /** @description 新增或更新租户短信渠道请求。 */ + UpsertPlatformSmsChannelDto: { + /** + * Format: uuid + * @description ID。 + */ + id?: null | string; + /** + * Format: uuid + * @description 租户 ID。 + */ + tenantId: string; + /** @description 服务提供方。 */ + provider: string; + /** @description 名称。 */ + name: string; + /** @description 短信签名。 */ + signature: string; + /** @description 使用场景。 */ + scene: string; + /** @description 状态。 */ + status?: components["schemas"]["TenantExternalProviderStatus"]; + /** @description 密钥引用。 */ + secretRef?: null | string; + /** + * Format: int32 + * @description 优先级。 + */ + priority?: null | number | string; + /** + * Format: int32 + * @description 月度配额。 + */ + monthlyQuota?: null | number | string; + /** @description 公开配置内容。 */ + configPublic?: components["schemas"]["JsonElement"]; + /** @description 扩展元数据。 */ + metadata?: components["schemas"]["JsonElement"]; + }; + /** @description 新增或更新租户短信模板请求。 */ + UpsertPlatformSmsTemplateDto: { + /** + * Format: uuid + * @description ID。 + */ + id?: null | string; + /** + * Format: uuid + * @description 租户 ID。 + */ + tenantId: string; + /** + * Format: uuid + * @description 短信渠道 ID。 + */ + channelId: string; + /** @description 编码。 */ + code: string; + /** @description 名称。 */ + name: string; + /** @description 类型。 */ + type?: components["schemas"]["SmsTemplateType"]; + /** @description 审核状态。 */ + auditStatus?: components["schemas"]["SmsTemplateAuditStatus"]; + /** @description 状态。 */ + status?: components["schemas"]["SmsTemplateStatus"]; + /** @description 渠道模板编码。 */ + providerTemplateCode?: null | string; + /** @description 模板内容。 */ + content: string; + /** @description Remark。 */ + remark?: null | string; + /** @description 扩展元数据。 */ + metadata?: components["schemas"]["JsonElement"]; + }; + /** @description 新增或更新平台Staff请求 DTO。 */ + UpsertPlatformStaffDto: { + /** + * Format: uuid + * @description 用户 ID。 + */ + userId?: null | string; + /** @description 邮箱。 */ + email?: null | string; + /** @description 手机号。 */ + phone?: null | string; + /** @description 名称。 */ + name?: null | string; + /** @description 状态。 */ + status?: components["schemas"]["UserStatus"]; + /** @description 角色 ID 列表。 */ + roleIds?: string[]; + }; + /** @description 新增或更新平台租户账务资料请求 DTO。 */ + UpsertPlatformTenantBillingProfileDto: { + /** + * Format: uuid + * @description 租户 ID。 + */ + tenantId: string; + /** @description 账务名称。 */ + billingName?: null | string; + /** @description 税号。 */ + taxId?: null | string; + /** @description 联系人姓名。 */ + contactName?: null | string; + /** @description 联系人手机号。 */ + contactPhone?: null | string; + /** @description 联系人邮箱。 */ + contactEmail?: null | string; + /** @description 账务地址。 */ + billingAddress?: null | string; + /** @description 发票抬头。 */ + invoiceTitle?: null | string; + invoiceType?: null | components["schemas"]["TenantBillingInvoiceTitleType"]; + /** @description 开户银行。 */ + bankName?: null | string; + /** @description 脱敏银行账号。 */ + bankAccountMasked?: null | string; + /** @description 扩展元数据。 */ + metadata?: components["schemas"]["JsonElement"]; + }; + /** @description 新增或更新租户支付应用请求。 */ + UpsertPlatformTenantPaymentAppDto: { + /** + * Format: uuid + * @description 租户 ID。 + */ + tenantId: string; + /** @description 服务提供方。 */ + provider: string; + /** @description 状态。 */ + status?: components["schemas"]["TenantExternalProviderStatus"]; + /** @description 显示名称。 */ + displayName?: null | string; + /** @description 密钥引用。 */ + secretRef?: null | string; + /** + * Format: int32 + * @description 优先级。 + */ + priority?: null | number | string; + /** @description 公开配置内容。 */ + configPublic?: components["schemas"]["JsonElement"]; + /** @description 扩展元数据。 */ + metadata?: components["schemas"]["JsonElement"]; + }; + /** @description 新增或更新积分兑换Item请求 DTO。 */ + UpsertPointExchangeItemDto: { + /** + * Format: uuid + * @description ID。 + */ + id?: null | string; + /** + * Format: uuid + * @description 地区 ID。 + */ + regionId?: null | string; + /** @description 兑换项键。 */ + itemKey: string; + /** @description 名称。 */ + name: string; + /** @description 说明。 */ + description?: null | string; + /** @description 兑换项类型。 */ + itemType?: components["schemas"]["PointExchangeItemType"]; + /** @description 状态。 */ + status?: components["schemas"]["PointExchangeItemStatus"]; + /** + * Format: int32 + * @description 所需积分。 + */ + pointsCost?: number | string; + /** + * Format: int32 + * @description 库存数量。 + */ + stock?: null | number | string; + /** + * Format: int32 + * @description 天数。 + */ + days?: null | number | string; + /** + * Format: int32 + * @description 排序值。 + */ + sortOrder?: number | string; + /** + * Format: date-time + * @description 开始时间。 + */ + startsAt?: null | string; + /** + * Format: date-time + * @description 结束时间。 + */ + endsAt?: null | string; + /** @description 履约载荷。 */ + fulfillmentPayload?: components["schemas"]["JsonElement"]; + /** @description 扩展元数据。 */ + metadata?: components["schemas"]["JsonElement"]; + }; + /** @description 新增或更新积分任务请求 DTO。 */ + UpsertPointTaskDto: { + /** + * Format: uuid + * @description ID。 + */ + id?: null | string; + /** @description 任务键。 */ + taskKey: string; + /** @description 标题。 */ + title: string; + /** @description 说明。 */ + description?: null | string; + /** @description 任务类型。 */ + taskType?: components["schemas"]["PointActivityTaskType"]; + /** @description 状态。 */ + status?: components["schemas"]["PointActivityTaskStatus"]; + /** + * Format: int32 + * @description 积分数量。 + */ + points?: number | string; + /** + * Format: int32 + * @description 每用户最多领取次数。 + */ + maxClaimsPerUser?: number | string; + /** + * Format: date-time + * @description 开始时间。 + */ + startsAt?: null | string; + /** + * Format: date-time + * @description 结束时间。 + */ + endsAt?: null | string; + /** + * Format: int32 + * @description 排序值。 + */ + sortOrder?: number | string; + /** @description 规则配置。 */ + rules?: components["schemas"]["JsonElement"]; + /** @description 扩展元数据。 */ + metadata?: components["schemas"]["JsonElement"]; + }; + /** @description 新增或更新练习Blueprint请求 DTO。 */ + UpsertPracticeBlueprintDto: { + /** + * Format: uuid + * @description ID。 + */ + id?: null | string; + /** + * Format: uuid + * @description 地区 ID。 + */ + regionId?: null | string; + /** + * Format: uuid + * @description 内容入口 ID。 + */ + entryId?: null | string; + /** + * Format: uuid + * @description 节点 ID。 + */ + nodeId?: null | string; + /** + * Format: uuid + * @description 题集 ID。 + */ + collectionId?: null | string; + /** @description 历史系统 ID。 */ + legacyId?: null | string; + /** @description 名称。 */ + name: string; + /** @description 模式。 */ + mode?: null | string; + /** @description 组卷方式。 */ + assemblyType?: null | string; + /** + * Format: int32 + * @description 题目数量上限。 + */ + questionLimit?: null | number | string; + /** + * Format: int32 + * @description 时长,单位为分钟。 + */ + durationMinutes?: null | number | string; + /** + * Format: double + * @description 总分。 + */ + totalScore?: null | number | string; + /** + * Format: double + * @description 及格分。 + */ + passScore?: null | number | string; + /** @description 分段配置。 */ + sections?: components["schemas"]["JsonElement"]; + /** @description 规则配置。 */ + rules?: components["schemas"]["JsonElement"]; + /** @description 访问规则。 */ + accessRules?: components["schemas"]["JsonElement"]; + /** @description 状态。 */ + status?: null | string; + /** + * Format: int32 + * @description 显示顺序。 + */ + order?: null | number | string; + }; + /** @description 新增或更新题目题集请求 DTO。 */ + UpsertQuestionCollectionDto: { + /** + * Format: uuid + * @description ID。 + */ + id?: null | string; + /** + * Format: uuid + * @description 地区 ID。 + */ + regionId?: null | string; + /** + * Format: uuid + * @description 内容入口 ID。 + */ + entryId?: null | string; + /** + * Format: uuid + * @description 节点 ID。 + */ + nodeId?: null | string; + /** + * Format: uuid + * @description 科目 ID。 + */ + subjectId?: null | string; + /** + * Format: uuid + * @description 分类 ID。 + */ + categoryId?: null | string; + /** + * Format: uuid + * @description 题库 ID。 + */ + questionBankId?: null | string; + /** @description 历史系统 ID。 */ + legacyId?: null | string; + /** @description 名称。 */ + name: string; + /** @description 题集类型。 */ + collectionType?: null | string; + /** @description 来源类型。 */ + sourceType?: null | string; + /** @description 筛选条件。 */ + filters?: components["schemas"]["JsonElement"]; + /** + * Format: double + * @description 总分。 + */ + totalScore?: null | number | string; + /** + * Format: int32 + * @description 时长,单位为分钟。 + */ + durationMinutes?: null | number | string; + /** @description 状态。 */ + status?: null | string; + /** + * Format: int32 + * @description 显示顺序。 + */ + order?: null | number | string; + /** @description 访问规则。 */ + accessRules?: components["schemas"]["JsonElement"]; + /** @description 扩展元数据。 */ + metadata?: components["schemas"]["JsonElement"]; + }; + /** @description 新增或更新推荐团队请求 DTO。 */ + UpsertReferralTeamDto: { + /** + * Format: uuid + * @description 成员用户 ID。 + */ + memberUserId: string; + /** + * Format: uuid + * @description 上级成员用户 ID。 + */ + leaderUserId?: null | string; + /** @description 关系类型。 */ + relationType?: null | string; + /** @description 状态。 */ + status?: null | string; + metadata?: null | components["schemas"]["JsonElement"]; + }; + /** @description 新增或更新SaaS功能请求 DTO。 */ + UpsertSaasFeatureDto: { + /** Format: uuid */ + id: null | string; + code: string; + name: string; + category: string; + description: null | string; + /** Format: int32 */ + referencePriceCents: number | string; + currency: string; + status: components["schemas"]["SaasFeatureStatus"]; + /** Format: int32 */ + sortOrder: number | string; + }; + /** @description 新增或更新 SaaS 功能额度定义。 */ + UpsertSaasFeatureLimitDto: { + /** Format: uuid */ + id: null | string; + metricCode: string; + featureCode: string; + name: string; + unit: string; + kind: components["schemas"]["SaasFeatureLimitKind"]; + /** Format: int32 */ + warningPercent: number | string; + isHardLimit: boolean; + }; + /** @description 新增或更新SaaS套餐请求 DTO。 */ + UpsertSaasOfferingDto: { + /** Format: uuid */ + id: null | string; + code: string; + name: string; + type: components["schemas"]["SaasOfferingType"]; + status: components["schemas"]["SaasOfferingStatus"]; + description: null | string; + /** Format: int32 */ + sortOrder: number | string; + }; + /** @description 新增或更新SaaS套餐版本请求 DTO。 */ + UpsertSaasOfferingVersionDto: { + /** Format: uuid */ + id: null | string; + /** Format: uuid */ + offeringId: string; + billingCycle: components["schemas"]["PlatformBillingCycle"]; + /** Format: int32 */ + originalAmountCents: number | string; + /** Format: int32 */ + amountCents: number | string; + currency: string; + /** Format: date-time */ + effectiveAt: null | string; + featureCodes: null | string[]; + limits: null | { + [key: string]: number | string; + }; + metadata: components["schemas"]["JsonElement"]; + }; + /** @description 新增或更新租户管理端徽章请求 DTO。 */ + UpsertTenantAdminBadgeDto: { + /** + * Format: uuid + * @description ID。 + */ + id?: null | string; + /** @description 历史系统 ID。 */ + legacyId?: null | string; + /** @description 名称。 */ + name: string; + /** @description 说明。 */ + description?: null | string; + /** @description 分类。 */ + category?: null | string; + /** @description 图标地址。 */ + iconUrl?: null | string; + /** + * Format: int32 + * @description 级别。 + */ + level?: null | number | string; + /** @description 解锁类型。 */ + unlockType?: null | string; + /** @description 条件字段。 */ + conditionField?: null | string; + /** @description 条件运算符。 */ + conditionOperator?: null | string; + /** + * Format: double + * @description 条件值。 + */ + conditionValue?: null | number | string; + /** @description 条件扩展配置。 */ + conditionExtra?: components["schemas"]["JsonElement"]; + /** + * Format: int32 + * @description 显示顺序。 + */ + order?: null | number | string; + /** @description 是否启用。 */ + isActive?: null | boolean; + }; + /** @description 新增或更新租户管理端班级请求 DTO。 */ + UpsertTenantAdminClassDto: { + /** + * Format: uuid + * @description ID。 + */ + id?: null | string; + /** + * Format: uuid + * @description 地区 ID。 + */ + regionId?: null | string; + /** @description 历史系统 ID。 */ + legacyId?: null | string; + /** @description 编码。 */ + code?: null | string; + /** @description 名称。 */ + name: string; + /** @description 说明。 */ + description?: null | string; + /** @description 状态。 */ + status?: null | string; + /** + * Format: int32 + * @description 显示顺序。 + */ + order?: null | number | string; + /** @description 扩展元数据。 */ + metadata?: components["schemas"]["JsonElement"]; + }; + /** @description 新增或更新租户管理端班级成员请求 DTO。 */ + UpsertTenantAdminClassMemberDto: { + /** + * Format: uuid + * @description 班级 ID。 + */ + classId: string; + /** @description 用户信息。 */ + user?: components["schemas"]["TenantAdminUserLookupDto"]; + /** @description 成员类型。 */ + memberType?: null | string; + /** @description 状态。 */ + status?: null | string; + /** @description 扩展元数据。 */ + metadata?: components["schemas"]["JsonElement"]; + }; + /** @description 新增或更新租户管理端成员请求 DTO。 */ + UpsertTenantAdminMemberDto: { + /** + * Format: uuid + * @description 成员关系 ID。 + */ + membershipId?: null | string; + /** @description 用户信息。 */ + user?: components["schemas"]["TenantAdminUserLookupDto"]; + /** @description 角色。 */ + role?: null | string; + /** @description 状态。 */ + status?: null | string; + /** @description 主要角色。 */ + primaryRole?: null | string; + }; + /** @description 新增或更新租户管理端通知请求 DTO。 */ + UpsertTenantAdminNotificationDto: { + /** + * Format: uuid + * @description 用户 ID。 + */ + userId: string; + /** @description 通知类型。 */ + notificationType: string; + /** @description 严重级别。 */ + severity?: null | string; + /** @description 标题。 */ + title: string; + /** @description 消息内容。 */ + message: string; + /** @description 操作按钮文案。 */ + actionLabel?: null | string; + /** @description 操作路径。 */ + actionPath?: null | string; + /** @description 来源类型。 */ + sourceType?: null | string; + /** + * Format: uuid + * @description 来源 ID。 + */ + sourceId?: null | string; + /** @description 去重键。 */ + dedupeKey?: null | string; + /** @description 扩展元数据。 */ + metadata?: components["schemas"]["JsonElement"]; + }; + /** @description 新增或更新租户管理端学生请求 DTO。 */ + UpsertTenantAdminStudentDto: { + /** @description 用户信息。 */ + user?: components["schemas"]["TenantAdminUserLookupDto"]; + /** + * Format: uuid + * @description 地区 ID。 + */ + regionId?: null | string; + /** + * Format: uuid + * @description 已选择院校 ID。 + */ + selectedSchoolId?: null | string; + /** + * Format: uuid + * @description 已选择专业 ID。 + */ + selectedMajorId?: null | string; + /** @description 头像预设。 */ + avatarPreset?: null | string; + /** @description 统计数据。 */ + stats?: components["schemas"]["JsonElement"]; + /** @description 进度数据。 */ + progress?: components["schemas"]["JsonElement"]; + /** @description 模块选择数据。 */ + moduleSelections?: components["schemas"]["JsonElement"]; + /** @description 原始用户资料。 */ + rawProfile?: components["schemas"]["JsonElement"]; + }; + /** @description 新增或更新租户管理端学生跟进请求 DTO。 */ + UpsertTenantAdminStudentFollowupDto: { + /** + * Format: uuid + * @description ID。 + */ + id?: null | string; + /** + * Format: uuid + * @description 学生用户 ID。 + */ + studentUserId: string; + /** + * Format: uuid + * @description 分配处理人用户 ID。 + */ + assignedToUserId?: null | string; + /** + * Format: uuid + * @description 班级 ID。 + */ + classId?: null | string; + /** @description 标题。 */ + title: string; + /** @description 说明。 */ + description?: null | string; + /** @description 跟进类型。 */ + followupType?: null | string; + /** @description 优先级。 */ + priority?: null | string; + /** @description 状态。 */ + status?: null | string; + /** + * Format: date-time + * @description 到期时间。 + */ + dueAt?: null | string; + /** @description 扩展元数据。 */ + metadata?: components["schemas"]["JsonElement"]; + }; + /** @description 新增或更新租户管理端学生Note请求 DTO。 */ + UpsertTenantAdminStudentNoteDto: { + /** + * Format: uuid + * @description ID。 + */ + id?: null | string; + /** + * Format: uuid + * @description 学生用户 ID。 + */ + studentUserId: string; + /** @description 备注类型。 */ + noteType?: null | string; + /** @description 内容。 */ + content: string; + /** @description 可见性。 */ + visibility?: null | string; + /** @description 是否置顶。 */ + isPinned?: null | boolean; + /** @description 扩展元数据。 */ + metadata?: components["schemas"]["JsonElement"]; + }; + /** @description 新增或更新租户品牌请求 DTO。 */ + UpsertTenantBrandingDto: { + /** @description 品牌名称。 */ + brandName: string; + /** @description 品牌简称。 */ + shortName?: null | string; + /** @description 品牌标语。 */ + slogan?: null | string; + /** @description 机构名称。 */ + organizationName?: null | string; + /** @description Logo 地址。 */ + logoUrl?: null | string; + /** @description 站点图标地址。 */ + faviconUrl?: null | string; + /** @description 客服微信。 */ + serviceWechat?: null | string; + /** @description 客服账号名称。 */ + serviceAccountName?: null | string; + }; + /** @description 新增或更新租户优惠券请求 DTO。 */ + UpsertTenantCouponDto: { + /** + * Format: uuid + * @description ID。 + */ + id?: null | string; + /** @description 编码。 */ + code: string; + /** + * Format: uuid + * @description 套餐 ID。 + */ + planId?: null | string; + /** @description 优惠类型。 */ + discountType?: components["schemas"]["DiscountType"]; + /** + * Format: double + * @description 优惠值。 + */ + discountValue?: number | string; + /** + * Format: date-time + * @description 有效期开始时间。 + */ + validFrom?: null | string; + /** + * Format: date-time + * @description 有效期结束时间。 + */ + validTo?: null | string; + /** + * Format: int32 + * @description 最大使用次数。 + */ + maxUses?: null | number | string; + /** @description 来源。 */ + source?: null | string; + /** @description 备注。 */ + remark?: null | string; + }; + /** @description 新增或更新租户功能覆盖规则请求 DTO。 */ + UpsertTenantFeatureOverrideDto: { + /** Format: uuid */ + tenantId: string; + featureCode: string; + mode: components["schemas"]["TenantFeatureOverrideMode"]; + /** Format: date-time */ + expiresAt: null | string; + reason: string; + }; + /** @description 新增或更新租户身份源Provider请求 DTO。 */ + UpsertTenantIdentityProviderDto: { + /** @description 服务提供方。 */ + provider: string; + /** @description 状态。 */ + status?: null | string; + /** @description 显示名称。 */ + displayName?: null | string; + /** @description 密钥引用。 */ + secretRef?: null | string; + /** + * Format: int32 + * @description 优先级。 + */ + priority?: null | number | string; + /** @description 公开配置内容。 */ + configPublic?: components["schemas"]["JsonElement"]; + }; + /** @description 新增或更新租户Secret请求 DTO。 */ + UpsertTenantSecretDto: { + /** @description 用途。 */ + purpose: string; + /** @description 服务提供方。 */ + provider: string; + /** @description 密钥键。 */ + secretKey: string; + /** @description 密钥引用。 */ + secretRef?: string; + /** @description 状态。 */ + status?: components["schemas"]["TenantSecretStatus"]; + /** @description 密钥载荷。 */ + secretPayload?: components["schemas"]["JsonElement"]; + /** + * Format: date-time + * @description 过期时间。 + */ + expiresAt?: null | string; + }; + /** @description 新增或更新租户设置请求 DTO。 */ + UpsertTenantSettingsDto: { + /** @description 前端功能开关。 */ + featureFlags?: components["schemas"]["JsonElement"]; + /** @description 管理端功能开关。 */ + adminFeatureFlags?: components["schemas"]["JsonElement"]; + /** @description 公开配置。 */ + publicConfig?: components["schemas"]["JsonElement"]; + }; + /** @description 新增或更新租户督导规则请求 DTO。 */ + UpsertTenantSupervisionRuleDto: { + /** @description 编码。 */ + code: string; + /** @description 标题。 */ + title: string; + /** @description 是否启用。 */ + enabled?: boolean; + /** + * Format: int32 + * @description 未签到天数。 + */ + daysWithoutCheckIn?: null | number | string; + /** + * Format: int32 + * @description 当天最大答题数。 + */ + maxQuestionsAnsweredToday?: null | number | string; + /** @description 跟进类型。 */ + followupType?: null | string; + /** @description 优先级。 */ + priority?: null | string; + /** @description 扩展元数据。 */ + metadata?: components["schemas"]["JsonElement"]; + }; + UserStatus: number; + VideoExplanationCatalogItem: { + /** Format: uuid */ + id: string; + legacyId: null | string; + /** Format: uuid */ + subjectId: null | string; + title: string; + description: null | string; + videoUrl: null | string; + thumbnailUrl: null | string; + /** Format: int32 */ + durationSeconds: null | number | string; + knowledgeTags: components["schemas"]["JsonElement"]; + isGeneral: boolean; + /** Format: int32 */ + difficulty: null | number | string; + /** Format: int32 */ + order: number | string; + isActive: boolean; + metadata: components["schemas"]["JsonElement"]; + }; + VideoManagementItem: { + /** Format: uuid */ + id: string; + /** Format: uuid */ + subjectId: null | string; + legacyId: null | string; + title: string; + description: null | string; + videoUrl: null | string; + thumbnailUrl: null | string; + /** Format: int32 */ + durationSeconds: null | number | string; + knowledgeTags: components["schemas"]["JsonElement"]; + isGeneral: boolean; + /** Format: int32 */ + difficulty: null | number | string; + /** Format: int32 */ + order: number | string; + isActive: boolean; + metadata: components["schemas"]["JsonElement"]; + }; + VideoPlaybackItem: { + /** Format: uuid */ + videoId: string; + /** Format: uuid */ + questionId: null | string; + title: string; + description: null | string; + playUrl: null | string; + thumbnailUrl: null | string; + /** Format: int32 */ + durationSeconds: null | number | string; + progress: null | components["schemas"]["VideoProgressItem"]; + metadata: components["schemas"]["JsonElement"]; + }; + /** @description 视频Play请求 DTO。 */ + VideoPlayDto: { + /** + * Format: uuid + * @description 视频 ID。 + */ + videoId: string; + /** + * Format: uuid + * @description 题目 ID。 + */ + questionId?: null | string; + }; + /** @description 视频Progress请求 DTO。 */ + VideoProgressDto: { + /** + * Format: uuid + * @description 视频 ID。 + */ + videoId: string; + /** + * Format: uuid + * @description 题目 ID。 + */ + questionId?: null | string; + /** + * Format: int32 + * @description 播放位置,单位为秒。 + */ + positionSeconds?: number | string; + /** + * Format: int32 + * @description 时长,单位为秒。 + */ + durationSeconds?: null | number | string; + /** + * Format: int32 + * @description 已观看时长,单位为秒。 + */ + watchedSeconds?: null | number | string; + /** @description 是否已完成。 */ + isCompleted?: null | boolean; + /** @description 扩展元数据。 */ + metadata?: components["schemas"]["JsonElement"]; + }; + VideoProgressItem: { + /** Format: uuid */ + id: string; + /** Format: uuid */ + videoId: string; + /** Format: uuid */ + questionId: null | string; + /** Format: int32 */ + positionSeconds: number | string; + /** Format: int32 */ + durationSeconds: null | number | string; + /** Format: int32 */ + watchedSeconds: number | string; + isCompleted: boolean; + /** Format: date-time */ + completedAt: null | string; + /** Format: date-time */ + lastPlayedAt: string; + /** Format: int32 */ + playCount: number | string; + metadata: components["schemas"]["JsonElement"]; + }; + VocabularyUnit: { + /** Format: uuid */ + regionId?: null | string; + /** Format: uuid */ + entryId?: null | string; + /** Format: uuid */ + contentNodeId?: null | string; + legacyId?: null | string; + name?: string; + description?: null | string; + /** Format: int32 */ + wordCount?: null | number | string; + /** Format: int32 */ + sortOrder?: number | string; + isActive?: boolean; + sourceHash?: null | string; + metadata?: components["schemas"]["JsonElement"]; + /** Format: date-time */ + createdAt?: string; + /** Format: date-time */ + updatedAt?: string; + /** Format: uuid */ + tenantId?: string; + /** Format: uuid */ + id?: string; + }; + VocabularyUnitCatalogItem: { + /** Format: uuid */ + id: string; + legacyId: null | string; + /** Format: uuid */ + regionId: null | string; + /** Format: uuid */ + entryId: null | string; + /** Format: uuid */ + contentNodeId: null | string; + name: string; + description: null | string; + /** Format: int32 */ + wordCount: null | number | string; + /** Format: int32 */ + order: number | string; + metadata: components["schemas"]["JsonElement"]; + }; + VocabularyWord: { + /** Format: uuid */ + unitId?: null | string; + /** Format: uuid */ + entryId?: null | string; + /** Format: uuid */ + contentNodeId?: null | string; + legacyId?: null | string; + word?: string; + phonetic?: null | string; + meaning?: null | string; + example?: null | string; + exampleTranslation?: null | string; + /** Format: int32 */ + difficulty?: null | number | string; + tags?: components["schemas"]["JsonElement"]; + /** Format: int32 */ + sortOrder?: number | string; + isActive?: boolean; + sourceHash?: null | string; + metadata?: components["schemas"]["JsonElement"]; + /** Format: date-time */ + createdAt?: string; + /** Format: date-time */ + updatedAt?: string; + /** Format: uuid */ + tenantId?: string; + /** Format: uuid */ + id?: string; + }; + VocabularyWordCatalogItem: { + /** Format: uuid */ + id: string; + legacyId: null | string; + /** Format: uuid */ + unitId: null | string; + /** Format: uuid */ + entryId: null | string; + /** Format: uuid */ + contentNodeId: null | string; + word: string; + phonetic: null | string; + meaning: null | string; + example: null | string; + exampleTranslation: null | string; + /** Format: int32 */ + difficulty: null | number | string; + tags: components["schemas"]["JsonElement"]; + /** Format: int32 */ + order: number | string; + metadata: components["schemas"]["JsonElement"]; + }; + WordDueLevel: number; + /** @description 单词Progress请求 DTO。 */ + WordProgressDto: { + /** + * Format: uuid + * @description 单词 ID。 + */ + wordId: string; + /** @description 状态。 */ + status?: null | string; + /** + * Format: int32 + * @description 答对数量变化。 + */ + correctDelta?: null | number | string; + /** + * Format: int32 + * @description 答错数量变化。 + */ + wrongDelta?: null | number | string; + /** + * Format: date-time + * @description 下次复习时间。 + */ + nextReviewAt?: null | string; + }; + WordProgressItem: { + /** Format: uuid */ + wordId: string; + status: components["schemas"]["WordProgressStatus"]; + /** Format: int32 */ + correctCount: number | string; + /** Format: int32 */ + wrongCount: number | string; + /** Format: date-time */ + lastReviewAt: null | string; + /** Format: date-time */ + nextReviewAt: null | string; + /** Format: int32 */ + reviewCount: number | string; + /** Format: int32 */ + correctStreak: number | string; + lastResult: null | components["schemas"]["WordReviewResult"]; + dueLevel: components["schemas"]["WordDueLevel"]; + metadata: components["schemas"]["JsonElement"]; + }; + WordProgressStatus: number; + /** @description 单词Review请求 DTO。 */ + WordReviewDto: { + /** + * Format: uuid + * @description 单词 ID。 + */ + wordId: string; + /** @description 结果。 */ + result?: null | string; + /** + * Format: date-time + * @description 下次复习时间。 + */ + nextReviewAt?: null | string; + }; + WordReviewPlan: { + items: components["schemas"]["WordReviewPlanItem"][]; + nextAction: components["schemas"]["JsonElement"]; + }; + WordReviewPlanItem: { + /** Format: uuid */ + wordId: string; + status: components["schemas"]["WordProgressStatus"]; + /** Format: date-time */ + nextReviewAt: null | string; + /** Format: int32 */ + correctCount: number | string; + /** Format: int32 */ + wrongCount: number | string; + dueLevel: components["schemas"]["WordDueLevel"]; + }; + WordReviewResult: number; + WordStatsItem: { + /** Format: int32 */ + total: number | string; + /** Format: int32 */ + newCount: number | string; + /** Format: int32 */ + learningCount: number | string; + /** Format: int32 */ + reviewingCount: number | string; + /** Format: int32 */ + masteredCount: number | string; + /** Format: int32 */ + dueCount: number | string; + /** Format: int32 */ + favoriteCount: number | string; + }; + WrongQuestionItem: { + /** Format: uuid */ + questionReferenceId: string; + locator: components["schemas"]["QuestionLocator"]; + /** Format: int32 */ + wrongCount: number | string; + /** Format: date-time */ + lastWrongAt: string; + /** Format: date-time */ + resolvedAt: null | string; + }; + WrongQuestionReviewPlan: { + items: components["schemas"]["WrongQuestionReviewPlanItem"][]; + nextAction: components["schemas"]["JsonElement"]; + }; + WrongQuestionReviewPlanItem: { + /** Format: uuid */ + questionReferenceId: string; + locator: components["schemas"]["QuestionLocator"]; + /** Format: int32 */ + wrongCount: number | string; + /** Format: date-time */ + lastWrongAt: string; + }; + }; + responses: never; + parameters: never; + requestBodies: never; + headers: never; + pathItems: never; +} +export type $defs = Record; +export type operations = Record; diff --git a/Tiku.PlatformAdmin.Web/src/api/token-store.ts b/Tiku.PlatformAdmin.Web/src/api/token-store.ts new file mode 100644 index 0000000..4d85e9c --- /dev/null +++ b/Tiku.PlatformAdmin.Web/src/api/token-store.ts @@ -0,0 +1,28 @@ +export interface TokenPair { + accessToken: string; + refreshToken: string; + accessTokenExpiresAt: string; + refreshTokenExpiresAt: string; +} + +const storageKey = 'tiku.platform-admin.tokens'; +let currentTokens: TokenPair | null = readTokens(); + +function readTokens(): TokenPair | null { + try { + const raw = localStorage.getItem(storageKey); + return raw ? (JSON.parse(raw) as TokenPair) : null; + } catch { + return null; + } +} + +export const tokenStore = { + get: () => currentTokens, + set(tokens: TokenPair | null) { + currentTokens = tokens; + if (tokens) localStorage.setItem(storageKey, JSON.stringify(tokens)); + else localStorage.removeItem(storageKey); + window.dispatchEvent(new CustomEvent('platform-auth-change')); + }, +}; diff --git a/Tiku.PlatformAdmin.Web/src/api/types.ts b/Tiku.PlatformAdmin.Web/src/api/types.ts new file mode 100644 index 0000000..d7240bd --- /dev/null +++ b/Tiku.PlatformAdmin.Web/src/api/types.ts @@ -0,0 +1,43 @@ +export type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE'; + +export interface JsonSchema { + [key: string]: unknown; + $ref?: string; + type?: string | readonly string[]; + format?: string; + description?: string; + default?: unknown; + enum?: readonly unknown[]; + oneOf?: readonly JsonSchema[]; + anyOf?: readonly JsonSchema[]; + items?: JsonSchema; + properties?: Readonly>; + required?: readonly string[]; + minimum?: number; + maximum?: number; + minLength?: number; + maxLength?: number; + pattern?: string; +} + +export interface OpenApiParameter { + name: string; + in: 'path' | 'query' | 'header'; + required?: boolean; + description?: string; + schema?: JsonSchema; +} + +export interface PlatformOperation { + id: string; + method: HttpMethod; + path: string; + tag: string; + summary: string; + description: string; + parameters: readonly OpenApiParameter[]; + requestSchema: JsonSchema | null; + responseSchema: JsonSchema | null; +} + +export type OperationInput = Record; diff --git a/Tiku.PlatformAdmin.Web/src/auth/AuthProvider.tsx b/Tiku.PlatformAdmin.Web/src/auth/AuthProvider.tsx new file mode 100644 index 0000000..e5a2acb --- /dev/null +++ b/Tiku.PlatformAdmin.Web/src/auth/AuthProvider.tsx @@ -0,0 +1,106 @@ +import { createContext, useCallback, useContext, useEffect, useMemo, useState, type PropsWithChildren } from 'react'; +import { authRequest, getCurrentUser } from '../api/http'; +import { tokenStore, type TokenPair } from '../api/token-store'; +import type { components } from '../api/schema.generated'; + +type AuthenticationResult = components['schemas']['AuthenticationResultDto']; +type CurrentUser = components['schemas']['MeResponse']; +const platformRealm = 1; + +interface AuthContextValue { + loading: boolean; + user: CurrentUser | null; + challengeToken: string | null; + login(identifier: string, password: string): Promise; + completePasswordChange(password: string): Promise; + logout(): Promise; +} + +const AuthContext = createContext(null); + +function tokensFrom(result: AuthenticationResult): TokenPair | null { + const tokens = result.user?.tokens; + return tokens?.accessToken && tokens.refreshToken ? (tokens as TokenPair) : null; +} + +export function AuthProvider({ children }: PropsWithChildren) { + const [loading, setLoading] = useState(Boolean(tokenStore.get())); + const [user, setUser] = useState(null); + const [challengeToken, setChallengeToken] = useState(null); + + const loadUser = useCallback(async () => { + if (!tokenStore.get()) { + setUser(null); + setLoading(false); + return; + } + try { + setUser(await getCurrentUser()); + } catch { + tokenStore.set(null); + setUser(null); + } finally { + setLoading(false); + } + }, []); + + useEffect(() => { void loadUser(); }, [loadUser]); + + const applyAuthentication = useCallback(async (result: AuthenticationResult) => { + const tokens = tokensFrom(result); + if (tokens) { + tokenStore.set(tokens); + setChallengeToken(null); + setLoading(true); + await loadUser(); + return; + } + if (result.challengeToken) { + setChallengeToken(result.challengeToken); + return; + } + throw new Error('认证响应中没有登录令牌或密码变更挑战'); + }, [loadUser]); + + const value = useMemo(() => ({ + loading, + user, + challengeToken, + async login(identifier, password) { + const result = await authRequest('/api/auth/login/password', { + realm: platformRealm, + tenantCode: null, + identifier, + phone: null, + password, + }); + await applyAuthentication(result); + }, + async completePasswordChange(password) { + if (!challengeToken) throw new Error('密码变更挑战已失效,请重新登录'); + const result = await authRequest('/api/auth/password/change-required', { + challengeToken, + newPassword: password, + }); + await applyAuthentication(result); + }, + async logout() { + const refreshToken = tokenStore.get()?.refreshToken; + try { + if (refreshToken) await authRequest('/api/auth/logout', { refreshToken }); + } finally { + tokenStore.set(null); + setUser(null); + setChallengeToken(null); + } + }, + }), [applyAuthentication, challengeToken, loading, user]); + + return {children}; +} + +export function useAuth() { + const value = useContext(AuthContext); + if (!value) throw new Error('useAuth 必须在 AuthProvider 内使用'); + return value; +} diff --git a/Tiku.PlatformAdmin.Web/src/components/BusinessTable.tsx b/Tiku.PlatformAdmin.Web/src/components/BusinessTable.tsx new file mode 100644 index 0000000..3660823 --- /dev/null +++ b/Tiku.PlatformAdmin.Web/src/components/BusinessTable.tsx @@ -0,0 +1,45 @@ +import { Table, Tag, Typography } from 'antd'; + +const labels: Record = { + id: '编号', tenantId: '租户', name: '名称', code: '编码', slug: '短编码', host: '域名', status: '状态', billingStatus: '账务状态', + createdAt: '创建时间', updatedAt: '更新时间', expiresAt: '到期时间', dueAt: '到期时间', amountCents: '金额', totalAmountCents: '金额', + balanceCents: '余额', phone: '手机号', email: '邮箱', ownerName: '负责人', provider: '服务商', enabled: '启用', appName: '应用名称', + appCode: '应用代码', title: '标题', summary: '摘要', action: '动作', targetType: '目标类型', targetId: '目标编号', severity: '级别', + version: '版本', billingCycle: '计费周期', effectiveAt: '生效时间', questionCount: '题目数', nodeType: '节点类型', sortOrder: '排序', +}; + +function isScalar(value: unknown) { return value == null || ['string', 'number', 'boolean'].includes(typeof value); } +function cell(value: unknown, key: string) { + if (value === null || value === undefined || value === '') return '-'; + if (typeof value === 'boolean') return {value ? '是' : '否'}; + if (/status|severity/i.test(key)) return {String(value)}; + if (/Cents$/.test(key) && typeof value === 'number') return `¥${(value / 100).toLocaleString('zh-CN', { minimumFractionDigits: 2 })}`; + return {String(value)}; +} + +export function rowsFromPayload(payload: unknown): Record[] { + if (Array.isArray(payload)) return payload.filter((item) => item && typeof item === 'object') as Record[]; + if (!payload || typeof payload !== 'object') return []; + const object = payload as Record; + for (const key of ['items', 'data', 'results', 'tenants', 'domains', 'staff', 'alerts', 'logs']) { + if (Array.isArray(object[key])) return object[key] as Record[]; + } + return [object]; +} + +export function BusinessTable({ payload, loading, onSelect }: { payload: unknown; loading: boolean; onSelect(record: Record | null): void }) { + const rows = rowsFromPayload(payload); + const keys = [...new Set(rows.flatMap((row) => Object.keys(row).filter((key) => isScalar(row[key]))))].slice(0, 9); + return ( + String(row.id || row.tenantId || row.code || index)} + rowSelection={{ type: 'radio', onChange: (_, selected) => onSelect(selected[0] || null) }} + scroll={{ x: 'max-content' }} + pagination={{ pageSize: 20, showSizeChanger: true, showTotal: (total) => `共 ${total} 条` }} + locale={{ emptyText: '暂无业务数据' }} + columns={keys.map((key) => ({ title: labels[key] || key, dataIndex: key, key, ellipsis: true, render: (value) => cell(value, key) }))} + /> + ); +} diff --git a/Tiku.PlatformAdmin.Web/src/components/OperationForm.tsx b/Tiku.PlatformAdmin.Web/src/components/OperationForm.tsx new file mode 100644 index 0000000..4fe0252 --- /dev/null +++ b/Tiku.PlatformAdmin.Web/src/components/OperationForm.tsx @@ -0,0 +1,61 @@ +import { Form, Input } from 'antd'; +import { SchemaFields } from './SchemaFields'; +import { resolveSchema, schemaType } from '../api/schema-utils'; +import type { JsonSchema, OperationInput, PlatformOperation } from '../api/types'; + +function parseJsonFields(target: Record, schema: JsonSchema) { + const resolved = resolveSchema(schema); + for (const [name, propertySchema] of Object.entries(resolved.properties || {})) { + const value = target[name]; + const type = schemaType(propertySchema); + if ((type === 'object' || type === 'array') && typeof value === 'string' && value.trim()) { + try { + target[name] = JSON.parse(value); + } catch { + throw new Error(`${propertySchema.description || name} 必须是有效 JSON`); + } + } + } +} + +export function normalizeOperationInput(operation: PlatformOperation, values: OperationInput): OperationInput { + const input = structuredClone(values); + if (input.body && typeof input.body === 'object' && operation.requestSchema) { + parseJsonFields(input.body as Record, operation.requestSchema); + } + return input; +} + +export function OperationForm({ operation }: { operation: PlatformOperation }) { + const pathParameters = operation.parameters.filter((item) => item.in === 'path'); + const queryParameters = operation.parameters.filter((item) => item.in === 'query'); + const bodySchema = resolveSchema(operation.requestSchema); + return ( + <> + {pathParameters.map((parameter) => ( + + + + ))} + {queryParameters.length > 0 && ( + item.required).map((item) => item.name)} + schema={{ + type: 'object', + properties: Object.fromEntries(queryParameters.map((item) => [item.name, { ...item.schema, description: item.description || item.name }])), + }} + /> + )} + {operation.requestSchema && schemaType(bodySchema) === 'object' && ( + + )} + + ); +} diff --git a/Tiku.PlatformAdmin.Web/src/components/ResponseView.tsx b/Tiku.PlatformAdmin.Web/src/components/ResponseView.tsx new file mode 100644 index 0000000..e45baed --- /dev/null +++ b/Tiku.PlatformAdmin.Web/src/components/ResponseView.tsx @@ -0,0 +1,54 @@ +import { Descriptions, Empty, Table, Tag, Typography } from 'antd'; + +function scalar(value: unknown) { + if (value === null || value === undefined) return '-'; + if (typeof value === 'boolean') return value ? : ; + if (typeof value === 'object') return {JSON.stringify(value)}; + return String(value); +} + +function rowsFrom(payload: unknown): Record[] | null { + if (Array.isArray(payload)) return payload.filter((item) => item && typeof item === 'object') as Record[]; + if (!payload || typeof payload !== 'object') return null; + const object = payload as Record; + for (const key of ['items', 'data', 'results']) { + if (Array.isArray(object[key])) return object[key] as Record[]; + } + return null; +} + +export function ResponseView({ payload }: { payload: unknown }) { + if (payload === undefined) return ; + if (payload === null) return ; + const rows = rowsFrom(payload); + if (rows) { + if (!rows.length) return ; + const keys = [...new Set(rows.flatMap((row) => Object.keys(row)))].slice(0, 8); + return ( +
String(row.id || row.code || row.userId || index)} + dataSource={rows} + scroll={{ x: 'max-content' }} + pagination={{ pageSize: 20, showSizeChanger: true }} + columns={keys.map((key) => ({ + title: key, + dataIndex: key, + key, + ellipsis: true, + render: scalar, + }))} + /> + ); + } + if (typeof payload === 'object') { + return ( + + {Object.entries(payload as Record).map(([key, value]) => ( + {scalar(value)} + ))} + + ); + } + return {String(payload)}; +} diff --git a/Tiku.PlatformAdmin.Web/src/components/SchemaFields.tsx b/Tiku.PlatformAdmin.Web/src/components/SchemaFields.tsx new file mode 100644 index 0000000..c2c63b1 --- /dev/null +++ b/Tiku.PlatformAdmin.Web/src/components/SchemaFields.tsx @@ -0,0 +1,55 @@ +import { Form, Input, InputNumber, Select, Switch } from 'antd'; +import type { NamePath } from 'antd/es/form/interface'; +import { defaultForSchema, resolveSchema, schemaType } from '../api/schema-utils'; +import type { JsonSchema } from '../api/types'; + +interface SchemaFieldsProps { + schema: JsonSchema; + prefix: NamePath; + required?: readonly string[]; +} + +function fieldName(prefix: NamePath, name: string): NamePath { + return [...(Array.isArray(prefix) ? prefix : [prefix]), name]; +} + +export function SchemaFields({ schema, prefix, required = [] }: SchemaFieldsProps) { + const resolved = resolveSchema(schema); + const properties = resolved.properties || {}; + return Object.entries(properties).map(([name, propertySchema]) => { + const property = resolveSchema(propertySchema); + const type = schemaType(property); + const label = property.description || name; + const isRequired = required.includes(name); + const rules = isRequired ? [{ required: true, message: `请填写${label}` }] : undefined; + let control = ; + + if (property.enum?.length) { + control = ; + } else if (property.maxLength && property.maxLength > 200) { + control = ; + } + + return ( + + {control} + + ); + }); +} diff --git a/Tiku.PlatformAdmin.Web/src/layout/AppLayout.tsx b/Tiku.PlatformAdmin.Web/src/layout/AppLayout.tsx new file mode 100644 index 0000000..32b7c6d --- /dev/null +++ b/Tiku.PlatformAdmin.Web/src/layout/AppLayout.tsx @@ -0,0 +1,95 @@ +import { + AlertOutlined, + ApartmentOutlined, + AuditOutlined, + BankOutlined, + BookOutlined, + ContactsOutlined, + CreditCardOutlined, + DashboardOutlined, + FileTextOutlined, + LogoutOutlined, + MenuFoldOutlined, + MenuUnfoldOutlined, + MessageOutlined, + PieChartOutlined, + ShopOutlined, + UserSwitchOutlined, +} from '@ant-design/icons'; +import { Avatar, Button, Dropdown, Flex, Layout, Menu, Space, Spin, Typography } from 'antd'; +import { useState } from 'react'; +import { Navigate, Outlet, useLocation, useNavigate } from 'react-router'; +import { useAuth } from '../auth/AuthProvider'; + +const { Header, Sider, Content } = Layout; +const items = [ + { key: '/', icon: , label: '经营概览' }, + { type: 'group' as const, label: '业务运营', children: [ + { key: '/tenants', icon: , label: '租户管理' }, + { key: '/subscriptions', icon: , label: '套餐与订阅' }, + { key: '/billing', icon: , label: '订单与发票' }, + { key: '/usage', icon: , label: '用量计费' }, + { key: '/dunning', icon: , label: '收款与催缴' }, + ] }, + { type: 'group' as const, label: '内容资产', children: [ + { key: '/question-banks', icon: , label: '公共题库' }, + ] }, + { type: 'group' as const, label: '平台服务', children: [ + { key: '/crm', icon: , label: 'CRM 服务' }, + { key: '/sms', icon: , label: '短信服务' }, + { key: '/payments', icon: , label: '支付服务' }, + ] }, + { type: 'group' as const, label: '安全与系统', children: [ + { key: '/staff', icon: , label: '员工与角色' }, + { key: '/audit', icon: , label: '审计日志' }, + { key: '/alerts', icon: , label: '审计告警' }, + ] }, +]; + +const pageTitles: Record = { + '/': '经营概览', '/tenants': '租户管理', '/subscriptions': '套餐与订阅', '/billing': '订单与发票', + '/usage': '用量计费', '/dunning': '收款与催缴', '/question-banks': '公共题库', '/crm': 'CRM 服务', + '/sms': '短信服务', '/payments': '支付服务', '/staff': '员工与角色', '/audit': '审计日志', '/alerts': '审计告警', +}; + +export function AppLayout() { + const auth = useAuth(); + const location = useLocation(); + const navigate = useNavigate(); + const [collapsed, setCollapsed] = useState(false); + if (auth.loading) return
; + if (!auth.user) return ; + const displayName = auth.user.name || auth.user.phone || auth.user.email || '平台管理员'; + return ( + + +
+
Logo
+ {!collapsed &&
恭学题库平台管理中心
} +
+
navigate(key)} />
+
+ +
+
+ +
+ {pageTitles[location.pathname] || '平台管理'} + , label: '退出登录', onClick: () => void auth.logout() }] }} + trigger={['click']} + > + + {String(displayName).slice(0, 1)} + + {displayName} + 平台管理 + + + +
+ +
+
+ ); +} diff --git a/Tiku.PlatformAdmin.Web/src/main.tsx b/Tiku.PlatformAdmin.Web/src/main.tsx new file mode 100644 index 0000000..60cff18 --- /dev/null +++ b/Tiku.PlatformAdmin.Web/src/main.tsx @@ -0,0 +1,24 @@ +import React from 'react'; +import ReactDOM from 'react-dom/client'; +import { App as AntApp, ConfigProvider } from 'antd'; +import zhCN from 'antd/locale/zh_CN'; +import { RouterProvider } from 'react-router'; +import { AuthProvider } from './auth/AuthProvider'; +import { router } from './router'; +import './styles.css'; + +ReactDOM.createRoot(document.getElementById('root')!).render( + + + + + + + , +); diff --git a/Tiku.PlatformAdmin.Web/src/pages/BusinessPage.tsx b/Tiku.PlatformAdmin.Web/src/pages/BusinessPage.tsx new file mode 100644 index 0000000..fdbc92b --- /dev/null +++ b/Tiku.PlatformAdmin.Web/src/pages/BusinessPage.tsx @@ -0,0 +1,91 @@ +import { PlusOutlined, ReloadOutlined, SearchOutlined } from '@ant-design/icons'; +import { App, Button, Card, Drawer, Empty, Flex, Form, Segmented, Space, Tabs, Typography } from 'antd'; +import { useEffect, useMemo, useState } from 'react'; +import { apiRequest } from '../api/http'; +import { platformOperations } from '../api/platform-operations.generated'; +import type { OperationInput, PlatformOperation } from '../api/types'; +import { BusinessTable } from '../components/BusinessTable'; +import { OperationForm, normalizeOperationInput } from '../components/OperationForm'; +import { businessPages } from './business-definitions'; + +function prefillFromRecord(operation: PlatformOperation, record: Record | null): OperationInput { + if (!record) return {}; + const path: Record = {}; + for (const parameter of operation.parameters.filter((item) => item.in === 'path')) path[parameter.name] = record[parameter.name] ?? record.id; + const body: Record = {}; + const properties = operation.requestSchema && '$ref' in operation.requestSchema ? {} : operation.requestSchema?.properties || {}; + for (const name of Object.keys(properties)) if (record[name] !== undefined) body[name] = record[name]; + return { path, body }; +} + +export function BusinessPage({ pageKey }: { pageKey: string }) { + const definition = businessPages.find((page) => page.key === pageKey)!; + const operations = useMemo(() => platformOperations.filter(definition.matches), [definition]); + const reads = operations.filter((operation) => operation.method === 'GET'); + const writes = operations.filter((operation) => operation.method !== 'GET'); + const [activeReadId, setActiveReadId] = useState(reads[0]?.id || ''); + const [payload, setPayload] = useState(); + const [selectedRecord, setSelectedRecord] = useState | null>(null); + const [loading, setLoading] = useState(false); + const [drawerOperation, setDrawerOperation] = useState(null); + const [filterForm] = Form.useForm(); + const [actionForm] = Form.useForm(); + const { message, modal } = App.useApp(); + const activeRead = reads.find((operation) => operation.id === activeReadId) || reads[0]; + + const runRead = async () => { + if (!activeRead) return; + setLoading(true); + try { setPayload(await apiRequest(activeRead, normalizeOperationInput(activeRead, filterForm.getFieldsValue(true)))); } + catch (error) { message.error(error instanceof Error ? error.message : '数据加载失败'); } + finally { setLoading(false); } + }; + + useEffect(() => { filterForm.resetFields(); setPayload(undefined); setSelectedRecord(null); if (activeRead) void runRead(); }, [activeReadId]); + + const openAction = (operation: PlatformOperation) => { + setDrawerOperation(operation); + actionForm.resetFields(); + queueMicrotask(() => actionForm.setFieldsValue(prefillFromRecord(operation, selectedRecord))); + }; + + const submitAction = async () => { + if (!drawerOperation) return; + const values = normalizeOperationInput(drawerOperation, await actionForm.validateFields()); + modal.confirm({ + title: `确认${drawerOperation.summary}`, + content: selectedRecord ? '该操作将作用于当前选中的业务记录,并写入平台审计。' : '请确认表单内容无误。', + okText: '确认执行', cancelText: '取消', + onOk: async () => { + setLoading(true); + try { await apiRequest(drawerOperation, values); message.success(`${drawerOperation.summary}完成`); setDrawerOperation(null); await runRead(); } + catch (error) { message.error(error instanceof Error ? error.message : '操作失败'); } + finally { setLoading(false); } + }, + }); + }; + + return ( +
+ +
{definition.eyebrow}{definition.title}{definition.description}
+ + {writes.map((operation) => )} + +
+ + {reads.length > 1 && ({ key: operation.id, label: operation.summary }))} />} + {activeRead ? ( + <> +
+ + + ) : } +
+ setDrawerOperation(null)} footer={}> + {selectedRecord && 已带入当前选中记录,可在提交前核对或修改。} + {drawerOperation &&
} +
+
+ ); +} diff --git a/Tiku.PlatformAdmin.Web/src/pages/DashboardPage.tsx b/Tiku.PlatformAdmin.Web/src/pages/DashboardPage.tsx new file mode 100644 index 0000000..603ba69 --- /dev/null +++ b/Tiku.PlatformAdmin.Web/src/pages/DashboardPage.tsx @@ -0,0 +1,88 @@ +import { ArrowRightOutlined, ReloadOutlined } from '@ant-design/icons'; +import { Alert, Button, Card, Col, Flex, Row, Skeleton, Statistic, Typography } from 'antd'; +import { useCallback, useEffect, useState } from 'react'; +import { useNavigate } from 'react-router'; +import { apiRequest } from '../api/http'; +import { platformOperations } from '../api/platform-operations.generated'; + +const overviewOperation = platformOperations.find((operation) => operation.path === '/api/platform-admin/overview' && operation.method === 'GET'); + +const metricLabels: Record = { + tenantCount: '租户总数', + activeTenantCount: '活跃租户', + suspendedTenantCount: '暂停租户', + activeSubscriptionCount: '有效订阅', + overdueInvoiceCount: '逾期账单', + outstandingAmountCents: '待收金额(分)', + openAuditAlertCount: '未处理告警', +}; + +const workspaces = [ + { path: '/tenants', title: '租户管理', description: '租户创建、详情、域名、账务资料与生命周期' }, + { path: '/subscriptions', title: '套餐与订阅', description: 'SaaS 功能、限额、套餐版本与租户订阅' }, + { path: '/billing', title: '订单与发票', description: '服务费订单、退款、发票及交易记录' }, + { path: '/usage', title: '用量计费', description: '租户用量与超额计费数据' }, + { path: '/dunning', title: '收款与催缴', description: '人工收款、提醒渠道、通知事件与重试' }, + { path: '/question-banks', title: '公共题库', description: '题库目录、题目、导入与资源管理' }, + { path: '/crm', title: 'CRM 服务', description: '租户接入配置、线索队列与推送日志' }, + { path: '/sms', title: '短信服务', description: '渠道、模板审核与发送日志' }, + { path: '/payments', title: '支付服务', description: '支付应用、渠道、事件与返佣' }, + { path: '/staff', title: '员工与角色', description: '平台员工、角色和权限绑定' }, + { path: '/audit', title: '审计日志', description: '跨租户敏感操作检索' }, + { path: '/alerts', title: '审计告警', description: '安全告警确认、解决与忽略' }, +]; + +export function DashboardPage() { + const [data, setData] = useState | null>(null); + const [error, setError] = useState(''); + const [loading, setLoading] = useState(true); + const navigate = useNavigate(); + const load = useCallback(async () => { + if (!overviewOperation) return; + setLoading(true); + setError(''); + try { + setData(await apiRequest>(overviewOperation)); + } catch (reason) { + setError(reason instanceof Error ? reason.message : '概览加载失败'); + } finally { + setLoading(false); + } + }, []); + + useEffect(() => { void load(); }, [load]); + const metrics = Object.entries(data || {}).filter(([, value]) => typeof value === 'number').slice(0, 8); + return ( +
+ +
+ 经营概览 + 平台运营、账务与安全状态 +
+ +
+ {error && void load()}>重试} />} + + + {metrics.map(([key, value]) => ( +
+ + + ))} + + + 业务工作台 + + {workspaces.map((group) => ( + + navigate(group.path)}> + {group.title} + {group.description} + + + + ))} + + + ); +} diff --git a/Tiku.PlatformAdmin.Web/src/pages/LoginPage.tsx b/Tiku.PlatformAdmin.Web/src/pages/LoginPage.tsx new file mode 100644 index 0000000..ac72639 --- /dev/null +++ b/Tiku.PlatformAdmin.Web/src/pages/LoginPage.tsx @@ -0,0 +1,57 @@ +import { LockOutlined, UserOutlined } from '@ant-design/icons'; +import { Alert, App, Button, Card, Form, Input, Typography } from 'antd'; +import { useState } from 'react'; +import { Navigate } from 'react-router'; +import { useAuth } from '../auth/AuthProvider'; + +export function LoginPage() { + const auth = useAuth(); + const { message } = App.useApp(); + const [submitting, setSubmitting] = useState(false); + if (auth.user) return ; + + const submit = async (values: { identifier: string; password: string; newPassword?: string }) => { + setSubmitting(true); + try { + if (auth.challengeToken) await auth.completePasswordChange(values.newPassword || ''); + else await auth.login(values.identifier, values.password); + message.success('登录成功'); + } catch (error) { + message.error(error instanceof Error ? error.message : '登录失败'); + } finally { + setSubmitting(false); + } + }; + + return ( +
+
+ 恭学题库 + 恭学题库 SaaS + 平台运营与资源管理中心 +
+ + {auth.challengeToken ? '设置新密码' : '平台管理员登录'} + {auth.challengeToken && } +
+ {!auth.challengeToken && ( + <> + + } autoComplete="username" placeholder="手机号或账号" /> + + + } autoComplete="current-password" placeholder="登录密码" /> + + + )} + {auth.challengeToken && ( + + } autoComplete="new-password" /> + + )} + + +
+
+ ); +} diff --git a/Tiku.PlatformAdmin.Web/src/pages/QuestionBankPage.tsx b/Tiku.PlatformAdmin.Web/src/pages/QuestionBankPage.tsx new file mode 100644 index 0000000..dab191a --- /dev/null +++ b/Tiku.PlatformAdmin.Web/src/pages/QuestionBankPage.tsx @@ -0,0 +1,322 @@ +import { + StopOutlined, + CloudUploadOutlined, + DeleteOutlined, + DownloadOutlined, + EditOutlined, + FileAddOutlined, + FolderAddOutlined, + PlusOutlined, + ReloadOutlined, + SearchOutlined, +} from '@ant-design/icons'; +import { + App, + Badge, + Button, + Card, + Descriptions, + Drawer, + Empty, + Flex, + Form, + Input, + InputNumber, + List, + Modal, + Popconfirm, + Progress, + Radio, + Select, + Space, + Splitter, + Table, + Tabs, + Tag, + Tree, + Typography, + Upload, +} from 'antd'; +import type { UploadProps } from 'antd'; +import type { DataNode } from 'antd/es/tree'; +import { useCallback, useEffect, useMemo, useState } from 'react'; +import { platformRequest } from '../api/platform'; +import type { components } from '../api/schema.generated'; + +type Bank = components['schemas']['PlatformQuestionBankItem']; +type BankNode = components['schemas']['PlatformQuestionBankNodeItem']; +type Question = components['schemas']['PlatformQuestionItem']; +type QuestionPage = components['schemas']['PlatformQuestionPage']; +type ImportResult = components['schemas']['PlatformQuestionImportResult']; +type UploadSignResult = components['schemas']['AssetUploadSignResult']; +type UploadConfirmResult = components['schemas']['AssetUploadConfirmResult']; +type UploadRequestOption = Parameters>[0]; + +const nodeTypes = [ + { value: 0, label: '分类' }, + { value: 1, label: '科目' }, + { value: 2, label: '章节' }, + { value: 3, label: '试卷' }, + { value: 4, label: '院校' }, + { value: 5, label: '专业' }, + { value: 6, label: '考试方向' }, + { value: 7, label: '资源组' }, + { value: 8, label: '自定义' }, +]; +const questionTypes = [ + ['choice', '单选题'], ['multi_choice', '多选题'], ['true_false', '判断题'], ['short_answer', '简答题'], + ['fill_blank', '填空题'], ['reading', '阅读理解'], ['case_analysis', '案例分析'], ['programming', '编程题'], +].map(([value, label]) => ({ value, label })); +const statusLabels: Record = { '0': '草稿', '1': '已发布', '2': '已归档', draft: '草稿', published: '已发布', archived: '已归档' }; + +function toTree(nodes: BankNode[]): DataNode[] { + const children = new Map(); + for (const node of nodes) { + const key = node.parentId || null; + children.set(key, [...(children.get(key) || []), node]); + } + const build = (parentId: string | null): DataNode[] => (children.get(parentId) || []) + .sort((a, b) => Number(a.sortOrder) - Number(b.sortOrder)) + .map((node) => ({ + key: node.id, + title: {node.name}, + children: build(node.id), + })); + return build(null); +} + +function parseJson(value: string | undefined, fallback: unknown) { + if (!value?.trim()) return fallback; + return JSON.parse(value); +} + +function downloadJson(name: string, value: unknown) { + const url = URL.createObjectURL(new Blob([JSON.stringify(value, null, 2)], { type: 'application/json' })); + const anchor = document.createElement('a'); + anchor.href = url; + anchor.download = name; + anchor.click(); + URL.revokeObjectURL(url); +} + +export function QuestionBankPage() { + const { message, modal } = App.useApp(); + const [banks, setBanks] = useState([]); + const [bankKeyword, setBankKeyword] = useState(''); + const [bankStatus, setBankStatus] = useState('active'); + const [bankId, setBankId] = useState(''); + const [nodes, setNodes] = useState([]); + const [nodeId, setNodeId] = useState(''); + const [questions, setQuestions] = useState([]); + const [total, setTotal] = useState(0); + const [page, setPage] = useState(1); + const [pageSize, setPageSize] = useState(20); + const [filters, setFilters] = useState({ keyword: '', type: '', status: '' }); + const [selectedQuestionIds, setSelectedQuestionIds] = useState([]); + const [loading, setLoading] = useState(false); + const [bankDrawer, setBankDrawer] = useState(); + const [nodeDrawer, setNodeDrawer] = useState(); + const [batchNodeOpen, setBatchNodeOpen] = useState(false); + const [questionDrawer, setQuestionDrawer] = useState(); + const [importOpen, setImportOpen] = useState(false); + const [importResult, setImportResult] = useState(null); + const [bankForm] = Form.useForm(); + const [nodeForm] = Form.useForm(); + const [batchForm] = Form.useForm(); + const [questionForm] = Form.useForm(); + const [importForm] = Form.useForm(); + + const bank = banks.find((item) => item.id === bankId); + const node = nodes.find((item) => item.id === nodeId); + + const loadBanks = useCallback(async (status = bankStatus, keyword = bankKeyword) => { + setLoading(true); + try { + const result = await platformRequest('GET', '/api/platform-admin/question-banks', { query: { keyword, status } }); + setBanks(result); + setBankId((current) => result.some((item) => item.id === current) ? current : result[0]?.id || ''); + } catch (error) { message.error(error instanceof Error ? error.message : '题库加载失败'); } + finally { setLoading(false); } + }, [bankKeyword, bankStatus, message]); + + const loadNodes = useCallback(async () => { + if (!bankId) { setNodes([]); setNodeId(''); return; } + try { + const result = await platformRequest('GET', '/api/platform-admin/question-banks/{bankId}/nodes', { path: { bankId } }); + setNodes(result); + setNodeId((current) => result.some((item) => item.id === current) ? current : ''); + } catch (error) { message.error(error instanceof Error ? error.message : '目录加载失败'); } + }, [bankId, message]); + + const loadQuestions = useCallback(async () => { + if (!bankId) { setQuestions([]); setTotal(0); return; } + setLoading(true); + try { + const result = await platformRequest('GET', '/api/platform-admin/question-banks/questions', { + query: { questionBankId: bankId, contentNodeId: nodeId || undefined, ...filters, page, pageSize }, + }); + setQuestions(result.items); + setTotal(Number(result.total)); + setSelectedQuestionIds([]); + } catch (error) { message.error(error instanceof Error ? error.message : '题目加载失败'); } + finally { setLoading(false); } + }, [bankId, filters, message, nodeId, page, pageSize]); + + useEffect(() => { void loadBanks(); }, []); + useEffect(() => { void loadNodes(); setPage(1); }, [bankId]); + useEffect(() => { void loadQuestions(); }, [loadQuestions]); + + const openBank = (record?: Bank) => { + setBankDrawer(record || null); + queueMicrotask(() => bankForm.setFieldsValue({ id: record?.id, name: record?.name, metadata: JSON.stringify(record?.metadata || {}, null, 2) })); + }; + const saveBank = async () => { + const values = await bankForm.validateFields(); + try { + const saved = await platformRequest('PUT', '/api/platform-admin/question-banks', { body: { id: values.id || null, name: values.name, metadata: parseJson(values.metadata, {}) } }); + message.success('题库已保存'); setBankDrawer(undefined); await loadBanks(); setBankId(saved.id); + } catch (error) { message.error(error instanceof Error ? error.message : '题库保存失败'); } + }; + + const openNode = (record?: BankNode) => { + if (!bankId) return message.warning('请先创建题库'); + setNodeDrawer(record || null); + queueMicrotask(() => nodeForm.setFieldsValue({ + id: record?.id, name: record?.name, parentId: record?.parentId || null, nodeKey: record?.nodeKey, + nodeType: record?.nodeType ?? 2, sortOrder: Number(record?.sortOrder || 0), isSelectable: record?.isSelectable ?? true, + metadata: JSON.stringify(record?.metadata || {}, null, 2), + })); + }; + const saveNode = async () => { + const values = await nodeForm.validateFields(); + try { + await platformRequest('PUT', '/api/platform-admin/question-banks/nodes', { body: { ...values, questionBankId: bankId, parentId: values.parentId || null, nodeKey: values.nodeKey || null, metadata: parseJson(values.metadata, {}) } }); + message.success('目录节点已保存'); setNodeDrawer(undefined); await loadNodes(); + } catch (error) { message.error(error instanceof Error ? error.message : '目录保存失败'); } + }; + const saveBatchNodes = async () => { + const values = await batchForm.validateFields(); + const names = String(values.names).split(/\n|,/).map((item) => item.trim()).filter(Boolean); + if (names.length > 100) return message.error('一次最多创建 100 个节点'); + await platformRequest('POST', '/api/platform-admin/question-banks/nodes/batch', { body: { questionBankId: bankId, parentId: values.parentId || null, nodeType: values.nodeType, names } }); + message.success(`已创建 ${names.length} 个节点`); setBatchNodeOpen(false); batchForm.resetFields(); await loadNodes(); + }; + + const openQuestion = (record?: Question) => { + if (!bankId || (!nodeId && !record)) return message.warning('请先选择一个章节或试卷'); + setQuestionDrawer(record || null); + queueMicrotask(() => questionForm.setFieldsValue({ + id: record?.id, type: record?.type || 'choice', typeLabel: record?.typeLabel, difficulty: record?.difficulty ? Number(record.difficulty) : 3, + status: record ? String(record.status) : 'published', content: record?.content, answerText: record?.answerText, explanation: record?.explanation, + options: JSON.stringify(record?.options || [], null, 2), correctOptionIndex: record?.correctOptionIndex == null ? null : Number(record.correctOptionIndex), + correctOptionIndices: JSON.stringify(record?.correctOptionIndices || [], null, 2), tags: JSON.stringify(record?.tags || [], null, 2), + subQuestions: JSON.stringify(record?.subQuestions || [], null, 2), codeLang: record?.codeLang, codeTemplate: record?.codeTemplate, + mediaUrl: record?.mediaUrl, + })); + }; + const saveQuestion = async () => { + const values = await questionForm.validateFields(); + try { + await platformRequest('PUT', '/api/platform-admin/question-banks/questions', { body: { + ...values, id: values.id || null, questionBankId: bankId, contentNodeId: questionDrawer?.contentNodeId || nodeId, + legacyId: questionDrawer?.legacyId || null, options: parseJson(values.options, []), correctOptionIndices: parseJson(values.correctOptionIndices, []), + tags: parseJson(values.tags, []), subQuestions: parseJson(values.subQuestions, []), examMarkers: {}, sourceHash: null, + } }); + message.success(questionDrawer ? '题目已更新并生成新版本' : '题目已创建'); setQuestionDrawer(undefined); await Promise.all([loadQuestions(), loadNodes()]); + } catch (error) { message.error(error instanceof Error ? error.message : '题目保存失败'); } + }; + + const archiveQuestions = () => modal.confirm({ + title: `归档 ${selectedQuestionIds.length} 道题目`, content: '归档后不会再作为正常题目展示。', okButtonProps: { danger: true }, + onOk: async () => { await platformRequest('POST', '/api/platform-admin/question-banks/questions/archive', { body: { questionIds: selectedQuestionIds } }); message.success('题目已归档'); await loadQuestions(); }, + }); + + const runImport = async (preview: boolean) => { + const values = await importForm.validateFields(); + try { + const payload = parseJson(values.payload, []); + const result = await platformRequest('POST', preview ? '/api/platform-admin/question-banks/imports/preview' : '/api/platform-admin/question-banks/imports', { + body: { questionBankId: bankId, contentNodeId: values.format === 'simple' ? (values.contentNodeId || nodeId || null) : null, format: values.format, sourceName: values.sourceName || null, payload }, + }); + setImportResult(result); + message.success(preview ? '预检完成' : '导入完成'); + if (!preview) await Promise.all([loadQuestions(), loadNodes(), loadBanks()]); + } catch (error) { message.error(error instanceof Error ? error.message : '导入处理失败'); } + }; + + const uploadAsset = async ({ file, onError, onSuccess, onProgress }: UploadRequestOption) => { + const blob = file as File; + try { + onProgress?.({ percent: 10 }); + const sign = await platformRequest('POST', '/api/platform-admin/question-banks/assets/upload-sign', { body: { + contentNodeId: nodeId || null, fileName: blob.name, mimeType: blob.type || 'application/octet-stream', fileSizeBytes: blob.size, + title: blob.name, category: 'question', assetType: 'image', visibility: 'public', isPublic: true, metadata: {}, + } }); + const headers = new Headers(sign.upload.headers); + const uploaded = await fetch(sign.upload.url, { method: sign.upload.method || 'PUT', headers, body: blob }); + if (!uploaded.ok) throw new Error(`文件上传失败(HTTP ${uploaded.status})`); + onProgress?.({ percent: 80 }); + const confirmed = await platformRequest('POST', '/api/platform-admin/question-banks/assets/upload-confirm', { body: { assetId: sign.item.id, mimeType: blob.type, fileSizeBytes: blob.size } }); + questionForm.setFieldValue('mediaUrl', confirmed.item.cdnUrl || sign.upload.url.split('?')[0]); + onProgress?.({ percent: 100 }); onSuccess?.(confirmed); message.success('资源上传成功'); + } catch (error) { onError?.(error as Error); message.error(error instanceof Error ? error.message : '资源上传失败'); } + }; + + const columns = [ + { title: '题型', dataIndex: 'typeLabel', width: 100, render: (_: unknown, record: Question) => record.typeLabel || questionTypes.find((item) => item.value === record.type)?.label || record.type }, + { title: '题干', dataIndex: 'content', ellipsis: true, render: (value: string) => value || 无文字题干 }, + { title: '难度', dataIndex: 'difficulty', width: 90, render: (value: number | string | null) => value ? `${value} 级` : '-' }, + { title: '状态', dataIndex: 'status', width: 90, render: (value: string | number) => {statusLabels[String(value)] || String(value)} }, + { title: '版本', dataIndex: 'versionNo', width: 75, render: (value: number | string) => `v${value}` }, + { title: '操作', key: 'actions', width: 80, fixed: 'right' as const, render: (_: unknown, record: Question) => }, + ]; + + const treeData = useMemo(() => toTree(nodes), [nodes]); + return ( +
+ +
公共题库维护题库目录、题目版本、批量导入与图片资源
+ +
+ + +
+ setBankKeyword(event.target.value)} onPressEnter={() => void loadBanks()} prefix={} placeholder="搜索题库" /> + rowKey="id" loading={loading} dataSource={questions} columns={columns} scroll={{ x: 760 }} rowSelection={{ selectedRowKeys: selectedQuestionIds, preserveSelectedRowKeys: true, onChange: setSelectedQuestionIds }} pagination={{ current: page, pageSize, total, showSizeChanger: true, showTotal: (value) => `共 ${value} 道题`, onChange: (next, size) => { setPage(next); setPageSize(size); } }} locale={{ emptyText: nodeId ? '当前节点暂无题目' : '当前题库暂无题目' }} /> +
+
+
+ + setBankDrawer(undefined)} extra={}> +
{ parseJson(value, {}); } }]}>{bankDrawer?.id && { await platformRequest('POST', '/api/platform-admin/question-banks/{bankId}/archive', { path: { bankId: bankDrawer.id } }); setBankDrawer(undefined); await loadBanks(); }}>} +
+ setNodeDrawer(undefined)} extra={}> +
+
+ setBatchNodeOpen(false)} onOk={() => void saveBatchNodes()} okText="创建"> +
[2, 3].includes(item.value))} /> +
+ setQuestionDrawer(undefined)} extra={}> +
({ value, label: `${value} 级` }))} /> }, { key: 'advanced', label: '扩展内容', children: <> }]} /> +
+ setImportOpen(false)} footer={ { importForm.setFieldsValue({ sourceName: file.name, payload: await file.text() }); return false; }} showUploadList={false} accept=".json,application/json">}> +
({ value: item.id, label: item.name }))} /> { parseJson(value, []); } }]}> + {importResult && {importResult.detail.issues.length > 0 &&
}} + + + ); +} diff --git a/Tiku.PlatformAdmin.Web/src/pages/WorkspacePage.tsx b/Tiku.PlatformAdmin.Web/src/pages/WorkspacePage.tsx new file mode 100644 index 0000000..7d9faac --- /dev/null +++ b/Tiku.PlatformAdmin.Web/src/pages/WorkspacePage.tsx @@ -0,0 +1,115 @@ +import { ApiOutlined, PlayCircleOutlined, ReloadOutlined } from '@ant-design/icons'; +import { App, Button, Card, Drawer, Empty, Flex, Form, List, Modal, Segmented, Space, Tag, Typography } from 'antd'; +import { useEffect, useMemo, useState } from 'react'; +import { apiRequest } from '../api/http'; +import { groupForOperation, platformGroups, type PlatformGroupKey } from '../api/groups'; +import { platformOperations } from '../api/platform-operations.generated'; +import type { OperationInput, PlatformOperation } from '../api/types'; +import { OperationForm, normalizeOperationInput } from '../components/OperationForm'; +import { ResponseView } from '../components/ResponseView'; + +const methodColors: Record = { GET: 'blue', POST: 'green', PUT: 'orange', PATCH: 'gold', DELETE: 'red' }; + +export function WorkspacePage({ groupKey }: { groupKey: PlatformGroupKey }) { + const group = platformGroups.find((item) => item.key === groupKey)!; + const operations = useMemo(() => platformOperations.filter((operation) => groupForOperation(operation) === groupKey), [groupKey]); + const [selectedId, setSelectedId] = useState(operations[0]?.id || ''); + const [payload, setPayload] = useState(undefined); + const [loading, setLoading] = useState(false); + const [drawerOpen, setDrawerOpen] = useState(false); + const [methodFilter, setMethodFilter] = useState('全部'); + const [form] = Form.useForm(); + const { message, modal } = App.useApp(); + const selected = operations.find((operation) => operation.id === selectedId) || operations[0]; + const visibleOperations = methodFilter === '全部' ? operations : operations.filter((operation) => operation.method === methodFilter); + + useEffect(() => { + setSelectedId(operations[0]?.id || ''); + setPayload(undefined); + }, [operations]); + + const execute = async (operation: PlatformOperation, values: OperationInput) => { + setLoading(true); + try { + const result = await apiRequest(operation, normalizeOperationInput(operation, values)); + setPayload(result); + setDrawerOpen(false); + message.success(`${operation.summary}完成`); + } catch (error) { + message.error(error instanceof Error ? error.message : '接口调用失败'); + } finally { + setLoading(false); + } + }; + + const submit = async () => { + if (!selected) return; + const values = await form.validateFields(); + if (selected.method !== 'GET') { + modal.confirm({ + title: `确认执行:${selected.summary}`, + content: `将调用 ${selected.method} ${selected.path}`, + okText: '确认执行', + cancelText: '取消', + okButtonProps: { danger: /archive|disable|status/.test(selected.path) }, + onOk: () => execute(selected, values), + }); + return; + } + await execute(selected, values); + }; + + const chooseOperation = (operation: PlatformOperation) => { + setSelectedId(operation.id); + setPayload(undefined); + form.resetFields(); + setDrawerOpen(true); + }; + + if (!selected) return ; + return ( +
+ +
+ {group.label} + {group.description} · {operations.length} 个后端接口 +
+ setMethodFilter(String(value))} options={['全部', ...new Set(operations.map((item) => item.method))]} /> +
+
+ }> + ( + chooseOperation(operation)}> + {operation.method}{operation.summary}} + description={{operation.path}} + /> + + )} + /> + + } onClick={() => chooseOperation(selected)}>重新执行} + > + + +
+ setDrawerOpen(false)} + extra={{selected.method}} + footer={} + > + {selected.description} + {selected.path} +
+
+
+ ); +} diff --git a/Tiku.PlatformAdmin.Web/src/pages/business-definitions.test.ts b/Tiku.PlatformAdmin.Web/src/pages/business-definitions.test.ts new file mode 100644 index 0000000..8e98d58 --- /dev/null +++ b/Tiku.PlatformAdmin.Web/src/pages/business-definitions.test.ts @@ -0,0 +1,12 @@ +import { describe, expect, it } from 'vitest'; +import { platformOperations } from '../api/platform-operations.generated'; +import { businessPageForOperation } from './business-definitions'; + +describe('平台业务页面覆盖', () => { + it('除经营概览外,每个 OpenAPI 平台接口只属于一个业务页面', () => { + const operations = platformOperations.filter((operation) => operation.path !== '/api/platform-admin/overview'); + expect(operations.map((operation) => [operation.id, businessPageForOperation(operation).length])).toEqual( + operations.map((operation) => [operation.id, 1]), + ); + }); +}); diff --git a/Tiku.PlatformAdmin.Web/src/pages/business-definitions.ts b/Tiku.PlatformAdmin.Web/src/pages/business-definitions.ts new file mode 100644 index 0000000..7748ea8 --- /dev/null +++ b/Tiku.PlatformAdmin.Web/src/pages/business-definitions.ts @@ -0,0 +1,30 @@ +import type { PlatformOperation } from '../api/types'; + +export interface BusinessPageDefinition { + key: string; + title: string; + description: string; + eyebrow: string; + matches(operation: PlatformOperation): boolean; +} + +const starts = (operation: PlatformOperation, prefix: string) => operation.path.startsWith(prefix); + +export const businessPages: readonly BusinessPageDefinition[] = [ + { key: 'tenants', eyebrow: '租户管理', title: '租户列表与生命周期', description: '管理租户主体、域名、业务状态、账务状态与开票资料。', matches: (op) => starts(op, '/api/platform-admin/tenants') || starts(op, '/api/platform-admin/domains') }, + { key: 'subscriptions', eyebrow: 'SaaS 账务', title: '套餐与订阅', description: '维护 SaaS 功能、限额、商品、版本与租户订阅。', matches: (op) => starts(op, '/api/platform-admin/saas/catalog') || starts(op, '/api/platform-admin/saas/features') || starts(op, '/api/platform-admin/saas/feature-limits') || starts(op, '/api/platform-admin/saas/offerings') || starts(op, '/api/platform-admin/saas/offering-versions') || starts(op, '/api/platform-admin/saas/tenant-feature-overrides') || starts(op, '/api/platform-admin/saas/subscriptions') }, + { key: 'billing', eyebrow: 'SaaS 账务', title: '服务费账单与交易', description: '集中查看平台订单、退款和服务费账单。', matches: (op) => starts(op, '/api/platform-admin/saas/orders') || starts(op, '/api/platform-admin/saas/refunds') || op.path === '/api/platform-admin/saas/invoices' }, + { key: 'usage', eyebrow: 'SaaS 账务', title: '用量与超额计费', description: '按租户和账期查看席位、题量、存储等 SaaS 用量。', matches: (op) => starts(op, '/api/platform-admin/saas/usage') }, + { key: 'dunning', eyebrow: 'SaaS 账务', title: '收款、逾期与催缴', description: '处理人工收款、账单提醒、催缴渠道与失败事件重试。', matches: (op) => starts(op, '/api/platform-admin/saas/payments') || starts(op, '/api/platform-admin/saas/dunning') || starts(op, '/api/platform-admin/saas/invoices/reminders') }, + { key: 'question-banks', eyebrow: '平台资产', title: '公共题库工作台', description: '维护题库、内容结构、题目版本、批量导入与资源上传。', matches: (op) => starts(op, '/api/platform-admin/question-banks') }, + { key: 'crm', eyebrow: '客户服务', title: 'CRM 接入与线索队列', description: '管理租户 CRM 配置、线索推送队列、失败重试与投递日志。', matches: (op) => starts(op, '/api/platform-admin/tenant-capabilities/crm') }, + { key: 'sms', eyebrow: '消息服务', title: '短信渠道、模板与发送日志', description: '管理租户短信渠道和模板审核,并检索短信发送记录。', matches: (op) => starts(op, '/api/platform-admin/tenant-capabilities/sms') }, + { key: 'payments', eyebrow: '支付服务', title: '支付应用、渠道与事件', description: '管理平台和租户支付应用、支付渠道、回调事件及返佣汇总。', matches: (op) => starts(op, '/api/platform-admin/payment-settings') || starts(op, '/api/platform-admin/tenant-capabilities/payments') }, + { key: 'staff', eyebrow: '安全治理', title: '平台员工与权限', description: '管理平台员工、角色、权限绑定与账号状态。', matches: (op) => starts(op, '/api/platform-admin/staff') || starts(op, '/api/backoffice/platform') }, + { key: 'audit', eyebrow: '安全治理', title: '平台审计日志', description: '检索跨租户敏感操作、账务变更与权限事件。', matches: (op) => starts(op, '/api/platform-admin/audit-logs') }, + { key: 'alerts', eyebrow: '安全治理', title: '审计告警与处理', description: '按开放、确认、解决或忽略状态处理平台安全告警。', matches: (op) => starts(op, '/api/platform-admin/audit-alerts') }, +]; + +export function businessPageForOperation(operation: PlatformOperation) { + return businessPages.filter((page) => page.matches(operation)); +} diff --git a/Tiku.PlatformAdmin.Web/src/pages/question-bank-contract.test.ts b/Tiku.PlatformAdmin.Web/src/pages/question-bank-contract.test.ts new file mode 100644 index 0000000..e886b53 --- /dev/null +++ b/Tiku.PlatformAdmin.Web/src/pages/question-bank-contract.test.ts @@ -0,0 +1,27 @@ +import { describe, expect, it } from 'vitest'; +import { platformOperations } from '../api/platform-operations.generated'; + +const expected = [ + ['GET', '/api/platform-admin/question-banks'], + ['PUT', '/api/platform-admin/question-banks'], + ['POST', '/api/platform-admin/question-banks/{bankId}/archive'], + ['GET', '/api/platform-admin/question-banks/{bankId}/nodes'], + ['PUT', '/api/platform-admin/question-banks/nodes'], + ['POST', '/api/platform-admin/question-banks/nodes/batch'], + ['POST', '/api/platform-admin/question-banks/nodes/{nodeId}/archive'], + ['GET', '/api/platform-admin/question-banks/questions'], + ['PUT', '/api/platform-admin/question-banks/questions'], + ['POST', '/api/platform-admin/question-banks/questions/archive'], + ['POST', '/api/platform-admin/question-banks/imports/preview'], + ['POST', '/api/platform-admin/question-banks/imports'], + ['GET', '/api/platform-admin/question-banks/imports/{jobId}'], + ['POST', '/api/platform-admin/question-banks/assets/upload-sign'], + ['POST', '/api/platform-admin/question-banks/assets/upload-confirm'], +] as const; + +describe('公共题库页面接口契约', () => { + it('页面使用的所有题库操作都存在于后端 OpenAPI', () => { + const keys = new Set(platformOperations.map((operation) => `${operation.method} ${operation.path}`)); + expect(expected.filter(([method, path]) => !keys.has(`${method} ${path}`))).toEqual([]); + }); +}); diff --git a/Tiku.PlatformAdmin.Web/src/router.tsx b/Tiku.PlatformAdmin.Web/src/router.tsx new file mode 100644 index 0000000..46c03b8 --- /dev/null +++ b/Tiku.PlatformAdmin.Web/src/router.tsx @@ -0,0 +1,30 @@ +import { createBrowserRouter, Navigate } from 'react-router'; +import { AppLayout } from './layout/AppLayout'; +import { DashboardPage } from './pages/DashboardPage'; +import { LoginPage } from './pages/LoginPage'; +import { BusinessPage } from './pages/BusinessPage'; +import { QuestionBankPage } from './pages/QuestionBankPage'; + +export const router = createBrowserRouter([ + { path: '/login', element: }, + { + path: '/', + element: , + children: [ + { index: true, element: }, + { path: 'tenants', element: }, + { path: 'subscriptions', element: }, + { path: 'billing', element: }, + { path: 'usage', element: }, + { path: 'dunning', element: }, + { path: 'question-banks', element: }, + { path: 'crm', element: }, + { path: 'sms', element: }, + { path: 'payments', element: }, + { path: 'staff', element: }, + { path: 'audit', element: }, + { path: 'alerts', element: }, + ], + }, + { path: '*', element: }, +]); diff --git a/Tiku.PlatformAdmin.Web/src/styles.css b/Tiku.PlatformAdmin.Web/src/styles.css new file mode 100644 index 0000000..1ea5210 --- /dev/null +++ b/Tiku.PlatformAdmin.Web/src/styles.css @@ -0,0 +1,78 @@ +* { box-sizing: border-box; } +html, body, #root { min-width: 320px; min-height: 100%; margin: 0; } +body { background: #f3f6fa; } +.full-screen-loading { min-height: 100vh; display: grid; place-items: center; } +.app-shell { min-height: 100vh; } +.app-sider { position: sticky !important; top: 0; height: 100vh; overflow: hidden; border-right: 1px solid #e8edf3; box-shadow: 8px 0 28px rgba(24, 55, 88, .035); display: flex; flex-direction: column; } +.app-sider .ant-layout-sider-children { display: flex; flex-direction: column; height: 100%; } +.sider-brand { height: 76px; display: flex; align-items: center; gap: 12px; padding: 14px 17px; white-space: nowrap; overflow: hidden; border-bottom: 1px solid #eef2f6; } +.brand-mark { width: 42px; height: 42px; flex: 0 0 42px; border-radius: 13px; overflow: hidden; box-shadow: 0 6px 16px rgba(28, 91, 175, .22); } +.brand-mark img { width: 100%; height: 100%; display: block; object-fit: cover; } +.brand-copy { min-width: 0; display: flex; flex-direction: column; line-height: 1.2; } +.brand-copy strong { color: #172b4d; font-size: 16px; letter-spacing: .02em; } +.brand-copy span { color: #8b98a8; font-size: 11px; margin-top: 5px; font-weight: 500; letter-spacing: .08em; } +.sider-navigation { flex: 1; min-height: 0; overflow: auto; padding: 12px 10px; } +.sider-navigation .ant-menu { border-inline-end: 0 !important; background: transparent; } +.sider-navigation .ant-menu-item-group-title { padding: 15px 12px 7px !important; color: #9aa6b5 !important; font-size: 11px !important; font-weight: 600; letter-spacing: .09em; } +.sider-navigation .ant-menu-item { height: 42px; line-height: 42px; margin: 3px 0; border-radius: 9px; color: #526173; font-weight: 500; } +.sider-navigation .ant-menu-item .anticon { color: #7c8998; font-size: 17px; } +.sider-navigation .ant-menu-item:hover { color: #1f66c2 !important; background: #f3f7fc !important; } +.sider-navigation .ant-menu-item-selected { color: #165eb8 !important; background: #eaf3ff !important; font-weight: 600; } +.sider-navigation .ant-menu-item-selected::after { display: none; } +.sider-navigation .ant-menu-item-selected .anticon { color: #1d6fd1; } +.ant-layout-sider-collapsed .sider-brand { padding-inline: 17px; } +.ant-layout-sider-collapsed .sider-navigation { padding-inline: 10px; } +.ant-layout-sider-collapsed .ant-menu-item-group-title { height: 12px; padding: 6px 0 !important; font-size: 0 !important; } +.sider-footer { padding: 10px 12px 14px; border-top: 1px solid #eef2f6; } +.sider-footer .ant-btn { height: 40px; color: #748294; text-align: left; border-radius: 9px; } +.sider-footer .ant-btn:hover { color: #1f66c2 !important; background: #f3f7fc !important; } +.ant-layout-sider-collapsed .sider-footer .ant-btn { text-align: center; } +.app-header { height: 72px; padding: 0 24px; display: flex; align-items: center; justify-content: space-between; border-bottom: 1px solid #e7ecf2; position: sticky; top: 0; z-index: 10; background: rgba(255,255,255,.92); backdrop-filter: blur(12px); } +.header-page-title { color: #26374a; font-size: 16px; font-weight: 600; } +.user-menu { cursor: pointer; padding: 8px; border-radius: 10px; } +.user-menu:hover { background: #f5f7fa; } +.user-role { font-size: 12px; } +.app-content { padding: 28px; min-width: 0; } +.business-page, .question-bank-page { display: flex; flex-direction: column; gap: 20px; min-width: 0; } +.business-page h2, .question-bank-page h2 { margin: 0 !important; } +.business-card { min-height: 520px; } +.business-filter { margin-bottom: 18px; gap: 8px; } +.question-workspace { height: calc(100vh - 190px); min-height: 640px; background: white; border: 1px solid #e6ebf0; border-radius: 12px; overflow: hidden; } +.workspace-panel { height: 100%; padding: 16px; overflow: auto; } +.workspace-panel + .workspace-panel { border-left: 1px solid #eef1f4; } +.bank-panel { display: flex; flex-direction: column; gap: 12px; } +.bank-panel .ant-list { flex: 1; overflow: auto; } +.bank-panel .ant-list-item { padding: 12px; border-radius: 8px; cursor: pointer; } +.bank-panel .ant-list-item:hover, .bank-panel .selected-business-item { background: #edf5fc; } +.bank-panel .ant-list-item-action { margin-inline-start: 4px; } +.node-panel { display: flex; flex-direction: column; gap: 10px; } +.node-panel h5 { margin: 0 !important; } +.node-panel .ant-tree { flex: 1; overflow: auto; } +.node-panel .ant-tree-node-content-wrapper { min-width: 0; } +.node-panel .ant-tree-title { display: block; min-width: 150px; } +.node-detail { margin-top: auto; background: #f8fafc; } +.question-panel { display: flex; flex-direction: column; gap: 16px; } +.question-panel > .ant-table-wrapper { min-height: 0; } +.flex-field { flex: 1; min-width: 0; } +.flex-field .ant-input-number { width: 100%; } +.code-editor textarea, textarea.code-editor { font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace; } +.workspace-page, .dashboard-page { display: flex; flex-direction: column; gap: 22px; } +.workspace-page h2, .dashboard-page h2 { margin: 0 !important; } +.workspace-grid { display: grid; grid-template-columns: minmax(340px, 0.8fr) minmax(520px, 1.6fr); gap: 18px; align-items: start; } +.operation-list-card .ant-card-body { padding: 0; max-height: calc(100vh - 245px); overflow: auto; } +.operation-list-card .ant-list-item { padding: 14px 18px; cursor: pointer; transition: background .2s; } +.operation-list-card .ant-list-item:hover, .operation-list-card .operation-active { background: #eef5fc; } +.operation-list-card .ant-list-item-meta-title { margin-bottom: 6px !important; } +.response-card { min-height: 460px; } +.metric-card { border: 0; box-shadow: 0 6px 24px rgba(31, 62, 92, .06); } +.dashboard-section-title { margin: 8px 0 -4px !important; } +.portal-card { height: 100%; } +.portal-card .ant-btn { padding: 0; } +.login-page { min-height: 100vh; display: grid; grid-template-columns: minmax(420px, 1.2fr) minmax(420px, .8fr); background: linear-gradient(135deg, #0c3158 0%, #1f659f 55%, #eaf2f8 55%); } +.login-brand { color: white; display: flex; flex-direction: column; justify-content: center; padding: 10vw; } +.login-brand img { width: 88px; height: 88px; object-fit: contain; border-radius: 22px; background: white; padding: 6px; box-shadow: 0 18px 50px rgba(0,0,0,.2); } +.login-brand h1, .login-brand .ant-typography { color: white; } +.login-card { width: min(430px, calc(100vw - 40px)); margin: auto; box-shadow: 0 24px 70px rgba(19, 43, 69, .18); } +.login-alert { margin-bottom: 18px; } +@media (max-width: 1100px) { .workspace-grid { grid-template-columns: 1fr; } .operation-list-card .ant-card-body { max-height: 420px; } .question-workspace { overflow-x: auto; } } +@media (max-width: 800px) { .login-page { grid-template-columns: 1fr; background: linear-gradient(160deg, #0c3158 0%, #1f659f 45%, #eef4f8 45%); } .login-brand { padding: 42px 28px 18px; } .login-brand img { width: 60px; height: 60px; } .login-brand h1 { font-size: 28px; margin: 12px 0 0; } .login-card { margin: 20px auto 48px; } .app-content { padding: 18px; } } diff --git a/Tiku.PlatformAdmin.Web/tsconfig.app.json b/Tiku.PlatformAdmin.Web/tsconfig.app.json new file mode 100644 index 0000000..ae7563c --- /dev/null +++ b/Tiku.PlatformAdmin.Web/tsconfig.app.json @@ -0,0 +1,22 @@ +{ + "compilerOptions": { + "target": "ES2022", + "useDefineForClassFields": true, + "lib": ["ES2022", "DOM", "DOM.Iterable"], + "allowJs": false, + "skipLibCheck": true, + "esModuleInterop": true, + "allowSyntheticDefaultImports": true, + "strict": true, + "noUncheckedIndexedAccess": true, + "forceConsistentCasingInFileNames": true, + "module": "ESNext", + "moduleResolution": "Bundler", + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "types": ["vite/client"], + "jsx": "react-jsx" + }, + "include": ["src"] +} diff --git a/Tiku.PlatformAdmin.Web/tsconfig.app.tsbuildinfo b/Tiku.PlatformAdmin.Web/tsconfig.app.tsbuildinfo new file mode 100644 index 0000000..5595794 --- /dev/null +++ b/Tiku.PlatformAdmin.Web/tsconfig.app.tsbuildinfo @@ -0,0 +1 @@ +{"root":["./src/main.tsx","./src/router.tsx","./src/api/groups.test.ts","./src/api/groups.ts","./src/api/http.ts","./src/api/platform-operations.generated.ts","./src/api/platform.ts","./src/api/schema-utils.ts","./src/api/schema.generated.d.ts","./src/api/token-store.ts","./src/api/types.ts","./src/auth/authprovider.tsx","./src/components/businesstable.tsx","./src/components/operationform.tsx","./src/components/responseview.tsx","./src/components/schemafields.tsx","./src/layout/applayout.tsx","./src/pages/businesspage.tsx","./src/pages/dashboardpage.tsx","./src/pages/loginpage.tsx","./src/pages/questionbankpage.tsx","./src/pages/workspacepage.tsx","./src/pages/business-definitions.test.ts","./src/pages/business-definitions.ts","./src/pages/question-bank-contract.test.ts"],"version":"5.9.3"} \ No newline at end of file diff --git a/Tiku.PlatformAdmin.Web/tsconfig.json b/Tiku.PlatformAdmin.Web/tsconfig.json new file mode 100644 index 0000000..1ffef60 --- /dev/null +++ b/Tiku.PlatformAdmin.Web/tsconfig.json @@ -0,0 +1,7 @@ +{ + "files": [], + "references": [ + { "path": "./tsconfig.app.json" }, + { "path": "./tsconfig.node.json" } + ] +} diff --git a/Tiku.PlatformAdmin.Web/tsconfig.node.json b/Tiku.PlatformAdmin.Web/tsconfig.node.json new file mode 100644 index 0000000..da50802 --- /dev/null +++ b/Tiku.PlatformAdmin.Web/tsconfig.node.json @@ -0,0 +1,11 @@ +{ + "compilerOptions": { + "composite": true, + "skipLibCheck": true, + "module": "ESNext", + "moduleResolution": "Bundler", + "allowImportingTsExtensions": true, + "noEmit": true + }, + "include": ["vite.config.ts", "vitest.config.ts"] +} diff --git a/Tiku.PlatformAdmin.Web/tsconfig.node.tsbuildinfo b/Tiku.PlatformAdmin.Web/tsconfig.node.tsbuildinfo new file mode 100644 index 0000000..41852d7 --- /dev/null +++ b/Tiku.PlatformAdmin.Web/tsconfig.node.tsbuildinfo @@ -0,0 +1 @@ +{"fileNames":["./node_modules/typescript/lib/lib.d.ts","./node_modules/typescript/lib/lib.es5.d.ts","./node_modules/typescript/lib/lib.es2015.d.ts","./node_modules/typescript/lib/lib.es2016.d.ts","./node_modules/typescript/lib/lib.es2017.d.ts","./node_modules/typescript/lib/lib.es2018.d.ts","./node_modules/typescript/lib/lib.es2019.d.ts","./node_modules/typescript/lib/lib.es2020.d.ts","./node_modules/typescript/lib/lib.dom.d.ts","./node_modules/typescript/lib/lib.webworker.importscripts.d.ts","./node_modules/typescript/lib/lib.scripthost.d.ts","./node_modules/typescript/lib/lib.es2015.core.d.ts","./node_modules/typescript/lib/lib.es2015.collection.d.ts","./node_modules/typescript/lib/lib.es2015.generator.d.ts","./node_modules/typescript/lib/lib.es2015.iterable.d.ts","./node_modules/typescript/lib/lib.es2015.promise.d.ts","./node_modules/typescript/lib/lib.es2015.proxy.d.ts","./node_modules/typescript/lib/lib.es2015.reflect.d.ts","./node_modules/typescript/lib/lib.es2015.symbol.d.ts","./node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts","./node_modules/typescript/lib/lib.es2016.array.include.d.ts","./node_modules/typescript/lib/lib.es2016.intl.d.ts","./node_modules/typescript/lib/lib.es2017.arraybuffer.d.ts","./node_modules/typescript/lib/lib.es2017.date.d.ts","./node_modules/typescript/lib/lib.es2017.object.d.ts","./node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts","./node_modules/typescript/lib/lib.es2017.string.d.ts","./node_modules/typescript/lib/lib.es2017.intl.d.ts","./node_modules/typescript/lib/lib.es2017.typedarrays.d.ts","./node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts","./node_modules/typescript/lib/lib.es2018.asynciterable.d.ts","./node_modules/typescript/lib/lib.es2018.intl.d.ts","./node_modules/typescript/lib/lib.es2018.promise.d.ts","./node_modules/typescript/lib/lib.es2018.regexp.d.ts","./node_modules/typescript/lib/lib.es2019.array.d.ts","./node_modules/typescript/lib/lib.es2019.object.d.ts","./node_modules/typescript/lib/lib.es2019.string.d.ts","./node_modules/typescript/lib/lib.es2019.symbol.d.ts","./node_modules/typescript/lib/lib.es2019.intl.d.ts","./node_modules/typescript/lib/lib.es2020.bigint.d.ts","./node_modules/typescript/lib/lib.es2020.date.d.ts","./node_modules/typescript/lib/lib.es2020.promise.d.ts","./node_modules/typescript/lib/lib.es2020.sharedmemory.d.ts","./node_modules/typescript/lib/lib.es2020.string.d.ts","./node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts","./node_modules/typescript/lib/lib.es2020.intl.d.ts","./node_modules/typescript/lib/lib.es2020.number.d.ts","./node_modules/typescript/lib/lib.esnext.disposable.d.ts","./node_modules/typescript/lib/lib.esnext.float16.d.ts","./node_modules/typescript/lib/lib.decorators.d.ts","./node_modules/typescript/lib/lib.decorators.legacy.d.ts","./node_modules/@types/node/compatibility/iterators.d.ts","./node_modules/@types/node/globals.typedarray.d.ts","./node_modules/@types/node/buffer.buffer.d.ts","./node_modules/@types/node/globals.d.ts","./node_modules/@types/node/web-globals/abortcontroller.d.ts","./node_modules/@types/node/web-globals/crypto.d.ts","./node_modules/@types/node/web-globals/domexception.d.ts","./node_modules/@types/node/web-globals/events.d.ts","./node_modules/undici-types/utility.d.ts","./node_modules/undici-types/header.d.ts","./node_modules/undici-types/readable.d.ts","./node_modules/undici-types/fetch.d.ts","./node_modules/undici-types/formdata.d.ts","./node_modules/undici-types/connector.d.ts","./node_modules/undici-types/client-stats.d.ts","./node_modules/undici-types/client.d.ts","./node_modules/undici-types/errors.d.ts","./node_modules/undici-types/dispatcher.d.ts","./node_modules/undici-types/global-dispatcher.d.ts","./node_modules/undici-types/global-origin.d.ts","./node_modules/undici-types/pool-stats.d.ts","./node_modules/undici-types/pool.d.ts","./node_modules/undici-types/handlers.d.ts","./node_modules/undici-types/balanced-pool.d.ts","./node_modules/undici-types/round-robin-pool.d.ts","./node_modules/undici-types/h2c-client.d.ts","./node_modules/undici-types/agent.d.ts","./node_modules/undici-types/mock-interceptor.d.ts","./node_modules/undici-types/mock-call-history.d.ts","./node_modules/undici-types/mock-agent.d.ts","./node_modules/undici-types/mock-client.d.ts","./node_modules/undici-types/mock-pool.d.ts","./node_modules/undici-types/snapshot-agent.d.ts","./node_modules/undici-types/mock-errors.d.ts","./node_modules/undici-types/proxy-agent.d.ts","./node_modules/undici-types/env-http-proxy-agent.d.ts","./node_modules/undici-types/retry-handler.d.ts","./node_modules/undici-types/retry-agent.d.ts","./node_modules/undici-types/api.d.ts","./node_modules/undici-types/cache-interceptor.d.ts","./node_modules/undici-types/interceptors.d.ts","./node_modules/undici-types/util.d.ts","./node_modules/undici-types/cookies.d.ts","./node_modules/undici-types/patch.d.ts","./node_modules/undici-types/websocket.d.ts","./node_modules/undici-types/eventsource.d.ts","./node_modules/undici-types/diagnostics-channel.d.ts","./node_modules/undici-types/content-type.d.ts","./node_modules/undici-types/cache.d.ts","./node_modules/undici-types/index.d.ts","./node_modules/@types/node/web-globals/fetch.d.ts","./node_modules/@types/node/web-globals/navigator.d.ts","./node_modules/@types/node/web-globals/storage.d.ts","./node_modules/@types/node/web-globals/streams.d.ts","./node_modules/@types/node/assert.d.ts","./node_modules/@types/node/assert/strict.d.ts","./node_modules/@types/node/async_hooks.d.ts","./node_modules/@types/node/buffer.d.ts","./node_modules/@types/node/child_process.d.ts","./node_modules/@types/node/cluster.d.ts","./node_modules/@types/node/console.d.ts","./node_modules/@types/node/constants.d.ts","./node_modules/@types/node/crypto.d.ts","./node_modules/@types/node/dgram.d.ts","./node_modules/@types/node/diagnostics_channel.d.ts","./node_modules/@types/node/dns.d.ts","./node_modules/@types/node/dns/promises.d.ts","./node_modules/@types/node/domain.d.ts","./node_modules/@types/node/events.d.ts","./node_modules/@types/node/fs.d.ts","./node_modules/@types/node/fs/promises.d.ts","./node_modules/@types/node/http.d.ts","./node_modules/@types/node/http2.d.ts","./node_modules/@types/node/https.d.ts","./node_modules/@types/node/inspector.d.ts","./node_modules/@types/node/inspector.generated.d.ts","./node_modules/@types/node/module.d.ts","./node_modules/@types/node/net.d.ts","./node_modules/@types/node/os.d.ts","./node_modules/@types/node/path.d.ts","./node_modules/@types/node/perf_hooks.d.ts","./node_modules/@types/node/process.d.ts","./node_modules/@types/node/punycode.d.ts","./node_modules/@types/node/querystring.d.ts","./node_modules/@types/node/readline.d.ts","./node_modules/@types/node/readline/promises.d.ts","./node_modules/@types/node/repl.d.ts","./node_modules/@types/node/sea.d.ts","./node_modules/@types/node/sqlite.d.ts","./node_modules/@types/node/stream.d.ts","./node_modules/@types/node/stream/promises.d.ts","./node_modules/@types/node/stream/consumers.d.ts","./node_modules/@types/node/stream/web.d.ts","./node_modules/@types/node/string_decoder.d.ts","./node_modules/@types/node/test.d.ts","./node_modules/@types/node/timers.d.ts","./node_modules/@types/node/timers/promises.d.ts","./node_modules/@types/node/tls.d.ts","./node_modules/@types/node/trace_events.d.ts","./node_modules/@types/node/tty.d.ts","./node_modules/@types/node/url.d.ts","./node_modules/@types/node/util.d.ts","./node_modules/@types/node/v8.d.ts","./node_modules/@types/node/vm.d.ts","./node_modules/@types/node/wasi.d.ts","./node_modules/@types/node/worker_threads.d.ts","./node_modules/@types/node/zlib.d.ts","./node_modules/@types/node/index.d.ts","./node_modules/vite/types/hmrpayload.d.ts","./node_modules/vite/dist/node/chunks/modulerunnertransport.d.ts","./node_modules/vite/types/customevent.d.ts","./node_modules/@types/estree/index.d.ts","./node_modules/rollup/dist/rollup.d.ts","./node_modules/rollup/dist/parseast.d.ts","./node_modules/vite/types/hot.d.ts","./node_modules/vite/dist/node/module-runner.d.ts","./node_modules/esbuild/lib/main.d.ts","./node_modules/vite/types/internal/terseroptions.d.ts","./node_modules/source-map-js/source-map.d.ts","./node_modules/postcss/lib/previous-map.d.ts","./node_modules/postcss/lib/input.d.ts","./node_modules/postcss/lib/css-syntax-error.d.ts","./node_modules/postcss/lib/declaration.d.ts","./node_modules/postcss/lib/root.d.ts","./node_modules/postcss/lib/warning.d.ts","./node_modules/postcss/lib/lazy-result.d.ts","./node_modules/postcss/lib/no-work-result.d.ts","./node_modules/postcss/lib/processor.d.ts","./node_modules/postcss/lib/result.d.ts","./node_modules/postcss/lib/document.d.ts","./node_modules/postcss/lib/rule.d.ts","./node_modules/postcss/lib/node.d.ts","./node_modules/postcss/lib/comment.d.ts","./node_modules/postcss/lib/container.d.ts","./node_modules/postcss/lib/at-rule.d.ts","./node_modules/postcss/lib/list.d.ts","./node_modules/postcss/lib/postcss.d.ts","./node_modules/postcss/lib/postcss.d.mts","./node_modules/vite/types/internal/csspreprocessoroptions.d.ts","./node_modules/vite/types/internal/lightningcssoptions.d.ts","./node_modules/vite/types/importglob.d.ts","./node_modules/vite/types/metadata.d.ts","./node_modules/vite/dist/node/index.d.ts","./node_modules/@babel/types/lib/index.d.ts","./node_modules/@types/babel__generator/index.d.ts","./node_modules/@babel/parser/typings/babel-parser.d.ts","./node_modules/@types/babel__template/index.d.ts","./node_modules/@types/babel__traverse/index.d.ts","./node_modules/@types/babel__core/index.d.ts","./node_modules/@vitejs/plugin-react/dist/index.d.ts","./vite.config.ts","./node_modules/@vitest/spy/optional-types.d.ts","./node_modules/@vitest/spy/dist/index.d.ts","./node_modules/tinyrainbow/dist/index.d.ts","./node_modules/@standard-schema/spec/dist/index.d.ts","./node_modules/@vitest/pretty-format/dist/index.d.ts","./node_modules/@vitest/utils/dist/types.d-bcelap-c.d.ts","./node_modules/@vitest/utils/dist/diff.d.ts","./node_modules/@vitest/utils/dist/display.d.ts","./node_modules/@types/deep-eql/index.d.ts","./node_modules/assertion-error/index.d.ts","./node_modules/@types/chai/index.d.ts","./node_modules/@vitest/expect/dist/index.d.ts","./node_modules/@vitest/utils/dist/types.d.ts","./node_modules/@vitest/utils/dist/helpers.d.ts","./node_modules/@vitest/utils/dist/timers.d.ts","./node_modules/@vitest/utils/dist/index.d.ts","./node_modules/@vitest/runner/dist/tasks.d-deyaimiu.d.ts","./node_modules/@vitest/runner/dist/index.d.ts","./node_modules/vitest/dist/chunks/traces.d.d2t_r8rx.d.ts","./node_modules/@vitest/snapshot/dist/environment.d-dojxxzv9.d.ts","./node_modules/@vitest/snapshot/dist/rawsnapshot.d-d_x3-62x.d.ts","./node_modules/@vitest/snapshot/dist/index.d.ts","./node_modules/vitest/dist/chunks/config.d.a1h_y6jt.d.ts","./node_modules/vitest/dist/chunks/environment.d.crsxczp1.d.ts","./node_modules/vitest/dist/chunks/rpc.d.b_8spu0w.d.ts","./node_modules/vitest/dist/chunks/worker.d.zphpo4yb.d.ts","./node_modules/vitest/dist/chunks/browser.d.bcoexmfg.d.ts","./node_modules/vitest/optional-types.d.ts","./node_modules/@vitest/runner/dist/utils.d.ts","./node_modules/tinybench/dist/index.d.ts","./node_modules/vitest/dist/chunks/benchmark.d.daahlpsq.d.ts","./node_modules/@vitest/mocker/dist/types.d-bji5eawu.d.ts","./node_modules/@vitest/mocker/dist/index.d-b41z0auw.d.ts","./node_modules/@vitest/mocker/dist/index.d.ts","./node_modules/@vitest/utils/dist/source-map.d.ts","./node_modules/vitest/dist/chunks/coverage.d.bztk59wp.d.ts","./node_modules/@vitest/utils/dist/serialize.d.ts","./node_modules/@vitest/utils/dist/error.d.ts","./node_modules/vitest/dist/browser.d.ts","./node_modules/vitest/browser/context.d.ts","./node_modules/@vitest/snapshot/dist/manager.d.ts","./node_modules/vitest/dist/chunks/reporters.d.dtokvv2s.d.ts","./node_modules/vitest/dist/chunks/plugin.d.dwfiij7i.d.ts","./node_modules/vitest/dist/config.d.ts","./node_modules/vitest/config.d.ts","./vitest.config.ts","./node_modules/@types/react/global.d.ts","./node_modules/csstype/index.d.ts","./node_modules/@types/react/index.d.ts","./node_modules/@types/react-dom/index.d.ts"],"fileIdsList":[[54,109,126,127,195],[54,109,126,127],[54,109,126,127,195,196,197,198,199],[54,109,126,127,195,197],[54,109,126,127,211,212],[54,106,107,109,126,127],[54,108,109,126,127],[109,126,127],[54,109,114,126,127,144],[54,109,110,115,120,126,127,129,141,152],[54,109,110,111,120,126,127,129],[54,109,112,126,127,153],[54,109,113,114,121,126,127,130],[54,109,114,126,127,141,149],[54,109,115,117,120,126,127,129],[54,108,109,116,126,127],[54,109,117,118,126,127],[54,109,119,120,126,127],[54,108,109,120,126,127],[54,109,120,121,122,126,127,141,152],[54,109,120,121,122,126,127,136,141,144],[54,101,109,117,120,123,126,127,129,141,152],[54,109,120,121,123,124,126,127,129,141,149,152],[54,109,123,125,126,127,141,149,152],[52,53,54,55,56,57,58,59,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158],[54,109,120,126,127],[54,109,126,127,128,152],[54,109,117,120,126,127,129,141],[54,109,126,127,130],[54,109,126,127,131],[54,108,109,126,127,132],[54,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158],[54,109,126,127,134],[54,109,126,127,135],[54,109,120,126,127,136,137],[54,109,126,127,136,138,153,155],[54,109,121,126,127],[54,109,120,126,127,141,142,144],[54,109,126,127,143,144],[54,109,126,127,141,142],[54,109,126,127,144],[54,109,126,127,145],[54,106,109,126,127,141,146,152],[54,109,120,126,127,147,148],[54,109,126,127,147,148],[54,109,114,126,127,129,141,149],[54,109,126,127,150],[54,109,126,127,129,151],[54,109,123,126,127,135,152],[54,109,114,126,127,153],[54,109,126,127,141,154],[54,109,126,127,128,155],[54,109,126,127,156],[54,109,114,126,127],[54,101,109,126,127],[54,109,126,127,157],[54,101,109,120,122,126,127,132,141,144,152,154,155,157],[54,109,126,127,141,158],[54,109,126,127,251],[54,109,126,127,249,250],[54,109,126,127,194,200,246],[54,109,126,127,204,205,206,209,210,213],[54,109,126,127,234],[54,109,126,127,234,235],[54,109,126,127,209,218,219],[54,109,126,127,209,218],[54,109,126,127,218],[54,109,126,127,207,218,222,223],[54,109,126,127,207,218,222],[54,109,126,127,203],[54,109,126,127,207,208],[54,109,126,127,207],[54,109,126,127,207,208,215,239],[54,109,126,127,215],[54,109,126,127,207,210,215,216,217],[54,109,126,127,185],[54,109,126,127,183,185],[54,109,126,127,174,182,183,184,186,188],[54,109,126,127,172],[54,109,126,127,175,180,185,188],[54,109,126,127,171,188],[54,109,126,127,175,176,179,180,181,188],[54,109,126,127,175,176,177,179,180,188],[54,109,126,127,172,173,174,175,176,180,181,182,184,185,186,188],[54,109,126,127,188],[54,109,126,127,170,172,173,174,175,176,177,179,180,181,182,183,184,185,186,187],[54,109,126,127,170,188],[54,109,126,127,175,177,178,180,181,188],[54,109,126,127,179,188],[54,109,126,127,180,181,185,188],[54,109,126,127,173,183],[54,109,126,127,164,193,194],[54,109,126,127,163,164],[54,66,69,72,73,109,126,127,152],[54,69,109,126,127,141,152],[54,69,73,109,126,127,152],[54,109,126,127,141],[54,63,109,126,127],[54,67,109,126,127],[54,65,66,69,109,126,127,152],[54,109,126,127,129,149],[54,109,126,127,159],[54,63,109,126,127,159],[54,65,69,109,126,127,129,152],[54,60,61,62,64,68,109,120,126,127,141,152],[54,69,78,86,109,126,127],[54,61,67,109,126,127],[54,69,95,96,109,126,127],[54,61,64,69,109,126,127,144,152,159],[54,69,109,126,127],[54,65,69,109,126,127,152],[54,60,109,126,127],[54,63,64,65,67,68,69,70,71,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,96,97,98,99,100,109,126,127],[54,69,88,91,109,117,126,127],[54,69,78,79,80,109,126,127],[54,67,69,79,81,109,126,127],[54,68,109,126,127],[54,61,63,69,109,126,127],[54,69,73,79,81,109,126,127],[54,73,109,126,127],[54,67,69,72,109,126,127,152],[54,61,65,69,78,109,126,127],[54,69,88,109,126,127],[54,81,109,126,127],[54,63,69,95,109,126,127,144,157,159],[54,109,126,127,160],[54,109,120,121,123,124,125,126,127,129,141,149,152,158,159,160,161,162,164,165,167,168,169,189,190,191,192,193,194],[54,109,126,127,160,161,162,166],[54,109,126,127,162],[54,109,126,127,164,194],[54,109,126,127,241],[54,109,126,127,214,246],[54,109,126,127,204,207,209,210,216,217,218,220,221,224,225,237,238,240],[54,109,126,127,220,231,232],[54,109,126,127,220,221,228],[54,109,126,127,207,209,220,221,224],[54,109,126,127,194,244,246],[54,109,112,121,126,127,141,194,207,209,214,218,220,221,224,225,228,229,230,233,236,237,238,242,243,246],[54,109,126,127,167,220,221,224],[54,109,126,127,167,220,225,226,227],[54,109,112,121,126,127,141,167,194,207,209,214,218,220,221,224,225,226,227,228,229,230,231,232,233,236,237,238,242,243,244,245,246],[54,109,126,127,194,201,246],[54,109,126,127,247]],"fileInfos":[{"version":"a7297ff837fcdf174a9524925966429eb8e5feecc2cc55cc06574e6b092c1eaa","impliedFormat":1},{"version":"c430d44666289dae81f30fa7b2edebf186ecc91a2d4c71266ea6ae76388792e1","affectsGlobalScope":true,"impliedFormat":1},{"version":"45b7ab580deca34ae9729e97c13cfd999df04416a79116c3bfb483804f85ded4","impliedFormat":1},{"version":"3facaf05f0c5fc569c5649dd359892c98a85557e3e0c847964caeb67076f4d75","impliedFormat":1},{"version":"e44bb8bbac7f10ecc786703fe0a6a4b952189f908707980ba8f3c8975a760962","impliedFormat":1},{"version":"5e1c4c362065a6b95ff952c0eab010f04dcd2c3494e813b493ecfd4fcb9fc0d8","impliedFormat":1},{"version":"68d73b4a11549f9c0b7d352d10e91e5dca8faa3322bfb77b661839c42b1ddec7","impliedFormat":1},{"version":"5efce4fc3c29ea84e8928f97adec086e3dc876365e0982cc8479a07954a3efd4","impliedFormat":1},{"version":"080941d9f9ff9307f7e27a83bcd888b7c8270716c39af943532438932ec1d0b9","affectsGlobalScope":true,"impliedFormat":1},{"version":"80e18897e5884b6723488d4f5652167e7bb5024f946743134ecc4aa4ee731f89","affectsGlobalScope":true,"impliedFormat":1},{"version":"cd034f499c6cdca722b60c04b5b1b78e058487a7085a8e0d6fb50809947ee573","affectsGlobalScope":true,"impliedFormat":1},{"version":"c57796738e7f83dbc4b8e65132f11a377649c00dd3eee333f672b8f0a6bea671","affectsGlobalScope":true,"impliedFormat":1},{"version":"dc2df20b1bcdc8c2d34af4926e2c3ab15ffe1160a63e58b7e09833f616efff44","affectsGlobalScope":true,"impliedFormat":1},{"version":"515d0b7b9bea2e31ea4ec968e9edd2c39d3eebf4a2d5cbd04e88639819ae3b71","affectsGlobalScope":true,"impliedFormat":1},{"version":"0559b1f683ac7505ae451f9a96ce4c3c92bdc71411651ca6ddb0e88baaaad6a3","affectsGlobalScope":true,"impliedFormat":1},{"version":"0dc1e7ceda9b8b9b455c3a2d67b0412feab00bd2f66656cd8850e8831b08b537","affectsGlobalScope":true,"impliedFormat":1},{"version":"ce691fb9e5c64efb9547083e4a34091bcbe5bdb41027e310ebba8f7d96a98671","affectsGlobalScope":true,"impliedFormat":1},{"version":"8d697a2a929a5fcb38b7a65594020fcef05ec1630804a33748829c5ff53640d0","affectsGlobalScope":true,"impliedFormat":1},{"version":"4ff2a353abf8a80ee399af572debb8faab2d33ad38c4b4474cff7f26e7653b8d","affectsGlobalScope":true,"impliedFormat":1},{"version":"fb0f136d372979348d59b3f5020b4cdb81b5504192b1cacff5d1fbba29378aa1","affectsGlobalScope":true,"impliedFormat":1},{"version":"d15bea3d62cbbdb9797079416b8ac375ae99162a7fba5de2c6c505446486ac0a","affectsGlobalScope":true,"impliedFormat":1},{"version":"68d18b664c9d32a7336a70235958b8997ebc1c3b8505f4f1ae2b7e7753b87618","affectsGlobalScope":true,"impliedFormat":1},{"version":"eb3d66c8327153d8fa7dd03f9c58d351107fe824c79e9b56b462935176cdf12a","affectsGlobalScope":true,"impliedFormat":1},{"version":"38f0219c9e23c915ef9790ab1d680440d95419ad264816fa15009a8851e79119","affectsGlobalScope":true,"impliedFormat":1},{"version":"69ab18c3b76cd9b1be3d188eaf8bba06112ebbe2f47f6c322b5105a6fbc45a2e","affectsGlobalScope":true,"impliedFormat":1},{"version":"a680117f487a4d2f30ea46f1b4b7f58bef1480456e18ba53ee85c2746eeca012","affectsGlobalScope":true,"impliedFormat":1},{"version":"2f11ff796926e0832f9ae148008138ad583bd181899ab7dd768a2666700b1893","affectsGlobalScope":true,"impliedFormat":1},{"version":"4de680d5bb41c17f7f68e0419412ca23c98d5749dcaaea1896172f06435891fc","affectsGlobalScope":true,"impliedFormat":1},{"version":"954296b30da6d508a104a3a0b5d96b76495c709785c1d11610908e63481ee667","affectsGlobalScope":true,"impliedFormat":1},{"version":"ac9538681b19688c8eae65811b329d3744af679e0bdfa5d842d0e32524c73e1c","affectsGlobalScope":true,"impliedFormat":1},{"version":"0a969edff4bd52585473d24995c5ef223f6652d6ef46193309b3921d65dd4376","affectsGlobalScope":true,"impliedFormat":1},{"version":"9e9fbd7030c440b33d021da145d3232984c8bb7916f277e8ffd3dc2e3eae2bdb","affectsGlobalScope":true,"impliedFormat":1},{"version":"811ec78f7fefcabbda4bfa93b3eb67d9ae166ef95f9bff989d964061cbf81a0c","affectsGlobalScope":true,"impliedFormat":1},{"version":"717937616a17072082152a2ef351cb51f98802fb4b2fdabd32399843875974ca","affectsGlobalScope":true,"impliedFormat":1},{"version":"d7e7d9b7b50e5f22c915b525acc5a49a7a6584cf8f62d0569e557c5cfc4b2ac2","affectsGlobalScope":true,"impliedFormat":1},{"version":"71c37f4c9543f31dfced6c7840e068c5a5aacb7b89111a4364b1d5276b852557","affectsGlobalScope":true,"impliedFormat":1},{"version":"576711e016cf4f1804676043e6a0a5414252560eb57de9faceee34d79798c850","affectsGlobalScope":true,"impliedFormat":1},{"version":"89c1b1281ba7b8a96efc676b11b264de7a8374c5ea1e6617f11880a13fc56dc6","affectsGlobalScope":true,"impliedFormat":1},{"version":"74f7fa2d027d5b33eb0471c8e82a6c87216223181ec31247c357a3e8e2fddc5b","affectsGlobalScope":true,"impliedFormat":1},{"version":"d6d7ae4d1f1f3772e2a3cde568ed08991a8ae34a080ff1151af28b7f798e22ca","affectsGlobalScope":true,"impliedFormat":1},{"version":"063600664504610fe3e99b717a1223f8b1900087fab0b4cad1496a114744f8df","affectsGlobalScope":true,"impliedFormat":1},{"version":"934019d7e3c81950f9a8426d093458b65d5aff2c7c1511233c0fd5b941e608ab","affectsGlobalScope":true,"impliedFormat":1},{"version":"52ada8e0b6e0482b728070b7639ee42e83a9b1c22d205992756fe020fd9f4a47","affectsGlobalScope":true,"impliedFormat":1},{"version":"3bdefe1bfd4d6dee0e26f928f93ccc128f1b64d5d501ff4a8cf3c6371200e5e6","affectsGlobalScope":true,"impliedFormat":1},{"version":"59fb2c069260b4ba00b5643b907ef5d5341b167e7d1dbf58dfd895658bda2867","affectsGlobalScope":true,"impliedFormat":1},{"version":"639e512c0dfc3fad96a84caad71b8834d66329a1f28dc95e3946c9b58176c73a","affectsGlobalScope":true,"impliedFormat":1},{"version":"368af93f74c9c932edd84c58883e736c9e3d53cec1fe24c0b0ff451f529ceab1","affectsGlobalScope":true,"impliedFormat":1},{"version":"51ad4c928303041605b4d7ae32e0c1ee387d43a24cd6f1ebf4a2699e1076d4fa","affectsGlobalScope":true,"impliedFormat":1},{"version":"196cb558a13d4533a5163286f30b0509ce0210e4b316c56c38d4c0fd2fb38405","affectsGlobalScope":true,"impliedFormat":1},{"version":"8e7f8264d0fb4c5339605a15daadb037bf238c10b654bb3eee14208f860a32ea","affectsGlobalScope":true,"impliedFormat":1},{"version":"782dec38049b92d4e85c1585fbea5474a219c6984a35b004963b00beb1aab538","affectsGlobalScope":true,"impliedFormat":1},{"version":"d153a11543fd884b596587ccd97aebbeed950b26933ee000f94009f1ab142848","affectsGlobalScope":true,"impliedFormat":1},{"version":"378281aa35786c27d5811af7e6bcaa492eebd0c7013d48137c35bbc69a2b9751","affectsGlobalScope":true,"impliedFormat":1},{"version":"3af97acf03cc97de58a3a4bc91f8f616408099bc4233f6d0852e72a8ffb91ac9","affectsGlobalScope":true,"impliedFormat":1},{"version":"1b2dd1cbeb0cc6ae20795958ba5950395ebb2849b7c8326853dd15530c77ab0c","affectsGlobalScope":true,"impliedFormat":1},{"version":"1db0b7dca579049ca4193d034d835f6bfe73096c73663e5ef9a0b5779939f3d0","affectsGlobalScope":true,"impliedFormat":1},{"version":"387a023d363f755eb63450a66c28b14cdd7bc30a104565e2dbf0a8988bb4a56c","affectsGlobalScope":true,"impliedFormat":1},{"version":"9798340ffb0d067d69b1ae5b32faa17ab31b82466a3fc00d8f2f2df0c8554aaa","affectsGlobalScope":true,"impliedFormat":1},{"version":"f26b11d8d8e4b8028f1c7d618b22274c892e4b0ef5b3678a8ccbad85419aef43","affectsGlobalScope":true,"impliedFormat":1},{"version":"cdcf9ea426ad970f96ac930cd176d5c69c6c24eebd9fc580e1572d6c6a88f62c","impliedFormat":1},{"version":"23cd712e2ce083d68afe69224587438e5914b457b8acf87073c22494d706a3d0","impliedFormat":1},{"version":"156a859e21ef3244d13afeeba4e49760a6afa035c149dda52f0c45ea8903b338","impliedFormat":1},{"version":"10ec5e82144dfac6f04fa5d1d6c11763b3e4dbbac6d99101427219ab3e2ae887","impliedFormat":1},{"version":"615754924717c0b1e293e083b83503c0a872717ad5aa60ed7f1a699eb1b4ea5c","impliedFormat":1},{"version":"074de5b2fdead0165a2757e3aaef20f27a6347b1c36adea27d51456795b37682","impliedFormat":1},{"version":"68834d631c8838c715f225509cfc3927913b9cc7a4870460b5b60c8dbdb99baf","impliedFormat":1},{"version":"24371e69a38fc33e268d4a8716dbcda430d6c2c414a99ff9669239c4b8f40dea","impliedFormat":1},{"version":"ccab02f3920fc75c01174c47fcf67882a11daf16baf9e81701d0a94636e94556","impliedFormat":1},{"version":"3e11fce78ad8c0e1d1db4ba5f0652285509be3acdd519529bc8fcef85f7dafd9","impliedFormat":1},{"version":"ea6bc8de8b59f90a7a3960005fd01988f98fd0784e14bc6922dde2e93305ec7d","impliedFormat":1},{"version":"36107995674b29284a115e21a0618c4c2751b32a8766dd4cb3ba740308b16d59","impliedFormat":1},{"version":"914a0ae30d96d71915fc519ccb4efbf2b62c0ddfb3a3fc6129151076bc01dc60","impliedFormat":1},{"version":"9c32412007b5662fd34a8eb04292fb5314ec370d7016d1c2fb8aa193c807fe22","impliedFormat":1},{"version":"7fd1b31fd35876b0aa650811c25ec2c97a3c6387e5473eb18004bed86cdd76b6","impliedFormat":1},{"version":"4d327f7d72ad0918275cea3eee49a6a8dc8114ae1d5b7f3f5d0774de75f7439a","impliedFormat":1},{"version":"6ebe8ebb8659aaa9d1acbf3710d7dae3e923e97610238b9511c25dc39023a166","impliedFormat":1},{"version":"e85d7f8068f6a26710bff0cc8c0fc5e47f71089c3780fbede05857331d2ddec9","impliedFormat":1},{"version":"7befaf0e76b5671be1d47b77fcc65f2b0aad91cc26529df1904f4a7c46d216e9","impliedFormat":1},{"version":"0a60a292b89ca7218b8616f78e5bbd1c96b87e048849469cccb4355e98af959a","impliedFormat":1},{"version":"0b6e25234b4eec6ed96ab138d96eb70b135690d7dd01f3dd8a8ab291c35a683a","impliedFormat":1},{"version":"9666f2f84b985b62400d2e5ab0adae9ff44de9b2a34803c2c5bd3c8325b17dc0","impliedFormat":1},{"version":"40cd35c95e9cf22cfa5bd84e96408b6fcbca55295f4ff822390abb11afbc3dca","impliedFormat":1},{"version":"b1616b8959bf557feb16369c6124a97a0e74ed6f49d1df73bb4b9ddf68acf3f3","impliedFormat":1},{"version":"5b03a034c72146b61573aab280f295b015b9168470f2df05f6080a2122f9b4df","impliedFormat":1},{"version":"40b463c6766ca1b689bfcc46d26b5e295954f32ad43e37ee6953c0a677e4ae2b","impliedFormat":1},{"version":"249b9cab7f5d628b71308c7d9bb0a808b50b091e640ba3ed6e2d0516f4a8d91d","impliedFormat":1},{"version":"80aae6afc67faa5ac0b32b5b8bc8cc9f7fa299cff15cf09cc2e11fd28c6ae29e","impliedFormat":1},{"version":"f473cd2288991ff3221165dcf73cd5d24da30391f87e85b3dd4d0450c787a391","impliedFormat":1},{"version":"499e5b055a5aba1e1998f7311a6c441a369831c70905cc565ceac93c28083d53","impliedFormat":1},{"version":"8aee8b6d4f9f62cf3776cda1305fb18763e2aade7e13cea5bbe699112df85214","impliedFormat":1},{"version":"c63b9ada8c72f95aac5db92aea07e5e87ec810353cdf63b2d78f49a58662cf6c","impliedFormat":1},{"version":"1cc2a09e1a61a5222d4174ab358a9f9de5e906afe79dbf7363d871a7edda3955","impliedFormat":1},{"version":"5d0375ca7310efb77e3ef18d068d53784faf62705e0ad04569597ae0e755c401","impliedFormat":1},{"version":"59af37caec41ecf7b2e76059c9672a49e682c1a2aa6f9d7dc78878f53aa284d6","impliedFormat":1},{"version":"addf417b9eb3f938fddf8d81e96393a165e4be0d4a8b6402292f9c634b1cb00d","impliedFormat":1},{"version":"b64d4d1c5f877f9c666e98e833f0205edb9384acc46e98a1fef344f64d6aba44","impliedFormat":1},{"version":"adf27937dba6af9f08a68c5b1d3fce0ca7d4b960c57e6d6c844e7d1a8e53adae","impliedFormat":1},{"version":"12950411eeab8563b349cb7959543d92d8d02c289ed893d78499a19becb5a8cc","impliedFormat":1},{"version":"2e85db9e6fd73cfa3d7f28e0ab6b55417ea18931423bd47b409a96e4a169e8e6","impliedFormat":1},{"version":"c46e079fe54c76f95c67fb89081b3e399da2c7d109e7dca8e4b58d83e332e605","impliedFormat":1},{"version":"c9381908473a1c92cb8c516b184e75f4d226dad95c3a85a5af35f670064d9a2f","impliedFormat":1},{"version":"f724236417941ea77ec8d38c6b7021f5fb7f8521c7f8c1538e87661f2c6a0774","affectsGlobalScope":true,"impliedFormat":1},{"version":"1cf059eaf468efcc649f8cf6075d3cb98e9a35a0fe9c44419ec3d2f5428d7123","affectsGlobalScope":true,"impliedFormat":1},{"version":"e7721c4f69f93c91360c26a0a84ee885997d748237ef78ef665b153e622b36c1","affectsGlobalScope":true,"impliedFormat":1},{"version":"d97fb21da858fb18b8ae72c314e9743fd52f73ebe2764e12af1db32fc03f853f","affectsGlobalScope":true,"impliedFormat":1},{"version":"4ea15fd99b2e34cb25fe8346c955000bb70c8b423ae4377a972ef46bfb37f595","impliedFormat":1},{"version":"7cf69dd5502c41644c9e5106210b5da7144800670cbe861f66726fa209e231c4","impliedFormat":1},{"version":"72c1f5e0a28e473026074817561d1bc9647909cf253c8d56c41d1df8d95b85f7","impliedFormat":1},{"version":"f9b4137a0d285bd77dba2e6e895530112264310ae47e07bf311feae428fb8b61","affectsGlobalScope":true,"impliedFormat":1},{"version":"c06b2652ffeb89afd0f1c52c165ced77032f9cd09bc481153fbd6b5504c69494","impliedFormat":1},{"version":"51aecd2df90a3cffea1eb4696b33b2d78594ea2aa2138e6b9471ec4841c6c2ee","impliedFormat":1},{"version":"9d8f9e63e29a3396285620908e7f14d874d066caea747dc4b2c378f0599166b4","affectsGlobalScope":true,"impliedFormat":1},{"version":"5524481e56c48ff486f42926778c0a3cce1cc85dc46683b92b1271865bcf015a","impliedFormat":1},{"version":"612422d5ba6b4a5c4537f423e9199645468ad80a689801da63ab7edb43f7b835","impliedFormat":1},{"version":"db9ada976f9e52e13f7ae8b9a320f4b67b87685938c5879187d8864b2fbe97f3","impliedFormat":1},{"version":"9f39e70a354d0fba29ac3cdf6eca00b7f9e96f64b2b2780c432e8ea27f133743","impliedFormat":1},{"version":"0dace96cc0f7bc6d0ee2044921bdf19fe42d16284dbcc8ae200800d1c9579335","impliedFormat":1},{"version":"a2e2bbde231b65c53c764c12313897ffdfb6c49183dd31823ee2405f2f7b5378","impliedFormat":1},{"version":"1cbdcdef62bf42688e5d825898c3a59458466c48ad8a4ef3f88d8a1cd04310d6","impliedFormat":1},{"version":"c64e1888baaa3253ca4405b455e4bf44f76357868a1bd0a52998ade9a092ad78","affectsGlobalScope":true,"impliedFormat":1},{"version":"dc8c6f5322961b56d9906601b20798725df60baeab45ec014fba9f795d5596fd","impliedFormat":1},{"version":"67e435fa530778903f5525904e6645b7368eb5ac622055febd19bb399e328ccd","impliedFormat":1},{"version":"060d305fe4494d8cb2b99d620928d369d1ee55c1645f5e729a2aca07d0f108cb","impliedFormat":1},{"version":"5b22bf96be06fca1e134e3a85351ffe7aa2edf0c9a5bd175b7239ee48186dbf5","impliedFormat":1},{"version":"0c50296ee73dae94efc3f0da4936b1146ca6ce2217acfabb44c19c9a33fa30e5","impliedFormat":1},{"version":"bbf42f98a5819f4f06e18c8b669a994afe9a17fe520ae3454a195e6eabf7700d","impliedFormat":1},{"version":"5b48cc670da1dfe926036deaf349085caf822def460a6d50de23f1cc12a5f8cd","impliedFormat":1},{"version":"418f34087d52d001e2688a6282a5de9bf583ff771ed5546af0ae36e4f60a458b","affectsGlobalScope":true,"impliedFormat":1},{"version":"036c9a03b01281f99f8251fdc7088e894566be44b3f139a9d48501a978b611df","impliedFormat":1},{"version":"ff65b8a8bd380c6d129becc35de02f7c29ad7ce03300331ca91311fb4044d1a9","impliedFormat":1},{"version":"04bf1aa481d1adfb16d93d76e44ce71c51c8ef68039d849926551199489637f6","impliedFormat":1},{"version":"2c9adcc85574b002c9a6311ff2141055769e0071856ec979d92ff989042b1f1b","affectsGlobalScope":true,"impliedFormat":1},{"version":"1569ad5969ae0de6ad0bdfaaab0dabcd8878bc3147ab096206eed2019bb84e7f","affectsGlobalScope":true,"impliedFormat":1},{"version":"a58a15da4c5ba3df60c910a043281256fa52d36a0fcdef9b9100c646282e88dd","impliedFormat":1},{"version":"b36beffbf8acdc3ebc58c8bb4b75574b31a2169869c70fc03f82895b93950a12","impliedFormat":1},{"version":"42a350ce4f6f291198dc89833afcc4fd078248b4e1fdc9d05c846c66a670f710","impliedFormat":1},{"version":"77fbe5eecb6fac4b6242bbf6eebfc43e98ce5ccba8fa44e0ef6a95c945ff4d98","impliedFormat":1},{"version":"8c81fd4a110490c43d7c578e8c6f69b3af01717189196899a6a44f93daa57a3a","impliedFormat":1},{"version":"5fb39858b2459864b139950a09adae4f38dad87c25bf572ce414f10e4bd7baab","impliedFormat":1},{"version":"b03754211d839cdc48979996525a32eb62130682c2f9801dfc2f25533ce7238d","impliedFormat":1},{"version":"3910dab597c40e173bf0e0d419d3ce9682c54ebf6ae84849f9b829b1451a17ec","impliedFormat":1},{"version":"37ba7b45141a45ce6e80e66f2a96c8a5ab1bcef0fc2d0f56bb58df96ec67e972","impliedFormat":1},{"version":"45650f47bfb376c8a8ed39d4bcda5902ab899a3150029684ee4c10676d9fbaee","impliedFormat":1},{"version":"486c074a5c0f2254345c0d1c9540380f5463999e42d7e1a159305ea823d3c4b1","affectsGlobalScope":true,"impliedFormat":1},{"version":"c119835edf36415081dfd9ed15fc0cd37aaa28d232be029ad073f15f3d88c323","impliedFormat":1},{"version":"f4d99ac08c4097a3cc202bec2c7198c19dcdd80d4ec6c62d1356b10d03b119d5","impliedFormat":1},{"version":"9705cd157ffbb91c5cab48bdd2de5a437a372e63f870f8a8472e72ff634d47c1","affectsGlobalScope":true,"impliedFormat":1},{"version":"ae86f30d5d10e4f75ce8dcb6e1bd3a12ecec3d071a21e8f462c5c85c678efb41","impliedFormat":1},{"version":"ca77e83162eccec633513723d178d4203bdd5465297267696be08013bab0aa1d","impliedFormat":1},{"version":"e03460fe72b259f6d25ad029f085e4bedc3f90477da4401d8fbc1efa9793230e","impliedFormat":1},{"version":"4286a3a6619514fca656089aee160bb6f2e77f4dd53dc5a96b26a0b4fc778055","impliedFormat":1},{"version":"f61c153d5abbe4381a1fba0d41be0babdd5de51c626ee7ff14cede14dedc33f1","affectsGlobalScope":true,"impliedFormat":1},{"version":"7803171d745ab18e77f16bf82e742268ff72b7f7382ab191e4277527580c2d89","affectsGlobalScope":true,"impliedFormat":1},{"version":"0e9ba65cd3d6d194bdda7343f9f2917f7144ead96a924ca58d1a14919992dc20","impliedFormat":1},{"version":"255d948f87f24ffd57bcb2fdf95792fd418a2e1f712a98cf2cce88744d75085c","impliedFormat":1},{"version":"0d5b085f36e6dc55bc6332ecb9c733be3a534958c238fb8d8d18d4a2b6f2a15a","impliedFormat":1},{"version":"0b0dfb2d3e8420ead06f6a11acfb02ddcec42257e6ce391993e895ba0af86de4","affectsGlobalScope":true,"impliedFormat":1},{"version":"bfd3b3c21a56104693183942e221c1896ee23bcb8f8d91ab0b941f7b32985411","impliedFormat":1},{"version":"d7e9ab1b0996639047c61c1e62f85c620e4382206b3abb430d9a21fb7bc23c77","impliedFormat":1},{"version":"a7ca8df4f2931bef2aa4118078584d84a0b16539598eaadf7dce9104dfaa381c","impliedFormat":1},{"version":"10073cdcf56982064c5337787cc59b79586131e1b28c106ede5bff362f912b70","impliedFormat":99},{"version":"72950913f4900b680f44d8cab6dd1ea0311698fc1eefb014eb9cdfc37ac4a734","impliedFormat":1},{"version":"751764bb94219b4ce8f5475dc35d3de2e432fea01a0c9610cd7f69ad05e398c6","impliedFormat":1},{"version":"21944c138a48dc23382cb6558b1d4498908faad2104ba7ff390ba8b27c06f3c0","affectsGlobalScope":true,"impliedFormat":1},{"version":"a660aa95476042d3fdcc1343cf6bb8fdf24772d31712b1db321c5a4dcc325434","impliedFormat":1},{"version":"36977c14a7f7bfc8c0426ae4343875689949fb699f3f84ecbe5b300ebf9a2c55","impliedFormat":1},{"version":"ff0a83c9a0489a627e264ffcb63f2264b935b20a502afa3a018848139e3d8575","impliedFormat":99},{"version":"161c8e0690c46021506e32fda85956d785b70f309ae97011fd27374c065cac9b","affectsGlobalScope":true,"impliedFormat":1},{"version":"f582b0fcbf1eea9b318ab92fb89ea9ab2ebb84f9b60af89328a91155e1afce72","impliedFormat":1},{"version":"402e5c534fb2b85fa771170595db3ac0dd532112c8fa44fc23f233bc6967488b","impliedFormat":1},{"version":"52dcc257df5119fb66d864625112ce5033ac51a4c2afe376a0b299d2f7f76e4a","impliedFormat":1},{"version":"e5bab5f871ef708d52d47b3e5d0aa72a08ee7a152f33931d9a60809711a2a9a3","impliedFormat":1},{"version":"e16dc2a81595736024a206c7d5c8a39bfe2e6039208ef29981d0d95434ba8fcf","impliedFormat":1},{"version":"cc4a4903fb698ca1d961d4c10dce658aa3a479faf40509d526f122b044eaf6a4","impliedFormat":1},{"version":"19ee8416e6473ed6c7adb868fa796b5653cf0fa2a337658e677eaa0d134388c3","impliedFormat":1},{"version":"1328ab4e442614b28cdb3d4b414cf68325c0da0dca07287a338d0654b7a00261","impliedFormat":1},{"version":"a039dc21f045919f3cbee2ec13812cc6cc3eebc99dae4be00973230f468d19a6","impliedFormat":1},{"version":"3fbe57af01460e49dcd29df55d6931e1672bc6f1be0fb073d11410bc16f9037d","impliedFormat":1},{"version":"f760be449e8562ec5c09bb5187e8e1eabf3c113c0c58cddda53ef8c69f3e2131","impliedFormat":1},{"version":"44325ed13294fce6ab825b82947bbeed2611db7dad9d9135260192f375e5a189","impliedFormat":1},{"version":"e392e8fb5b514eafc585601c1d781485aa6dd6a320e75daf1064a4c6918a1b45","impliedFormat":1},{"version":"46e4a36e8ddbdfb4e7330e11c81c970dc8b218611df9183d39c41c5f8c653b55","impliedFormat":1},{"version":"3cc8a3d123b6b232d48d34b51b785f9da8d193f5b5817fa521fcd2f3b9315c55","impliedFormat":1},{"version":"6332f565867cf4a740a70e30f31cefba37ef7cebcf74f22eab8d744fde6d193e","impliedFormat":1},{"version":"2977b7884aedc895a1d0c9c210c7cf3272c29d6959a08a6fa3ff71e0aff08175","impliedFormat":1},{"version":"17f2922d41ddd032830a91371c948cd9ce903b35c95adca72271a54584f19b0b","impliedFormat":1},{"version":"3eed76ede2a1a14d7c9bb0a642041282dcc264811139d3dd275c9fe14efc9840","impliedFormat":1},{"version":"354a7f8e1287d9d6b7561bc97fdd8cbc2f7c1dd79e4cb37b942e8a5cfaff1085","impliedFormat":1},{"version":"8d369483f0c2b9ee388129cfdb6a43bc8112b377e86a41884bd06e19ce04f4c1","impliedFormat":99},{"version":"960bd764c62ac43edc24eaa2af958a4b4f1fa5d27df5237e176d0143b36a39c6","affectsGlobalScope":true,"impliedFormat":1},{"version":"4ec16d7a4e366c06a4573d299e15fe6207fc080f41beac5da06f4af33ea9761e","impliedFormat":1},{"version":"59f8dc89b9e724a6a667f52cdf4b90b6816ae6c9842ce176d38fcc973669009e","affectsGlobalScope":true,"impliedFormat":1},{"version":"e4af494f7a14b226bbe732e9c130d8811f8c7025911d7c58dd97121a85519715","impliedFormat":1},{"version":"cbb1c5ba5dbabe42c19ca31b83e48fec95895484fe1d1a8fb649b69ea224c5b8","impliedFormat":99},{"version":"556ccd493ec36c7d7cb130d51be66e147b91cc1415be383d71da0f1e49f742a9","impliedFormat":1},{"version":"b6d03c9cfe2cf0ba4c673c209fcd7c46c815b2619fd2aad59fc4229aaef2ed43","impliedFormat":1},{"version":"95aba78013d782537cc5e23868e736bec5d377b918990e28ed56110e3ae8b958","impliedFormat":1},{"version":"670a76db379b27c8ff42f1ba927828a22862e2ab0b0908e38b671f0e912cc5ed","impliedFormat":1},{"version":"13b77ab19ef7aadd86a1e54f2f08ea23a6d74e102909e3c00d31f231ed040f62","impliedFormat":1},{"version":"069bebfee29864e3955378107e243508b163e77ab10de6a5ee03ae06939f0bb9","impliedFormat":1},{"version":"ef94438f848be3a3b0033013bf64753f771f983c1e205e4a06675eb253ca7cd2","impliedFormat":99},{"version":"966910ec9cd924474a52c4238ee5da9211de4fa87785ce2e3b8c97c90c592766","signature":"f1a1b21a223c18a29308ebff0b002317e4bb8aa5e350164f8c8c3b8bde33a535"},{"version":"c76c02846ba7d40b9b3488f0e8d75d02cbdee2f0bc5fcd55dd3bd2e1457646ea","impliedFormat":99},{"version":"4ead13a482c539b77394b2a97e3b877b809eac596390371cea490286f53b996a","impliedFormat":99},{"version":"12405c748be62bbefb6df7515956b0921f84d7b444d1f6c3e00af1980cc3af17","impliedFormat":99},{"version":"bdd14f07b4eca0b4b5203b85b8dbc4d084c749fa590bee5ea613e1641dcd3b29","impliedFormat":99},{"version":"3a582c6e8906f5b094ccf0de6cc6f4f8a54b05a34f52517aba5c9c7f704f6b28","impliedFormat":99},{"version":"ef13c73d6157a32933c612d476c1524dd674cf5b9a88571d7d6a0d147544d529","impliedFormat":99},{"version":"49ab4f1d153a252779958fc87b700743d32b5ffa42addd70ae23ad3f429daa5c","impliedFormat":99},{"version":"0528f6d21f7a02d4092895090d2dd86104bd5a3e79eced96d5a1a7dd90943d17","impliedFormat":99},{"version":"427fe2004642504828c1476d0af4270e6ad4db6de78c0b5da3e4c5ca95052a99","impliedFormat":1},{"version":"2eeffcee5c1661ddca53353929558037b8cf305ffb86a803512982f99bcab50d","impliedFormat":99},{"version":"9afb4cb864d297e4092a79ee2871b5d3143ea14153f62ef0bb04ede25f432030","affectsGlobalScope":true,"impliedFormat":99},{"version":"5c935b7fc4ddc1410ea1cd7cd4e35ed106a6e4920dd27a9480a40fd224359dc3","affectsGlobalScope":true,"impliedFormat":99},{"version":"b5ce343886d23392be9c8280e9f24a87f1d7d3667f6672c2fe4aa61fa4ece7d4","impliedFormat":99},{"version":"72ce5b734c05da85c85a6f6dc05823b051d6aa41acaedeeb1d17c72f3b4efa72","impliedFormat":99},{"version":"b0857bb28fd5236ace84280f79a25093f919fd0eff13e47cc26ea03de60a7294","impliedFormat":99},{"version":"5e43e0824f10cd8c48e7a8c5c673638488925a12c31f0f9e0957965c290eb14c","impliedFormat":99},{"version":"53cf4076f42b29b8d411259d168d51b3a0274c42c8814e5b44dfa8803a35d4fc","impliedFormat":99},{"version":"a39461ee1f27cf3e6cfd63d21045713d26d521da55ea4d8efccb705f689e6dbb","impliedFormat":99},{"version":"61bb64660ee150f3ab618340e15cca0a81664801bede7c966ca0eca3a952fe63","impliedFormat":99},{"version":"42a12f2faa483c9b48195ed794d22698162274e755f6e07219c2351c4f08d732","impliedFormat":99},{"version":"ec0c42bb0f465e4993f2bc68a6ce9df9a2dcbc7b83e21748f82f1b69561938e3","impliedFormat":99},{"version":"f50ff37a9cbbe74475f426474d9827083c7c2c138a954d28f1690df338f69291","impliedFormat":99},{"version":"61fd6c17235d530c40f543dd7c40afab091d91c1ef890baeed30db6d82b04b28","impliedFormat":99},{"version":"bcbd3becd08b4515225880abea0dbfbbf0d1181ce3af8f18f72f61edbe4febfb","impliedFormat":99},{"version":"091767bc841f937654ed597d49e023ed59850355e746ae1a6f20ab31076ee1fb","impliedFormat":99},{"version":"19c6d6135af59693698d384050b45a8a049493500add442f58e4bd7c8a255ab6","impliedFormat":99},{"version":"6a0dba12d55314638a8c51108b20fe2f68f1364a619d098918bda91c22dec154","impliedFormat":99},{"version":"8124828a11be7db984fcdab052fd4ff756b18edcfa8d71118b55388176210923","impliedFormat":99},{"version":"2b39c6cf59088713babbfc3e20ee85f1375d40e66953156fa658346b8346f24f","impliedFormat":99},{"version":"69bf2422313487956e4dacf049f30cb91b34968912058d244cb19e4baa24da97","impliedFormat":99},{"version":"6987dfb4b0c4e02112cc4e548e7a77b3d9ddfeffa8c8a2db13ceac361a4567d9","impliedFormat":99},{"version":"5e2ba3d18d78aebbde1f34bde356e41e9c76eeaeaeee56a37036596a9eff4211","impliedFormat":99},{"version":"8280ae8ccc0493b32d1742d585357ab9f0a508ea050af25a5a20d64010d0a5cf","impliedFormat":99},{"version":"7adfd9f9056ecd4ae6c65fde2a98654960c662714c73f048478959d04c09e144","impliedFormat":99},{"version":"437b7613a30a2fcde463f7b707c6d5567a8823fbc51de50b8641bf5b1d126fad","impliedFormat":99},{"version":"63ea959e28c110923f495576e614fb8b36c09b6828b467b2c7cd7f03b03ccf9f","impliedFormat":99},{"version":"1601a95dbb33059fc3d12638ed2a9aecff899e339c5c0f3a0b28768866d385b4","impliedFormat":99},{"version":"56fc978580577d30f4c2cdb5b1eb9217b66ed66537dd27141256f426e4b8dd68","impliedFormat":99},{"version":"2c5413050a2580becf9d82dd7e3006b95623e96f145356bf73230cd635352f70","impliedFormat":99},{"version":"860bedc71ead192ea4a0ea5ef4686e65724d14b391ebd1a6671a7044e6bd8e15","impliedFormat":99},{"version":"7c0a845bee4a084cbb8654709f48e5f13e2f6d45e5e2dde7c57cadf79fd9e3d5","impliedFormat":99},{"version":"7fa6fdc6eeeb3850e6b3166836f8c9199594c4f4bed3cee02cac0ca33d71894d","impliedFormat":99},{"version":"e53757f3e6688e8be16b36ccbeedc85637e607353fc67ff7b6665d6005aeaa12","impliedFormat":99},{"version":"88ba2660f5b024c7afd02ea700bc0c677687e17e34f0a94c3256ddb55e0f1c5d","impliedFormat":99},{"version":"7bbff6783e96c691a41a7cf12dd5486b8166a01b0c57d071dbcfca55c9525ec4","impliedFormat":99},{"version":"b72c0d7892f40c03e9aabfc6d7bde8274102736de4c7a00744398caa92d84215","signature":"4b96dd19fd2949d28ce80e913412b0026dc421e5bf6c31d87c7b5eb11b5753b4"},{"version":"7e29f41b158de217f94cb9676bf9cbd0cd9b5a46e1985141ed36e075c52bf6ad","affectsGlobalScope":true,"impliedFormat":1},{"version":"ac51dd7d31333793807a6abaa5ae168512b6131bd41d9c5b98477fc3b7800f9f","impliedFormat":1},{"version":"dc782ff85b2cb10075ecffc158af7bfb27ff97bf8491c917efea0c3d622d5ac4","impliedFormat":1},{"version":"be1cc4d94ea60cbe567bc29ed479d42587bf1e6cba490f123d329976b0fe4ee5","impliedFormat":1}],"root":[202,248],"options":{"allowImportingTsExtensions":true,"composite":true,"module":99,"skipLibCheck":true},"referencedMap":[[197,1],[195,2],[206,2],[200,3],[196,1],[198,4],[199,1],[213,5],[211,2],[163,2],[106,6],[107,6],[108,7],[54,8],[109,9],[110,10],[111,11],[52,2],[112,12],[113,13],[114,14],[115,15],[116,16],[117,17],[118,17],[119,18],[120,19],[121,20],[122,21],[55,2],[53,2],[123,22],[124,23],[125,24],[159,25],[126,26],[127,2],[128,27],[129,28],[130,29],[131,30],[132,31],[133,32],[134,33],[135,34],[136,35],[137,35],[138,36],[139,2],[140,37],[141,38],[143,39],[142,40],[144,41],[145,42],[146,43],[147,44],[148,45],[149,46],[150,47],[151,48],[152,49],[153,50],[154,51],[155,52],[156,53],[56,2],[57,54],[58,2],[59,2],[102,55],[103,56],[104,2],[105,41],[157,57],[158,58],[252,59],[249,2],[251,60],[201,61],[214,62],[235,63],[236,64],[234,2],[207,2],[220,65],[219,66],[231,65],[222,67],[224,68],[243,68],[223,69],[204,70],[203,2],[209,71],[210,72],[240,73],[216,74],[218,75],[239,2],[237,74],[217,2],[208,72],[215,2],[212,2],[250,2],[168,2],[186,76],[184,77],[185,78],[173,79],[174,77],[181,80],[172,81],[177,82],[187,2],[178,83],[183,84],[189,85],[188,86],[171,87],[179,88],[180,89],[175,90],[182,76],[176,91],[165,92],[164,93],[170,2],[232,2],[205,2],[1,2],[50,2],[51,2],[9,2],[13,2],[12,2],[3,2],[14,2],[15,2],[16,2],[17,2],[18,2],[19,2],[20,2],[21,2],[4,2],[22,2],[23,2],[5,2],[24,2],[28,2],[25,2],[26,2],[27,2],[29,2],[30,2],[31,2],[6,2],[32,2],[33,2],[34,2],[35,2],[7,2],[39,2],[36,2],[37,2],[38,2],[40,2],[8,2],[41,2],[46,2],[47,2],[42,2],[43,2],[44,2],[45,2],[2,2],[48,2],[49,2],[11,2],[10,2],[78,94],[90,95],[75,96],[91,97],[100,98],[66,99],[67,100],[65,101],[99,102],[94,103],[98,104],[69,105],[87,106],[68,107],[97,108],[63,109],[64,103],[70,110],[71,2],[77,111],[74,110],[61,112],[101,113],[92,114],[81,115],[80,110],[82,116],[85,117],[79,118],[83,119],[95,102],[72,120],[73,121],[86,122],[62,97],[89,123],[88,110],[76,121],[84,124],[93,2],[60,2],[96,125],[161,126],[194,127],[167,128],[162,126],[160,2],[166,129],[192,2],[190,2],[191,2],[169,2],[193,130],[242,131],[247,132],[241,133],[233,134],[229,135],[225,136],[238,2],[226,67],[245,137],[244,138],[227,139],[221,2],[228,140],[246,141],[230,2],[202,142],[248,143]],"affectedFilesPendingEmit":[[202,17]],"latestChangedDtsFile":"./vitest.config.d.ts","version":"5.9.3"} \ No newline at end of file diff --git a/Tiku.PlatformAdmin.Web/vite.config.d.ts b/Tiku.PlatformAdmin.Web/vite.config.d.ts new file mode 100644 index 0000000..089eeef --- /dev/null +++ b/Tiku.PlatformAdmin.Web/vite.config.d.ts @@ -0,0 +1,2 @@ +declare const _default: import("vite").UserConfigFnObject; +export default _default; diff --git a/Tiku.PlatformAdmin.Web/vite.config.js b/Tiku.PlatformAdmin.Web/vite.config.js new file mode 100644 index 0000000..17a9913 --- /dev/null +++ b/Tiku.PlatformAdmin.Web/vite.config.js @@ -0,0 +1,17 @@ +import { defineConfig, loadEnv } from 'vite'; +import react from '@vitejs/plugin-react'; +export default defineConfig(function (_a) { + var mode = _a.mode; + var env = loadEnv(mode, process.cwd(), ''); + var apiTarget = env.VITE_DEV_API_TARGET || 'http://localhost:5090'; + return { + plugins: [react()], + server: { + port: 5173, + proxy: { + '/api': { target: apiTarget, changeOrigin: true }, + '/openapi': { target: apiTarget, changeOrigin: true }, + }, + }, + }; +}); diff --git a/Tiku.PlatformAdmin.Web/vite.config.ts b/Tiku.PlatformAdmin.Web/vite.config.ts new file mode 100644 index 0000000..005a476 --- /dev/null +++ b/Tiku.PlatformAdmin.Web/vite.config.ts @@ -0,0 +1,29 @@ +import { defineConfig, loadEnv } from 'vite'; +import react from '@vitejs/plugin-react'; + +export default defineConfig(({ mode }) => { + const env = loadEnv(mode, process.cwd(), ''); + const apiTarget = env.VITE_DEV_API_TARGET || 'http://localhost:5090'; + + return { + plugins: [react()], + build: { + rollupOptions: { + output: { + manualChunks(id) { + if (id.includes('node_modules/react') || id.includes('node_modules/scheduler')) return 'react'; + if (id.includes('node_modules/antd') || id.includes('node_modules/@ant-design') || id.includes('node_modules/rc-')) return 'antd'; + if (id.includes('node_modules')) return 'vendor'; + }, + }, + }, + }, + server: { + port: 5173, + proxy: { + '/api': { target: apiTarget, changeOrigin: true }, + '/openapi': { target: apiTarget, changeOrigin: true }, + }, + }, + }; +}); diff --git a/Tiku.PlatformAdmin.Web/vitest.config.d.ts b/Tiku.PlatformAdmin.Web/vitest.config.d.ts new file mode 100644 index 0000000..340562a --- /dev/null +++ b/Tiku.PlatformAdmin.Web/vitest.config.d.ts @@ -0,0 +1,2 @@ +declare const _default: import("vite").UserConfig; +export default _default; diff --git a/Tiku.PlatformAdmin.Web/vitest.config.js b/Tiku.PlatformAdmin.Web/vitest.config.js new file mode 100644 index 0000000..63c67e4 --- /dev/null +++ b/Tiku.PlatformAdmin.Web/vitest.config.js @@ -0,0 +1,6 @@ +import { defineConfig } from 'vitest/config'; +export default defineConfig({ + test: { + environment: 'node', + }, +}); diff --git a/Tiku.PlatformAdmin.Web/vitest.config.ts b/Tiku.PlatformAdmin.Web/vitest.config.ts new file mode 100644 index 0000000..4ac6027 --- /dev/null +++ b/Tiku.PlatformAdmin.Web/vitest.config.ts @@ -0,0 +1,7 @@ +import { defineConfig } from 'vitest/config'; + +export default defineConfig({ + test: { + environment: 'node', + }, +}); diff --git a/docs/architecture/overview.md b/docs/architecture/overview.md index 73c7ae9..d683e6d 100644 --- a/docs/architecture/overview.md +++ b/docs/architecture/overview.md @@ -53,7 +53,7 @@ Forwarded Headers -> Controllers ``` -OpenAPI 和 Scalar 只在 Development 映射。平台管理静态文件由 `Tiku.Api/wwwroot` 同源托管,默认入口是 `/platform-admin/`。 +OpenAPI 和 Scalar 只在 Development 映射。平台管理端位于独立的 `Tiku.PlatformAdmin.Web` React 工程,由 OpenAPI 生成接口契约并单独构建、部署;`Tiku.Api` 不再托管平台前端静态文件。 ### DbMigrator diff --git a/docs/quickstart.md b/docs/quickstart.md index 34e2e60..22804b0 100644 --- a/docs/quickstart.md +++ b/docs/quickstart.md @@ -81,7 +81,7 @@ dotnet run --project Tiku.Api 默认 Development 入口: -- 平台管理端: +- 平台管理端:首次在 `Tiku.PlatformAdmin.Web` 执行 `npm install`;之后启动 `Tiku.Api` 时会在 Development 自动启动前端,访问 - Scalar: - OpenAPI JSON: - Liveness: