Files
OPC/Demo/operator.html
T
freedakandDevin f307e877c9 feat: OPC 社区运营公共服务平台 Demo v1.3
一人公司/超级个体产业社区公共服务基础设施 Demo,包含:
- 18 个角色页面(运营商/OPC/企业/个人/学员/培训机构/服务机构/政府/审计/金融)
- 暖橙活力主题 UI(渐变毛玻璃 + 暖色侧栏)
- 五步运营闭环(选方向→育人才→建平台→立SOP→聚产业)
- 华强北硬件供应链接入
- 蜂群式交付 + 产业集聚效应展示
- 需求文档(REQ-001~118 全覆盖)

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

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-13 09:07:23 +08:00

156 lines
6.4 KiB
HTML
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.
<!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="operator">
<header class="topnav" id="topnav"></header>
<div class="container">
<div class="page-title">运营工作台</div>
<div class="page-sub">运营商待办与全业务运营入口 · 审核、仲裁、派单、结算批次</div>
<div class="grid grid-4" id="op-stats"></div>
<!-- 业务方向选择与培育(§1.5 步骤①②) -->
<div class="section">
<h2>业务方向选择与培育 <span class="req">§1.5 ①② · 选方向 → 育人才</span></h2>
<div class="card"><table id="op-biz"></table></div>
<p class="muted" style="margin-top:8px">运营五步闭环:选方向 → 育人才 → 建平台 → 立 SOP → 聚产业。每个方向有对应 SOP 标准体系与质量指标集,支撑蜂群式交付。</p>
</div>
<!-- 待办审核队列 -->
<div class="section">
<h2>待办审核队列 <span class="req">REQ-099/100/114/106/060/010 · ADT_ 统一编号</span></h2>
<div class="card"><table id="op-audits"></table></div>
</div>
<!-- 项目总览 -->
<div class="section">
<h2>进行中项目 <span class="req">REQ-031/036 · 运营商统一拆单与质检</span></h2>
<div class="card"><table id="op-proj"></table></div>
</div>
<!-- 快捷入口 -->
<div class="section">
<div class="card">
<h3>快捷入口</h3>
<p>
<a class="btn sm" href="leads.html">供需对接</a>
<a class="btn sm" href="order.html">订单协同</a>
<a class="btn sm" href="institution.html">机构管理</a>
<a class="btn sm" href="market.html">橙果商城审核</a>
<a class="btn sm ghost" href="profile.html">画像中心</a>
<a class="btn sm ghost" href="showcase.html">社区大屏</a>
</p>
</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 O = DB.operator;
document.getElementById('op-stats').innerHTML = O.stats.map(s =>
`<div class="card"><h3>${s.label}</h3><div class="num">${s.num}</div><p class="muted">${s.sub}</p></div>`).join('');
renderBizDirections();
renderAudits();
document.getElementById('op-proj').innerHTML =
`<tr><th>项目</th><th>客户</th><th>承接</th><th>进度</th><th>状态</th><th>操作</th></tr>` +
O.projects.map(p => `<tr><td>${p.code} ${p.name}</td><td>${p.client}</td><td>${p.opc}</td><td>${BAR(p.pct)}</td><td>${B(p.status)}</td><td><a class="btn sm ghost" href="order.html">进入协同</a></td></tr>`).join('');
}
function renderBizDirections() {
const dirs = DB.operator.bizDirections || [];
document.getElementById('op-biz').innerHTML =
`<tr><th>业务方向</th><th>阶段</th><th>认证 OPC</th><th>在训学员</th><th>累计订单</th><th>收入</th><th>SOP 标准</th><th>状态</th></tr>` +
dirs.map(d => `<tr>
<td><b>${d.name}</b></td>
<td>${d.stage}</td>
<td>${d.opcs} 人</td>
<td>${d.trainees} 人</td>
<td>${d.orders} 单</td>
<td>${d.revenue}</td>
<td><code>${d.sop}</code></td>
<td>${B(d.status)}</td>
</tr>`).join('');
}
function renderAudits() {
document.getElementById('op-audits').innerHTML =
`<tr><th>待办号</th><th>类型</th><th>对象</th><th>要点</th><th>操作</th></tr>` +
DB.operator.audits.map((a, i) => `<tr><td>${a.code}</td><td><span class="badge pri">${a.type}</span></td><td>${a.target}</td><td class="muted">${a.detail}</td><td>${
a.action === 'arbitrate'
? `<button class="btn sm" onclick="arbitrate(${i})">仲裁</button>`
: `<button class="btn sm" onclick="approve(${i})">通过</button> <button class="btn sm ghost" onclick="reject(${i})">驳回</button>`
}</td></tr>`).join('');
}
function applyAuditResult(a, pass) {
// 联动更新对应业务域,演示数据一致性
if (a.domain === 'course') {
const c = DB.institution.courses.find(x => x.code === 'CRS_0104');
if (c) { c.status = pass ? ['已上架', 'ok'] : ['已驳回', 'err']; c.action = pass ? 'edit' : 'withdraw'; }
}
if (a.domain === 'work') {
const w = DB.market.items.find(x => x.code === 'WORK_0060');
if (w) { w.status = pass ? ['已上架', 'ok'] : ['已驳回', 'err']; w.action = pass ? 'buy' : 'audit'; }
}
}
function approve(i) {
const a = DB.operator.audits[i];
confirmDlg('审核通过确认', `确认通过「${a.type} · ${a.target}」?结果将写入对应业务台账并留痕。`, '确认通过', () => {
applyAuditResult(a, true);
DB.operator.audits.splice(i, 1);
renderAudits();
toast(`已通过:${a.target}${a.domain === 'course' ? '(课程已在机构端同步上架)' : a.domain === 'work' ? '(成果已上架商城)' : ''}`);
});
}
function reject(i) {
const a = DB.operator.audits[i];
openModal({
title: '驳回 · ' + a.target,
body: `<div class="field"><label>驳回原因(将反馈给提交方)</label><textarea placeholder="如:材料不全 / 资质不符 / 内容违规"></textarea></div>`,
actions: [
{ label: '取消', cls: 'ghost' },
{ label: '确认驳回', cls: 'danger', onClick: m => {
m.remove();
applyAuditResult(a, false);
DB.operator.audits.splice(i, 1);
renderAudits();
toast('已驳回并通知提交方', 'warn');
} },
],
});
}
function arbitrate(i) {
const a = DB.operator.audits[i];
openModal({
title: '争议仲裁 · ' + a.target,
body: `<p class="muted">争议点:详情页返工责任归属。双方提交材料已归档。</p>
<div class="checks">
<label><input type="radio" name="ab" checked> 判定为客户责任(需求变更),返工费用客户承担</label>
<label><input type="radio" name="ab"> 判定为 OPC 责任,计入返工率并免费返工</label>
<label><input type="radio" name="ab"> 双方分摊(50/50)</label>
</div>`,
actions: [
{ label: '取消', cls: 'ghost' },
{ label: '下达仲裁结论', onClick: m => {
m.remove();
DB.operator.audits.splice(i, 1);
renderAudits();
toast('仲裁结论已下达并留痕(REQ-060),结算节点已解冻');
} },
],
});
}
</script>
</body>
</html>