Files
2026-08-11 17:41:36 +08:00

308 lines
10 KiB
JavaScript
Raw Permalink 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.
"use strict";
const common_vendor = require("../../common/vendor.js");
const tongji_utils_aiStreamRequest = require("../utils/aiStreamRequest.js");
const DIET_AI_PREFILL_KEY = "tongji_diet_ai_prefill";
const emptyDietAiRecommend = () => ({
breakfast: "",
drinks: "",
lunch: "",
dinner: "",
tips: "",
avoid: [],
analysis: [],
exercise: null,
disclaimer: "",
rules_summary: "",
source: "",
date: ""
});
function useDietAi(proxy, { diagnosisId, showUserToast, formatUserMessage }) {
const dietAiRecommend = common_vendor.ref(emptyDietAiRecommend());
const dietAiLoading = common_vendor.ref(false);
const dietAiStreaming = common_vendor.ref(false);
const dietAiReplacing = common_vendor.ref(false);
const dietAiStreamField = common_vendor.ref("");
let dietStreamBuffer = "";
const dietAiAskText = common_vendor.ref("");
const dietAiAsking = common_vendor.ref(false);
const dietAiAskResult = common_vendor.ref({ advice: "", level: "", level_label: "", portion: "", food: "" });
const hasDietAiMealContent = common_vendor.computed(() => {
const r = dietAiRecommend.value;
return !!(r.breakfast || r.drinks || r.lunch || r.dinner || r.tips);
});
function detectDietStreamField(text) {
const tail = String(text || "").match(/(?:^|\n)(早餐|喝的|午餐|晚餐|提示|少碰)[::]\s*([^\n]*)$/);
if (!tail)
return "breakfast";
const map = { "早餐": "breakfast", "喝的": "drinks", "午餐": "lunch", "晚餐": "dinner", "提示": "tips", "少碰": "tips" };
return map[tail[1]] || "breakfast";
}
function mergePartialDietFromStream() {
const partial = tongji_utils_aiStreamRequest.parsePartialDietPlainText(dietStreamBuffer);
const next = { ...dietAiRecommend.value };
for (const key of ["breakfast", "drinks", "lunch", "dinner", "tips"]) {
if (partial[key] != null)
next[key] = partial[key];
}
if (Array.isArray(partial.avoid))
next.avoid = partial.avoid;
dietAiRecommend.value = next;
dietAiStreamField.value = detectDietStreamField(dietStreamBuffer);
}
function applyDietRecommendPayload(payload) {
if (!payload)
return;
const prevAnalysis = dietAiRecommend.value.analysis;
const prevExercise = dietAiRecommend.value.exercise;
dietAiRecommend.value = {
...emptyDietAiRecommend(),
...payload,
avoid: Array.isArray(payload.avoid) ? payload.avoid : [],
analysis: Array.isArray(payload.analysis) && payload.analysis.length ? payload.analysis : Array.isArray(prevAnalysis) ? prevAnalysis : [],
exercise: payload.exercise && typeof payload.exercise === "object" ? payload.exercise : prevExercise || null
};
}
function resolveDietDonePayload(payload) {
if (!payload)
return payload;
if (payload.source !== "rule" || !dietStreamBuffer)
return payload;
const streamed = tongji_utils_aiStreamRequest.parsePartialDietPlainText(dietStreamBuffer);
if (!streamed.breakfast)
return payload;
return {
...emptyDietAiRecommend(),
...payload,
breakfast: streamed.breakfast,
drinks: streamed.drinks || payload.drinks || "",
lunch: streamed.lunch || payload.lunch || "",
dinner: streamed.dinner || payload.dinner || "",
tips: streamed.tips || payload.tips || "",
avoid: Array.isArray(streamed.avoid) && streamed.avoid.length ? streamed.avoid : payload.avoid || [],
source: "ai",
disclaimer: "AI 建议供参考,仍请结合医嘱与血糖监测。"
};
}
function onDietAiStreamEvent(event, payload) {
if (event === "analysis") {
if (Array.isArray(payload == null ? void 0 : payload.analysis)) {
dietAiRecommend.value = { ...dietAiRecommend.value, analysis: payload.analysis };
}
} else if (event === "exercise") {
if ((payload == null ? void 0 : payload.exercise) && typeof payload.exercise === "object") {
dietAiRecommend.value = { ...dietAiRecommend.value, exercise: payload.exercise };
}
} else if (event === "delta") {
dietAiStreaming.value = true;
if (payload.buffer != null) {
dietStreamBuffer = payload.buffer;
} else {
dietStreamBuffer += payload.text || "";
}
mergePartialDietFromStream();
} else if (event === "done") {
applyDietRecommendPayload(resolveDietDonePayload(payload));
dietStreamBuffer = "";
dietAiStreamField.value = "";
} else if (event === "error") {
showUserToast(formatUserMessage(payload == null ? void 0 : payload.message, "饮食建议加载失败"));
}
}
async function fetchDietAiRecommendFallback(refresh) {
const res = await proxy.apiUrl({
url: "/api/tcm/dailyDietAiRecommend",
method: "GET",
timeout: 35e3,
data: {
diagnosis_id: diagnosisId.value,
refresh: refresh ? 1 : 0,
...refresh ? { _t: Date.now() } : {}
}
}, false);
if ((res == null ? void 0 : res.code) === 1 && res.data) {
applyDietRecommendPayload(res.data);
} else if (res == null ? void 0 : res.msg) {
showUserToast(res.msg);
}
}
async function fetchDietAiRecommend(refresh = false) {
if (!diagnosisId.value || dietAiLoading.value)
return;
dietAiLoading.value = true;
dietAiStreaming.value = false;
dietAiReplacing.value = !!refresh;
dietStreamBuffer = "";
dietAiStreamField.value = "";
if (refresh) {
applyDietRecommendPayload(emptyDietAiRecommend());
}
try {
await tongji_utils_aiStreamRequest.requestAiStream({
baseUrl: proxy.$url,
url: "/api/tcm/dailyDietAiRecommendStream",
method: "GET",
data: {
diagnosis_id: diagnosisId.value,
refresh: refresh ? 1 : 0,
...refresh ? { _t: Date.now() } : {}
},
onEvent: onDietAiStreamEvent,
fallback: () => fetchDietAiRecommendFallback(refresh)
});
} catch (e) {
try {
await fetchDietAiRecommendFallback(refresh);
} catch (e2) {
showUserToast("饮食建议加载失败");
}
} finally {
dietAiLoading.value = false;
dietAiStreaming.value = false;
dietAiReplacing.value = false;
dietAiStreamField.value = "";
}
}
function refreshDietAiRecommend() {
if (dietAiLoading.value)
return;
fetchDietAiRecommend(true);
}
async function askDietAiFoodFallback(q) {
const res = await proxy.apiUrl({
url: "/api/tcm/dailyDietAiAsk",
method: "POST",
timeout: 35e3,
data: {
diagnosis_id: diagnosisId.value,
question: q
}
}, false);
if ((res == null ? void 0 : res.code) === 1 && res.data) {
dietAiAskResult.value = {
advice: res.data.advice || "",
level: res.data.level || "",
level_label: res.data.level_label || "",
portion: res.data.portion || "",
food: res.data.food || q
};
} else {
showUserToast(formatUserMessage(res == null ? void 0 : res.msg, "咨询失败"));
}
}
async function askDietAiFood() {
const q = String(dietAiAskText.value || "").trim();
if (!q) {
showUserToast("请输入想咨询的食物");
return;
}
if (!diagnosisId.value)
return;
dietAiAskText.value = "";
dietAiAsking.value = true;
dietAiAskResult.value = { advice: "", level: "", level_label: "", portion: "", food: "" };
try {
await tongji_utils_aiStreamRequest.requestAiStream({
baseUrl: proxy.$url,
url: "/api/tcm/dailyDietAiAskStream",
method: "POST",
data: {
diagnosis_id: diagnosisId.value,
question: q
},
onEvent: (event, payload) => {
if (event === "start" && !dietAiAskResult.value.advice) {
dietAiAskResult.value = { ...dietAiAskResult.value, advice: payload.message || "正在想…" };
} else if (event === "delta") {
dietAiAskResult.value = {
...dietAiAskResult.value,
advice: payload.advice || dietAiAskResult.value.advice
};
} else if (event === "done") {
dietAiAskResult.value = {
advice: payload.advice || "",
level: payload.level || "",
level_label: payload.level_label || "",
portion: payload.portion || "",
food: payload.food || q
};
} else if (event === "error") {
showUserToast(formatUserMessage(payload == null ? void 0 : payload.message, "咨询失败"));
}
},
fallback: () => askDietAiFoodFallback(q)
});
} catch (e) {
try {
await askDietAiFoodFallback(q);
} catch (e2) {
showUserToast("网络异常,请稍后再试");
}
} finally {
dietAiAsking.value = false;
}
}
function onDietAiAskInput(e) {
var _a;
dietAiAskText.value = ((_a = e == null ? void 0 : e.detail) == null ? void 0 : _a.value) ?? "";
}
function saveDietPrefillToStorage() {
const r = dietAiRecommend.value;
if (!r.breakfast)
return;
try {
common_vendor.index.setStorageSync(DIET_AI_PREFILL_KEY, {
breakfast: r.breakfast,
drinks: r.drinks || "",
lunch: r.lunch,
dinner: r.dinner,
tips: r.tips || ""
});
} catch (e) {
}
}
function goMoreDietForm(withPrefill = false) {
if (withPrefill)
saveDietPrefillToStorage();
common_vendor.index.navigateTo({ url: "/tongji/pages/more?openDiet=1" });
}
async function applyDietAiToForm() {
if (!dietAiRecommend.value.breakfast) {
await fetchDietAiRecommend(false);
}
goMoreDietForm(true);
}
function openDietForm() {
goMoreDietForm(false);
}
return {
dietAiRecommend,
dietAiLoading,
dietAiStreaming,
dietAiReplacing,
dietAiStreamField,
dietAiAskText,
dietAiAsking,
dietAiAskResult,
hasDietAiMealContent,
fetchDietAiRecommend,
refreshDietAiRecommend,
askDietAiFood,
onDietAiAskInput,
applyDietAiToForm,
openDietForm
};
}
function consumeDietAiPrefill() {
try {
const data = common_vendor.index.getStorageSync(DIET_AI_PREFILL_KEY);
common_vendor.index.removeStorageSync(DIET_AI_PREFILL_KEY);
if (data && typeof data === "object" && data.breakfast)
return data;
} catch (e) {
}
return null;
}
exports.consumeDietAiPrefill = consumeDietAiPrefill;
exports.useDietAi = useDietAi;
//# sourceMappingURL=../../../.sourcemap/mp-weixin/tongji/composables/useDietAi.js.map