feat: OPC 平台功能增强 v1.4 · 8 项需求变更实施
CHG-006 抢单订单池:OPC 工作台加抢单池(REQ-128/129) CHG-004 政策落地:OPC 加算力券申领/核销+贷款+租金,运营商加政策跟踪(REQ-124/125/126) CHG-001 组队模块:新增 team.html 组队协同页(REQ-119/120/121) CHG-003 活动管理:运营工作台加活动创建/发布/报名管理(REQ-122/123) CHG-005 OPC 财务分析:OPC 工作台加财务看板(REQ-127) CHG-008 平台撮合归集:运营工作台加录入入口(REQ-130) CHG-002 入口跳转:确认已正确(OPC→opc.html) CHG-007 服务中心定位:明确为运营商服务资源管理 Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
@@ -24,6 +24,7 @@ const MENUS = [
|
||||
{ page: 'leads', label: '供需对接', href: 'leads.html', roles: ['operator', 'gov'], group: '运营管理' },
|
||||
{ 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: '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: '我的工作台' },
|
||||
|
||||
+439
-1
@@ -368,7 +368,228 @@
|
||||
"\"详情页转化率提升明显\"",
|
||||
"4.8"
|
||||
]
|
||||
]
|
||||
],
|
||||
"grabPool": [
|
||||
{
|
||||
"id": "ORDER_2026091401",
|
||||
"type": [
|
||||
"标准化派单",
|
||||
"pri"
|
||||
],
|
||||
"items": "电商详情页 ×15 套",
|
||||
"budget": "¥9,000",
|
||||
"ddl": "09-20",
|
||||
"sop": "SOP_电商视觉_V3.2",
|
||||
"count": "3/5",
|
||||
"status": [
|
||||
"开放抢单",
|
||||
"ok"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "ORDER_2026091402",
|
||||
"type": [
|
||||
"标准化派单",
|
||||
"pri"
|
||||
],
|
||||
"items": "活动 Banner ×20",
|
||||
"budget": "¥6,000",
|
||||
"ddl": "09-18",
|
||||
"sop": "SOP_电商视觉_V3.2",
|
||||
"count": "0/5",
|
||||
"status": [
|
||||
"开放抢单",
|
||||
"ok"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "ORDER_2026091403",
|
||||
"type": [
|
||||
"AI 漫剧",
|
||||
"info"
|
||||
],
|
||||
"items": "短视频分镜 ×8 集",
|
||||
"budget": "¥12,000",
|
||||
"ddl": "09-25",
|
||||
"sop": "SOP_漫剧_V2.1",
|
||||
"count": "2/3",
|
||||
"status": [
|
||||
"开放抢单",
|
||||
"ok"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "ORDER_2026091404",
|
||||
"type": [
|
||||
"数据标注",
|
||||
"gray"
|
||||
],
|
||||
"items": "图像标注 2000 条",
|
||||
"budget": "¥4,000",
|
||||
"ddl": "09-22",
|
||||
"sop": "SOP_标注_V1.0",
|
||||
"count": "5/10",
|
||||
"status": [
|
||||
"开放抢单",
|
||||
"ok"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "ORDER_2026091405",
|
||||
"type": [
|
||||
"硬件供应链",
|
||||
"warn"
|
||||
],
|
||||
"items": "AI 产品说明书 ×3 版本",
|
||||
"budget": "¥8,000",
|
||||
"ddl": "09-28",
|
||||
"sop": "SOP_硬件供应链_V1.0",
|
||||
"count": "1/2",
|
||||
"status": [
|
||||
"开放抢单",
|
||||
"ok"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "ORDER_2026091306",
|
||||
"type": [
|
||||
"标准化派单",
|
||||
"pri"
|
||||
],
|
||||
"items": "商品场景图 ×30",
|
||||
"budget": "¥7,500",
|
||||
"ddl": "09-19",
|
||||
"sop": "SOP_电商视觉_V3.2",
|
||||
"count": "5/5",
|
||||
"status": [
|
||||
"已满",
|
||||
"gray"
|
||||
]
|
||||
}
|
||||
],
|
||||
"policySupport": {
|
||||
"compute": {
|
||||
"title": "算力券申领与核销",
|
||||
"balance": 8000,
|
||||
"total": 10000,
|
||||
"used": 2000,
|
||||
"records": [
|
||||
{
|
||||
"code": "VCH_20260901",
|
||||
"amount": "¥500",
|
||||
"target": "ORDER_2026091001 图像生成",
|
||||
"status": [
|
||||
"已核销",
|
||||
"ok"
|
||||
]
|
||||
},
|
||||
{
|
||||
"code": "VCH_20260905",
|
||||
"amount": "¥1,500",
|
||||
"target": "ORDER_2026090501 模型推理",
|
||||
"status": [
|
||||
"已核销",
|
||||
"ok"
|
||||
]
|
||||
},
|
||||
{
|
||||
"code": "VCH_20260912",
|
||||
"amount": "¥500",
|
||||
"target": "ORDER_2026091201 批量生成",
|
||||
"status": [
|
||||
"待核销",
|
||||
"warn"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"loan": {
|
||||
"title": "贷款支持",
|
||||
"records": [
|
||||
{
|
||||
"code": "LOAN_20260801",
|
||||
"type": "创业担保贷款",
|
||||
"amount": "¥30 万",
|
||||
"rate": "政府贴息 2%",
|
||||
"status": [
|
||||
"已放款",
|
||||
"ok"
|
||||
]
|
||||
},
|
||||
{
|
||||
"code": "LOAN_20260901",
|
||||
"type": "算力信用贷",
|
||||
"amount": "¥10 万",
|
||||
"rate": "年化 3.85%",
|
||||
"status": [
|
||||
"审批中",
|
||||
"warn"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"rent": {
|
||||
"title": "租金补贴",
|
||||
"records": [
|
||||
{
|
||||
"code": "RENT_20260901",
|
||||
"type": "园区租金减免",
|
||||
"amount": "¥2,000/月",
|
||||
"status": [
|
||||
"生效中",
|
||||
"ok"
|
||||
]
|
||||
},
|
||||
{
|
||||
"code": "RENT_20260902",
|
||||
"type": "工位补贴",
|
||||
"amount": "¥500/月",
|
||||
"status": [
|
||||
"生效中",
|
||||
"ok"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"finance": {
|
||||
"income": {
|
||||
"total": "¥46,800",
|
||||
"orders": 4,
|
||||
"avg": "¥11,700/单"
|
||||
},
|
||||
"costs": [
|
||||
{
|
||||
"item": "算力消耗",
|
||||
"amount": "¥3,200",
|
||||
"pct": 28,
|
||||
"detail": "图像生成+模型推理"
|
||||
},
|
||||
{
|
||||
"item": "灵活就业社保",
|
||||
"amount": "¥1,580",
|
||||
"pct": 14,
|
||||
"detail": "灵活就业人员社保补贴后"
|
||||
},
|
||||
{
|
||||
"item": "平台服务费",
|
||||
"amount": "¥1,872",
|
||||
"detail": "收入 4%"
|
||||
},
|
||||
{
|
||||
"item": "其他成本",
|
||||
"amount": "¥500",
|
||||
"pct": 4,
|
||||
"detail": "素材采购+工具订阅"
|
||||
}
|
||||
],
|
||||
"net": "¥39,648",
|
||||
"suggestions": [
|
||||
"算力券余额 ¥8,000 可覆盖下月算力消耗,建议优先使用券核销",
|
||||
"灵活就业社保已享受补贴,当前综合税负约 3.2%",
|
||||
"本月复购订单占比 62%,建议提升 L3 认证后接高单价项目"
|
||||
]
|
||||
}
|
||||
},
|
||||
"enterprise": {
|
||||
"code": "ENT_00001",
|
||||
@@ -2712,6 +2933,133 @@
|
||||
],
|
||||
"pct": 78
|
||||
}
|
||||
],
|
||||
"activities": [
|
||||
{
|
||||
"code": "ACT_0001",
|
||||
"name": "供需对接会 · 跨境电商专场",
|
||||
"date": "09-18",
|
||||
"status": [
|
||||
"报名中",
|
||||
"ok"
|
||||
],
|
||||
"signups": 42,
|
||||
"capacity": 80,
|
||||
"leads": 12
|
||||
},
|
||||
{
|
||||
"code": "ACT_0002",
|
||||
"name": "政策宣讲 · 算力券申领辅导",
|
||||
"date": "09-22",
|
||||
"status": [
|
||||
"报名中",
|
||||
"ok"
|
||||
],
|
||||
"signups": 28,
|
||||
"capacity": 50,
|
||||
"leads": 5
|
||||
},
|
||||
{
|
||||
"code": "ACT_0003",
|
||||
"name": "项目路演 · AI 应用创新赛",
|
||||
"date": "09-30",
|
||||
"status": [
|
||||
"筹备中",
|
||||
"warn"
|
||||
],
|
||||
"signups": 0,
|
||||
"capacity": 120,
|
||||
"leads": 0
|
||||
},
|
||||
{
|
||||
"code": "ACT_0004",
|
||||
"name": "企业路演 · 智能体场景专场",
|
||||
"date": "10-10",
|
||||
"status": [
|
||||
"筹备中",
|
||||
"warn"
|
||||
],
|
||||
"signups": 0,
|
||||
"capacity": 60,
|
||||
"leads": 0
|
||||
}
|
||||
],
|
||||
"brokerOrders": [
|
||||
{
|
||||
"code": "ORDER_BRK_001",
|
||||
"client": "ENT_00015 某科技公司",
|
||||
"opc": "OPC_00017 张设计",
|
||||
"amount": "¥18,000",
|
||||
"source": "平台撮合",
|
||||
"status": [
|
||||
"已签约",
|
||||
"ok"
|
||||
]
|
||||
},
|
||||
{
|
||||
"code": "ORDER_BRK_002",
|
||||
"client": "ENT_00016 某品牌公司",
|
||||
"opc": "OPC_00045 陈视觉",
|
||||
"amount": "¥12,000",
|
||||
"source": "平台撮合",
|
||||
"status": [
|
||||
"交付中",
|
||||
"info"
|
||||
]
|
||||
},
|
||||
{
|
||||
"code": "ORDER_BRK_003",
|
||||
"client": "ENT_00017 某贸易公司",
|
||||
"opc": "待匹配",
|
||||
"amount": "¥8,000",
|
||||
"source": "平台撮合",
|
||||
"status": [
|
||||
"待撮合",
|
||||
"warn"
|
||||
]
|
||||
}
|
||||
],
|
||||
"policyTracking": [
|
||||
{
|
||||
"policy": "算力券补贴",
|
||||
"applied": 268,
|
||||
"approved": 240,
|
||||
"used": 186,
|
||||
"status": [
|
||||
"执行中",
|
||||
"ok"
|
||||
]
|
||||
},
|
||||
{
|
||||
"policy": "创业担保贷款",
|
||||
"applied": 48,
|
||||
"approved": 35,
|
||||
"used": 32,
|
||||
"status": [
|
||||
"执行中",
|
||||
"ok"
|
||||
]
|
||||
},
|
||||
{
|
||||
"policy": "园区租金减免",
|
||||
"applied": 120,
|
||||
"approved": 110,
|
||||
"used": 110,
|
||||
"status": [
|
||||
"执行中",
|
||||
"ok"
|
||||
]
|
||||
},
|
||||
{
|
||||
"policy": "灵活就业社保补贴",
|
||||
"applied": 198,
|
||||
"approved": 185,
|
||||
"used": 180,
|
||||
"status": [
|
||||
"执行中",
|
||||
"ok"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"audit": {
|
||||
@@ -2824,5 +3172,95 @@
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"team": {
|
||||
"myTeams": [
|
||||
{
|
||||
"code": "TEAM_0001",
|
||||
"name": "跨境电商视觉组",
|
||||
"leader": "OPC_00017 张设计",
|
||||
"members": 5,
|
||||
"openings": 2,
|
||||
"status": [
|
||||
"招募中",
|
||||
"warn"
|
||||
],
|
||||
"direction": "跨境电商视觉"
|
||||
},
|
||||
{
|
||||
"code": "TEAM_0002",
|
||||
"name": "AI 漫剧协作组",
|
||||
"leader": "OPC_00031 王编",
|
||||
"members": 3,
|
||||
"openings": 1,
|
||||
"status": [
|
||||
"招募中",
|
||||
"warn"
|
||||
],
|
||||
"direction": "AI 漫剧"
|
||||
}
|
||||
],
|
||||
"recruitList": [
|
||||
{
|
||||
"code": "REC_0001",
|
||||
"team": "TEAM_0001 跨境电商视觉组",
|
||||
"role": "详情页设计",
|
||||
"level": "L2+",
|
||||
"count": 2,
|
||||
"budget": "¥600-1200/单",
|
||||
"status": [
|
||||
"开放",
|
||||
"ok"
|
||||
]
|
||||
},
|
||||
{
|
||||
"code": "REC_0002",
|
||||
"team": "TEAM_0002 AI 漫剧协作组",
|
||||
"role": "分镜+上色",
|
||||
"level": "L1+",
|
||||
"count": 1,
|
||||
"budget": "¥300-500/集",
|
||||
"status": [
|
||||
"开放",
|
||||
"ok"
|
||||
]
|
||||
},
|
||||
{
|
||||
"code": "REC_0003",
|
||||
"team": "TEAM_0003 硬件供应链组",
|
||||
"role": "工业设计",
|
||||
"level": "L2+",
|
||||
"count": 1,
|
||||
"budget": "¥800-1500/项",
|
||||
"status": [
|
||||
"开放",
|
||||
"ok"
|
||||
]
|
||||
}
|
||||
],
|
||||
"collabList": [
|
||||
{
|
||||
"code": "COL_0001",
|
||||
"name": "品牌视觉升级分包",
|
||||
"leader": "OPC_00017",
|
||||
"parts": 3,
|
||||
"budget": "¥24,000",
|
||||
"status": [
|
||||
"进行中",
|
||||
"info"
|
||||
]
|
||||
},
|
||||
{
|
||||
"code": "COL_0002",
|
||||
"name": "漫剧 12 集协同",
|
||||
"leader": "OPC_00031",
|
||||
"parts": 4,
|
||||
"budget": "¥96,000",
|
||||
"status": [
|
||||
"招募中",
|
||||
"warn"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@
|
||||
* mock.json 结构升级时提升 SCHEMA_VER 使旧存档失效。
|
||||
*/
|
||||
|
||||
const SCHEMA_VER = 4;
|
||||
const SCHEMA_VER = 5;
|
||||
const DB_KEY = 'opc_demo_db';
|
||||
|
||||
let DB = null;
|
||||
|
||||
+119
@@ -51,6 +51,50 @@
|
||||
<div class="card"><table id="pool-tbl"></table></div>
|
||||
</div>
|
||||
|
||||
<!-- REQ-128 抢单订单池 -->
|
||||
<div class="section">
|
||||
<h2>抢单订单池 <span class="req">REQ-128/129 · 标准化任务公开抢单 · 先到先得</span></h2>
|
||||
<div class="card"><table id="grab-tbl"></table></div>
|
||||
<p class="muted" style="margin-top:8px">运营商将标准化任务放入抢单池,OPC 按 SOP 标准自主抢单;抢单后锁定 30 分钟内确认接单,超时释放回池。</p>
|
||||
</div>
|
||||
|
||||
<!-- REQ-124/125 政策落地:算力券 + 贷款 + 租金 -->
|
||||
<div class="section">
|
||||
<h2>政策落地 · 算力券 / 贷款 / 租金 <span class="req">REQ-124/125 · 全链路可见</span></h2>
|
||||
<div class="three-col" style="display:grid;grid-template-columns:repeat(3,1fr);gap:16px">
|
||||
<div class="card">
|
||||
<h3>算力券申领与核销 <span class="req">REQ-124</span></h3>
|
||||
<p class="muted">余额 <b id="vc-bal">¥8,000</b> / ¥10,000</p>
|
||||
<table id="vc-tbl" style="margin-top:8px"></table>
|
||||
<button class="btn sm" style="margin-top:8px" onclick="applyCompute()">申领算力券</button>
|
||||
</div>
|
||||
<div class="card">
|
||||
<h3>贷款支持 <span class="req">REQ-125</span></h3>
|
||||
<table id="loan-tbl"></table>
|
||||
<button class="btn sm" style="margin-top:8px" onclick="applyLoan()">申请贷款</button>
|
||||
</div>
|
||||
<div class="card">
|
||||
<h3>租金补贴</h3>
|
||||
<table id="rent-tbl"></table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- REQ-127 OPC 财务分析 -->
|
||||
<div class="section">
|
||||
<h2>财务分析 <span class="req">REQ-127 · 接单收入 - 算力 - 社保 = 净收益</span></h2>
|
||||
<div class="two-col">
|
||||
<div class="card">
|
||||
<h3>本月收支概览</h3>
|
||||
<table id="fin-tbl"></table>
|
||||
</div>
|
||||
<div class="card">
|
||||
<h3>财务建议</h3>
|
||||
<ul class="list" id="fin-suggest"></ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- REQ-043/046 收入与结算 -->
|
||||
<div class="section">
|
||||
<h2>收入与结算 <span class="req">REQ-043/046 · 分账核算 + 保证金托管</span></h2>
|
||||
@@ -118,6 +162,9 @@ function renderPage(DB) {
|
||||
<p class="muted" style="margin-top:6px">${c.next}</p>`;
|
||||
|
||||
renderPool();
|
||||
renderGrab();
|
||||
renderPolicySupport();
|
||||
renderFinance();
|
||||
document.getElementById('stl-summary').innerHTML = O.settlement.summary.map(s => LI(s[0], s[1])).join('');
|
||||
document.getElementById('stl-tbl').innerHTML =
|
||||
`<tr><th>结算单</th><th>关联订单</th><th>金额</th><th>状态</th></tr>` +
|
||||
@@ -252,6 +299,78 @@ function verifyCert() {
|
||||
</table>`,
|
||||
});
|
||||
}
|
||||
|
||||
/* === 抢单订单池 === */
|
||||
function renderGrab() {
|
||||
const pool = DB.opc.grabPool || [];
|
||||
document.getElementById('grab-tbl').innerHTML =
|
||||
`<tr><th>订单号</th><th>类型</th><th>交付物</th><th>预算</th><th>截止</th><th>SOP</th><th>已抢单/上限</th><th>状态</th><th>操作</th></tr>` +
|
||||
pool.map((o, i) => `<tr>
|
||||
<td>${o.id}</td><td>${B(o.type)}</td><td>${o.items}</td><td>${o.budget}</td><td>${o.ddl}</td>
|
||||
<td><code>${o.sop}</code></td><td>${o.count}</td><td>${B(o.status)}</td>
|
||||
<td>${o.status[1] === 'ok' ? `<button class="btn sm" onclick="grabOrder(${i})">立即抢单</button>` : '<span class="muted">已满</span>'}</td>
|
||||
</tr>`).join('');
|
||||
}
|
||||
function grabOrder(i) {
|
||||
const o = DB.opc.grabPool[i];
|
||||
confirmDlg('抢单确认', `${o.items} · ${o.budget} · 截止 ${o.ddl}。抢单后 30 分钟内确认接单,超时释放。`, '确认抢单', () => {
|
||||
toast('抢单成功!请在 30 分钟内确认接单,否则任务释放回池');
|
||||
o.count = o.count.split('/')[0] + '/' + o.count.split('/')[1];
|
||||
const cur = parseInt(o.count) + 1;
|
||||
o.count = cur + '/' + o.count.split('/')[1];
|
||||
if (cur >= parseInt(o.count.split('/')[1])) o.status = ['已满', 'gray'];
|
||||
renderGrab();
|
||||
});
|
||||
}
|
||||
|
||||
/* === 政策落地 === */
|
||||
function renderPolicySupport() {
|
||||
const P = DB.opc.policySupport;
|
||||
if (!P) return;
|
||||
// 算力券
|
||||
document.getElementById('vc-bal').textContent = `¥${P.compute.balance.toLocaleString()}`;
|
||||
document.getElementById('vc-tbl').innerHTML =
|
||||
`<tr><th>券号</th><th>金额</th><th>关联</th><th>状态</th></tr>` +
|
||||
P.compute.records.map(r => `<tr><td>${r.code}</td><td>${r.amount}</td><td class="muted">${r.target}</td><td>${B(r.status)}</td></tr>`).join('');
|
||||
// 贷款
|
||||
document.getElementById('loan-tbl').innerHTML =
|
||||
`<tr><th>编号</th><th>类型</th><th>金额</th><th>利率</th><th>状态</th></tr>` +
|
||||
P.loan.records.map(r => `<tr><td>${r.code}</td><td>${r.type}</td><td>${r.amount}</td><td>${r.rate}</td><td>${B(r.status)}</td></tr>`).join('');
|
||||
// 租金
|
||||
document.getElementById('rent-tbl').innerHTML =
|
||||
`<tr><th>编号</th><th>类型</th><th>金额</th><th>状态</th></tr>` +
|
||||
P.rent.records.map(r => `<tr><td>${r.code}</td><td>${r.type}</td><td>${r.amount}</td><td>${B(r.status)}</td></tr>`).join('');
|
||||
}
|
||||
function applyCompute() {
|
||||
confirmDlg('申领算力券', '按细则可申领 ≤¥10,000/年。当前余额 ¥8,000,可追加申领 ¥2,000。', '确认申领', () => {
|
||||
toast('算力券申领已提交,经信局审核后发放至券台账');
|
||||
});
|
||||
}
|
||||
function applyLoan() {
|
||||
openModal({
|
||||
title: '申请贷款支持',
|
||||
body: `<div class="field"><label>贷款类型</label><select><option>创业担保贷款(政府贴息 2%)</option><option>算力信用贷(年化 3.85%)</option><option>经营性贷款(年化 4.5%)</option></select></div>
|
||||
<div class="field-row"><div class="field"><label>申请额度</label><input placeholder="如:¥20 万"></div>
|
||||
<div class="field"><label>期限</label><select><option>6 个月</option><option selected>12 个月</option><option>24 个月</option></select></div></div>
|
||||
<p class="muted">贷款申请将关联 OPC 信用档案与订单收入流水,运营商初审后推送合作金融机构。</p>`,
|
||||
actions: [
|
||||
{ label: '取消', cls: 'ghost' },
|
||||
{ label: '提交申请', onClick: m => { m.remove(); toast('贷款申请已提交,运营商初审中'); } },
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
/* === 财务分析 === */
|
||||
function renderFinance() {
|
||||
const F = DB.opc.finance;
|
||||
if (!F) return;
|
||||
document.getElementById('fin-tbl').innerHTML =
|
||||
`<tr><th>项目</th><th>金额</th><th>占比</th><th>说明</th></tr>` +
|
||||
`<tr><td><b>接单收入</b></td><td><b>${F.income.total}</b></td><td>—</td><td>${F.income.orders} 单 · 均 ${F.income.avg}</td></tr>` +
|
||||
F.costs.map(c => `<tr><td>${c.item}</td><td style="color:var(--danger)">-${c.amount}</td><td>${c.pct || '—'}%</td><td class="muted">${c.detail}</td></tr>`).join('') +
|
||||
`<tr style="border-top:2px solid var(--primary)"><td><b>净收益</b></td><td><b style="color:var(--success)">${F.net}</b></td><td>—</td><td>税后</td></tr>`;
|
||||
document.getElementById('fin-suggest').innerHTML = F.suggestions.map(s => `<li><span>${s}</span></li>`).join('');
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -28,6 +28,31 @@
|
||||
<div class="card"><table id="op-audits"></table></div>
|
||||
</div>
|
||||
|
||||
<!-- 活动管理(REQ-122/123) -->
|
||||
<div class="section">
|
||||
<h2>活动管理 <span class="req">REQ-122/123 · 创建/发布/报名 · 关联线索转化</span>
|
||||
<span style="margin-left:auto"><button class="btn sm" onclick="createActivity()">创建活动</button></span>
|
||||
</h2>
|
||||
<div class="card"><table id="op-acts"></table></div>
|
||||
<p class="muted" style="margin-top:8px">活动 → 线索 → 订单转化链路(REQ-096/097)。每场活动关联后续线索与订单转化。</p>
|
||||
</div>
|
||||
|
||||
<!-- 政策落地跟踪(REQ-126) -->
|
||||
<div class="section">
|
||||
<h2>政策落地跟踪 <span class="req">REQ-126 · 算力券/贷款/租金/社保 · 全链路</span></h2>
|
||||
<div class="card"><table id="op-policy"></table></div>
|
||||
<p class="muted" style="margin-top:8px">运营商跟踪政策落地进度:申请 → 审批 → 使用 → 绩效。数据脱敏同步政府驾驶舱。</p>
|
||||
</div>
|
||||
|
||||
<!-- 平台撮合订单归集(REQ-130) -->
|
||||
<div class="section">
|
||||
<h2>平台撮合订单归集 <span class="req">REQ-130 · 平台介入撮合 · 统一归集</span>
|
||||
<span style="margin-left:auto"><button class="btn sm" onclick="brokerOrder()">录入撮合订单</button></span>
|
||||
</h2>
|
||||
<div class="card"><table id="op-broker"></table></div>
|
||||
<p class="muted" style="margin-top:8px">平台介入撮合的订单手动录入或批量导入,标注来源为"平台撮合",走统一订单状态机和结算流程。</p>
|
||||
</div>
|
||||
|
||||
<!-- 项目总览 -->
|
||||
<div class="section">
|
||||
<h2>进行中项目 <span class="req">REQ-031/036 · 运营商统一拆单与质检</span></h2>
|
||||
@@ -60,6 +85,9 @@ function renderPage(DB) {
|
||||
`<div class="card"><h3>${s.label}</h3><div class="num">${s.num}</div><p class="muted">${s.sub}</p></div>`).join('');
|
||||
renderBizDirections();
|
||||
renderAudits();
|
||||
renderActivities();
|
||||
renderPolicyTracking();
|
||||
renderBrokerOrders();
|
||||
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('');
|
||||
@@ -150,6 +178,114 @@ function arbitrate(i) {
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
/* === 活动管理 === */
|
||||
function renderActivities() {
|
||||
const acts = DB.operator.activities || [];
|
||||
document.getElementById('op-acts').innerHTML =
|
||||
`<tr><th>活动号</th><th>名称</th><th>日期</th><th>报名</th><th>容量</th><th>转化线索</th><th>状态</th><th>操作</th></tr>` +
|
||||
acts.map((a, i) => `<tr>
|
||||
<td>${a.code}</td><td>${a.name}</td><td>${a.date}</td>
|
||||
<td>${a.signups}</td><td>${a.capacity}</td><td>${a.leads}</td><td>${B(a.status)}</td>
|
||||
<td><button class="btn sm ghost" onclick="actDetail(${i})">详情</button> <button class="btn sm ghost" onclick="actSignups(${i})">报名</button></td>
|
||||
</tr>`).join('');
|
||||
}
|
||||
function createActivity() {
|
||||
openModal({
|
||||
title: '创建活动(REQ-122)',
|
||||
body: `<div class="field"><label>活动名称</label><input placeholder="如:供需对接会 · 智能体专场"></div>
|
||||
<div class="field-row">
|
||||
<div class="field"><label>日期</label><input type="date"></div>
|
||||
<div class="field"><label>容量</label><input value="80"></div>
|
||||
</div>
|
||||
<div class="field"><label>活动介绍</label><textarea placeholder="活动主题、目标受众、议程安排"></textarea></div>
|
||||
<div class="field"><label>关联业务方向</label><select><option>跨境电商视觉</option><option>AI 漫剧</option><option>企业智能体</option><option>华强北硬件供应链</option><option>综合</option></select></div>`,
|
||||
actions: [
|
||||
{ label: '取消', cls: 'ghost' },
|
||||
{ label: '发布活动', onClick: m => { m.remove(); toast('活动已发布,进入报名阶段(REQ-122)'); } },
|
||||
],
|
||||
});
|
||||
}
|
||||
function actDetail(i) {
|
||||
const a = DB.operator.activities[i];
|
||||
openModal({
|
||||
title: a.name,
|
||||
body: `<table>
|
||||
<tr><th>活动号</th><td>${a.code}</td></tr>
|
||||
<tr><th>日期</th><td>${a.date}</td></tr>
|
||||
<tr><th>报名</th><td>${a.signups} / ${a.capacity}</td></tr>
|
||||
<tr><th>转化线索</th><td>${a.leads} 条(REQ-096)</td></tr>
|
||||
<tr><th>状态</th><td>${B(a.status)}</td></tr>
|
||||
</table>`,
|
||||
});
|
||||
}
|
||||
function actSignups(i) {
|
||||
const a = DB.operator.activities[i];
|
||||
openModal({
|
||||
title: '报名管理 · ' + a.name,
|
||||
body: `<p class="muted">已报名 ${a.signups} 人,容量 ${a.capacity} 人</p>
|
||||
<table>
|
||||
<tr><th>OPC/企业</th><th>报名时间</th><th>状态</th></tr>
|
||||
<tr><td>OPC_00017 张设计</td><td>09-10 14:30</td><td><span class="badge ok">已确认</span></td></tr>
|
||||
<tr><td>OPC_00045 陈视觉</td><td>09-11 09:15</td><td><span class="badge ok">已确认</span></td></tr>
|
||||
<tr><td>ENT_00009 某科技公司</td><td>09-12 10:00</td><td><span class="badge info">待确认</span></td></tr>
|
||||
</table>`,
|
||||
actions: [{ label: '关闭', cls: 'ghost' }],
|
||||
});
|
||||
}
|
||||
|
||||
/* === 政策落地跟踪 === */
|
||||
function renderPolicyTracking() {
|
||||
const tracks = DB.operator.policyTracking || [];
|
||||
document.getElementById('op-policy').innerHTML =
|
||||
`<tr><th>政策</th><th>申请数</th><th>已审批</th><th>已使用</th><th>执行率</th><th>状态</th></tr>` +
|
||||
tracks.map(t => {
|
||||
const rate = Math.round(t.used / t.applied * 100);
|
||||
return `<tr><td><b>${t.policy}</b></td><td>${t.applied}</td><td>${t.approved}</td><td>${t.used}</td><td>${BAR(rate, 'ok')}</td><td>${B(t.status)}</td></tr>`;
|
||||
}).join('');
|
||||
}
|
||||
|
||||
/* === 平台撮合订单归集 === */
|
||||
function renderBrokerOrders() {
|
||||
const orders = DB.operator.brokerOrders || [];
|
||||
document.getElementById('op-broker').innerHTML =
|
||||
`<tr><th>订单号</th><th>客户</th><th>OPC</th><th>金额</th><th>来源</th><th>状态</th><th>操作</th></tr>` +
|
||||
orders.map((o, i) => `<tr>
|
||||
<td>${o.code}</td><td>${o.client}</td><td>${o.opc}</td><td>${o.amount}</td>
|
||||
<td><span class="badge pri">${o.source}</span></td><td>${B(o.status)}</td>
|
||||
<td><button class="btn sm ghost" onclick="brokerDetail(${i})">详情</button></td>
|
||||
</tr>`).join('');
|
||||
}
|
||||
function brokerOrder() {
|
||||
openModal({
|
||||
title: '录入撮合订单(REQ-130)',
|
||||
body: `<div class="field"><label>客户</label><input placeholder="如:ENT_00018 某公司"></div>
|
||||
<div class="field"><label>OPC</label><input placeholder="如:OPC_00017 张设计"></div>
|
||||
<div class="field-row">
|
||||
<div class="field"><label>金额</label><input placeholder="如:¥15,000"></div>
|
||||
<div class="field"><label>来源</label><select><option>平台撮合</option><option>线下转介</option><option>政府推荐</option></select></div>
|
||||
</div>
|
||||
<div class="field"><label>备注</label><textarea placeholder="撮合过程说明"></textarea></div>
|
||||
<p class="muted">录入后走统一订单状态机(签约→进行中→验收→结算),数据自动归集到政府驾驶舱。</p>`,
|
||||
actions: [
|
||||
{ label: '取消', cls: 'ghost' },
|
||||
{ label: '录入', onClick: m => { m.remove(); toast('撮合订单已录入,进入订单状态机'); } },
|
||||
],
|
||||
});
|
||||
}
|
||||
function brokerDetail(i) {
|
||||
const o = DB.operator.brokerOrders[i];
|
||||
openModal({
|
||||
title: '撮合订单详情 · ' + o.code,
|
||||
body: `<table>
|
||||
<tr><th>客户</th><td>${o.client}</td></tr>
|
||||
<tr><th>OPC</th><td>${o.opc}</td></tr>
|
||||
<tr><th>金额</th><td>${o.amount}</td></tr>
|
||||
<tr><th>来源</th><td>${o.source}</td></tr>
|
||||
<tr><th>状态</th><td>${B(o.status)}</td></tr>
|
||||
</table>`,
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -62,6 +62,7 @@ function renderPage(DB) {
|
||||
const role = currentRole();
|
||||
document.getElementById('svc-sub').textContent =
|
||||
role === 'service' ? '服务机构视图 · 资质上架、工单办理、评价与退出管理'
|
||||
: role === 'operator' ? '运营商服务资源管理 · 自营服务包 + 入驻服务商管理 + 工单分发(REQ-061~070)'
|
||||
: role === 'opc' ? '自营外包服务 + 第三方服务机构超市 · 为 OPC 提供经营支撑'
|
||||
: '自营外包服务 + 第三方服务机构超市 · 标准化服务包';
|
||||
document.getElementById('svc-catalog').innerHTML = S.catalog.map(c => `
|
||||
|
||||
+175
@@ -0,0 +1,175 @@
|
||||
<!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="team">
|
||||
<header class="topnav" id="topnav"></header>
|
||||
|
||||
<div class="container">
|
||||
<div class="page-title">组队协同</div>
|
||||
<div class="page-sub" id="team-sub"></div>
|
||||
|
||||
<!-- 我的团队 -->
|
||||
<div class="section">
|
||||
<h2>我的团队 <span class="req">REQ-119 · 组长/组员 · 成员可流动</span>
|
||||
<span style="margin-left:auto"><button class="btn sm" onclick="createTeam()">创建团队</button></span>
|
||||
</h2>
|
||||
<div class="card"><table id="team-tbl"></table></div>
|
||||
<p class="muted" style="margin-top:8px">OPC 往往不是一人公司,分组长和组员两个角色。支持招聘组队和业务协同/分包。</p>
|
||||
</div>
|
||||
|
||||
<!-- 招聘招募 -->
|
||||
<div class="section">
|
||||
<h2>招聘招募 <span class="req">REQ-120 · 组长招人手 · 成员可流动</span>
|
||||
<span style="margin-left:auto"><button class="btn sm" onclick="postRecruit()">发布招募</button></span>
|
||||
</h2>
|
||||
<div class="card"><table id="recruit-tbl"></table></div>
|
||||
</div>
|
||||
|
||||
<!-- 协同/分包 -->
|
||||
<div class="section">
|
||||
<h2>业务协同 / 分包 <span class="req">REQ-121 · OPC 间协同或分包</span>
|
||||
<span style="margin-left:auto"><button class="btn sm" onclick="postCollab()">发布协同</button></span>
|
||||
</h2>
|
||||
<div class="card"><table id="collab-tbl"></table></div>
|
||||
<p class="muted" style="margin-top:8px">OPC 之间可基于订单进行业务协同或分包,组长统一对接客户,组员按 SOP 标准并行交付。</p>
|
||||
</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 T = DB.team || {};
|
||||
const role = currentRole();
|
||||
document.getElementById('team-sub').textContent = role === 'operator'
|
||||
? '运营商管理视角 · 查看团队组建、招募发布与协同分包'
|
||||
: '组队协同 · 招聘组队、业务协同与分包协作';
|
||||
|
||||
// 我的团队
|
||||
document.getElementById('team-tbl').innerHTML =
|
||||
`<tr><th>团队号</th><th>名称</th><th>组长</th><th>方向</th><th>成员</th><th>空缺</th><th>状态</th><th>操作</th></tr>` +
|
||||
(T.myTeams || []).map((t, i) => `<tr>
|
||||
<td>${t.code}</td><td><b>${t.name}</b></td><td>${t.leader}</td><td>${t.direction}</td>
|
||||
<td>${t.members} 人</td><td>${t.openings > 0 ? `<span class="badge warn">${t.openings} 个</span>` : '<span class="badge ok">满员</span>'}</td>
|
||||
<td>${B(t.status)}</td>
|
||||
<td><button class="btn sm ghost" onclick="teamDetail(${i})">管理</button></td>
|
||||
</tr>`).join('');
|
||||
|
||||
// 招聘招募
|
||||
document.getElementById('recruit-tbl').innerHTML =
|
||||
`<tr><th>招募号</th><th>团队</th><th>角色</th><th>等级要求</th><th>人数</th><th>预算</th><th>状态</th><th>操作</th></tr>` +
|
||||
(T.recruitList || []).map((r, i) => `<tr>
|
||||
<td>${r.code}</td><td>${r.team}</td><td>${r.role}</td><td><span class="badge pri">${r.level}</span></td>
|
||||
<td>${r.count} 人</td><td>${r.budget}</td><td>${B(r.status)}</td>
|
||||
<td><button class="btn sm" onclick="applyRecruit(${i})">申请加入</button></td>
|
||||
</tr>`).join('');
|
||||
|
||||
// 协同/分包
|
||||
document.getElementById('collab-tbl').innerHTML =
|
||||
`<tr><th>协同号</th><th>名称</th><th>组长</th><th>分包数</th><th>预算</th><th>状态</th><th>操作</th></tr>` +
|
||||
(T.collabList || []).map((c, i) => `<tr>
|
||||
<td>${c.code}</td><td><b>${c.name}</b></td><td>${c.leader}</td><td>${c.parts} 份</td>
|
||||
<td>${c.budget}</td><td>${B(c.status)}</td>
|
||||
<td><button class="btn sm" onclick="joinCollab(${i})">参与分包</button></td>
|
||||
</tr>`).join('');
|
||||
}
|
||||
|
||||
function createTeam() {
|
||||
openModal({
|
||||
title: '创建团队(REQ-119)',
|
||||
body: `<div class="field"><label>团队名称</label><input placeholder="如:智能体开发协作组"></div>
|
||||
<div class="field-row">
|
||||
<div class="field"><label>业务方向</label><select><option>跨境电商视觉</option><option>AI 漫剧</option><option>企业智能体</option><option>华强北硬件供应链</option></select></div>
|
||||
<div class="field"><label>招募人数</label><input value="3"></div>
|
||||
</div>
|
||||
<div class="field"><label>团队简介</label><textarea placeholder="团队定位、目标客户、分工模式"></textarea></div>
|
||||
<p class="muted">创建后你将成为组长,可在招募区发布岗位需求。</p>`,
|
||||
actions: [
|
||||
{ label: '取消', cls: 'ghost' },
|
||||
{ label: '创建团队', onClick: m => { m.remove(); toast('团队已创建,可在招募区发布岗位'); } },
|
||||
],
|
||||
});
|
||||
}
|
||||
function postRecruit() {
|
||||
openModal({
|
||||
title: '发布招募(REQ-120)',
|
||||
body: `<div class="field"><label>所属团队</label><select><option>TEAM_0001 跨境电商视觉组</option><option>TEAM_0002 AI 漫剧协作组</option></select></div>
|
||||
<div class="field-row">
|
||||
<div class="field"><label>角色</label><input placeholder="如:详情页设计"></div>
|
||||
<div class="field"><label>等级要求</label><select><option>L1+</option><option>L2+</option><option>L3+</option></select></div>
|
||||
</div>
|
||||
<div class="field-row">
|
||||
<div class="field"><label>人数</label><input value="2"></div>
|
||||
<div class="field"><label>预算</label><input placeholder="如:¥600-1200/单"></div>
|
||||
</div>
|
||||
<div class="field"><label>要求说明</label><textarea placeholder="技能要求、交付标准、协作方式"></textarea></div>`,
|
||||
actions: [
|
||||
{ label: '取消', cls: 'ghost' },
|
||||
{ label: '发布', onClick: m => { m.remove(); toast('招募已发布,OPC 可申请加入'); } },
|
||||
],
|
||||
});
|
||||
}
|
||||
function postCollab() {
|
||||
openModal({
|
||||
title: '发布协同/分包(REQ-121)',
|
||||
body: `<div class="field"><label>协同名称</label><input placeholder="如:品牌视觉升级分包"></div>
|
||||
<div class="field-row">
|
||||
<div class="field"><label>分包数</label><input value="3"></div>
|
||||
<div class="field"><label>总预算</label><input placeholder="如:¥24,000"></div>
|
||||
</div>
|
||||
<div class="field"><label>分包说明</label><textarea placeholder="各分包任务、SOP 标准、交付节点"></textarea></div>
|
||||
<p class="muted">协同/分包基于蜂群式交付模式,各分包按统一 SOP 标准并行执行。</p>`,
|
||||
actions: [
|
||||
{ label: '取消', cls: 'ghost' },
|
||||
{ label: '发布', onClick: m => { m.remove(); toast('协同分包已发布,OPC 可参与分包'); } },
|
||||
],
|
||||
});
|
||||
}
|
||||
function teamDetail(i) {
|
||||
const t = DB.team.myTeams[i];
|
||||
openModal({
|
||||
title: '团队管理 · ' + t.name,
|
||||
body: `<table>
|
||||
<tr><th>团队号</th><td>${t.code}</td></tr>
|
||||
<tr><th>组长</th><td>${t.leader}</td></tr>
|
||||
<tr><th>方向</th><td>${t.direction}</td></tr>
|
||||
<tr><th>成员</th><td>${t.members} 人 · 空缺 ${t.openings}</td></tr>
|
||||
</table>
|
||||
<h4 style="margin-top:12px">成员列表</h4>
|
||||
<table>
|
||||
<tr><th>OPC</th><th>角色</th><th>状态</th></tr>
|
||||
<tr><td>OPC_00017 张设计</td><td>组长</td><td><span class="badge ok">在职</span></td></tr>
|
||||
<tr><td>OPC_00045 陈视觉</td><td>组员</td><td><span class="badge ok">在职</span></td></tr>
|
||||
<tr><td>OPC_00052 赵图</td><td>组员</td><td><span class="badge warn">流动中</span></td></tr>
|
||||
</table>
|
||||
<p class="muted" style="margin-top:8px">成员可流动:离职后任务自动转派替补,不影响整体交付。</p>`,
|
||||
actions: [{ label: '关闭', cls: 'ghost' }],
|
||||
});
|
||||
}
|
||||
function applyRecruit(i) {
|
||||
const r = DB.team.recruitList[i];
|
||||
confirmDlg('申请加入', `${r.team} · ${r.role} · ${r.budget}。申请后组长审核你的能力档案。`, '确认申请', () => {
|
||||
toast('申请已提交,组长审核能力档案后通知');
|
||||
});
|
||||
}
|
||||
function joinCollab(i) {
|
||||
const c = DB.team.collabList[i];
|
||||
openModal({
|
||||
title: '参与分包 · ' + c.name,
|
||||
body: `<div class="field"><label>选择分包</label><select><option>分包 1 · 首页设计 ¥8,000</option><option>分包 2 · 详情页 ¥10,000</option><option>分包 3 · Banner ¥6,000</option></select></div>
|
||||
<div class="field"><label>交付说明</label><textarea placeholder="交付计划、排产说明"></textarea></div>`,
|
||||
actions: [
|
||||
{ label: '取消', cls: 'ghost' },
|
||||
{ label: '参与', onClick: m => { m.remove(); toast('已参与分包,进入蜂群交付队列'); } },
|
||||
],
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user