You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
202 lines
8.6 KiB
202 lines
8.6 KiB
|
2 weeks ago
|
<!DOCTYPE html>
|
||
|
|
<html lang="zh-CN">
|
||
|
|
<head>
|
||
|
|
<meta charset="UTF-8">
|
||
|
|
<title>03 列表族实测</title>
|
||
|
|
<style>
|
||
|
|
body { font-family: system-ui, sans-serif; padding: 20px; background: #f5f5f5; max-width: 1100px; }
|
||
|
|
h1 { font-size: 1.2rem; }
|
||
|
|
h2 { font-size: 1rem; margin-top: 28px; border-left: 4px solid #1976d2; padding-left: 8px; }
|
||
|
|
button { padding: 6px 14px; font-size: 13px; cursor: pointer;
|
||
|
|
background: #1976d2; color: #fff; border: none; border-radius: 4px; margin-right: 6px; }
|
||
|
|
button.run-all { background: #388e3c; font-size: 14px; padding: 8px 20px; margin-bottom: 16px; }
|
||
|
|
pre { background: #fff; border: 1px solid #ddd; border-radius: 4px;
|
||
|
|
padding: 12px; font-size: 11px; white-space: pre-wrap; max-height: 300px; overflow-y: auto; }
|
||
|
|
ul.assertions { list-style: none; padding: 0; margin: 6px 0; }
|
||
|
|
ul.assertions li { font-size: 13px; padding: 2px 0; }
|
||
|
|
.case { background: #fff; border: 1px solid #ddd; border-radius: 6px;
|
||
|
|
padding: 14px; margin-top: 14px; }
|
||
|
|
.case h3 { margin: 0 0 8px; font-size: 13px; color: #333; }
|
||
|
|
a.back { font-size: 13px; color: #1976d2; }
|
||
|
|
</style>
|
||
|
|
</head>
|
||
|
|
<body>
|
||
|
|
<a class="back" href="index.html">← 返回首页</a>
|
||
|
|
<h1>🗒 03 列表族实测</h1>
|
||
|
|
<p>对应 spec-endpoints.md「列表」子域 6 条接口</p>
|
||
|
|
|
||
|
|
<button class="run-all" onclick="runAll()">▶ 全部运行</button>
|
||
|
|
|
||
|
|
<!-- ① POST /api/opportunity/page (viewType=MINE) -->
|
||
|
|
<div class="case" id="case-mine">
|
||
|
|
<h3>① POST /api/opportunity/page — viewType=MINE(我负责的)</h3>
|
||
|
|
<button onclick="runMine()">运行</button>
|
||
|
|
<ul class="assertions" id="assert-mine"></ul>
|
||
|
|
<pre id="result-mine">(待运行)</pre>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<!-- ② POST /api/opportunity/page (viewType=RECENT) -->
|
||
|
|
<div class="case" id="case-recent">
|
||
|
|
<h3>② POST /api/opportunity/page — viewType=RECENT(最近访问)</h3>
|
||
|
|
<button onclick="runRecent()">运行</button>
|
||
|
|
<ul class="assertions" id="assert-recent"></ul>
|
||
|
|
<pre id="result-recent">(待运行)</pre>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<!-- ③ POST /api/opportunity/page (viewType=PUBLIC_POOL) -->
|
||
|
|
<div class="case" id="case-pool">
|
||
|
|
<h3>③ POST /api/opportunity/page — viewType=PUBLIC_POOL(公海)</h3>
|
||
|
|
<button onclick="runPool()">运行</button>
|
||
|
|
<ul class="assertions" id="assert-pool"></ul>
|
||
|
|
<pre id="result-pool">(待运行)</pre>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<!-- ④ POST /api/opportunity/page (viewType=MANAGE) -->
|
||
|
|
<div class="case" id="case-manage">
|
||
|
|
<h3>④ POST /api/opportunity/page — viewType=MANAGE(管理列表)</h3>
|
||
|
|
<button onclick="runManage()">运行</button>
|
||
|
|
<ul class="assertions" id="assert-manage"></ul>
|
||
|
|
<pre id="result-manage">(待运行)</pre>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<!-- ⑤ POST /api/opportunity/page?viewType=RECENT — 最近访问(已合并) -->
|
||
|
|
<div class="case" id="case-rv">
|
||
|
|
<h3>⑤ POST /api/opportunity/page?viewType=RECENT — 最近访问(已合并入 /page)</h3>
|
||
|
|
<button onclick="runRecentVisits()">运行</button>
|
||
|
|
<ul class="assertions" id="assert-rv"></ul>
|
||
|
|
<pre id="result-rv">(待运行)</pre>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<!-- ⑥ POST /api/opportunity/board/stage-summary — 看板汇总 -->
|
||
|
|
<div class="case" id="case-board-summary">
|
||
|
|
<h3>⑥ POST /api/opportunity/board/stage-summary — 看板各阶段汇总(spec 预期)</h3>
|
||
|
|
<button onclick="runBoardSummary()">运行</button>
|
||
|
|
<ul class="assertions" id="assert-board-summary"></ul>
|
||
|
|
<pre id="result-board-summary">(待运行)</pre>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<!-- ⑦ POST /api/opportunity/board/cards — 看板单阶段卡片 -->
|
||
|
|
<div class="case" id="case-board-cards">
|
||
|
|
<h3>⑦ POST /api/opportunity/board/cards — 看板单阶段卡片(spec 预期)</h3>
|
||
|
|
<button onclick="runBoardCards()">运行</button>
|
||
|
|
<ul class="assertions" id="assert-board-cards"></ul>
|
||
|
|
<pre id="result-board-cards">(待运行)</pre>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<!-- ⑧ POST /api/opportunity/view-touch — 访问上报(实际路径) -->
|
||
|
|
<div class="case" id="case-touch">
|
||
|
|
<h3>⑧ POST /api/opportunity/view-touch — 访问上报</h3>
|
||
|
|
<button onclick="runTouch()">运行</button>
|
||
|
|
<ul class="assertions" id="assert-touch"></ul>
|
||
|
|
<pre id="result-touch">(待运行)</pre>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<script src="common.js"></script>
|
||
|
|
<script>
|
||
|
|
// 断言辅助(指定 ul id)
|
||
|
|
function a(ulId, label, pass, hint) {
|
||
|
|
const ul = document.getElementById(ulId);
|
||
|
|
const li = document.createElement('li');
|
||
|
|
li.style.color = pass ? '#1a7a1a' : '#b00020';
|
||
|
|
li.textContent = (pass ? '✅ ' : '❌ ') + label + (hint && !pass ? ` — ${hint}` : '');
|
||
|
|
ul.appendChild(li);
|
||
|
|
}
|
||
|
|
function clearCase(suffix) {
|
||
|
|
document.getElementById('assert-' + suffix).innerHTML = '';
|
||
|
|
document.getElementById('result-' + suffix).textContent = '运行中…';
|
||
|
|
}
|
||
|
|
|
||
|
|
// ① MINE
|
||
|
|
async function runMine() {
|
||
|
|
clearCase('mine');
|
||
|
|
const res = await apiFetch('POST', '/api/opportunity/page', { viewType: 'MINE', page: 1, size: 10 });
|
||
|
|
renderResult('result-mine', res);
|
||
|
|
a('assert-mine', 'HTTP 200', res.status === 200, `实际 ${res.status}`);
|
||
|
|
a('assert-mine', 'success=true', res.data?.success === true, JSON.stringify(res.data?.message));
|
||
|
|
const d = res.data?.data;
|
||
|
|
a('assert-mine', '返回 PageResult(含 records 字段)', Array.isArray(d?.records), `data=${JSON.stringify(d)?.slice(0,80)}`);
|
||
|
|
if (Array.isArray(d?.records) && d.records.length > 0) {
|
||
|
|
const row = d.records[0];
|
||
|
|
a('assert-mine', '行有 id 字段', !!row.id, JSON.stringify(row).slice(0,80));
|
||
|
|
a('assert-mine', '行有 name/opportunityName 字段', !!(row.name || row.opportunityName || row.projectName), JSON.stringify(row).slice(0,80));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// ② RECENT
|
||
|
|
async function runRecent() {
|
||
|
|
clearCase('recent');
|
||
|
|
const res = await apiFetch('POST', '/api/opportunity/page', { viewType: 'RECENT', page: 1, size: 10 });
|
||
|
|
renderResult('result-recent', res);
|
||
|
|
a('assert-recent', 'HTTP 200', res.status === 200, `实际 ${res.status}`);
|
||
|
|
a('assert-recent', 'success=true', res.data?.success === true, JSON.stringify(res.data?.message));
|
||
|
|
a('assert-recent', '返回 PageResult', Array.isArray(res.data?.data?.records), JSON.stringify(res.data?.data)?.slice(0,80));
|
||
|
|
}
|
||
|
|
|
||
|
|
// ③ PUBLIC_POOL
|
||
|
|
async function runPool() {
|
||
|
|
clearCase('pool');
|
||
|
|
const res = await apiFetch('POST', '/api/opportunity/page', { viewType: 'PUBLIC_POOL', page: 1, size: 10 });
|
||
|
|
renderResult('result-pool', res);
|
||
|
|
a('assert-pool', 'HTTP 200', res.status === 200, `实际 ${res.status}`);
|
||
|
|
a('assert-pool', 'success=true', res.data?.success === true, JSON.stringify(res.data?.message));
|
||
|
|
a('assert-pool', '返回 PageResult', Array.isArray(res.data?.data?.records), JSON.stringify(res.data?.data)?.slice(0,80));
|
||
|
|
}
|
||
|
|
|
||
|
|
// ④ MANAGE
|
||
|
|
async function runManage() {
|
||
|
|
clearCase('manage');
|
||
|
|
const res = await apiFetch('POST', '/api/opportunity/page', { viewType: 'MANAGE', page: 1, size: 10 });
|
||
|
|
renderResult('result-manage', res);
|
||
|
|
a('assert-manage', 'HTTP 200', res.status === 200, `实际 ${res.status}`);
|
||
|
|
a('assert-manage', 'success=true', res.data?.success === true, JSON.stringify(res.data?.message));
|
||
|
|
a('assert-manage', '返回 PageResult', Array.isArray(res.data?.data?.records), JSON.stringify(res.data?.data)?.slice(0,80));
|
||
|
|
}
|
||
|
|
|
||
|
|
// ⑤ /page?viewType=RECENT(已合并)
|
||
|
|
async function runRecentVisits() {
|
||
|
|
clearCase('rv');
|
||
|
|
const res = await apiFetch('POST', '/api/opportunity/page', { viewType: 'RECENT', pageNum: 1, pageSize: 10 });
|
||
|
|
renderResult('result-rv', res);
|
||
|
|
a('assert-rv', 'HTTP 200', res.status === 200, `实际 ${res.status}`);
|
||
|
|
a('assert-rv', 'success=true', res.data?.success === true, JSON.stringify(res.data?.message));
|
||
|
|
}
|
||
|
|
|
||
|
|
// ⑥ board/stage-summary
|
||
|
|
async function runBoardSummary() {
|
||
|
|
clearCase('board-summary');
|
||
|
|
const res = await apiFetch('POST', '/api/opportunity/board/stage-summary', {});
|
||
|
|
renderResult('result-board-summary', res);
|
||
|
|
a('assert-board-summary', 'HTTP 200(spec 预期看板汇总接口)', res.status === 200, `实际 ${res.status}`);
|
||
|
|
}
|
||
|
|
|
||
|
|
// ⑦ board/cards
|
||
|
|
async function runBoardCards() {
|
||
|
|
clearCase('board-cards');
|
||
|
|
const res = await apiFetch('POST', '/api/opportunity/board/cards', { offset: 0, limit: 5 });
|
||
|
|
renderResult('result-board-cards', res);
|
||
|
|
a('assert-board-cards', 'HTTP 200(spec 预期看板卡片接口)', res.status === 200, `实际 ${res.status}`);
|
||
|
|
}
|
||
|
|
|
||
|
|
// ⑧ /view-touch(实际路径)
|
||
|
|
async function runTouch() {
|
||
|
|
clearCase('touch');
|
||
|
|
const res = await apiFetch('POST', '/api/opportunity/view-touch', null, { oppId: '999999999001' });
|
||
|
|
renderResult('result-touch', res);
|
||
|
|
a('assert-touch', 'HTTP 200', res.status === 200, `实际 ${res.status}`);
|
||
|
|
a('assert-touch', 'success=true', res.data?.success === true, JSON.stringify(res.data?.message));
|
||
|
|
}
|
||
|
|
|
||
|
|
async function runAll() {
|
||
|
|
await runMine();
|
||
|
|
await runRecent();
|
||
|
|
await runPool();
|
||
|
|
await runManage();
|
||
|
|
await runRecentVisits();
|
||
|
|
await runBoardSummary();
|
||
|
|
await runBoardCards();
|
||
|
|
await runTouch();
|
||
|
|
}
|
||
|
|
</script>
|
||
|
|
</body>
|
||
|
|
</html>
|