feat(xingbang): 兴邦金租 AI 评审平台前端页面(深色商务风)
- 独立路由 /xingbang: 兴邦评审工作台 - 五智能体流水线可视化(状态动画: 排队/运行/成功/失败) - 评审任务表单(客户/金额/租赁物) + SSE 实时进度 - 审批结论卡片(五智能体产出) + 自进化洞察面板 - Navbar 加兴邦评审入口, 支持返回聊天 - 深色商务风 (渐变背景/玻璃拟态/金蓝主题) - api.ts 新增兴邦 API 调用(workflow/evolution/trajectories) 前端已在 next dev 验证渲染 OK, 后端 API 就绪(7条轨迹样本)
This commit is contained in:
@@ -254,3 +254,80 @@ export async function setRagMode(
|
||||
if (!resp.ok) throw new Error(`Failed to set RAG mode: ${resp.status}`);
|
||||
return resp.json();
|
||||
}
|
||||
|
||||
/* ── 兴邦金租评审平台 API ───────────────────────────── */
|
||||
|
||||
/** 兴邦项目配置(数据源/五智能体/档位)。 */
|
||||
export async function getXingbangConfig(): Promise<any> {
|
||||
const resp = await fetch(`${API_BASE}/xingbang/config`);
|
||||
if (!resp.ok) throw new Error(`Xingbang config error: ${resp.status}`);
|
||||
return resp.json();
|
||||
}
|
||||
|
||||
/**
|
||||
* 流式运行兴邦五智能体审批流水线(SSE)。
|
||||
* 逐步 yield: agent_start / agent_end / done。
|
||||
*/
|
||||
export async function* streamXingbangWorkflow(
|
||||
task: string,
|
||||
customer: string
|
||||
): AsyncGenerator<SSEEvent> {
|
||||
const response = await fetch(`${API_BASE}/xingbang/workflow/stream`, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ task, customer }),
|
||||
});
|
||||
if (!response.ok) throw new Error(`Xingbang workflow error: ${response.status}`);
|
||||
const reader = response.body?.getReader();
|
||||
if (!reader) throw new Error("No response body");
|
||||
const decoder = new TextDecoder();
|
||||
let buffer = "";
|
||||
|
||||
while (true) {
|
||||
const { done, value } = await reader.read();
|
||||
if (done) break;
|
||||
buffer += decoder.decode(value, { stream: true });
|
||||
const lines = buffer.split("\n");
|
||||
buffer = lines.pop() || "";
|
||||
let currentEvent = "message";
|
||||
for (const line of lines) {
|
||||
if (line.startsWith("event:")) {
|
||||
currentEvent = line.slice(6).trim();
|
||||
} else if (line.startsWith("data:")) {
|
||||
const dataStr = line.slice(5).trim();
|
||||
if (dataStr) {
|
||||
try {
|
||||
yield { event: currentEvent, data: JSON.parse(dataStr) };
|
||||
} catch {
|
||||
/* skip */
|
||||
}
|
||||
}
|
||||
}
|
||||
if (line === "") currentEvent = "message";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** 兴邦自进化洞察。 */
|
||||
export async function getXingbangEvolution(): Promise<any> {
|
||||
const resp = await fetch(`${API_BASE}/xingbang/evolution`);
|
||||
if (!resp.ok) throw new Error(`Xingbang evolution error: ${resp.status}`);
|
||||
return resp.json();
|
||||
}
|
||||
|
||||
/** 兴邦历史轨迹列表。 */
|
||||
export async function listXingbangTrajectories(): Promise<any> {
|
||||
const resp = await fetch(`${API_BASE}/xingbang/trajectories`);
|
||||
if (!resp.ok) throw new Error(`Xingbang trajectories error: ${resp.status}`);
|
||||
return resp.json();
|
||||
}
|
||||
|
||||
/** 读取单条兴邦轨迹。 */
|
||||
export async function getXingbangTrajectory(id: string): Promise<any> {
|
||||
const resp = await fetch(
|
||||
`${API_BASE}/xingbang/trajectories/${encodeURIComponent(id)}`
|
||||
);
|
||||
if (!resp.ok) throw new Error(`Xingbang trajectory error: ${resp.status}`);
|
||||
return resp.json();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user