Files
PlantAI-rag-new/frontend/src/stores/health.js
T
jerryandClaude Fable 5 1e94de7464 PlantAI-rag-new 首次提交:文献知识工作台
- BFF 薄适配层(FastAPI,8090):QA 代理/SSE 中继/Neo4j 直连/抽取代理/会话持久化
- Vue3 前端:五相位检索流水线、文献来源与证据链、知识图谱、提取任务四 tab
- 四档响应式(桌面/笔记本/平板/手机)、深浅主题
- 81 个 FR 全部实现,测试追溯矩阵 81/81,后端 121 测/前端 156 测
- 真实凭据已脱敏,运行时配置在 backend/.env(不入 git)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-25 20:47:52 +08:00

80 lines
2.9 KiB
JavaScript
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.
// stores/health.js —— B1 归属。上游健康轮询与降级状态(FR-HEALTH-001/002/003/004)。
// 数据源:GET /api/health(30s 轮询)+ GET /api/qa/info(QA 版本号)。
// 上游状态驱动各 store 的降级消费:导出 getter qaOk / neo4jOk / extractionOk。
import { defineStore } from 'pinia';
import { api } from '../api/http.js';
const HEALTH_INTERVAL = 30000;
export const useHealthStore = defineStore('health', {
state: () => ({
/** 最近一次成功轮询的 health 数据(失败时保留旧值,供降级展示) */
data: null,
/** 探活错误 */
error: null,
/** 轮询是否在运行 */
polling: false,
/** 最近成功轮询的 ISO 时间 */
lastOkAt: null,
/** /api/qa/info 结果 */
qaInfo: null,
/** 首次探测尚未返回(未知态:显示空心点而非错误) */
unknown: true,
}),
getters: {
bffOk: (s) => !!s.data && !s.error,
/** QA 上游可用(FR-HEALTH-002:不可用→作曲器禁用) */
qaOk: (s) => !!s.data && s.data.upstreams?.qa?.ok === true,
/** Neo4j 可用(FR-HEALTH-003:不可用→图谱搜索/邻域禁用) */
neo4jOk: (s) => !!s.data && s.data.upstreams?.neo4j?.ok === true,
/** 抽取上游可用(FR-HEALTH-004:8000 或 7900 任一在线) */
extractionOk: (s) => !!s.data && (s.data.upstreams?.rag?.ok === true || s.data.upstreams?.ragAlt?.ok === true),
/** BFF 整体状态(status:"ok" 即未降级) */
bffHealthy: (s) => !!s.data && s.data.status === 'ok',
qaVersion: (s) => s.qaInfo?.version || null,
/** 会话数(status bar 展示) */
sessionCount: (s) => (s.data && typeof s.data.db?.sessions === 'number' ? s.data.db.sessions : null),
},
actions: {
async _fetch() {
try {
const data = await api.get('/api/health');
this.data = data;
this.error = null;
this.unknown = false;
this.lastOkAt = new Date().toISOString();
} catch (e) {
this.error = e;
this.unknown = false;
// 失败不弹窗,仅标记;旧 data 保留供降级展示
}
},
/** 启动轮询:先取一次,此后每 30s 一次;页面 hidden 时跳过 */
start() {
if (this.polling) return;
this.polling = true;
this._fetch();
this._timer = setInterval(() => {
if (typeof document !== 'undefined' && document.hidden) return;
this._fetch();
}, HEALTH_INTERVAL);
},
/** 停止轮询(组件卸载时调用) */
stop() {
if (this._timer) {
clearInterval(this._timer);
this._timer = null;
}
this.polling = false;
},
/** 拉取 QA 版本号(FR-SHELL-003:版本来自 /api/qa/info;失败不阻塞渲染) */
async fetchQaInfo() {
try {
this.qaInfo = await api.get('/api/qa/info');
} catch (e) {
this.qaInfo = null;
}
},
},
});