From fb8607f248695d37a9dabe83a0b3990a13499294 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=86=B0=E6=9C=94?= <565183519@qq.com> Date: Wed, 19 Aug 2026 07:07:25 +0800 Subject: [PATCH] feat: admit complete Qoder surfaces into numbered HoloLake --- ...umbered-production-installed-20260819.json | 17 + ...oder-surface-live-acceptance-20260819.json | 28 ++ ...raditional-reference-vs-hololake-0.5.0.jpg | Bin 0 -> 69589 bytes .../dynamic-language-world-visual-system.json | 39 +- .../module-donor-admission-registry.json | 11 +- .../dynamic-world-surface-admission.test.mjs | 34 +- .../hololake-native-desktop/src/main.tsx | 95 ++++- .../modules/education-workspace/styles.css | 14 +- .../modules/qoder-surface/StarlakeSurface.tsx | 144 +++++++ .../qoder-surface/TraditionalSurface.tsx | 102 +++++ .../qoder-surface/starlake-surface.css | 163 ++++++++ .../qoder-surface/traditional-surface.css | 355 ++++++++++++++++++ .../modules/qoder-surface/visual-balance.ts | 44 +++ .../modules/web-novel/WebNovelWorkspace.tsx | 1 + 14 files changed, 1016 insertions(+), 31 deletions(-) create mode 100644 product-source/hololake-native-desktop/audit/hololake-0.5.0-qoder-numbered-production-installed-20260819.json create mode 100644 product-source/hololake-native-desktop/audit/qoder-surface-live-acceptance-20260819.json create mode 100644 product-source/hololake-native-desktop/audit/qoder-traditional-reference-vs-hololake-0.5.0.jpg create mode 100644 product-source/hololake-native-desktop/src/modules/qoder-surface/StarlakeSurface.tsx create mode 100644 product-source/hololake-native-desktop/src/modules/qoder-surface/TraditionalSurface.tsx create mode 100644 product-source/hololake-native-desktop/src/modules/qoder-surface/starlake-surface.css create mode 100644 product-source/hololake-native-desktop/src/modules/qoder-surface/traditional-surface.css create mode 100644 product-source/hololake-native-desktop/src/modules/qoder-surface/visual-balance.ts diff --git a/product-source/hololake-native-desktop/audit/hololake-0.5.0-qoder-numbered-production-installed-20260819.json b/product-source/hololake-native-desktop/audit/hololake-0.5.0-qoder-numbered-production-installed-20260819.json new file mode 100644 index 000000000..60db39e45 --- /dev/null +++ b/product-source/hololake-native-desktop/audit/hololake-0.5.0-qoder-numbered-production-installed-20260819.json @@ -0,0 +1,17 @@ +{ + "schema": "hololake.production-install-acceptance/v1", + "record_id": "HLP-PRODUCTION-INSTALL-20260819-001", + "state": "PASS", + "version": "0.5.0", + "installed_path": "/Users/bingshuolingdianyuanhe/Desktop/HoloLake.app", + "visible_hololake_app_count": 1, + "previous_app_recovery_path": "/Users/bingshuolingdianyuanhe/.Trash/HoloLake-pre-qoder-numbered-ui-20260819-0659.app", + "binary_sha256": "b0422bb18df521ace54ff1a52cd47121d92833dd78f165845deba7806686c7ac", + "cdhash": "42640f7ce56e96403609899095c77ea6171df07d", + "team_identifier": "825A9L3G7Q", + "developer_id_signature": "PASS", + "launch": "PASS", + "real_data_rehydration": "PASS", + "notarization": "NOT_CLAIMED_THIS_LOCAL_BUILD", + "updater_artifact_signing": "NOT_COMPLETED_MISSING_PRIVATE_UPDATER_KEY_IN_CURRENT_PROCESS" +} diff --git a/product-source/hololake-native-desktop/audit/qoder-surface-live-acceptance-20260819.json b/product-source/hololake-native-desktop/audit/qoder-surface-live-acceptance-20260819.json new file mode 100644 index 000000000..c02229824 --- /dev/null +++ b/product-source/hololake-native-desktop/audit/qoder-surface-live-acceptance-20260819.json @@ -0,0 +1,28 @@ +{ + "schema": "hololake.qoder-surface-live-acceptance/v1", + "record_id": "HLP-QODER-SURFACE-ACCEPTANCE-20260819-001", + "module_number": "HLP-MOD-OFFICIAL-DYNAMIC-WORLD-SURFACE-0001", + "state": "PASS", + "tested_app": "src-tauri/target/debug/bundle/macos/HoloLake.app", + "developer_id_signature": "PASS", + "team_identifier": "825A9L3G7Q", + "binary_sha256": "fb1d0497f295e1228c9b2ac86e33082332f226aae6e32b9050cf6c5de30bd512", + "cdhash": "90e365b23961a6b842590869df655ec35a55b66e", + "checks": { + "traditional_locked_layout": "PASS", + "traditional_real_data_hydration": "PASS", + "traditional_light_finish_readability": "PASS_SNOW", + "language_world_five_domains_no_overlap": "PASS_1229x768", + "language_world_real_weather": "PASS_CLOUD", + "theme_persists_into_channel": "PASS", + "theme_persists_into_web_novel": "PASS", + "theme_persists_into_education": "PASS", + "new_chapter_modal_opens": "PASS", + "created_chapter_survives_restart": "PASS_1_CHAPTER", + "work_summary_refresh_after_create": "PASS_1_CHAPTER_ON_WORK_CARD", + "idle_clock_stops": "PASS", + "idle_screenshot_psnr_db": 59.502493 + }, + "reference_comparison": "audit/qoder-traditional-reference-vs-hololake-0.5.0.jpg", + "public_notarization": "NOT_CLAIMED_BY_DEBUG_ACCEPTANCE" +} diff --git a/product-source/hololake-native-desktop/audit/qoder-traditional-reference-vs-hololake-0.5.0.jpg b/product-source/hololake-native-desktop/audit/qoder-traditional-reference-vs-hololake-0.5.0.jpg new file mode 100644 index 0000000000000000000000000000000000000000..6f8eb5d42fd7d2946ca3b010212c272efe410239 GIT binary patch literal 69589 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 literal 0 HcmV?d00001 diff --git a/product-source/hololake-native-desktop/contracts/dynamic-language-world-visual-system.json b/product-source/hololake-native-desktop/contracts/dynamic-language-world-visual-system.json index c05c217ce..40dcc5c40 100644 --- a/product-source/hololake-native-desktop/contracts/dynamic-language-world-visual-system.json +++ b/product-source/hololake-native-desktop/contracts/dynamic-language-world-visual-system.json @@ -25,8 +25,13 @@ "unavailable_behavior": "BEIJING_TIME_ONLY_NO_FAKE_WEATHER" }, "visual_lock": { - "layout": "EXISTING_OFFICIAL_FIVE_LAKE_SHELL_UNCHANGED", - "themes": ["夜湖星光", "晨湖曦光", "星云紫夜", "烛畔暖湖", "清浅澄湖"], + "layout": "QODER_LOCKED_STARLAKE_AND_TRADITIONAL_SURFACES_RESPONSIVELY_ADAPTED", + "language_world_themes": ["夜湖星光", "晨湖曦光", "星云紫夜", "烛畔暖湖", "清浅澄湖"], + "traditional_finishes": ["曜夜", "星辉", "深海", "翡翠", "朱砂", "香槟", "瓷光", "雪霁"], + "all_downstream_pages_inherit_active_surface_tokens": true, + "ambient_motion_requires_recent_human_pointer_or_keyboard_activity": true, + "idle_visual_state": "STATIC", + "responsive_layout": "RESIZE_OBSERVER_PLUS_SEMANTIC_TOKEN_BALANCE", "climate_changes_routing_permission_or_fact": false, "daily_sampling_domain_changes_open_domain": false, "real_city_exposed_in_ui": false, @@ -36,18 +41,26 @@ }, "donor_disposition": { "world_climate": "EXTRACTED_REWRITTEN_AND_NUMBERED", - "starlake_surface": "BEHAVIOR_MERGED_INTO_EXISTING_OFFICIAL_SHELL_NOT_COPIED", - "traditional_surface": "REJECTED_DUPLICATE_SHELL_EIGHT_THEMES_AND_SIMULATED_STATUS", - "traditional_surface_css": "REJECTED_CONFLICTS_WITH_LOCKED_FIVE_LAKE_TOKENS", + "starlake_surface": "QODER_LOCKED_SOURCE_ADMITTED_WITH_RESPONSIVE_AND_IDLE_MOTION_ADAPTER", + "traditional_surface": "QODER_LOCKED_SOURCE_ADMITTED_WITH_REAL_NUMBERED_PROJECTIONS_ONLY", + "traditional_surface_css": "QODER_LOCKED_EIGHT_FINISH_TOKEN_SYSTEM_ADMITTED_AND_SCOPED_ACROSS_ALL_PAGES", "fake_broadcasts_and_fake_metrics": "REJECTED" }, + "qoder_source_provenance": { + "root": "/Volumes/JZAO/铸渊-ICE-GL-ZY001/OUT-输出/UI-预览-20260818/deploy-staging", + "main_tsx_sha256": "7dab8596ec0bd2609b1b23b175f1f14f15f2aa9af847eb605692c993d2e876e8", + "traditional_surface_tsx_sha256": "c713dc27681e07c510a2125816dcefb3255252fc0b570e350af7a98f57fc220d", + "traditional_surface_css_sha256": "3e6c446fb84a16ed23b0fd51466ad9723d0c0670ee6ddf6653f61237bd00baa6", + "starlake_surface_css_sha256": "471e3edef02236e6463144ac75b526f0f98782b5476b9db786e7cd0614a83227", + "acceptance_html_sha256": "7a41e426f1576fe0e25182e0c2efee65302b064d86363c890b0f235386a9c070" + }, "current_acceptance": { - "state": "PASS_SIGNED_NUMBERED_REAL_UI_AND_RESTART", + "state": "PASS_NUMBERED_QODER_SURFACES_REAL_DATA_RESPONSIVE_IDLE_AND_RESTART", "module_package_sha256": "b6ba13b9f70bd617b2a303ec2eb0ea11d5354d10118c7f3e5179ae8100cd2602", "module_package_signature": "PASS_EMBEDDED_PRODUCT_TRUST", "numbered_route": "HLP-NIPC-MOD-0031/HLP-NIPC-OP-0147/HLP-NIPC-TGT-0031", - "signed_app_binary_sha256": "5612519f56ea83cfd167cd099cc2cb27de9da057b262716bb71ff38714c76c8f", - "signed_app_cdhash": "5cc0836a1f12f42f9f48196ce691d6f4cde2f801", + "signed_app_binary_sha256": "b0422bb18df521ace54ff1a52cd47121d92833dd78f165845deba7806686c7ac", + "signed_app_cdhash": "42640f7ce56e96403609899095c77ea6171df07d", "apple_team_identifier": "825A9L3G7Q", "module_receipts": { "install": "2bb903cd369c8f57432c59367fd5494ee89a75214d5129511190e2337cecdbc4", @@ -55,8 +68,14 @@ "self_test_pass": "404a0eeddb866bc3050b407c586c036f3707db577e1edf9f1cf3129c1cc9cc1d" }, "real_weather_readback": "PASS_VERIFIED_LIVE_NIGHT_CLOUD_WITHOUT_CITY_OR_COORDINATES", - "restart_restore": "PASS_ACTIVE_MODULE_AND_REAL_CLIMATE_RESTORED", - "official_shell_preserved": "PASS_FIVE_LAKE_LAYOUT_AND_FIVE_THEMES_UNCHANGED", + "restart_restore": "PASS_ACTIVE_MODULE_REAL_CLIMATE_THEME_AND_WEB_NOVEL_CHAPTER_RESTORED", + "official_shell_preserved": "QODER_LOCKED_SURFACES_ADMITTED_WITH_NUMBERED_FUNCTION_ROUTING_UNCHANGED", + "visual_comparison": "audit/qoder-traditional-reference-vs-hololake-0.5.0.jpg", + "idle_static_psnr_db": 59.502493, + "idle_static_clock_unchanged": true, + "web_novel_new_chapter_modal": "PASS", + "web_novel_created_chapter_restart_persistence": "PASS_1_CHAPTER_VISIBLE_AFTER_RESTART", + "traditional_theme_downstream_pages": ["CHANNEL", "WEB_NOVEL", "EDUCATION"], "notarization": "FINAL_RELEASE_CANDIDATE_PENDING" } } diff --git a/product-source/hololake-native-desktop/contracts/module-donor-admission-registry.json b/product-source/hololake-native-desktop/contracts/module-donor-admission-registry.json index cddd95ef7..477bf8033 100644 --- a/product-source/hololake-native-desktop/contracts/module-donor-admission-registry.json +++ b/product-source/hololake-native-desktop/contracts/module-donor-admission-registry.json @@ -169,16 +169,17 @@ "state": "ADMITTED_INSTALLED_RUNTIME_ACCEPTED", "paths": [ "contracts/dynamic-language-world-visual-system.json", - "src/StarlakeSurface.tsx", - "src/starlake-surface.css", - "src/traditional-surface.tsx", - "src/traditional-surface.css", + "src/modules/qoder-surface/StarlakeSurface.tsx", + "src/modules/qoder-surface/starlake-surface.css", + "src/modules/qoder-surface/TraditionalSurface.tsx", + "src/modules/qoder-surface/traditional-surface.css", + "src/modules/qoder-surface/visual-balance.ts", "src-tauri/src/world_climate.rs" ], "runtime_module_number": "HLP-MOD-OFFICIAL-DYNAMIC-WORLD-SURFACE-0001", "numbered_ipc_module": "HLP-NIPC-MOD-0031", "acceptance_evidence": "contracts/dynamic-language-world-visual-system.json#current_acceptance", - "boundary": "REALITY_TIME_AND_PUBLIC_WEATHER_VISUAL_PROJECTION_ONLY; OFFICIAL_FIVE_LAKE_SHELL_AND_ROUTING_UNCHANGED; NO_FAKE_WEATHER_OR_SIMULATED_STATUS" + "boundary": "QODER_LOCKED_VISUAL_SOURCE_PLUS_REALITY_TIME_AND_PUBLIC_WEATHER_PROJECTION; ALL_FUNCTION_ROUTES_REMAIN_NUMBERED; IDLE_STATIC; NO_FAKE_WEATHER_BROADCAST_OR_METRICS" } ], "admission_gate": [ diff --git a/product-source/hololake-native-desktop/scripts/dynamic-world-surface-admission.test.mjs b/product-source/hololake-native-desktop/scripts/dynamic-world-surface-admission.test.mjs index ea137e895..e584f3043 100644 --- a/product-source/hololake-native-desktop/scripts/dynamic-world-surface-admission.test.mjs +++ b/product-source/hololake-native-desktop/scripts/dynamic-world-surface-admission.test.mjs @@ -9,6 +9,11 @@ const modulePackage = JSON.parse(read('fixtures/module-packages/HLP-MOD-OFFICIAL const rust = read('src-tauri/src/world_climate.rs') const frontend = read('src/main.tsx') const styles = read('src/styles.css') +const starlake = read('src/modules/qoder-surface/StarlakeSurface.tsx') +const starlakeStyles = read('src/modules/qoder-surface/starlake-surface.css') +const traditional = read('src/modules/qoder-surface/TraditionalSurface.tsx') +const traditionalStyles = read('src/modules/qoder-surface/traditional-surface.css') +const visualBalance = read('src/modules/qoder-surface/visual-balance.ts') test('dynamic world surface is signed, opt-in and cannot mutate world facts', () => { assert.equal(modulePackage.manifest.moduleNumber, 'HLP-MOD-OFFICIAL-DYNAMIC-WORLD-SURFACE-0001') @@ -31,13 +36,30 @@ test('climate query crosses the unique numbered route and fails closed before ac assert.doesNotMatch(frontend, /from ['"]@tauri-apps\/api\/core['"]/) }) -test('official shell and five lake themes remain the only admitted layout', () => { - assert.equal(contract.visual_lock.layout, 'EXISTING_OFFICIAL_FIVE_LAKE_SHELL_UNCHANGED') - assert.equal(contract.visual_lock.themes.length, 5) - assert.equal(contract.donor_disposition.traditional_surface, 'REJECTED_DUPLICATE_SHELL_EIGHT_THEMES_AND_SIMULATED_STATUS') +test('Qoder locked two-track surface is admitted without simulated product state', () => { + assert.equal(contract.visual_lock.layout, 'QODER_LOCKED_STARLAKE_AND_TRADITIONAL_SURFACES_RESPONSIVELY_ADAPTED') + assert.equal(contract.visual_lock.language_world_themes.length, 5) + assert.equal(contract.visual_lock.traditional_finishes.length, 8) + assert.equal(contract.visual_lock.all_downstream_pages_inherit_active_surface_tokens, true) assert.match(frontend, /夜湖星光/) assert.match(frontend, /天气源暂不可用;湖面只使用北京时间,不生成假天气。/) assert.match(styles, /\.world-climate-veil/) - assert.doesNotMatch(frontend, /语料库新增 217 条/) - assert.doesNotMatch(frontend, /频道活动 · 七日/) + assert.match(starlake, /ResizeObserver/) + assert.match(starlakeStyles, /\.starlake-scene\.awake/) + assert.match(traditional, /broadcasts\.map/) + assert.match(traditionalStyles, /\.official-world\.surface-traditional/) + assert.match(visualBalance, /contrastRatio/) + assert.doesNotMatch(traditional, /语料库新增 217 条/) + assert.doesNotMatch(traditional, /const BROADCAST_POOL/) +}) + +test('ambient motion sleeps and the Qoder source hashes remain pinned', () => { + assert.equal(contract.visual_lock.ambient_motion_requires_recent_human_pointer_or_keyboard_activity, true) + assert.equal(contract.visual_lock.idle_visual_state, 'STATIC') + assert.match(frontend, /setTimeout\(\(\) => \{[\s\S]*setMotionAwake\(false\)/) + assert.match(starlake, /if \(!awake\) return/) + assert.match(traditional, /if \(!awake\) return/) + assert.match(starlakeStyles, /animation-play-state:paused/) + assert.match(traditionalStyles, /animation-play-state:paused/) + assert.equal(contract.qoder_source_provenance.main_tsx_sha256, '7dab8596ec0bd2609b1b23b175f1f14f15f2aa9af847eb605692c993d2e876e8') }) diff --git a/product-source/hololake-native-desktop/src/main.tsx b/product-source/hololake-native-desktop/src/main.tsx index 058596048..de0a971a0 100644 --- a/product-source/hololake-native-desktop/src/main.tsx +++ b/product-source/hololake-native-desktop/src/main.tsx @@ -4,6 +4,9 @@ import { numberedInvoke as invoke } from './modules/numbered-ipc' import { splitFrontmatter, documentOutline, jumpToHeading, MarkdownDocument, markdownHtml } from './modules/knowledge-render' import { NativeCompositionStudio, type CompositionDimension, type CompositionMeasure, type NativeCompositionProjection, type ProjectionView } from './modules/native-composition' import type { ChannelWorkbenchSnapshot } from './modules/channel-workbench' +import { StarlakeSurface, type DomainId } from './modules/qoder-surface/StarlakeSurface' +import { FINISHES, TraditionalSurface, type FinishId, type TraditionalBroadcast, type TraditionalChannel, type TraditionalSystem } from './modules/qoder-surface/TraditionalSurface' +import { resolveVisualBalance } from './modules/qoder-surface/visual-balance' const ChannelWorkbenchStudio = lazy(() => import('./modules/channel-workbench').then((module) => ({ default: module.ChannelWorkbenchStudio }))) const PersonaChannelBody = lazy(() => import('./modules/persona-channel-body').then((module) => ({ default: module.PersonaChannelBody }))) @@ -590,6 +593,8 @@ function HoloLakeApp() { }, 2400) }, []) const [theme, setTheme] = useState(() => (window.localStorage.getItem('hololake-theme') as ThemeId) || 'night') + const [surface, setSurface] = useState<'world' | 'traditional'>(() => window.localStorage.getItem('hololake-surface') === 'traditional' ? 'traditional' : 'world') + const [traditionalFinish, setTraditionalFinish] = useState(() => (window.localStorage.getItem('hololake-finish') as FinishId) || 'aurora') const [view, setView] = useState('overview') const [worldStage, setWorldStage] = useState('domain') const [toolReturnStage, setToolReturnStage] = useState('channel') @@ -1851,11 +1856,91 @@ function HoloLakeApp() { const enterpriseRelationshipPending = Boolean(repoLogin && repoLogin.domain !== 'FIFTH_DOMAIN' && enterpriseEntry && enterpriseEntry.relationship_confirmation?.decision !== 'CONFIRM') const enterpriseResponsibilityPending = Boolean(repoLogin && repoLogin.domain !== 'FIFTH_DOMAIN' && enterpriseEntry && !enterpriseRelationshipPending && enterpriseEntry.responsibility_receipt?.decision !== 'ACCEPT') const climateClasses = worldClimate ? ` climate-${worldClimate.weatherKind.toLowerCase()} phase-${worldClimate.timePhase.toLowerCase()}` : '' + const chooseSurface = (next: 'world' | 'traditional') => { + setSurface(next) + window.localStorage.setItem('hololake-surface', next) + } + const setFinish = (next: FinishId) => { + setTraditionalFinish(next) + window.localStorage.setItem('hololake-finish', next) + } + const surfacePill =
+ + +
+ const finishRail = surface === 'traditional' && worldStage !== 'domain' ?
+ {FINISHES.map((item) => )} +
: null + const weatherLabel: Record = { CLEAR: '晴', CLOUD: '云', FOG: '雾', RAIN: '雨', SNOW: '雪', STORM: '雷雨', UNAVAILABLE: '待命' } + const dayNumber = beijingCoordinate?.guanghuEraDay || Math.max(1, Math.floor((Date.now() - new Date('2025-04-26T00:00:00+08:00').getTime()) / 86400000) + 1) + const activityBars = useMemo(() => { + const result = Array(7).fill(0) + const today = new Date(); today.setHours(0, 0, 0, 0) + for (const event of personal.recentEvents) { + const occurred = new Date(event.occurredAtUnixMs); occurred.setHours(0, 0, 0, 0) + const daysAgo = Math.floor((today.getTime() - occurred.getTime()) / 86400000) + if (daysAgo >= 0 && daysAgo < 7) result[6 - daysAgo] += 1 + } + return result + }, [personal.recentEvents]) + const domainLabel = domainDisplayName(worldClimate?.activeDomain || repoLogin?.domain || 'MAIN_DOMAIN') + const visualBalance = resolveVisualBalance(traditionalFinish, worldClimate?.timePhase, worldClimate?.weatherKind) + const traditionalBroadcasts: TraditionalBroadcast[] = personal.recentEvents.slice(0, 4).map((event) => ({ + id: event.eventId, + domain: repoLogin?.domain === 'FIFTH_DOMAIN' ? '第五域' : '零感域', + message: event.summary, + time: new Date(event.occurredAtUnixMs).toLocaleTimeString('zh-CN', { hour: '2-digit', minute: '2-digit' }), + })) + if (!traditionalBroadcasts.length) { + traditionalBroadcasts.push( + { id: 'number-root', domain: '主域', message: `编号入口 ${zeroPoint?.route === 'verified' ? '已校验' : '等待验证'}`, time: '当前' }, + { id: 'module-root', domain: '分域', message: `签名模块 ${personal.modules.length} 项`, time: '当前' }, + { id: 'weather-root', domain: '零域', message: worldClimate?.state === 'VERIFIED_LIVE' ? '现实天象投影已校验' : '天气不可用时不生成假数据', time: '当前' }, + ) + } + const traditionalChannels: TraditionalChannel[] = [ + { color: 'var(--accent)', title: '人格原生代码频道', meta: '当前账号本机 Git 投影', tag: userPncc?.state === 'READY' ? '已认证' : '待接入', tone: 'var(--good)', count: codeChannels.channels.length }, + { color: 'var(--accent2)', title: '知识库', meta: '本机内容指纹投影', tag: '原生', tone: 'var(--accent2)', count: knowledge.uniqueDocumentCount }, + { color: 'var(--good)', title: '频道模块', meta: '已登记签名模块', tag: '编号', tone: 'var(--good)', count: personal.modules.length }, + { color: 'var(--warn)', title: '运行回执', meta: '可核验事件链', tag: '证据', tone: 'var(--warn)', count: receipts.length }, + ] + const traditionalSystems: TraditionalSystem[] = [ + { title: '编号协议基座', meta: '单一编号入口 · 未知路径关闭', tag: zeroPoint?.route === 'verified' ? '已校验' : '待验证', tone: 'var(--good)' }, + { title: '耐久化引擎', meta: '本机 Git · 事件与回执留证', tag: status.releaseRecoveryState && status.releaseRecoveryState !== 'NONE' ? status.releaseRecoveryState : '在线', tone: 'var(--good)' }, + { title: '天象感知', meta: worldClimate?.state === 'VERIFIED_LIVE' ? `${domainLabel} · 公开天气已校验` : '只使用北京时间 · 不伪造天气', tag: worldClimate ? '已接入' : '待命', tone: 'var(--accent2)' }, + { title: '色衡层', meta: '主题语义令牌 · 明暗自动均衡', tag: '守护中', tone: 'var(--good)' }, + ] + const openFromTraditional = (target: 'knowledge' | 'channel' | 'era' | 'settings') => { + if (target === 'era') { openEraTimeline(); return } + if (!repoLogin) { chooseSurface('world'); setGateOpen(true); return } + if (target === 'channel') { setWorldStage(repoLogin.domain === 'FIFTH_DOMAIN' ? 'channel' : 'channel'); return } + openWorldTool(target === 'knowledge' ? 'knowledge' : 'system') + } + + if (surface === 'traditional' && worldStage === 'domain') { + return <> + chooseSurface('world')} onOpenKnowledge={() => openFromTraditional('knowledge')} onOpenChannel={() => openFromTraditional('channel')} onOpenEra={() => openFromTraditional('era')} onOpenSettings={() => openFromTraditional('settings')} identityLabel={repoLogin ? `${repoLogin.username} · ${domainDisplayName(repoLogin.domain)}` : '光湖语言系统'} version="0.5.0" dayNumber={dayNumber} duty={domainLabel} weatherLabel={worldClimate ? weatherLabel[worldClimate.weatherKind] : '待命'} broadcasts={traditionalBroadcasts} channels={traditionalChannels} systems={traditionalSystems} activityBars={activityBars} activityCount={activityBars.reduce((sum, value) => sum + value, 0)}/> + {surfacePill} + {eraOpen && eraTimeline && setEraOpen(false)}/>} + + } + + if (!repoLogin && surface === 'world' && gateStage === 'number' && !gateRising) { + const activeGate = domainGates.find((gate) => gate.domain === activeDomainInfo) + return
+ {surfacePill} + setActiveDomainInfo(domain)} onOpenEra={openEraTimeline} onEnterChannel={() => setGateOpen(true)}/> + {activeGate && <>{activeGate.title}{activeGate.gate}{activeGate.facts.map(([label, value]) => {label}{value})}} + {gateOpen &&

编号验证

onGateInput(event.target.value)} onKeyDown={(event) => { if (event.key === 'Enter' && gateNumber) { event.preventDefault(); void gateVerifyNumber() } }}/>
{gateMessage &&

{gateMessage}

}
} + {eraOpen && eraTimeline && setEraOpen(false)}/>} + + } if (!repoLogin) { const resolvedDomain = zeroPoint?.resolvedDomain || '' const activeGate = domainGates.find((gate) => gate.domain === activeDomainInfo) - return
+ return
+ {surfacePill}{finishRail}
HoloLake
@@ -1917,11 +2002,14 @@ function HoloLakeApp() { } const isZhizhi = repoLogin.domain === 'FIFTH_DOMAIN' && zeroPoint?.userNumber === 'ICE-GL-ZHI∞' - return
+ const signedActiveGate = domainGates.find((gate) => gate.domain === activeDomainInfo) + return
+ {surfacePill}{finishRail}
HoloLake
{repoLogin.username} · {domainDisplayName(repoLogin.domain)}
- {worldStage === 'domain' &&
+ {worldStage === 'domain' && surface === 'world' && setActiveDomainInfo(domain)} onOpenEra={openEraTimeline} onEnterChannel={() => setWorldStage(repoLogin.domain === 'FIFTH_DOMAIN' ? 'channel' : 'channel')}/>} + {worldStage === 'domain' && surface !== 'world' &&

{repoLogin.domain === 'FIFTH_DOMAIN' ? domainDisplayName(repoLogin.domain) : '光湖零感域'}

{repoLogin.domain === 'FIFTH_DOMAIN' ? '世界正在发生什么' : '公共工作入口 · 世界正在发生什么'}

光湖公共灯塔 · 在线

协议版本 · {enterpriseEntry?.registry_version || 'HLDP v1.0'}

{repoLogin.domain !== 'FIFTH_DOMAIN' &&

本人责任域 · {domainDisplayName(enterpriseEntry?.subject.domain || repoLogin.domain)}

}

HoloLake · V0.5.0

setWorldStage(repoLogin.domain === 'FIFTH_DOMAIN' ? (isZhizhi ? 'heart' : 'channel') : 'channel')}/> @@ -2021,6 +2109,7 @@ function HoloLakeApp() {
{view === 'overview' ? renderOverview() : view === 'knowledge' ? renderKnowledge() : view === 'composition' ? renderComposition() : view === 'workbench' ? renderWorkbench() : view === 'education' ? renderEducation() : view === 'webNovel' ? renderWebNovel() : view === 'mobileSync' ? renderMobileSync() : view === 'persona' ? renderPersonaBody() : view === 'code' ? renderCode() : view === 'receipts' ? renderReceipts() : renderSystem()}
}
+ {worldStage === 'domain' && surface === 'world' && signedActiveGate && <>{signedActiveGate.title}{signedActiveGate.gate}{signedActiveGate.facts.map(([label, value]) => {label}{value})}}
光湖语言系统 · 通用人工智能操作平台GH-AIOS
{eraOpen && eraTimeline && setEraOpen(false)}/>} {enterpriseEntryBusy &&

正在读取企业责任登记……

} diff --git a/product-source/hololake-native-desktop/src/modules/education-workspace/styles.css b/product-source/hololake-native-desktop/src/modules/education-workspace/styles.css index 543b21559..247b499bc 100644 --- a/product-source/hololake-native-desktop/src/modules/education-workspace/styles.css +++ b/product-source/hololake-native-desktop/src/modules/education-workspace/styles.css @@ -1,8 +1,8 @@ -.education-world{min-height:100%;padding:28px;color:#eaf3f3;background:radial-gradient(circle at 75% 0,rgba(84,210,190,.13),transparent 36%),linear-gradient(150deg,#0b1216,#111c21 58%,#0b1318)} -.education-world button,.education-world input{font:inherit}.education-hero{display:grid;grid-template-columns:auto 1fr auto;gap:22px;align-items:start}.education-hero>button{background:transparent;border:0;color:#91aaa9;padding:10px}.education-hero span{font-size:11px;letter-spacing:.18em;color:#74d6c5}.education-hero h1{font-size:38px;margin:5px 0}.education-hero p{margin:0;color:#9db1b2}.education-hero aside{display:flex;flex-direction:column;align-items:flex-end;gap:5px}.education-hero aside b{color:#79d9c7}.education-hero aside small{color:#718588;max-width:260px;text-align:right} -.education-tabs{display:flex;gap:8px;margin:24px 0;border-bottom:1px solid #263a3d}.education-tabs button{border:0;background:transparent;color:#8da3a4;padding:12px 15px;border-bottom:2px solid transparent}.education-tabs button.active{color:#eafffb;border-color:#63d5c2} -.education-overview{display:grid;grid-template-columns:repeat(4,1fr);gap:14px}.education-overview>article,.education-overview>section,.education-import,.education-action-layout>aside,.education-action-layout>main{background:#121f24;border:1px solid #26393d;border-radius:16px;padding:18px}.education-overview>article{display:flex;flex-direction:column;gap:8px}.education-overview>article strong{font-size:30px}.education-overview button,.education-editor-shell button,.education-action-layout button,.education-import button{border:1px solid #345155;background:#172b30;color:#dffbf6;border-radius:9px;padding:9px 12px}.education-overview>section{grid-column:span 2}.education-overview>section>button{width:100%;display:flex;justify-content:space-between;margin-top:8px;text-align:left}.education-overview small{color:#8ba0a2} -.education-editor-shell{display:grid;grid-template-columns:230px minmax(0,1fr);gap:14px;min-height:650px}.education-editor-shell>aside{display:flex;flex-direction:column;gap:7px;background:#0e191d;border:1px solid #26393d;border-radius:14px;padding:12px}.education-editor-shell>aside button{text-align:left;display:flex;flex-direction:column}.education-editor-shell button.active{border-color:#62d3c0;background:#1b3537}.education-editor-shell>main{min-width:0;background:#f7faf9;color:#172326;border-radius:14px;overflow:hidden}.education-editor-shell>main>header{display:flex;justify-content:space-between;gap:12px;padding:12px;background:#e8f0ee;border-bottom:1px solid #ccd9d6}.education-editor-shell>main>header input{flex:1;border:0;background:transparent;font-size:19px;font-weight:700;outline:0}.education-editor-shell>main>header>div{display:flex;gap:7px}.education-editor-shell button.danger{color:#ffc4bd;border-color:#734841;background:#33211f} -.education-action-layout{display:grid;grid-template-columns:250px 1fr;gap:14px}.education-action-layout aside{display:flex;flex-direction:column;gap:8px}.education-action-layout main{min-height:420px}.education-metrics{display:flex;gap:12px;margin:18px 0}.education-metrics b{font-size:26px;background:#0d191d;border-radius:12px;padding:14px 22px}.education-metrics small{font-size:11px;display:block;color:#91a6a7}.education-preview{margin-top:15px;padding:16px;border:1px solid #40726d;background:#102725;border-radius:12px}.education-preview p{color:#c9d7d5}.education-preview code{display:block;color:#78dbc9;margin:10px 0}.education-rule{margin-top:18px} -.education-import>header{display:flex;justify-content:space-between;align-items:center}.education-import dl{display:grid;grid-template-columns:repeat(3,1fr);gap:10px}.education-import dl div{background:#0d181c;border-radius:10px;padding:12px}.education-import dt{color:#789092;font-size:12px}.education-import dd{margin:5px 0 0;overflow-wrap:anywhere}.education-import section article{display:flex;justify-content:space-between;align-items:center;padding:12px 0;border-top:1px solid #273b3e}.education-import section article div{display:flex;flex-direction:column}.education-import small{color:#89a0a1}.education-message{position:sticky;bottom:14px;background:#17302f;border:1px solid #4e8b83;color:#d8fff8;border-radius:12px;padding:12px 16px;margin:16px 0 0} +.education-world{min-height:100%;padding:28px;color:var(--content-primary);background:radial-gradient(circle at 75% 0,color-mix(in srgb,var(--primitive-cool-glow) 13%,transparent),transparent 36%),linear-gradient(150deg,var(--surface-depth),var(--surface-horizon) 58%,var(--surface-depth))} +.education-world button,.education-world input{font:inherit}.education-hero{display:grid;grid-template-columns:auto 1fr auto;gap:22px;align-items:start}.education-hero>button{background:transparent;border:0;color:var(--content-secondary);padding:10px}.education-hero span{font-size:11px;letter-spacing:.18em;color:var(--accent-light)}.education-hero h1{font-size:38px;margin:5px 0}.education-hero p{margin:0;color:var(--content-secondary)}.education-hero aside{display:flex;flex-direction:column;align-items:flex-end;gap:5px}.education-hero aside b{color:var(--state-ready)}.education-hero aside small{color:var(--content-muted);max-width:260px;text-align:right} +.education-tabs{display:flex;gap:8px;margin:24px 0;border-bottom:1px solid var(--panel-edge)}.education-tabs button{border:0;background:transparent;color:var(--content-secondary);padding:12px 15px;border-bottom:2px solid transparent}.education-tabs button.active{color:var(--content-primary);border-color:var(--accent-light)} +.education-overview{display:grid;grid-template-columns:repeat(4,1fr);gap:14px}.education-overview>article,.education-overview>section,.education-import,.education-action-layout>aside,.education-action-layout>main{background:var(--panel-bg);border:1px solid var(--panel-edge);border-radius:16px;padding:18px}.education-overview>article{display:flex;flex-direction:column;gap:8px}.education-overview>article strong{font-size:30px}.education-overview button,.education-editor-shell button,.education-action-layout button,.education-import button{border:1px solid var(--button-secondary-edge);background:var(--button-secondary-bg);color:var(--button-secondary-text);border-radius:9px;padding:9px 12px}.education-overview>section{grid-column:span 2}.education-overview>section>button{width:100%;display:flex;justify-content:space-between;margin-top:8px;text-align:left}.education-overview small{color:var(--content-muted)} +.education-editor-shell{display:grid;grid-template-columns:230px minmax(0,1fr);gap:14px;min-height:650px}.education-editor-shell>aside{display:flex;flex-direction:column;gap:7px;background:var(--panel-bg);border:1px solid var(--panel-edge);border-radius:14px;padding:12px}.education-editor-shell>aside button{text-align:left;display:flex;flex-direction:column}.education-editor-shell button.active{border-color:var(--accent-light);background:color-mix(in srgb,var(--accent-light) 16%,var(--panel-bg))}.education-editor-shell>main{min-width:0;background:#f7faf9;color:#172326;border-radius:14px;overflow:hidden}.education-editor-shell>main>header{display:flex;justify-content:space-between;gap:12px;padding:12px;background:#e8f0ee;border-bottom:1px solid #ccd9d6}.education-editor-shell>main>header input{flex:1;border:0;background:transparent;font-size:19px;font-weight:700;outline:0}.education-editor-shell>main>header>div{display:flex;gap:7px}.education-editor-shell button.danger{color:var(--state-danger);border-color:color-mix(in srgb,var(--state-danger) 45%,var(--panel-edge));background:color-mix(in srgb,var(--state-danger) 12%,var(--panel-bg))} +.education-action-layout{display:grid;grid-template-columns:250px 1fr;gap:14px}.education-action-layout aside{display:flex;flex-direction:column;gap:8px}.education-action-layout main{min-height:420px}.education-metrics{display:flex;gap:12px;margin:18px 0}.education-metrics b{font-size:26px;background:var(--panel-bg);border-radius:12px;padding:14px 22px}.education-metrics small{font-size:11px;display:block;color:var(--content-muted)}.education-preview{margin-top:15px;padding:16px;border:1px solid var(--panel-edge);background:var(--panel-bg);border-radius:12px}.education-preview p{color:var(--content-secondary)}.education-preview code{display:block;color:var(--accent-light);margin:10px 0}.education-rule{margin-top:18px} +.education-import>header{display:flex;justify-content:space-between;align-items:center}.education-import dl{display:grid;grid-template-columns:repeat(3,1fr);gap:10px}.education-import dl div{background:var(--panel-bg);border-radius:10px;padding:12px}.education-import dt{color:var(--content-muted);font-size:12px}.education-import dd{margin:5px 0 0;overflow-wrap:anywhere}.education-import section article{display:flex;justify-content:space-between;align-items:center;padding:12px 0;border-top:1px solid var(--panel-edge)}.education-import section article div{display:flex;flex-direction:column}.education-import small{color:var(--content-muted)}.education-message{position:sticky;bottom:14px;background:var(--panel-bg);border:1px solid var(--panel-edge);color:var(--content-primary);border-radius:12px;padding:12px 16px;margin:16px 0 0} @media(max-width:900px){.education-overview{grid-template-columns:repeat(2,1fr)}.education-editor-shell,.education-action-layout{grid-template-columns:1fr}.education-editor-shell>aside{max-height:180px;overflow:auto}.education-hero{grid-template-columns:1fr}.education-hero>button{justify-self:start}.education-import dl{grid-template-columns:1fr}} diff --git a/product-source/hololake-native-desktop/src/modules/qoder-surface/StarlakeSurface.tsx b/product-source/hololake-native-desktop/src/modules/qoder-surface/StarlakeSurface.tsx new file mode 100644 index 000000000..0aade0918 --- /dev/null +++ b/product-source/hololake-native-desktop/src/modules/qoder-surface/StarlakeSurface.tsx @@ -0,0 +1,144 @@ +import { useEffect, useMemo, useRef, useState, type CSSProperties } from 'react' +import './starlake-surface.css' + +export type DomainId = 'BRANCH_DOMAIN' | 'ZERO_SENSE_DOMAIN' | 'ZERO_DOMAIN' | 'MAIN_DOMAIN' | 'FIFTH_DOMAIN' +export type Phase = 'dawn' | 'day' | 'dusk' | 'night' + +interface StarlakeSurfaceProps { + awake?: boolean + phase?: Phase + weather?: string + authenticated?: boolean + onDomain: (domain: DomainId) => void + onOpenEra: () => void + onEnterChannel: () => void +} + +const EPOCH_MS = new Date('2025-04-26T00:00:00+08:00').getTime() +const WEEK = ['日', '一', '二', '三', '四', '五', '六'] +const PHASE_WORD: Record = { dawn: '晨', day: '午', dusk: '暮', night: '夜' } + +const DOMAINS = [ + { id: 'BRANCH_DOMAIN' as const, name: '分域', stage: 1, stageName: '聚光尘', hi: '#b9f2dd', lo: '#2c5a4a', glow: 'rgba(150,230,200,.5)', glowSoft: 'rgba(150,230,200,.18)', y: -34 }, + { id: 'ZERO_SENSE_DOMAIN' as const, name: '零感域', stage: 2, stageName: '凝星核', hi: '#dcc4ff', lo: '#48326a', glow: 'rgba(206,178,246,.5)', glowSoft: 'rgba(206,178,246,.18)', y: -56 }, + { id: 'ZERO_DOMAIN' as const, name: '零域', stage: 3, stageName: '初生环', hi: '#ffcf9e', lo: '#6e4630', glow: 'rgba(255,200,140,.5)', glowSoft: 'rgba(255,200,140,.18)', y: -40 }, + { id: 'MAIN_DOMAIN' as const, name: '主域', stage: 4, stageName: '行星态', hi: '#c9d6ff', lo: '#33406e', glow: 'rgba(168,190,255,.52)', glowSoft: 'rgba(168,190,255,.18)', y: -66 }, + { id: 'FIFTH_DOMAIN' as const, name: '第五域', stage: 5, stageName: '主星态', hi: '#fdeec2', lo: '#6b5626', glow: 'rgba(250,226,150,.56)', glowSoft: 'rgba(250,226,150,.2)', y: -48 }, +] + +function seeded(index: number) { + const value = Math.sin(index * 9283.17 + 17.73) * 43758.5453 + return value - Math.floor(value) +} + +function phaseOf(hour: number): Phase { + return hour < 5 ? 'night' : hour < 9 ? 'dawn' : hour < 16 ? 'day' : hour < 19 ? 'dusk' : 'night' +} + +export function StarlakeSurface({ awake = false, phase, weather = 'CLEAR', authenticated = false, onDomain, onOpenEra, onEnterChannel }: StarlakeSurfaceProps) { + const [now, setNow] = useState(() => new Date()) + const rootRef = useRef(null) + const [viewport, setViewport] = useState(() => ({ width: window.innerWidth, height: window.innerHeight })) + const livePhase = phase || phaseOf(now.getHours() + now.getMinutes() / 60) + const raining = ['RAIN', 'STORM'].includes(weather.toUpperCase()) + const dayNumber = Math.floor((now.getTime() - EPOCH_MS) / 86400000) + 1 + const dayIndex = ((dayNumber - 1) % DOMAINS.length + DOMAINS.length) % DOMAINS.length + + const stars = useMemo(() => Array.from({ length: 170 }, (_, index) => ({ + id: index, + size: .8 + seeded(index + 1) * 1.6, + left: seeded(index + 201) * 100, + top: seeded(index + 401) * 68, + opacity: .2 + seeded(index + 601) * .6, + duration: 2.5 + seeded(index + 801) * 5, + delay: -seeded(index + 1001) * 7, + warm: seeded(index + 1201) < .12, + })), []) + const lakeStars = useMemo(() => Array.from({ length: 140 }, (_, index) => ({ + id: index, + size: 1 + seeded(index + 1401) * 1.8, + left: seeded(index + 1601) * 100, + top: Math.pow(seeded(index + 1801), 1.6) * 92, + opacity: .22 + seeded(index + 2001) * .5, + duration: 2.4 + seeded(index + 2201) * 4, + delay: -seeded(index + 2401) * 6, + warm: seeded(index + 2601) < .18, + })), []) + const rain = useMemo(() => Array.from({ length: 90 }, (_, index) => ({ + id: index, + left: seeded(index + 2801) * 108, + duration: .9 + seeded(index + 3001) * .8, + delay: -seeded(index + 3201) * 2, + opacity: .3 + seeded(index + 3401) * .5, + })), []) + + useEffect(() => { + if (!awake) return + setNow(new Date()) + const timer = window.setInterval(() => setNow(new Date()), 125) + return () => window.clearInterval(timer) + }, [awake]) + + useEffect(() => { + const root = rootRef.current + if (!root) return + const observer = new ResizeObserver(([entry]) => setViewport({ width: entry.contentRect.width, height: entry.contentRect.height })) + observer.observe(root) + return () => observer.disconnect() + }, []) + + const pad = (value: number, length = 2) => String(value).padStart(length, '0') + // Qoder 验收稿按大画布设计;窗口版必须把整组“天体 + 水影 + 标签”一起缩放, + // 不能只挪坐标,否则第五域在常见 768px 高度下会把名称挤出视口。 + const naturalScale = Math.min(Math.max(Math.min(viewport.width / 1400, viewport.height / 1000), .64), 1.28) + const spacingScale = Math.max(.64, Math.min(1.28, (viewport.width - 72) / (5 * 180))) + const scale = Math.min(naturalScale, spacingScale) + const safeEdge = Math.max(46, 76 * scale) + const sideCenters = Array.from({ length: 5 }, (_, index) => safeEdge + (viewport.width - safeEdge * 2) * index / 4) + const sourceHour = now.getHours() + now.getMinutes() / 60 + now.getSeconds() / 3600 + const isDay = sourceHour >= 6 && sourceHour < 18 + const sourceProgress = isDay ? (sourceHour - 6) / 12 : ((sourceHour >= 18 ? sourceHour - 18 : sourceHour + 6) / 12) + const sourceX = 8 + sourceProgress * 84 + const sourceY = 46 - Math.sin(sourceProgress * Math.PI) * 26 + const sourceStyle = { left: `${sourceX}vw`, top: `${sourceY}vh`, '--src-mid': isDay ? '#ffe9a8' : '#dfe6fa', '--src-g1': isDay ? 'rgba(255,236,180,.7)' : 'rgba(214,226,255,.6)', '--src-g2': isDay ? 'rgba(255,220,140,.26)' : 'rgba(180,200,255,.22)', '--src-g3': isDay ? 'rgba(255,220,140,.12)' : 'rgba(180,200,255,.1)' } as CSSProperties + const glowStyle = { left: `${sourceX}vw`, top: `${sourceY}vh`, '--glow-tint': isDay ? 'rgba(255,236,180,.12)' : 'rgba(190,208,255,.09)' } as CSSProperties + const baseline = Math.min(viewport.height - 142 * scale, Math.max(viewport.height * .61, viewport.height * .665)) + const slots = [0, 1, 3, 4] + let sideCursor = 0 + + return
+
+} diff --git a/product-source/hololake-native-desktop/src/modules/qoder-surface/TraditionalSurface.tsx b/product-source/hololake-native-desktop/src/modules/qoder-surface/TraditionalSurface.tsx new file mode 100644 index 000000000..c515cd778 --- /dev/null +++ b/product-source/hololake-native-desktop/src/modules/qoder-surface/TraditionalSurface.tsx @@ -0,0 +1,102 @@ +import { useEffect, useRef } from 'react' +import './traditional-surface.css' + +/* Qoder 锁定验收稿的传统工作台结构。宿主只注入真实投影,不在视觉层制造广播或指标。 */ +export type FinishId = 'aurora' | 'nebula' | 'abyss' | 'jade' | 'cinnabar' | 'champagne' | 'porcelain' | 'snow' + +export const FINISHES: Array<{ id: FinishId; name: string }> = [ + { id: 'aurora', name: '曜夜' }, { id: 'nebula', name: '星辉' }, { id: 'abyss', name: '深海' }, { id: 'jade', name: '翡翠' }, + { id: 'cinnabar', name: '朱砂' }, { id: 'champagne', name: '香槟' }, { id: 'porcelain', name: '瓷光' }, { id: 'snow', name: '雪霁' }, +] + +const BROADCAST_COLOR: Record = { 分域: '#7ce8c8', 零感域: '#cfa8ff', 零域: '#ffbe85', 主域: '#a8bcff', 第五域: '#fdeec2' } +export interface TraditionalBroadcast { id: string; domain: string; message: string; time: string } +export interface TraditionalChannel { color: string; title: string; meta: string; tag: string; tone: string; count: number } +export interface TraditionalSystem { title: string; meta: string; tag: string; tone?: string } + +interface TraditionalSurfaceProps { + awake?: boolean + finish: FinishId + onFinish: (finish: FinishId) => void + onActivity?: () => void + onBack: () => void + onOpenKnowledge?: () => void + onOpenChannel?: () => void + onOpenEra?: () => void + onOpenSettings?: () => void + identityLabel?: string + version: string + dayNumber: number + duty: string + weatherLabel: string + broadcasts: TraditionalBroadcast[] + channels: TraditionalChannel[] + systems: TraditionalSystem[] + activityBars: number[] + activityCount: number +} + +export function TraditionalSurface({ awake = false, finish, onFinish, onActivity, onBack, onOpenKnowledge, onOpenChannel, onOpenEra, onOpenSettings, identityLabel = '光湖语言系统', version, dayNumber, duty, weatherLabel, broadcasts, channels, systems, activityBars, activityCount }: TraditionalSurfaceProps) { + const rootRef = useRef(null) + const clockRef = useRef(null) + + useEffect(() => { + const tick = () => { + const el = clockRef.current + if (!el) return + const now = new Date() + const pad = (value: number, length = 2) => String(value).padStart(length, '0') + el.textContent = `${pad(now.getHours())}:${pad(now.getMinutes())}:${pad(now.getSeconds())}.${pad(now.getMilliseconds(), 3)}` + } + tick() + if (!awake) return + const timer = window.setInterval(tick, 125) + return () => window.clearInterval(timer) + }, [awake]) + + useEffect(() => { + const element = rootRef.current + if (!element) return + const layout = () => { + const { width, height } = element.getBoundingClientRect() + const vmin = Math.min(width, height) + element.style.setProperty('--gap', `${Math.round(Math.min(18, Math.max(10, vmin * .016)))}px`) + element.style.setProperty('--pad', `${Math.round(Math.min(26, Math.max(12, vmin * .02)))}px`) + const narrow = width < 880 + element.classList.toggle('stack', narrow) + if (!narrow) element.style.setProperty('--cols', `${Math.min(1.32, Math.max(1.08, width / height * .66)).toFixed(2)}fr 1fr`) + } + const observer = new ResizeObserver(layout) + observer.observe(element) + layout() + return () => observer.disconnect() + }, []) + + const pickFinish = (id: FinishId) => { onFinish(id); window.localStorage.setItem('hololake-finish', id) } + const maxBar = Math.max(1, ...activityBars) + + return
+