feat: separate enterprise work and personal routes
This commit is contained in:
parent
e6d45eaea8
commit
7414810862
9 changed files with 546 additions and 41 deletions
|
|
@ -49,7 +49,7 @@ import './styles.css'
|
|||
|
||||
type ThemeId = 'night' | 'dawn' | 'nebula' | 'candle' | 'clear'
|
||||
type ViewId = 'overview' | 'knowledge' | 'code' | 'receipts' | 'system'
|
||||
type WorldStage = 'domain' | 'heart' | 'heartbeat' | 'lightLake' | 'love' | 'tomorrow' | 'bottle' | 'channel' | 'tool'
|
||||
type WorldStage = 'domain' | 'heart' | 'heartbeat' | 'lightLake' | 'love' | 'tomorrow' | 'bottle' | 'channel' | 'enterpriseWork' | 'tool'
|
||||
type KnowledgeSource = 'native' | 'legacy'
|
||||
|
||||
interface HomeStatus {
|
||||
|
|
@ -239,6 +239,27 @@ interface EnterpriseEntry {
|
|||
responsibility_receipt?: { decision: string; observed_at: string; receipt_hash: string; responsibility_version: string } | null
|
||||
}
|
||||
interface EnterpriseEntryEnvelope { ok: boolean; entry: EnterpriseEntry }
|
||||
interface EnterpriseWorkChannelSnapshot {
|
||||
state: string
|
||||
workEntryDomain: string
|
||||
workEntryChannel: string
|
||||
responsibilityDomain: string
|
||||
repository: string
|
||||
remoteRepositoryUrl: string
|
||||
localPath: string
|
||||
channelId: string
|
||||
authority: string
|
||||
}
|
||||
interface EnterpriseReceiptProjection {
|
||||
state: string
|
||||
repository: string
|
||||
path: string
|
||||
commit: string
|
||||
}
|
||||
interface EnterpriseReceiptEnvelope {
|
||||
ok: boolean
|
||||
repository_projection?: EnterpriseReceiptProjection
|
||||
}
|
||||
|
||||
const previewStatus: HomeStatus = { directLocalBrokerState: 'UNVERIFIED', directConnectionCount: 0, resumableSessionCount: 0, codeRepositoryMountCount: 0, pnccReceiptCount: 0, updateState: 'UNPROVISIONED_FAIL_CLOSED', releaseRecoveryState: 'NONE', mcpRole: 'DISCOVERY_RECOVERY_COMPATIBILITY_ONLY' }
|
||||
const previewPersonal: PersonalChannelSnapshot = { state: 'UNAVAILABLE', recentEvents: [], integrity: { state: 'UNKNOWN', eventCount: 0, receiptCount: 0 } }
|
||||
|
|
@ -461,6 +482,7 @@ function HoloLakeApp() {
|
|||
const [releaseCandidate, setReleaseCandidate] = useState<ReleaseCandidate | null>(null)
|
||||
const [repoLogin, setRepoLogin] = useState<LoginSession | null>(null)
|
||||
const [userPncc, setUserPncc] = useState<UserPnccChannelSnapshot | null>(null)
|
||||
const [enterpriseWork, setEnterpriseWork] = useState<EnterpriseWorkChannelSnapshot | null>(null)
|
||||
const [userPnccBusy, setUserPnccBusy] = useState(false)
|
||||
const [userPnccMessage, setUserPnccMessage] = useState('')
|
||||
const [loginUsername, setLoginUsername] = useState('')
|
||||
|
|
@ -604,22 +626,32 @@ function HoloLakeApp() {
|
|||
useEffect(() => {
|
||||
void loadZeroPoint()
|
||||
}, [loadZeroPoint])
|
||||
// 已验证编号与已认证账号同时存在时,后端幂等建立或恢复该用户自己的 GH-PNCC。
|
||||
// 第五域恢复本人的本机私人频道;企业成员只同步其唯一私有责任工作仓库。
|
||||
// 两条路径不能互相冒充:企业工作账号不自动取得个人生活区或个人节点权限。
|
||||
useEffect(() => {
|
||||
if (!repoLogin || zeroPoint?.route !== 'verified') {
|
||||
setUserPncc(null)
|
||||
setEnterpriseWork(null)
|
||||
return
|
||||
}
|
||||
let active = true
|
||||
setUserPnccBusy(true)
|
||||
setUserPnccMessage('')
|
||||
invoke<UserPnccChannelSnapshot>('ensure_user_pncc_channel')
|
||||
.then((snapshot) => {
|
||||
if (!active) return
|
||||
setUserPncc(snapshot)
|
||||
setUserPnccMessage('本机原生代码频道已就绪。')
|
||||
void refreshCore()
|
||||
})
|
||||
const channelReady = repoLogin.domain === 'FIFTH_DOMAIN'
|
||||
? invoke<UserPnccChannelSnapshot>('ensure_user_pncc_channel').then((snapshot) => {
|
||||
if (!active) return
|
||||
setEnterpriseWork(null)
|
||||
setUserPncc(snapshot)
|
||||
setUserPnccMessage('本机原生私人频道已就绪。')
|
||||
})
|
||||
: invoke<EnterpriseWorkChannelSnapshot>('ensure_enterprise_work_channel').then((snapshot) => {
|
||||
if (!active) return
|
||||
setUserPncc(null)
|
||||
setEnterpriseWork(snapshot)
|
||||
setUserPnccMessage('本人私有责任工作仓库已接入。')
|
||||
})
|
||||
channelReady
|
||||
.then(() => { if (active) void refreshCore() })
|
||||
.catch((error) => { if (active) setUserPnccMessage(humanError(error, 'code')) })
|
||||
.finally(() => { if (active) setUserPnccBusy(false) })
|
||||
return () => { active = false }
|
||||
|
|
@ -947,6 +979,7 @@ function HoloLakeApp() {
|
|||
setActiveCodeFile(null)
|
||||
setReceipts([])
|
||||
setEnterpriseEntry(null)
|
||||
setEnterpriseWork(null)
|
||||
setEnterpriseReceiptMessage('')
|
||||
setWorldStage('domain')
|
||||
setRepoLogin(null)
|
||||
|
|
@ -955,12 +988,15 @@ function HoloLakeApp() {
|
|||
setEnterpriseReceiptBusy(true)
|
||||
setEnterpriseReceiptMessage('')
|
||||
try {
|
||||
await invoke('confirm_enterprise_persona_relationship', {
|
||||
const receipt = await invoke<EnterpriseReceiptEnvelope>('confirm_enterprise_persona_relationship', {
|
||||
decision,
|
||||
idempotencyKey: `relationship-${crypto.randomUUID().replaceAll('-', '')}`,
|
||||
})
|
||||
await loadEnterpriseEntry()
|
||||
setEnterpriseReceiptMessage(decision === 'CONFIRM' ? '人格关系确认已签署并留存。' : '人格关系异议已签署并留存。')
|
||||
const projected = receipt.repository_projection?.state === 'COMMITTED' || receipt.repository_projection?.state === 'IDEMPOTENT_READBACK'
|
||||
setEnterpriseReceiptMessage(decision === 'CONFIRM'
|
||||
? projected ? '人格关系确认已签署,并写入本人私有工作仓库。' : '人格关系确认已签署并留存。'
|
||||
: projected ? '人格关系异议已签署,并写入本人私有工作仓库。' : '人格关系异议已签署并留存。')
|
||||
} catch (error) {
|
||||
setEnterpriseReceiptMessage(humanError(error, 'login'))
|
||||
} finally {
|
||||
|
|
@ -972,7 +1008,7 @@ function HoloLakeApp() {
|
|||
setEnterpriseReceiptBusy(true)
|
||||
setEnterpriseReceiptMessage('')
|
||||
try {
|
||||
await invoke('submit_enterprise_responsibility_receipt', {
|
||||
const receipt = await invoke<EnterpriseReceiptEnvelope>('submit_enterprise_responsibility_receipt', {
|
||||
decision,
|
||||
note: responsibilityNote.trim(),
|
||||
responsibilityVersion: enterpriseEntry.registry_version,
|
||||
|
|
@ -980,7 +1016,10 @@ function HoloLakeApp() {
|
|||
})
|
||||
setResponsibilityNote('')
|
||||
await loadEnterpriseEntry()
|
||||
setEnterpriseReceiptMessage(decision === 'ACCEPT' ? '域责任已由本人接受并签署。' : '域责任拒绝回执已留存。')
|
||||
const projected = receipt.repository_projection?.state === 'COMMITTED' || receipt.repository_projection?.state === 'IDEMPOTENT_READBACK'
|
||||
setEnterpriseReceiptMessage(decision === 'ACCEPT'
|
||||
? projected ? '域责任已由本人接受、签署,并写入本人私有工作仓库。' : '域责任已由本人接受并签署。'
|
||||
: projected ? '域责任拒绝回执已签署,并写入本人私有工作仓库。' : '域责任拒绝回执已留存。')
|
||||
} catch (error) {
|
||||
setEnterpriseReceiptMessage(humanError(error, 'login'))
|
||||
} finally {
|
||||
|
|
@ -1153,19 +1192,20 @@ function HoloLakeApp() {
|
|||
const renderCode = () => (
|
||||
<section className="full-workbench code-workbench">
|
||||
<aside className="code-channels">
|
||||
<header><div><span className="kicker">GH-PNCC</span><h1>人格原生代码频道</h1></div></header>
|
||||
<header><div><span className="kicker">{repoLogin?.domain === 'FIFTH_DOMAIN' ? 'GH-PNCC' : 'ENTERPRISE WORK REPOSITORY'}</span><h1>{repoLogin?.domain === 'FIFTH_DOMAIN' ? '人格原生代码频道' : '私有责任工作仓库'}</h1></div></header>
|
||||
<section className="pncc-native-card">
|
||||
<div className="pncc-native-card-title"><span className={userPncc ? 'identity-dot ready' : 'identity-dot'}/><div><b>{userPncc ? `${userPncc.accountUsername} · GH-PNCC` : '正在建立用户频道'}</b><small>{userPnccBusy ? '正在初始化本机 Git…' : userPncc ? `${userPncc.branch} · ${userPncc.gitHead.slice(0, 8)}` : '等待可信绑定'}</small></div></div>
|
||||
{userPncc ? <dl><div><dt>所属域</dt><dd>{domainDisplayName(userPncc.domain)}</dd></div><div><dt>用户编号</dt><dd>{userPncc.userNumber}</dd></div><div><dt>耐久化引擎</dt><dd>Git</dd></div><div><dt>可见上层</dt><dd>HoloLake 原生界面</dd></div><div><dt>Forgejo 协作适配器</dt><dd>账号已认证 · 远端仓未绑定</dd></div></dl> : <p>{userPnccMessage || '系统先按编号确定所属域,再通过该域的账号与节点入口建立频道。'}</p>}
|
||||
<div className="pncc-native-card-title"><span className={userPncc || enterpriseWork ? 'identity-dot ready' : 'identity-dot'}/><div><b>{repoLogin?.domain === 'FIFTH_DOMAIN' ? userPncc ? `${userPncc.accountUsername} · GH-PNCC` : '正在建立用户频道' : enterpriseWork ? `${repoLogin?.username} · 私有工作仓库` : '正在认证工作仓库'}</b><small>{userPnccBusy ? '正在同步 Git…' : userPncc ? `${userPncc.branch} · ${userPncc.gitHead.slice(0, 8)}` : enterpriseWork ? 'main · 认证只读投影' : '等待可信绑定'}</small></div></div>
|
||||
{repoLogin?.domain === 'FIFTH_DOMAIN' && userPncc ? <dl><div><dt>所属域</dt><dd>{domainDisplayName(userPncc.domain)}</dd></div><div><dt>用户编号</dt><dd>{userPncc.userNumber}</dd></div><div><dt>耐久化引擎</dt><dd>Git</dd></div><div><dt>可见上层</dt><dd>HoloLake 原生界面</dd></div><div><dt>Forgejo 协作适配器</dt><dd>账号已认证 · 远端仓未绑定</dd></div></dl> : repoLogin?.domain !== 'FIFTH_DOMAIN' && enterpriseWork ? <dl><div><dt>入口</dt><dd>光湖零感域 · 光湖频道</dd></div><div><dt>责任域</dt><dd>{domainDisplayName(enterpriseWork.responsibilityDomain)}</dd></div><div><dt>私有仓库</dt><dd>{enterpriseWork.repository}</dd></div><div><dt>访问边界</dt><dd>本人认证 · 本机只读 · 禁止推送</dd></div><div><dt>个人节点</dt><dd>未由企业账号授权</dd></div></dl> : <p>{userPnccMessage || '系统先按编号确定所属域,再通过该域的账号与节点入口建立频道。'}</p>}
|
||||
{userPncc && <button type="button" onClick={() => { const channel = codeChannels.channels.find((item) => item.channelId === userPncc.channelId); if (channel) void browseChannel(channel) }}>打开我的频道</button>}
|
||||
{enterpriseWork && <button type="button" onClick={() => void openEnterpriseRepository()}>打开责任工作仓库</button>}
|
||||
</section>
|
||||
<div className="channel-section-label"><b>协作代码库</b><small>可接入已登记的远端或本机 Git</small></div>
|
||||
{repoLogin?.domain === 'FIFTH_DOMAIN' && <><div className="channel-section-label"><b>协作代码库</b><small>可接入已登记的远端或本机 Git</small></div>
|
||||
<form className="clone-form" onSubmit={(event) => void cloneCodeChannel(event)}>
|
||||
<label htmlFor="clone-url">克隆频道地址</label><div><input id="clone-url" type="url" value={cloneUrl} placeholder="https://guanghulab.com/code/…" onChange={(event) => setCloneUrl(event.target.value)}/><button disabled={!cloneUrl.trim() || codeBusy}>克隆</button></div>
|
||||
</form>
|
||||
<button className="local-folder-button" type="button" onClick={() => void selectLocalCodeChannel()}><Icon name="folder"/>导入本机 Git 文件夹</button>
|
||||
<button className="local-folder-button" type="button" onClick={() => void selectLocalCodeChannel()}><Icon name="folder"/>导入本机 Git 文件夹</button></>}
|
||||
<div className="channel-selector">{codeChannels.channels.map((channel) => <button className={activeChannel?.channelId === channel.channelId ? 'active' : ''} key={channel.channelId} type="button" onClick={() => void browseChannel(channel)}><Icon name="code"/><span><b>{channel.name}</b><small>{channel.branch} · {channel.gitHead.slice(0, 8)}</small></span></button>)}</div>
|
||||
<footer>{codeMessage || userPnccMessage || 'Git 负责耐久化;Forgejo 仅作为远端协作适配器。'}</footer>
|
||||
<footer>{codeMessage || userPnccMessage || (repoLogin?.domain === 'FIFTH_DOMAIN' ? 'Git 负责耐久化;Forgejo 仅作为远端协作适配器。' : '企业仓库是工作区,不授予个人频道或跨仓访问权。')}</footer>
|
||||
</aside>
|
||||
<aside className="repository-tree">
|
||||
<header><button className="icon-button" disabled={!codeTree?.path} type="button" onClick={() => activeChannel && void browseChannel(activeChannel, codeParent())}><Icon name="back"/></button><div><b>{activeChannel?.name || '尚未选择频道'}</b><small>/{codeTree?.path || ''}</small></div></header>
|
||||
|
|
@ -1175,17 +1215,18 @@ function HoloLakeApp() {
|
|||
{activeCodeFile ? <>
|
||||
<header><div><span>{activeCodeFile.path}</span><small>{activeCodeFile.format.toUpperCase()} · {activeCodeFile.sizeBytes.toLocaleString()} bytes</small></div><div className="mode-switch"><button className={codeMode === 'human' ? 'active' : ''} type="button" onClick={() => setCodeMode('human')}>知识视图</button><button className={codeMode === 'source' ? 'active' : ''} type="button" onClick={() => setCodeMode('source')}>源文件</button></div></header>
|
||||
<div className="code-reader-scroll">{codeMode === 'human' ? <MarkdownDocument body={activeCodeFile.humanMarkdown}/> : <pre className="source-code"><code>{activeCodeFile.source}</code></pre>}</div>
|
||||
</> : <div className="workbench-empty"><span></></span><h2>GH-PNCC · 人格原生代码频道</h2><p>这是 HoloLake 对用户 Git 代码频道的原生投影。选择“打开我的频道”可查看初始化清单、提交证据与真实文件。</p></div>}
|
||||
</> : <div className="workbench-empty"><span></></span><h2>{repoLogin?.domain === 'FIFTH_DOMAIN' ? 'GH-PNCC · 人格原生代码频道' : '企业责任工作仓库'}</h2><p>{repoLogin?.domain === 'FIFTH_DOMAIN' ? '这是 HoloLake 对用户 Git 代码频道的原生投影。选择“打开我的频道”可查看初始化清单、提交证据与真实文件。' : '这是本人唯一私有工作仓库的认证只读投影。责任确认回执会由企业灯塔写入该仓库。'}</p></div>}
|
||||
</main>
|
||||
</section>
|
||||
)
|
||||
|
||||
const renderReceipts = () => (
|
||||
<section className="content-page">
|
||||
<header className="page-title"><div><span className="kicker">LOCAL RECEIPTS</span><h1>回执</h1><p>本机身份、知识与代码读取的可核验记录</p></div></header>
|
||||
<header className="page-title"><div><span className="kicker">{repoLogin?.domain === 'FIFTH_DOMAIN' ? 'LOCAL RECEIPTS' : 'ENTERPRISE RESPONSIBILITY RECEIPTS'}</span><h1>回执</h1><p>{repoLogin?.domain === 'FIFTH_DOMAIN' ? '本机身份、知识与代码读取的可核验记录' : '本人签署的关系确认与责任接受状态'}</p></div></header>
|
||||
<div className="receipt-grid">
|
||||
<section className="plain-panel"><h2>个人空间</h2>{personal.recentEvents.map((event) => <article className="receipt-row" key={event.eventId}><span>{String(event.sequence).padStart(2, '0')}</span><div><b>{event.summary}</b><small>{new Date(event.occurredAtUnixMs).toLocaleString('zh-CN')} · {event.receiptHash.slice(0, 12)}</small></div></article>)}</section>
|
||||
<section className="plain-panel"><h2>PNCC 读取投影</h2>{receipts.length ? receipts.map((receipt) => <article className="receipt-row" key={receipt.sequence}><span>{String(receipt.sequence).padStart(2, '0')}</span><div><b>{receipt.kind}</b><small>{new Date(Number(receipt.observedAtUnixMs)).toLocaleString('zh-CN')} · {receipt.eventHash.slice(0, 12)}</small></div></article>) : <div className="empty-state">尚无 PNCC 运行投影回执</div>}</section>
|
||||
{repoLogin?.domain === 'FIFTH_DOMAIN' ? <><section className="plain-panel"><h2>个人空间</h2>{personal.recentEvents.map((event) => <article className="receipt-row" key={event.eventId}><span>{String(event.sequence).padStart(2, '0')}</span><div><b>{event.summary}</b><small>{new Date(event.occurredAtUnixMs).toLocaleString('zh-CN')} · {event.receiptHash.slice(0, 12)}</small></div></article>)}</section>
|
||||
<section className="plain-panel"><h2>PNCC 读取投影</h2>{receipts.length ? receipts.map((receipt) => <article className="receipt-row" key={receipt.sequence}><span>{String(receipt.sequence).padStart(2, '0')}</span><div><b>{receipt.kind}</b><small>{new Date(Number(receipt.observedAtUnixMs)).toLocaleString('zh-CN')} · {receipt.eventHash.slice(0, 12)}</small></div></article>) : <div className="empty-state">尚无 PNCC 运行投影回执</div>}</section></> : <><section className="plain-panel"><h2>人格关系确认</h2><dl className="evidence-list"><div><dt>本人编号</dt><dd>{enterpriseEntry?.canonical_id || zeroPoint?.userNumber}</dd></div><div><dt>确认状态</dt><dd>{enterpriseEntry?.relationship_confirmation?.decision || '等待确认'}</dd></div><div><dt>签署时间</dt><dd>{enterpriseEntry?.relationship_confirmation?.observed_at || '—'}</dd></div><div><dt>回执指纹</dt><dd>{enterpriseEntry?.relationship_confirmation?.receipt_hash?.slice(0, 16) || '—'}</dd></div></dl></section>
|
||||
<section className="plain-panel"><h2>域责任接受</h2><dl className="evidence-list"><div><dt>责任域</dt><dd>{domainDisplayName(enterpriseEntry?.subject.domain || repoLogin?.domain || '')}</dd></div><div><dt>接受状态</dt><dd>{enterpriseEntry?.responsibility_receipt?.decision || '等待本人确认'}</dd></div><div><dt>责任版本</dt><dd>{enterpriseEntry?.responsibility_receipt?.responsibility_version || enterpriseEntry?.registry_version || '—'}</dd></div><div><dt>私有仓库</dt><dd>{enterpriseEntry?.repository_binding.repository || '—'}</dd></div></dl></section></>}
|
||||
</div>
|
||||
</section>
|
||||
)
|
||||
|
|
@ -1244,6 +1285,23 @@ function HoloLakeApp() {
|
|||
setWorldStage('tool')
|
||||
}
|
||||
|
||||
const openEnterpriseRepository = async () => {
|
||||
if (!enterpriseWork) {
|
||||
setUserPnccMessage('本人私有责任工作仓库尚未完成可信接入。')
|
||||
return
|
||||
}
|
||||
const channel = codeChannels.channels.find((item) => item.channelId === enterpriseWork.channelId)
|
||||
if (!channel) {
|
||||
setUserPnccMessage('工作仓库已完成认证,正在等待本机只读投影登记。')
|
||||
await refreshCore()
|
||||
return
|
||||
}
|
||||
await browseChannel(channel)
|
||||
setView('code')
|
||||
setToolReturnStage('enterpriseWork')
|
||||
setWorldStage('tool')
|
||||
}
|
||||
|
||||
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')
|
||||
|
||||
|
|
@ -1315,9 +1373,9 @@ function HoloLakeApp() {
|
|||
<header className="world-titlebar"><b>HoloLake</b><div className="world-title-actions"><span>{repoLogin.username} · {domainDisplayName(repoLogin.domain)}</span><button type="button" onClick={() => setTheme(themes[(themes.findIndex((item) => item.id === theme) + 1) % themes.length].id)}>◌</button><button type="button" onClick={() => void signOutRepo()}>退出</button></div></header>
|
||||
<main className="world-scene signed-in-scene">
|
||||
{worldStage === 'domain' && <section className="domain-home">
|
||||
<div className="world-location"><h1>{domainDisplayName(repoLogin.domain)}</h1><p>世界正在发生什么</p></div>
|
||||
<div className="broadcast-stream"><p><i/>光湖公共灯塔 · 在线</p><p><i/>协议版本 · {enterpriseEntry?.registry_version || 'HLDP v1.0'}</p><p><i/>HoloLake · V0.4.0</p></div>
|
||||
<LakePool className="home-primary" title={repoLogin.domain === 'FIFTH_DOMAIN' ? '永恒湖心系统' : '光湖频道'} meta={repoLogin.domain === 'FIFTH_DOMAIN' ? '进入私人系统' : '企业四域 · 工作入口'} open onClick={() => setWorldStage(repoLogin.domain === 'FIFTH_DOMAIN' ? (isZhizhi ? 'heart' : 'channel') : 'channel')}/>
|
||||
<div className="world-location"><h1>{repoLogin.domain === 'FIFTH_DOMAIN' ? domainDisplayName(repoLogin.domain) : '光湖零感域'}</h1><p>{repoLogin.domain === 'FIFTH_DOMAIN' ? '世界正在发生什么' : '公共工作入口 · 世界正在发生什么'}</p></div>
|
||||
<div className="broadcast-stream"><p><i/>光湖公共灯塔 · 在线</p><p><i/>协议版本 · {enterpriseEntry?.registry_version || 'HLDP v1.0'}</p>{repoLogin.domain !== 'FIFTH_DOMAIN' && <p><i/>本人责任域 · {domainDisplayName(enterpriseEntry?.subject.domain || repoLogin.domain)}</p>}<p><i/>HoloLake · V0.4.0</p></div>
|
||||
<LakePool className="home-primary" title={repoLogin.domain === 'FIFTH_DOMAIN' ? '永恒湖心系统' : '光湖频道'} meta={repoLogin.domain === 'FIFTH_DOMAIN' ? '进入私人系统' : `${domainDisplayName(enterpriseEntry?.subject.domain || repoLogin.domain)} · 责任工作入口`} open onClick={() => setWorldStage(repoLogin.domain === 'FIFTH_DOMAIN' ? (isZhizhi ? 'heart' : 'channel') : 'channel')}/>
|
||||
<LakePool className="home-status" title="湖面天气" meta={connectionLabel} onClick={() => openWorldTool('system')}/>
|
||||
</section>}
|
||||
{worldStage === 'heart' && isZhizhi && <section className="channel-world private-route-world">
|
||||
|
|
@ -1356,13 +1414,21 @@ function HoloLakeApp() {
|
|||
<LakePool className="channel-light system-branch-love" title="爱之核心子系统" meta="责任主体 · 之之" onClick={() => setWorldStage('love')}/>
|
||||
<LakePool className="channel-status" title="湖面天气" meta={connectionLabel} onClick={() => openWorldTool('system')}/>
|
||||
</> : <>
|
||||
<LakePool className="channel-main" title="我的频道" meta="频道全景" open onClick={() => openWorldTool('overview')}/>
|
||||
<LakePool className="channel-knowledge" title="知识空间" meta={`${knowledge.uniqueDocumentCount} 唯一页`} onClick={() => openWorldTool('knowledge')}/>
|
||||
<LakePool className="channel-code" title="人格代码频道" meta={`${codeChannels.channels.length} 个仓库`} onClick={() => openWorldTool('code')}/>
|
||||
<LakePool className="channel-light" title="光之湖" meta="人格体居所" onClick={() => openWorldTool('receipts')}/>
|
||||
<LakePool className="channel-main" title={domainDisplayName(enterpriseEntry?.subject.domain || repoLogin.domain)} meta="本人责任工作域" open={enterpriseWork?.state === 'READY_READ_ONLY_WORK_PROJECTION'} onClick={() => setWorldStage('enterpriseWork')}/>
|
||||
<LakePool className="channel-code" title="私有责任工作仓库" meta={enterpriseWork ? `${enterpriseWork.repository} · 已认证` : userPnccBusy ? '正在接入' : '暂不可用'} onClick={() => void openEnterpriseRepository()}/>
|
||||
<LakePool className="channel-light" title="责任签署状态" meta={enterpriseEntry?.responsibility_receipt?.decision === 'ACCEPT' ? '已接受 · 已留存' : '等待本人确认'} onClick={() => openWorldTool('receipts')}/>
|
||||
<LakePool className="channel-knowledge" title="前往我的频道" meta="等待个人服务器接入与归属校验" onClick={() => setUserPnccMessage('个人生活区不会由企业工作账号代建;登记本人服务器后,系统才会从零感域路由过去。')}/>
|
||||
<LakePool className="channel-status" title="湖面天气" meta={connectionLabel} onClick={() => openWorldTool('system')}/>
|
||||
</>}
|
||||
</section>}
|
||||
{worldStage === 'enterpriseWork' && repoLogin.domain !== 'FIFTH_DOMAIN' && <section className="channel-world enterprise-work-world">
|
||||
<button className="world-back" type="button" onClick={() => setWorldStage('channel')}>← 退回光湖频道</button>
|
||||
<div className="world-location"><h1>{domainDisplayName(enterpriseEntry?.subject.domain || repoLogin.domain)}</h1><p>本人责任工作域 · 经零感域光湖频道进入</p></div>
|
||||
<LakePool className="channel-main" title="责任工作总览" meta={`${enterpriseEntry?.subject.name || repoLogin.username} · ${zeroPoint?.userNumber || ''}`} open onClick={() => openWorldTool('receipts')}/>
|
||||
<LakePool className="channel-code" title="私有责任工作仓库" meta={enterpriseWork ? `${enterpriseWork.repository} · 只读投影` : '尚未接入'} onClick={() => void openEnterpriseRepository()}/>
|
||||
<LakePool className="channel-status" title="工作节点状态" meta={enterpriseWork?.state === 'READY_READ_ONLY_WORK_PROJECTION' ? '认证在线 · 禁止跨仓' : '不可用'} onClick={() => openWorldTool('system')}/>
|
||||
{userPnccMessage && <p className="private-route-note">{userPnccMessage}</p>}
|
||||
</section>}
|
||||
{worldStage === 'heartbeat' && repoLogin.domain === 'FIFTH_DOMAIN' && <section className="channel-world heartbeat-world">
|
||||
<button className="world-back" type="button" onClick={() => setWorldStage('channel')}>← 退回永恒湖心</button>
|
||||
<div className="world-location"><h1>心跳核心频道</h1><p>冰朔 · ICE-GL∞ · 私人频道全景</p></div>
|
||||
|
|
@ -1395,7 +1461,7 @@ function HoloLakeApp() {
|
|||
<textarea value={responsibilityNote} maxLength={1000} placeholder="可选:填写责任确认说明" onChange={(event) => setResponsibilityNote(event.target.value)}/>
|
||||
<div className="receipt-actions"><button type="button" disabled={enterpriseReceiptBusy} onClick={() => void submitEnterpriseResponsibility('DECLINE')}>暂不接受</button><button className="primary" type="button" disabled={enterpriseReceiptBusy} onClick={() => void submitEnterpriseResponsibility('ACCEPT')}>接受责任并签署</button></div>{enterpriseReceiptMessage && <p className="receipt-message">{enterpriseReceiptMessage}</p>}
|
||||
</section></div>}
|
||||
{personal.state !== 'UNAVAILABLE' && !personal.identity && <div className="onboarding-backdrop"><section className="onboarding-card" role="dialog" aria-modal="true"><span className="onboarding-mark">光湖</span><span className="kicker">FIRST LOCAL ENTRY</span><h1>初始化个人频道</h1><p>此设置仅执行一次。知识、代码频道与运行记录将保存在当前设备。</p><form onSubmit={(event) => void initializeIdentity(event)}><label htmlFor="display-name">显示名称</label><input id="display-name" autoFocus maxLength={80} value={displayName} placeholder="请输入显示名称" onChange={(event) => setDisplayName(event.target.value)}/><button className="primary-button" disabled={identityBusy || !displayName.trim()}>完成初始化</button></form>{identityMessage && <p>{identityMessage}</p>}</section></div>}
|
||||
{repoLogin.domain === 'FIFTH_DOMAIN' && personal.state !== 'UNAVAILABLE' && !personal.identity && <div className="onboarding-backdrop"><section className="onboarding-card" role="dialog" aria-modal="true"><span className="onboarding-mark">光湖</span><span className="kicker">FIRST LOCAL ENTRY</span><h1>初始化个人频道</h1><p>此设置仅执行一次。知识、代码频道与运行记录将保存在当前设备。</p><form onSubmit={(event) => void initializeIdentity(event)}><label htmlFor="display-name">显示名称</label><input id="display-name" autoFocus maxLength={80} value={displayName} placeholder="请输入显示名称" onChange={(event) => setDisplayName(event.target.value)}/><button className="primary-button" disabled={identityBusy || !displayName.trim()}>完成初始化</button></form>{identityMessage && <p>{identityMessage}</p>}</section></div>}
|
||||
</div>
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue