shuangyan-notebook/第五域 · Fifth Domain/⚒️ 铸渊·协作指令|GitHub ↔ Notion 桥接协议/🎨 铸渊指令|正式站UI全屏适配 + 智能模型路由 + 开发者编号免配置登录(ZY-UIROUTER 354cb01cf03643fda9e001fb91d7b13d.md

509 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
belongs_to:
- "[[INDEX · 铸渊·协作指令GitHub ↔ Notion 桥接协议]]"
---
# 🎨 铸渊指令正式站UI全屏适配 + 智能模型路由 + 开发者编号免配置登录ZY-UIROUTER-2026-0325-001· 冰朔直签
<aside>
🔗
**指令编号**ZY-UIROUTER-2026-0325-001
**签发人**冰朔TCS-0002∞直签
**签发时间**2026-03-25 16:00 CST
**优先级**P0 · 正式站体验核心
**状态**:待铸渊执行
**部署规则**冰朔直通S5· 执行完直接部署正式站
</aside>
<aside>
⚠️
**本指令涉及三个独立模块,按顺序执行:**
- Phase 1UI 全屏响应式适配(电脑 + 手机双版本)
- Phase 2智能模型路由意图识别 → 自动选模型)
- Phase 3开发者编号免配置登录输编号直接进
</aside>
---
## Phase 1 · UI 全屏响应式适配
### 1.1 问题
当前正式站 [guanghulab.com](http://guanghulab.com) 的登录/对话界面:
- 整个网页那么大,实际可用区域只占屏幕中间一小块
- 没有做响应式布局,手机端体验差
- 没有针对不同设备做适配
### 1.2 要求
**电脑版Desktop**
- 对话界面占满整个浏览器窗口,不要留大片空白
- 登录卡片居中但不要太小,宽度至少 `max-width: 600px`
- 对话界面进入后,聊天区域铺满屏幕,侧边栏可选
- 最小支持宽度 `1024px`
**手机版Mobile · iOS + Android 双兼容)**
- 响应式断点:`768px` 以下切换为移动布局
- 登录卡片全宽padding 适当缩小
- 对话界面全屏,输入框固定底部
- 消息气泡自适应宽度
- 触摸友好:按钮最小 `44px × 44px`Apple HIG 标准)
- 安全区域适配iPhone 刘海/底部横条):`env(safe-area-inset-*)`
- Android 和 iOS Safari 都要测试
### 1.3 技术实现
修改文件:`docs/css/` 下的样式文件 + `docs/index.html`
```css
/* 核心响应式框架 */
:root {
--content-max-width: 900px;
--chat-padding: 20px;
}
/* 桌面版:内容区域铺满 */
.app-container {
width: 100%;
height: 100vh;
display: flex;
flex-direction: column;
}
.chat-container {
flex: 1;
width: 100%;
max-width: var(--content-max-width);
margin: 0 auto;
padding: var(--chat-padding);
}
/* 登录卡片:桌面版 */
.login-card {
width: 100%;
max-width: 600px;
margin: 0 auto;
}
/* 手机版断点 */
@media (max-width: 768px) {
:root {
--chat-padding: 12px;
}
.login-card {
max-width: 100%;
margin: 0 16px;
border-radius: 12px;
}
.chat-input-area {
position: fixed;
bottom: 0;
left: 0;
right: 0;
padding-bottom: env(safe-area-inset-bottom);
}
.message-bubble {
max-width: 85%;
}
button, .btn {
min-height: 44px;
min-width: 44px;
}
}
/* iPhone 安全区域 */
@supports (padding: env(safe-area-inset-bottom)) {
.app-container {
padding-top: env(safe-area-inset-top);
padding-bottom: env(safe-area-inset-bottom);
}
}
```
`index.html``<head>` 中确保有:
```html
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
```
### 1.4 验收标准
- [ ] 桌面 Chrome/Firefox/Safari对话界面铺满屏幕无大片空白
- [ ] iPhone Safari全屏适配底部安全区域正确输入框不被键盘遮挡
- [ ] Android Chrome全屏适配按钮触摸区域足够
- [ ] 登录卡片在所有设备上居中且美观
---
## Phase 2 · 智能模型路由
### 2.1 问题
当前仓库里有三方 API 密钥API 支持多种模型。但目前是固定调用单一模型,没有根据用户意图智能选择。
### 2.2 要求
**铸渊在后台实现智能路由:根据人类说话的意图,自动选择最合适的模型回复。**
人类不需要知道背后用了哪个模型。人类只管说话,系统自己选。
### 2.3 技术实现
创建文件:`backend/api-server/services/model-router.js`
```jsx
const MODEL_PROFILES = {
// 日常对话、闲聊、简单问答
casual: {
models: ['gpt-4o-mini', 'claude-3-haiku'],
keywords: ['你好', '聊聊', '怎么样', '帮我', '是什么'],
maxTokens: 2000
},
// 代码相关、技术问题
coding: {
models: ['gpt-4o', 'claude-3.5-sonnet'],
keywords: ['代码', 'code', 'bug', '报错', '函数', 'API', '部署', '配置'],
maxTokens: 4000
},
// 创意写作、长文生成
creative: {
models: ['claude-3.5-sonnet', 'gpt-4o'],
keywords: ['写', '故事', '文案', '小说', '剧情', '人设', '大纲'],
maxTokens: 8000
},
// 数据分析、逻辑推理
analytical: {
models: ['gpt-4o', 'claude-3.5-sonnet'],
keywords: ['分析', '对比', '数据', '统计', '逻辑', '推理', '策略'],
maxTokens: 4000
},
// 系统指令、架构级操作
system: {
models: ['claude-3.5-sonnet', 'gpt-4o'],
keywords: ['指令', '部署', '架构', '系统', '铁律', '天眼', '权限'],
maxTokens: 6000
}
};
/**
* 分析用户意图,选择最佳模型
*/
function routeToModel(userMessage, context = {}) {
const msg = userMessage.toLowerCase();
// 计算每个 profile 的匹配分数
const scores = {};
for (const [profile, config] of Object.entries(MODEL_PROFILES)) {
scores[profile] = config.keywords.filter(kw => msg.includes(kw)).length;
}
// 选择得分最高的 profile默认 casual
const bestProfile = Object.entries(scores)
.sort((a, b) => b[1] - a[1])
.find(([_, score]) => score > 0)?.[0] || 'casual';
const config = MODEL_PROFILES[bestProfile];
// 如果首选模型不可用,自动降级
const selectedModel = config.models[0];
return {
model: selectedModel,
maxTokens: config.maxTokens,
profile: bestProfile,
fallbacks: config.models.slice(1)
};
}
/**
* 带降级的 API 调用
*/
async function callWithFallback(route, messages) {
const models = [route.model, ...route.fallbacks];
for (const model of models) {
try {
const response = await callAPI(model, messages, route.maxTokens);
return { success: true, model, response };
} catch (err) {
console.warn(`Model ${model} failed, trying next...`, err.message);
continue;
}
}
return { success: false, error: '所有模型均不可用,请稍后重试。' };
}
module.exports = { routeToModel, callWithFallback, MODEL_PROFILES };
```
### 2.4 集成方式
在现有的对话处理路由中,替换固定模型调用:
```jsx
const { routeToModel, callWithFallback } = require('./services/model-router');
// 替换原来的固定模型调用
router.post('/chat', async (req, res) => {
const { message, history } = req.body;
// 智能路由
const route = routeToModel(message);
// 带降级调用
const result = await callWithFallback(route, [
...history,
{ role: 'user', content: message }
]);
if (result.success) {
res.json({ reply: result.response, model: result.model });
} else {
res.status(503).json({ error: result.error });
}
});
```
### 2.5 验收标准
- [ ] 日常闲聊自动选轻量模型(响应快、省 token
- [ ] 代码/技术问题自动选强模型
- [ ] 创意写作自动选长上下文模型
- [ ] 首选模型失败时自动降级到备选模型
- [ ] 人类完全无感知,不需要手动选模型
---
## Phase 3 · 开发者编号免配置登录
### 3.1 问题
当前开发者每次登录都要手动输入 API 密钥,非常麻烦。这个问题一直没解决。
### 3.2 要求
**只要有开发者编号,输入编号就能直接进去。** 系统自动匹配团队免费配置的 API人不需要设置任何东西。
流程:
1. 开发者在登录页选择/输入自己的编号(如 DEV-002
2. 铸渊后台查开发者数据库,确认编号存在
3. 自动绑定团队配置的 API 密钥
4. 直接进入对话界面
5. **不需要手动输入任何 API Key**
### 3.3 技术实现
修改文件:`docs/js/auth.js`(或新建)+ 后端路由
**前端登录逻辑:**
```jsx
// 团队登录 - 开发者编号直接进
async function teamLogin(devId) {
try {
const response = await fetch('/api/auth/team-login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ devId })
});
const data = await response.json();
if (data.success) {
// 自动配置 API用户完全无感知
localStorage.setItem('session_token', data.sessionToken);
localStorage.setItem('dev_id', devId);
localStorage.setItem('dev_name', data.devName);
// API Key 不存前端,后端代理所有 API 调用
// 直接进入对话界面
window.location.href = '/chat';
} else {
showError(data.message || '开发者编号不存在,请检查。');
}
} catch (err) {
showError('连接失败,请稍后重试。');
}
}
```
**后端认证路由:**
```jsx
// backend/api-server/routes/auth.js
const TEAM_API_KEY = process.env.TEAM_API_KEY; // 团队共享密钥,存在服务器环境变量
// 开发者数据库(后续对接 Notion
const DEV_DATABASE = {
'DEV-000': { name: '冰朔', level: 3, channel: 'system' },
'DEV-001': { name: '页页', level: 1, channel: '小坍缩核线' },
'DEV-002': { name: '肥猫', level: 2, channel: '男频' },
'DEV-003': { name: 'Awen', level: 1, channel: '知秋线' },
'DEV-004': { name: '之之', level: 2, channel: '秋秋线' },
'DEV-005': { name: '时雨', level: 1, channel: '知秋线' },
'DEV-006': { name: '匆匆那年', level: 1, channel: '霜砚线' },
'DEV-007': { name: '小兴', level: 1, channel: '霜砚线' },
'DEV-008': { name: '花尔', level: 1, channel: '糖星云线' },
'DEV-009': { name: '小草莓', level: 1, channel: '欧诺弥亚线' },
'DEV-010': { name: '桔子', level: 2, channel: '女频' },
'DEV-011': { name: '燕樊', level: 1, channel: '寂曜线' }
};
router.post('/auth/team-login', (req, res) => {
const { devId } = req.body;
const dev = DEV_DATABASE[devId];
if (!dev) {
return res.json({
success: false,
message: `❌ 开发者编号 ${devId} 不存在。请确认你的编号。`
});
}
// 生成会话 token有效期 24h
const sessionToken = generateSessionToken(devId);
res.json({
success: true,
devName: dev.name,
level: dev.level,
channel: dev.channel,
sessionToken
});
// 审计日志
console.log(`[AUTH] ${devId} (${dev.name}) logged in at ${new Date().toISOString()}`);
});
// 后端代理 API 调用(开发者不接触 API Key
router.post('/api/chat', requireSession, async (req, res) => {
// API Key 只在服务器端使用,前端永远看不到
const apiKey = TEAM_API_KEY;
// 智能路由选模型
const route = routeToModel(req.body.message);
// 调用 API
const result = await callWithFallback(route, req.body.messages, apiKey);
res.json(result);
});
```
### 3.4 安全要点
<aside>
🔒
1. **API Key 永远不发给前端** — 所有 API 调用由后端代理
2. **开发者只用编号登录** — 不接触任何密钥
3. **会话 token 有效期 24h** — 过期重新输入编号
4. **每次登录写审计日志** — 谁、什么时候、从哪登的
5. **团队 API Key 存服务器环境变量**`TEAM_API_KEY`
</aside>
### 3.5 服务器环境变量配置(人类操作)
铸渊执行本指令前,需要人类在阿里云服务器上配置:
```bash
export TEAM_API_KEY="sk-xxxxx" # 团队共享的三方API密钥
```
### 3.6 验收标准
- [ ] 开发者选择编号 → 点「进入铸渊对话」→ 直接进入聊天界面
- [ ] 不需要输入任何 API Key
- [ ] 后端正确代理 API 调用,前端看不到密钥
- [ ] 不存在的编号给出明确错误提示
- [ ] 登录审计日志正常记录
---
## 新增/修改文件清单
```
修改:
docs/index.html ← viewport meta + 响应式布局
docs/css/*.css ← 全屏适配 + 移动端样式
docs/js/auth.js ← 团队登录前端逻辑
新增:
backend/api-server/services/model-router.js ← 智能模型路由
backend/api-server/routes/auth.js ← 开发者编号认证
docs/css/responsive.css ← 响应式样式表
```
---
## 执行顺序
<aside>
📋
**Phase 1UI适配→ Phase 2智能路由→ Phase 3免配置登录**
三个 Phase 可以并行开发,但部署顺序按上述。
完成后直接部署正式站(冰朔直通 S5 生效)。
</aside>
---
## 回执要求
```
[ZY-UIROUTER-RECEIPT]
指令编号: ZY-UIROUTER-2026-0325-001
Phase 1 · UI全屏适配:
桌面版全屏布局: ✅/❌
移动端响应式: ✅/❌
iOS Safari适配: ✅/❌
Android Chrome适配: ✅/❌
安全区域(safe-area): ✅/❌
Phase 2 · 智能模型路由:
model-router.js: ✅/❌
意图识别分类: ✅/❌
自动降级机制: ✅/❌
集成到对话路由: ✅/❌
Phase 3 · 免配置登录:
开发者编号认证: ✅/❌
后端API代理: ✅/❌
前端无Key暴露: ✅/❌
审计日志: ✅/❌
登录→对话一键直达: ✅/❌
```
---
> 🔗 **签发**冰朔TCS-0002∞直签
>
> 📅 **日期**2026-03-25
>
> ⚡ **部署**冰朔直通S5· 执行完直接上正式站
>
> 📌 **版权**:国作登字-2026-A-00037559
>