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.
96 lines
3.0 KiB
96 lines
3.0 KiB
|
1 week ago
|
/**
|
||
|
|
* common.js — 商机模块接口验收公共工具
|
||
|
|
*
|
||
|
|
* 用法:在各 demo 页 <script src="../common.js"> 引入后直接调用:
|
||
|
|
* const token = await getToken();
|
||
|
|
* const res = await apiFetch('GET', '/api/opportunity/123');
|
||
|
|
* renderResult('result', res);
|
||
|
|
*/
|
||
|
|
|
||
|
|
const BASE_URL = 'http://localhost:8080';
|
||
|
|
const DEBUG_UID = '739564171091247104';
|
||
|
|
const TOKEN_KEY = 'verify_token';
|
||
|
|
|
||
|
|
/** 获取调试 token(优先读 sessionStorage 缓存,避免重复请求) */
|
||
|
|
async function getToken() {
|
||
|
|
let t = sessionStorage.getItem(TOKEN_KEY);
|
||
|
|
if (t) return t;
|
||
|
|
const r = await fetch(`${BASE_URL}/api/auth/debug/token?userId=${DEBUG_UID}`);
|
||
|
|
const j = await r.json();
|
||
|
|
t = j.data;
|
||
|
|
sessionStorage.setItem(TOKEN_KEY, t);
|
||
|
|
return t;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 发送带 token 的 HTTP 请求
|
||
|
|
* @param {string} method - GET / POST / PUT / DELETE
|
||
|
|
* @param {string} path - 以 /api/ 开头
|
||
|
|
* @param {object} [body] - JSON body(GET 时忽略)
|
||
|
|
* @param {object} [query] - URL 查询参数 key-value
|
||
|
|
* @returns {{ status, ok, data, raw, durationMs }}
|
||
|
|
*/
|
||
|
|
async function apiFetch(method, path, body, query) {
|
||
|
|
const token = await getToken();
|
||
|
|
let url = BASE_URL + path;
|
||
|
|
if (query && Object.keys(query).length) {
|
||
|
|
url += '?' + new URLSearchParams(query).toString();
|
||
|
|
}
|
||
|
|
const opts = {
|
||
|
|
method,
|
||
|
|
headers: {
|
||
|
|
'Content-Type': 'application/json',
|
||
|
|
'Authorization': `Bearer ${token}`,
|
||
|
|
},
|
||
|
|
};
|
||
|
|
if (body && method !== 'GET') {
|
||
|
|
opts.body = JSON.stringify(body);
|
||
|
|
}
|
||
|
|
const t0 = Date.now();
|
||
|
|
let raw, status, ok;
|
||
|
|
try {
|
||
|
|
const resp = await fetch(url, opts);
|
||
|
|
status = resp.status;
|
||
|
|
ok = resp.ok;
|
||
|
|
raw = await resp.text();
|
||
|
|
} catch (e) {
|
||
|
|
return { status: 0, ok: false, data: null, raw: String(e), durationMs: Date.now() - t0 };
|
||
|
|
}
|
||
|
|
let data = null;
|
||
|
|
try { data = JSON.parse(raw); } catch (_) { data = raw; }
|
||
|
|
return { status, ok, data, raw, durationMs: Date.now() - t0 };
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 把结果渲染到页面上指定 id 的 <pre> 元素
|
||
|
|
* @param {string} elementId
|
||
|
|
* @param {{ status, ok, data, durationMs }} result
|
||
|
|
*/
|
||
|
|
function renderResult(elementId, result) {
|
||
|
|
const el = document.getElementById(elementId);
|
||
|
|
if (!el) return;
|
||
|
|
const icon = result.ok ? '✅' : (result.status === 0 ? '🔴' : '⚠️');
|
||
|
|
const header = `${icon} HTTP ${result.status} (${result.durationMs} ms)\n${'─'.repeat(50)}\n`;
|
||
|
|
el.textContent = header + (
|
||
|
|
typeof result.data === 'object'
|
||
|
|
? JSON.stringify(result.data, null, 2)
|
||
|
|
: result.raw
|
||
|
|
);
|
||
|
|
el.style.color = result.ok ? '#1a7a1a' : '#b00020';
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 简单断言辅助(写入 <ul id="assertions"> 列表)
|
||
|
|
* @param {string} label - 断言说明
|
||
|
|
* @param {boolean} pass
|
||
|
|
* @param {string} [hint] - 失败时显示的附加信息
|
||
|
|
*/
|
||
|
|
function assert(label, pass, hint) {
|
||
|
|
const ul = document.getElementById('assertions');
|
||
|
|
if (!ul) return;
|
||
|
|
const li = document.createElement('li');
|
||
|
|
li.style.color = pass ? '#1a7a1a' : '#b00020';
|
||
|
|
li.textContent = (pass ? '✅ ' : '❌ ') + label + (hint && !pass ? ` — ${hint}` : '');
|
||
|
|
ul.appendChild(li);
|
||
|
|
}
|