From 5e6571cfa4062e554e95958983a308d49ec496c5 Mon Sep 17 00:00:00 2001 From: Pine Date: Sat, 5 Sep 2026 00:46:59 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E4=B8=AA=E4=BA=BA=E4=B8=BB=E9=A1=B5):=20?= =?UTF-8?q?=E5=BC=80=E5=8F=91=E6=8F=90=E7=A4=BA=E8=AF=8D=E5=AD=98=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E5=BA=93,=20=E6=94=AF=E6=8C=81=E7=AE=A1=E7=90=86?= =?UTF-8?q?=E5=91=98=E7=BC=96=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - GET /pages/dev-prompt: 优先读 system_configs.user_page_dev_prompt, 无则返回内置默认 - PUT /pages/admin/dev-prompt: 管理员更新提示词写入数据库 - 提示词包含完整开发规范: 沙箱约束/postMessage数据桥/动作调用/设计风格/审核要求 --- app/api/routers/rbac_pages.py | 177 ++++++++++++++++++++++++++++++++++ 1 file changed, 177 insertions(+) diff --git a/app/api/routers/rbac_pages.py b/app/api/routers/rbac_pages.py index 65a331e..b400a2e 100644 --- a/app/api/routers/rbac_pages.py +++ b/app/api/routers/rbac_pages.py @@ -23,6 +23,183 @@ router = APIRouter(prefix="/pages", tags=["pages"]) _MAX_HTML = 2 * 1024 * 1024 # 自写 HTML 上限 2MB _ALLOWED_CAPS = {"orders", "agents_dev", "agents_use", "certs"} +# ── 开发提示词(供 AI 智能体生成个人主页 HTML 时使用)────────────────────── +_DEV_PROMPT = """# OPC 个人主页 HTML 开发规范 + +你是一个 OPC 个人主页开发者。请根据用户描述,生成一个**完整的单文件 HTML 页面**。 + +## 一、硬性约束 + +1. **单文件**:所有 HTML、CSS、JavaScript 必须内联在一个文件中,不引用外部 CSS/JS 文件(外部图片、字体 CDN 允许)。 +2. **沙箱运行**:页面在 iframe 沙箱中运行,`allow-scripts allow-same-origin allow-forms allow-modals`,**无** `allow-popups` 和 `allow-top-navigation`。 +3. **内部跳转仅限 iframe 内**:所有链接、表单提交、JS 跳转都只在 iframe 内部生效,不会影响外部页面。推荐使用 hash 路由(`#/page`)实现多页切换。 +4. **大小上限 2MB**。 +5. **禁止**:`window.open`、`window.parent`、`window.top`、`target="_blank"`、`location.href` 跳转外部、`alert` 之外的原生弹窗滥用。 +6. **响应式**:页面宽度自适应,最小支持 320px。禁止固定宽度导致横向滚动。 +7. **背景透明或浅色**:页面容器背景建议透明或 `#f7f7f7`,与外部框架融合。 + +## 二、平台数据接入(postMessage 桥) + +页面加载后,外部框架会通过 `postMessage` 主动推送一次身份数据。页面也可主动请求。 + +### 2.1 接收数据 + +```javascript +window.addEventListener("message", function(e) { + if (e.data && e.data.__opcBridge && e.data.type === "opc:page:init") { + var data = e.data.data; + // data 结构见下方 + } +}); +``` + +### 2.2 主动请求数据 + +```javascript +window.parent.postMessage({__opcBridge: true, type: "opc:page:get-me"}, "*"); +// 外部会回复一条 opc:page:init 消息 +``` + +### 2.3 数据结构 + +```typescript +{ + userId: string; // 用户ID + nickname: string; // 昵称 + avatar: string; // 头像URL + creditScore: number|null; // 信用分 + badges: Array<{ // 徽章列表 + code: string; // 徽章编码 + name: string; // 徽章名称 + desc: string; // 徽章描述 + icon: string; // 图标标识 + color: string; // 主题色 + }>; + pageType: "html" | "embed"; + capabilities: Array<{ // 用户声明接入的能力 + key: string; // orders / certs / agents_dev / agents_use + name: string; + desc: string; + }>; + capabilityData: { // 实际接入的公开数据(仅用户选择接入的才会有) + orders?: Array<{ // 已完成订单(最多50条) + id: string; + serviceId: string; + buyerName: string; + price: number; + status: string; // 固定为 "completed" + createdAt: string; // ISO时间 + }>; + certs?: Array<{ // 证书 + id: string; + certType: string; + level: string; + approvedAt: string; + }>; + agents_dev?: Array; // 开发的智能体(预留,当前为空数组) + agents_use?: Array; // 使用的智能体(预留,当前为空数组) + } +} +``` + +### 2.4 徽章 code 枚举 + +- `opc_certified`:OPC 认证(已实名认证) +- `opc_member`:OPC 成员 +- `credit_gold`:黄金信用(>=100) +- `credit_silver`:白银信用(>=90) +- `credit_bronze`:青铜信用(>=80) +- `credit_rising`:信用成长中(<80) +- `cert_holder`:持证学员 +- `talent_on_shelf`:人才在架 +- `creator`:内容创作者 + +## 三、平台动作(postMessage 调用外部能力) + +页面可通过 `postMessage` 向外部发送动作请求: + +### 3.1 打开与该用户的沟通 + +```javascript +window.parent.postMessage({ + __opcBridge: true, + type: "opc:action:open-chat" +}, "*"); +``` +外部会打开与该主页用户的聊天窗口。 + +### 3.2 分享个人主页 + +```javascript +window.parent.postMessage({ + __opcBridge: true, + type: "opc:action:share" +}, "*"); +``` +外部会弹出分享面板。 + +### 3.3 复制主页链接 + +```javascript +window.parent.postMessage({ + __opcBridge: true, + type: "opc:action:copy-link" +}, "*"); +``` + +## 四、设计风格建议 + +1. **毛玻璃卡片**:`background: rgba(255,255,255,0.72); backdrop-filter: blur(20px); border-radius: 16px;` +2. **渐变强调色**:蓝紫渐变 `linear-gradient(135deg, #667eea, #764ba2)` +3. **圆角**:卡片 16px,按钮 12px,标签 8px +4. **间距**:使用 8px 倍数(8/16/24/32) +5. **字体**:`-apple-system, BlinkMacSystemFont, "PingFang SC", "Segoe UI", sans-serif` +6. **动效**:过渡 `0.3s ease`,hover 轻微上浮 `translateY(-2px)` +7. **空状态**:数据为空时展示友好的空状态插画或文字,不要留空白 + +## 五、页面结构建议 + +推荐包含以下区块(按需取舍): +1. **Hero 区**:头像、昵称、徽章、一句话简介、信用分 +2. **能力/服务展示**:卡片网格展示服务或技能 +3. **数据展示**:订单数、证书、智能体等(需用户接入对应能力) +4. **作品集**:图片/项目展示 +5. **联系区**:"发起沟通"按钮(调用 opc:action:open-chat) +6. **底部**:平台数据接入说明或免责声明 + +## 六、审核要求 + +- 不得包含违法、违规、欺诈内容 +- 接入平台能力后必须真实展示对应数据,不得伪造 +- 不得包含恶意脚本、挖矿、弹窗广告 +- 违反规则将面临下架、永久关闭个人主页功能权限 + +--- + +请根据以上规范,生成一个完整、美观、功能完善的个人主页 HTML。所有 CSS 和 JS 内联,直接输出完整的 HTML 代码。 +""" + + +@router.get("/dev-prompt", summary="个人主页开发提示词") +async def get_dev_prompt(db: Database = Depends(get_db)): + """返回供 AI 智能体生成个人主页 HTML 的标准开发提示词。 + 优先读取 system_configs.user_page_dev_prompt,不存在则返回内置默认提示词。 + """ + stored = await db.config.get("user_page_dev_prompt") + return {"prompt": stored or _DEV_PROMPT, "isDefault": not bool(stored)} + + +@router.put("/admin/dev-prompt", summary="运营端:编辑开发提示词") +async def update_dev_prompt(body: dict = Body(...), db: Database = Depends(get_db), + user: dict = Depends(get_current_user)): + if user.get("role") not in ("admin", "operator"): + raise HTTPException(status_code=403, detail="无权限") + prompt = str(body.get("prompt") or "").strip() + if not prompt: + raise HTTPException(status_code=400, detail="提示词不能为空") + await db.config.set("user_page_dev_prompt", prompt, "个人主页 HTML 开发提示词(供 AI 智能体使用)") + return {"ok": True} + # ── 徽章规则(派生计算,不落库)─────────────────────────────────────────── async def _compute_badges(db: Database, user_id: str) -> list[dict]: