feat: 新增智能体服务订阅功能(REQ-131~134)

企业、个人用户和 OPC 均可订阅运营商提供的智能体服务:
- 智能体服务目录(6 个智能体:电商视觉/AI漫剧/企业智能体/数据标注/硬件供应链/跨境文案)
- 订阅管理(月度/季度/年度套餐、用量跟踪、续费/取消)
- 调用记录与账单(按月计费、算力券抵扣)
- 新增 agent.html 页面,opc/enterprise/personal/operator 角色可见

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
2026-09-14 09:07:04 +08:00
co-authored by Devin
parent e27104fca1
commit 6027898fbe
7 changed files with 399 additions and 12 deletions
+171
View File
@@ -0,0 +1,171 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>智能体服务 · OPC 公共服务平台 Demo</title>
<link rel="stylesheet" href="assets/style.css">
</head>
<body data-page="agent">
<header class="topnav" id="topnav"></header>
<div class="container">
<div class="page-title">智能体服务</div>
<div class="page-sub" id="agent-sub"></div>
<!-- REQ-131 智能体服务目录 -->
<div class="section">
<h2>智能体服务目录 <span class="req">REQ-131 · 运营商提供 · 企业/个人/OPC 均可订阅</span></h2>
<div class="grid grid-3" id="agt-catalog"></div>
<p class="muted" style="margin-top:10px">运营商提供的智能体服务覆盖电商视觉、AI 漫剧、企业智能体、数据标注、硬件供应链、跨境电商等方向。订阅后按调用次数计费,套餐内不另收费。</p>
</div>
<!-- REQ-132 我的订阅 -->
<div class="section">
<h2>我的订阅 <span class="req">REQ-132 · 订阅管理 · 用量与到期</span></h2>
<div class="card"><table id="agt-subs"></table></div>
</div>
<!-- REQ-133 使用记录 -->
<div class="section">
<div class="two-col">
<div class="card">
<h3>近期使用记录 <span class="req">REQ-133</span></h3>
<table id="agt-usage"></table>
</div>
<div class="card">
<h3>本月账单 <span class="req">REQ-134</span></h3>
<ul class="list" id="agt-bill"></ul>
<button class="btn sm" style="margin-top:10px" onclick="agentBill()">查看账单明细</button>
</div>
</div>
</div>
</div>
<div class="footer">OPC 公共服务平台 Demo · 智能体服务</div>
<script src="assets/app.js"></script>
<script src="assets/store.js"></script>
<script>
function renderPage(DB) {
const A = DB.agent || {};
const role = currentRole();
const roleLabel = { operator: '运营商管理视角 · 智能体服务运营与订阅统计', enterprise: '企业订阅 · 调用智能体提升业务效率', personal: '个人订阅 · 调用智能体辅助工作', opc: 'OPC 订阅 · 调用智能体提升交付效率' }[role] || '智能体服务订阅';
document.getElementById('agent-sub').textContent = roleLabel;
// 目录
document.getElementById('agt-catalog').innerHTML = (A.catalog || []).map((a, i) => `
<div class="card">
<h3>${a.name} ${B(a.status)}</h3>
<p class="muted">${a.desc}</p>
<div style="margin:8px 0">${a.tags.map(t => `<span class="badge pri">${t}</span> `).join('')}</div>
<table style="margin:6px 0">
<tr><td class="muted">分类</td><td>${a.category}</td></tr>
<tr><td class="muted">价格</td><td><b>${a.price}</b></td></tr>
<tr><td class="muted">额度</td><td>${a.calls}</td></tr>
<tr><td class="muted">评分</td><td>★ ${a.rating} · ${a.users} 用户</td></tr>
</table>
<button class="btn sm" onclick="subscribe(${i})">订阅</button>
<button class="btn sm ghost" onclick="agentDetail(${i})">详情</button>
</div>`).join('');
// 我的订阅
document.getElementById('agt-subs').innerHTML =
`<tr><th>订阅号</th><th>智能体</th><th>套餐</th><th>价格</th><th>用量</th><th>到期</th><th>状态</th><th>操作</th></tr>` +
(A.mySubs || []).map((s, i) => `<tr>
<td>${s.code}</td><td>${s.agent}</td><td>${s.plan}</td><td>${s.price}</td>
<td>${s.calls}</td><td>${s.expire}</td><td>${B(s.status)}</td>
<td><button class="btn sm ghost" onclick="subDetail(${i})">管理</button> <button class="btn sm ghost" onclick="renew(${i})">续费</button></td>
</tr>`).join('');
// 使用记录
document.getElementById('agt-usage').innerHTML =
`<tr><th>日期</th><th>智能体</th><th>调用</th><th>任务</th><th>费用</th></tr>` +
(A.usage || []).map(u => `<tr><td>${u.date}</td><td>${u.agent}</td><td>${u.calls} 次</td><td class="muted">${u.task}</td><td>${u.cost}</td></tr>`).join('');
// 账单
const bi = A.billing || {};
document.getElementById('agt-bill').innerHTML =
LI('订阅费', bi.subs || '—') +
LI('调用次数', (bi.calls || 0) + ' 次') +
LI('超额费用', bi.extra || '¥0') +
LI('本月合计', `<b>${bi.total || '—'}</b>`);
}
function subscribe(i) {
const a = DB.agent.catalog[i];
openModal({
title: '订阅 · ' + a.name,
body: `<p class="muted">${a.desc}</p>
<div class="field"><label>订阅套餐</label>
<select><option>${a.price} · 月度</option><option>${a.price.replace('/月','/季')} · 季度(9 折)</option><option>${a.price.replace('/月','/年')} · 年度(8 折)</option></select>
</div>
<div class="field"><label>支付方式</label><select><option>余额支付</option><option>算力券抵扣</option><option>对公转账</option></select></div>
<p class="muted">订阅后立即生效,套餐内调用不另收费,超额按 ¥0.05/次 计费。</p>`,
actions: [
{ label: '取消', cls: 'ghost' },
{ label: '确认订阅', onClick: m => { m.remove(); toast('订阅成功!可在「我的订阅」管理用量与续费'); } },
],
});
}
function agentDetail(i) {
const a = DB.agent.catalog[i];
openModal({
title: a.name + ' · 详情',
body: `<table>
<tr><th>编号</th><td>${a.code}</td></tr>
<tr><th>分类</th><td>${a.category}</td></tr>
<tr><th>说明</th><td>${a.desc}</td></tr>
<tr><th>价格</th><td>${a.price}</td></tr>
<tr><th>调用额度</th><td>${a.calls}</td></tr>
<tr><th>评分</th><td>★ ${a.rating} · ${a.users} 活跃用户</td></tr>
<tr><th>能力标签</th><td>${a.tags.map(t => `<span class="badge pri">${t}</span> `).join('')}</td></tr>
</table>
<h4 style="margin-top:12px">典型场景</h4>
<ul class="list">
<li><span>批量商品主图生成(100 张 / 10 分钟)</span></li>
<li><span>多语言详情页自动翻译+排版</span></li>
<li><span>活动 Banner 模板化批量出图</span></li>
</ul>`,
});
}
function subDetail(i) {
const s = DB.agent.mySubs[i];
openModal({
title: '订阅管理 · ' + s.agent,
body: `<table>
<tr><th>订阅号</th><td>${s.code}</td></tr>
<tr><th>套餐</th><td>${s.plan} · ${s.price}</td></tr>
<tr><th>用量</th><td>${s.calls}</td></tr>
<tr><th>到期</th><td>${s.expire}</td></tr>
<tr><th>状态</th><td>${B(s.status)}</td></tr>
</table>
<p class="muted" style="margin-top:8px">可操作:续费、升级套餐、取消订阅。取消后到期停止服务,期间仍可使用。</p>`,
actions: [
{ label: '关闭', cls: 'ghost' },
{ label: '取消订阅', cls: 'danger', onClick: m => { m.remove(); toast('订阅已取消,到期后停止服务'); } },
],
});
}
function renew(i) {
const s = DB.agent.mySubs[i];
confirmDlg('续费确认', `${s.agent} · ${s.price}。续费后到期日顺延一个月。`, '确认续费', () => {
toast('续费成功,到期日已顺延至 ' + s.expire.replace(/\d{2}$/, String(parseInt(s.expire.match(/\d{2}$/)[0]) + 1).padStart(2, '0')));
});
}
function agentBill() {
openModal({
title: '本月账单明细',
body: `<table>
<tr><th>项目</th><th>金额</th><th>说明</th></tr>
<tr><td>AGT_001 电商视觉 月度</td><td>¥299</td><td class="muted">1000 次额度 · 已用 326</td></tr>
<tr><td>AGT_004 数据标注 月度</td><td>¥199</td><td class="muted">5000 次额度 · 已用 1820</td></tr>
<tr><td>超额调用</td><td>¥0</td><td class="muted">未超额</td></tr>
<tr style="border-top:2px solid var(--primary)"><td><b>合计</b></td><td><b>¥498</b></td><td>—</td></tr>
</table>
<p class="muted" style="margin-top:8px">账单次月 1 日生成,支持算力券抵扣和对公转账。</p>`,
actions: [{ label: '关闭', cls: 'ghost' }],
});
}
</script>
</body>
</html>
+14
View File
@@ -25,6 +25,7 @@ const MENUS = [
{ page: 'profile', label: '画像中心', href: 'profile.html', roles: ['operator', 'gov', 'enterprise'], group: '运营管理' },
{ page: 'opc', label: 'OPC 工作台', href: 'opc.html', roles: ['opc'], group: '我的工作台' },
{ page: 'team', label: '组队协同', href: 'team.html', roles: ['opc', 'operator'], group: '我的工作台' },
{ page: 'agent', label: '智能体服务', href: 'agent.html', roles: ['opc', 'enterprise', 'personal', 'operator'], group: '我的工作台' },
{ page: 'enterprise', label: '企业工作台', href: 'enterprise.html', roles: ['enterprise', 'personal'], labelMap: { personal: '个人工作台' }, group: '我的工作台' },
{ page: 'order', label: '订单与协同', href: 'order.html', roles: ['opc', 'enterprise', 'personal', 'operator'], group: '我的工作台' },
{ page: 'market', label: '橙果商城', href: 'market.html', roles: ['opc', 'enterprise', 'personal', 'learner', 'operator'], group: '我的工作台' },
@@ -95,6 +96,19 @@ function renderNav() {
return;
}
// 门户首页:已登录也不显示侧边栏(公开展示页),顶栏显示品牌 + 帮助 + 角色徽章 + 退出
if (page === 'index') {
host.innerHTML = `
<a class="brand" href="index.html">OPC<span>公共服务平台</span></a>
<a href="req-doc.html" class="muted" style="margin-left:auto;font-size:13px" target="_blank">帮助 / 需求文档</a>
<span class="role-badge">${ROLES[role].name}</span>
<button class="btn sm ghost" onclick="resetDemo()">重置数据</button>
<button class="btn sm" onclick="logout()">退出</button>
`;
document.body.style.paddingLeft = '0';
return;
}
// 按分组组织菜单
const groups = [];
const groupMap = {};
+181
View File
@@ -3262,5 +3262,186 @@
]
}
]
},
"agent": {
"catalog": [
{
"code": "AGT_001",
"name": "电商视觉智能体",
"desc": "商品主图/详情页/Banner 自动生成,支持批量出图",
"category": "电商视觉",
"price": "¥299/月",
"calls": "1000 次/月",
"rating": 4.8,
"users": 128,
"status": [
"热销",
"ok"
],
"tags": [
"商品主图",
"详情页",
"Banner"
]
},
{
"code": "AGT_002",
"name": "AI 漫剧分镜智能体",
"desc": "剧本→分镜→线稿→上色全流程辅助,支持风格切换",
"category": "AI 漫剧",
"price": "¥499/月",
"calls": "500 次/月",
"rating": 4.6,
"users": 56,
"status": [
"热销",
"ok"
],
"tags": [
"分镜",
"上色",
"风格"
]
},
{
"code": "AGT_003",
"name": "企业智能体 FDE",
"desc": "企业知识库构建+智能问答+工作流自动化",
"category": "企业智能体",
"price": "¥999/月",
"calls": "不限",
"rating": 4.9,
"users": 32,
"status": [
"企业版",
"pri"
],
"tags": [
"知识库",
"问答",
"自动化"
]
},
{
"code": "AGT_004",
"name": "数据标注智能体",
"desc": "图像/文本/音频预标注+人工校验,标注效率提升 5 倍",
"category": "数据标注",
"price": "¥199/月",
"calls": "5000 次/月",
"rating": 4.5,
"users": 85,
"status": [
"在售",
"ok"
],
"tags": [
"预标注",
"校验",
"批量"
]
},
{
"code": "AGT_005",
"name": "硬件方案智能体",
"desc": "AI 产品定义→工业设计→BOM 清单→打样建议",
"category": "硬件供应链",
"price": "¥799/月",
"calls": "200 次/月",
"rating": 4.7,
"users": 18,
"status": [
"新品",
"warn"
],
"tags": [
"产品定义",
"BOM",
"打样"
]
},
{
"code": "AGT_006",
"name": "跨境文案智能体",
"desc": "多语言商品描述/广告文案/SEO 优化自动生成",
"category": "跨境电商",
"price": "¥199/月",
"calls": "2000 次/月",
"rating": 4.4,
"users": 142,
"status": [
"在售",
"ok"
],
"tags": [
"多语言",
"文案",
"SEO"
]
}
],
"mySubs": [
{
"code": "SUB_0001",
"agent": "AGT_001 电商视觉智能体",
"plan": "月度订阅",
"price": "¥299/月",
"calls": "326 / 1000",
"expire": "2026-10-15",
"status": [
"使用中",
"ok"
]
},
{
"code": "SUB_0002",
"agent": "AGT_004 数据标注智能体",
"plan": "月度订阅",
"price": "¥199/月",
"calls": "1820 / 5000",
"expire": "2026-10-20",
"status": [
"使用中",
"ok"
]
}
],
"usage": [
{
"date": "09-14",
"agent": "AGT_001 电商视觉",
"calls": 28,
"cost": "¥0",
"task": "商品主图 ×28"
},
{
"date": "09-13",
"agent": "AGT_001 电商视觉",
"calls": 45,
"cost": "¥0",
"task": "详情页 ×15"
},
{
"date": "09-12",
"agent": "AGT_004 数据标注",
"calls": 320,
"cost": "¥0",
"task": "图像标注 320 条"
},
{
"date": "09-11",
"agent": "AGT_001 电商视觉",
"calls": 18,
"cost": "¥0",
"task": "Banner ×6"
}
],
"billing": {
"month": "2026-09",
"subs": "¥498/月",
"calls": 2211,
"extra": "¥0",
"total": "¥498"
}
}
}
+1 -1
View File
@@ -6,7 +6,7 @@
* mock.json 结构升级时提升 SCHEMA_VER 使旧存档失效。
*/
const SCHEMA_VER = 5;
const SCHEMA_VER = 6;
const DB_KEY = 'opc_demo_db';
let DB = null;
+1 -1
View File
@@ -95,7 +95,7 @@ a:hover { color: var(--primary-dark); }
/* body 留出侧边栏空间(login/showcase 无侧边栏除外) */
body { padding-left: 220px; }
body[data-page="login"], body.screen { padding-left: 0; }
body[data-page="login"], body[data-page="index"], body.screen { padding-left: 0; }
@media (max-width: 900px) {
body { padding-left: 0; }
.topnav .nav-toggle { display: inline-block; }