"use strict"; const common_vendor = require("../../common/vendor.js"); const tongji_composables_useDietAi = require("../composables/useDietAi.js"); if (!Math) { (TongjiIcon + SugarTreeGraphic)(); } const SugarTreeGraphic = () => "../components/SugarTreeGraphic.js"; const TongjiIcon = () => "../components/TongjiIcon.js"; const VIEWER_KEY_STORAGE = "tongji_viewer_key_v1"; const _sfc_main = { __name: "index", setup(__props) { const { proxy } = common_vendor.getCurrentInstance(); function formatUserMessage(msg, fallback = "") { if (msg == null || msg === "") return fallback; if (typeof msg === "string") return msg; if (typeof msg === "number" || typeof msg === "boolean") return String(msg); if (Array.isArray(msg)) { const parts = msg.map((item) => { if (item == null) return ""; if (typeof item === "string") return item; if (typeof item === "number" || typeof item === "boolean") return String(item); if (typeof item === "object") { return item.msg || item.message || item.error || item.title || item.label || ""; } return String(item); }).filter(Boolean); return parts.length ? parts.join(";") : fallback; } if (typeof msg === "object") { return msg.msg || msg.message || msg.error || msg.title || msg.label || fallback; } return String(msg); } function showUserToast(title, options = {}) { const text = formatUserMessage(title, ""); if (!text) return; common_vendor.index.showToast({ title: text, icon: options.icon || "none", duration: options.duration }); } const diagnosisId = common_vendor.ref(0); const patientId = common_vendor.ref(0); const patientName = common_vendor.ref(""); const age = common_vendor.ref(0); const gender = common_vendor.ref(0); const { dietAiRecommend, dietAiLoading, dietAiStreaming, dietAiReplacing, dietAiStreamField, dietAiAskText, dietAiAsking, dietAiAskResult, hasDietAiMealContent, fetchDietAiRecommend, refreshDietAiRecommend, askDietAiFood, onDietAiAskInput, applyDietAiToForm, openDietForm } = tongji_composables_useDietAi.useDietAi(proxy, { diagnosisId, showUserToast, formatUserMessage }); const dietAnalysisList = common_vendor.computed(() => { const list = dietAiRecommend.value && Array.isArray(dietAiRecommend.value.analysis) ? dietAiRecommend.value.analysis : []; return list.filter((s) => s && typeof s === "object"); }); const hasDietAnalysis = common_vendor.computed(() => dietAnalysisList.value.length > 0); const dietExercise = common_vendor.computed(() => { const ex = dietAiRecommend.value && dietAiRecommend.value.exercise; return ex && typeof ex === "object" && Array.isArray(ex.items) && ex.items.length ? ex : null; }); function dietRateClass(rate) { const n = Number(rate); if (!Number.isFinite(n)) return "rate-mid"; if (n >= 80) return "rate-good"; if (n >= 50) return "rate-mid"; return "rate-low"; } function dietAvgText(v) { return v == null || v === "" ? "—" : v; } const authChecking = common_vendor.ref(false); const userMobile = common_vendor.ref(""); const phoneGateVisible = common_vendor.ref(false); const phoneGateSex = common_vendor.ref(0); const phoneBinding = common_vendor.ref(false); const loading = common_vendor.ref(false); const cardsLoading = common_vendor.ref(false); const cards = common_vendor.ref([]); const rangeMode = common_vendor.ref("7"); const rangeOptions = [ { value: "7", label: "最近 7 天" }, { value: "30", label: "最近 30 天" } ]; const bloodRecords = common_vendor.ref([]); const dietRecords = common_vendor.ref([]); const exerciseRecords = common_vendor.ref([]); const trackingNotes = common_vendor.ref([]); const hoverInfo = common_vendor.ref(null); let hoverTimer = null; const chartSeriesVisible = common_vendor.ref({ fasting: true, postprandial: true }); let canvasNode = null; let canvasCtx = null; let canvasWidth = 0; let canvasHeight = 0; let canvasDpr = 1; let chartCoords = null; common_vendor.computed(() => age.value > 0 ? `${age.value} 岁` : ""); common_vendor.computed(() => { const map = { 1: "男", 2: "女" }; return map[Number(gender.value)] || ""; }); const rangeText = common_vendor.computed(() => { const opt = rangeOptions.find((o) => o.value === rangeMode.value); return opt ? opt.label : ""; }); function formatDate(date) { const y = date.getFullYear(); const m = String(date.getMonth() + 1).padStart(2, "0"); const d = String(date.getDate()).padStart(2, "0"); return `${y}-${m}-${d}`; } function parseDate(str) { if (!str) return /* @__PURE__ */ new Date(); const [y, m, d] = str.split("-").map(Number); return new Date(y, (m || 1) - 1, d || 1); } const currentRange = common_vendor.computed(() => { const days = rangeMode.value === "30" ? 30 : 7; const end = /* @__PURE__ */ new Date(); end.setHours(0, 0, 0, 0); const start = new Date(end); start.setDate(start.getDate() - (days - 1)); return { start: formatDate(start), end: formatDate(end) }; }); const visibleDates = common_vendor.computed(() => { const { start, end } = currentRange.value; if (!start || !end) return []; const dates = []; const cursor = parseDate(end); const lower = parseDate(start).getTime(); while (cursor.getTime() >= lower) { dates.push(formatDate(cursor)); cursor.setDate(cursor.getDate() - 1); } return dates; }); const chartDates = common_vendor.computed(() => [...visibleDates.value].reverse()); function toNumber(v) { if (v === null || v === void 0 || v === "") return null; const n = Number(v); return Number.isFinite(n) && n !== 0 ? n : null; } function getBloodSugarThresholds(ageValue) { const a = Number(ageValue); if (!Number.isFinite(a) || a <= 0) return { fasting: 7, postprandial: 10 }; if (a < 50) return { fasting: 7, postprandial: 9 }; return { fasting: 8, postprandial: 10 }; } function isHighFasting(v) { const n = toNumber(v); const t = getBloodSugarThresholds(age.value); return n !== null && t !== null && n >= t.fasting; } function isHighPostprandial(v) { const n = toNumber(v); const t = getBloodSugarThresholds(age.value); return n !== null && t !== null && n >= t.postprandial; } function isHighBp(row) { if (!row) return false; const s = toNumber(row.systolic_pressure); const d = toNumber(row.diastolic_pressure); return s !== null && s > 140 || d !== null && d > 90; } function formatBp(row) { const s = row == null ? void 0 : row.systolic_pressure; const d = row == null ? void 0 : row.diastolic_pressure; if ((s === null || s === void 0 || s === "" || s === 0) && (d === null || d === void 0 || d === "" || d === 0)) return "—"; return `${s || "—"} / ${d || "—"}`; } const intensityTextMap = { 1: "低强度", 2: "中强度", 3: "高强度" }; const bloodByDate = common_vendor.computed(() => { const map = {}; for (const r of bloodRecords.value) { const date = String(r.record_date || ""); if (!date) continue; if (!map[date]) { map[date] = { record_date: date, record_time: r.record_time || "", fasting_blood_sugar: "", postprandial_blood_sugar: "", other_blood_sugar: "", systolic_pressure: "", diastolic_pressure: "", western_medicine: "", insulin: "", remark: "" }; } const merged = map[date]; const fields = ["fasting_blood_sugar", "postprandial_blood_sugar", "other_blood_sugar", "systolic_pressure", "diastolic_pressure", "western_medicine", "insulin", "remark"]; for (const f of fields) { if ((merged[f] === "" || merged[f] === null || merged[f] === void 0) && r[f] !== "" && r[f] !== null && r[f] !== void 0) { merged[f] = r[f]; } } } for (const date in map) { const m = map[date]; m.isHighFasting = isHighFasting(m.fasting_blood_sugar); m.isHighPostprandial = isHighPostprandial(m.postprandial_blood_sugar); m.isHighOther = isHighPostprandial(m.other_blood_sugar); m.isHighBp = isHighBp(m); m.bpText = formatBp(m); } return map; }); common_vendor.computed(() => { const map = {}; for (const r of dietRecords.value) { const date = String(r.record_date || ""); if (!date || map[date]) continue; map[date] = r; } return map; }); common_vendor.computed(() => { const map = {}; for (const r of exerciseRecords.value) { const date = String(r.record_date || ""); if (!date || map[date]) continue; const item = { ...r }; item.intensityText = intensityTextMap[Number(r.intensity)] || ""; map[date] = item; } return map; }); common_vendor.computed(() => { const map = {}; for (const r of trackingNotes.value) { const date = String(r.note_date || ""); if (!date || map[date]) continue; map[date] = r; } return map; }); const weekdayNames = ["周日", "周一", "周二", "周三", "周四", "周五", "周六"]; function getWeekday(dateStr) { return weekdayNames[parseDate(dateStr).getDay()] || ""; } const todayStr = common_vendor.computed(() => formatDate(/* @__PURE__ */ new Date())); common_vendor.computed(() => { const result = []; for (const date of visibleDates.value) { const blood = bloodByDate.value[date]; if (!blood) continue; const hasSugar = toNumber(blood.fasting_blood_sugar) !== null || toNumber(blood.postprandial_blood_sugar) !== null || toNumber(blood.other_blood_sugar) !== null; if (!hasSugar) continue; const [y, m, d] = date.split("-"); result.push({ date, dateLabel: `${m}-${d}`, weekday: getWeekday(date), isToday: date === todayStr.value, blood }); } return result; }); const bloodHasData = common_vendor.computed(() => { return chartDates.value.some((date) => { const b = bloodByDate.value[date]; return b && (toNumber(b.fasting_blood_sugar) !== null || toNumber(b.postprandial_blood_sugar) !== null); }); }); const bloodRecordDayCount = common_vendor.computed(() => { return chartDates.value.filter((date) => { const b = bloodByDate.value[date]; return b && (toNumber(b.fasting_blood_sugar) !== null || toNumber(b.postprandial_blood_sugar) !== null); }).length; }); const bloodHighDayCount = common_vendor.computed(() => { return chartDates.value.filter((date) => { const b = bloodByDate.value[date]; return b && (b.isHighFasting || b.isHighPostprandial); }).length; }); const bloodNormalDayCount = common_vendor.computed(() => bloodRecordDayCount.value - bloodHighDayCount.value); function makeTrend(curr, prev, precision = 1) { if (curr == null || prev == null) return null; const diff = Number(curr) - Number(prev); if (!Number.isFinite(diff)) return null; const abs = Math.abs(diff); const dir = abs < 0.01 ? "flat" : diff > 0 ? "up" : "down"; const sign = dir === "up" ? "+" : dir === "down" ? "-" : ""; const deltaText = dir === "flat" ? "持平" : `${sign}${abs.toFixed(precision)}`; return { dir, delta: abs, deltaText, prev }; } function findPrev(field, beforeDate) { const dates = chartDates.value; const idx = dates.indexOf(beforeDate); if (idx <= 0) return null; for (let i = idx - 1; i >= 0; i--) { const b = bloodByDate.value[dates[i]]; if (!b) continue; const v = toNumber(b[field]); if (v !== null) return { date: dates[i], value: v }; } return null; } const latestStat = common_vendor.computed(() => { const dates = [...chartDates.value].reverse(); const dummy = { value: "—", date: "暂无记录", isHigh: false, trend: null }; const result = { fasting: { ...dummy }, postprandial: { ...dummy }, other: { ...dummy } }; for (const date of dates) { const b = bloodByDate.value[date]; if (!b) continue; if (result.fasting.value === "—" && toNumber(b.fasting_blood_sugar) !== null) { const cur = toNumber(b.fasting_blood_sugar); const prev = findPrev("fasting_blood_sugar", date); result.fasting = { value: String(b.fasting_blood_sugar), date: date.slice(5), isHigh: b.isHighFasting, trend: prev ? makeTrend(cur, prev.value) : null }; } if (result.postprandial.value === "—" && toNumber(b.postprandial_blood_sugar) !== null) { const cur = toNumber(b.postprandial_blood_sugar); const prev = findPrev("postprandial_blood_sugar", date); result.postprandial = { value: String(b.postprandial_blood_sugar), date: date.slice(5), isHigh: b.isHighPostprandial, trend: prev ? makeTrend(cur, prev.value) : null }; } if (result.other.value === "—" && toNumber(b.other_blood_sugar) !== null) { const cur = toNumber(b.other_blood_sugar); const prev = findPrev("other_blood_sugar", date); result.other = { value: String(b.other_blood_sugar), date: date.slice(5), isHigh: b.isHighOther, trend: prev ? makeTrend(cur, prev.value) : null }; } if (result.fasting.value !== "—" && result.postprandial.value !== "—" && result.other.value !== "—") break; } return result; }); function elderMetricFromBlood(blood, field, label) { if (!blood) return { label, value: "—", isHigh: false }; const num = toNumber(blood[field]); if (num === null) return { label, value: "—", isHigh: false }; const isHigh = field === "fasting_blood_sugar" ? blood.isHighFasting : field === "postprandial_blood_sugar" ? blood.isHighPostprandial : blood.isHighOther; return { label, value: String(blood[field]), isHigh: !!isHigh }; } const todayBlood = common_vendor.computed(() => bloodByDate.value[todayStr.value] || null); const elderFasting = common_vendor.computed( () => elderMetricFromBlood(todayBlood.value, "fasting_blood_sugar", "空腹") ); const elderPostprandial = common_vendor.computed( () => elderMetricFromBlood(todayBlood.value, "postprandial_blood_sugar", "餐后") ); let authSessionPromise = null; function hasAuthToken() { return !!String(common_vendor.index.getStorageSync("token") || "").trim(); } function clearAuthStorage() { common_vendor.index.removeStorageSync("token"); authSessionPromise = null; } function wxLoginGetCode() { return new Promise((resolve, reject) => { common_vendor.index.login({ provider: "weixin", success: (res) => { if (res && res.code) resolve(res.code); else reject(new Error("微信登录未返回 code")); }, fail: reject }); }); } async function mnpLoginWithCode(code) { const res = await proxy.apiUrl({ url: "/api/login/mnpLogin", method: "POST", data: { code } }, false); if (res && res.code === 1 && res.data && res.data.token) { common_vendor.index.setStorageSync("token", res.data.token); common_vendor.index.setStorageSync("userData", res.data); return res.data; } clearAuthStorage(); throw new Error(formatUserMessage(res == null ? void 0 : res.msg, "登录失败")); } async function doWxLogin() { const code = await wxLoginGetCode(); await mnpLoginWithCode(code); return hasAuthToken(); } async function verifyOrLogin() { if (!hasAuthToken()) { return doWxLogin(); } try { const res = await proxy.apiUrl({ url: "/api/user/info", method: "POST" }, false); if (res && res.code === 1 && res.data) { common_vendor.index.setStorageSync("userData", res.data); return true; } } catch (e) { } clearAuthStorage(); try { return await doWxLogin(); } catch (e2) { return false; } } async function ensureLoggedIn() { if (authSessionPromise) { return authSessionPromise; } authSessionPromise = verifyOrLogin().then((ok) => { if (!ok) authSessionPromise = null; return !!ok; }).catch(() => { authSessionPromise = null; return false; }); return authSessionPromise; } async function fetchCardList() { if (!hasAuthToken()) return []; cardsLoading.value = true; try { const res = await proxy.apiUrl({ url: "/api/tcm/getCardList", method: "GET", data: {} }, false); if (res && res.code === 1 && Array.isArray(res.data)) { cards.value = res.data; return res.data; } cards.value = []; return []; } catch (e) { cards.value = []; return []; } finally { cardsLoading.value = false; } } async function applyCard(card) { if (!card || !hasAuthToken()) return; diagnosisId.value = Number(card.id) || 0; patientId.value = Number(card.patient_id) || 0; patientName.value = card.patient_name || ""; age.value = Number(card.age) || 0; gender.value = Number(card.gender) || 0; } function readUserMobile() { try { const userData = common_vendor.index.getStorageSync("userData") || {}; userMobile.value = String(userData.mobile || userData.phone || "").trim(); } catch (e) { userMobile.value = ""; } return userMobile.value; } function syncPhoneGateSexFromUser() { try { const userData = common_vendor.index.getStorageSync("userData") || {}; const sex = Number(userData.sex); phoneGateSex.value = sex === 1 || sex === 2 ? sex : 0; } catch (e) { phoneGateSex.value = 0; } } function openPhoneGate() { syncPhoneGateSexFromUser(); phoneGateVisible.value = true; } async function refreshUserMobile() { try { const res = await proxy.apiUrl({ url: "/api/user/info", method: "POST" }, false); if (res && res.code === 1 && res.data) { common_vendor.index.setStorageSync("userData", res.data); userMobile.value = String(res.data.mobile || res.data.phone || "").trim(); } } catch (e) { } return userMobile.value; } async function ensureDailyContextByPhone(sex) { if (diagnosisId.value) return true; const payload = {}; const sexVal = sex ?? phoneGateSex.value; if (sexVal === 1 || sexVal === 2) { payload.sex = sexVal; } const res = await proxy.apiUrl({ url: "/api/tcm/dailyEnsurePhoneContext", method: "POST", data: payload }, false); if (res && res.code === 1 && res.data && res.data.diagnosis_id) { await applyCard({ id: res.data.diagnosis_id, patient_id: res.data.patient_id, patient_name: res.data.patient_name || "", age: res.data.age || 0, gender: res.data.gender || 0 }); if (res.data.created) { await fetchCardList(); } return true; } if (res && res.data && res.data.need_mobile) { return "need_mobile"; } showUserToast(formatUserMessage(res == null ? void 0 : res.msg, "无法开始录入")); return false; } async function ensureCanRecordGlucose() { if (diagnosisId.value) return true; readUserMobile(); if (!userMobile.value) { openPhoneGate(); return false; } const ok = await ensureDailyContextByPhone(); if (ok === "need_mobile") { openPhoneGate(); return false; } return !!ok; } function closePhoneGate() { if (phoneBinding.value) return; phoneGateVisible.value = false; } async function onPhoneGateAuthorize(e) { const detail = (e == null ? void 0 : e.detail) || {}; if (detail.errMsg && !String(detail.errMsg).includes("ok")) { showUserToast("需要授权手机号后才能录入血糖"); return; } const code = detail.code; if (!code) { showUserToast("获取手机号失败,请重试"); return; } if (phoneGateSex.value !== 1 && phoneGateSex.value !== 2) { showUserToast("请先选择性别"); return; } phoneBinding.value = true; try { const res = await proxy.apiUrl({ url: "/api/user/getMobileByMnp", method: "POST", data: { code, sex: phoneGateSex.value } }, false); if (!res || res.code !== 1) { showUserToast(formatUserMessage(res == null ? void 0 : res.msg, "绑定手机号失败")); return; } await refreshUserMobile(); phoneGateVisible.value = false; const ok = await ensureDailyContextByPhone(phoneGateSex.value); if (ok === true) { await openInputForm(true); } else if (ok === "need_mobile") { openPhoneGate(); } } catch (err) { showUserToast("网络异常,请稍后再试"); } finally { phoneBinding.value = false; } } async function onSelectCard(card) { if (!card || Number(card.id) === Number(diagnosisId.value)) return; bloodRecords.value = []; dietRecords.value = []; exerciseRecords.value = []; trackingNotes.value = []; hoverInfo.value = null; await applyCard(card); fetchAll(); } async function fetchAll() { if (!hasAuthToken() || !diagnosisId.value) return; loading.value = true; const { start, end } = currentRange.value; try { const [winRes, noteRes] = await Promise.all([ proxy.apiUrl({ url: "/api/tcm/dailyTrackingWindow", method: "GET", data: { diagnosis_id: diagnosisId.value, patient_id: patientId.value || 0, start_date: start, end_date: end } }, false), proxy.apiUrl({ url: "/api/tcm/dailyTrackingNotes", method: "GET", data: { diagnosis_id: diagnosisId.value, patient_id: patientId.value || 0 } }, false) ]); if (winRes && winRes.code === 1) { const d = winRes.data || {}; bloodRecords.value = Array.isArray(d.blood_records) ? d.blood_records : []; dietRecords.value = Array.isArray(d.diet_records) ? d.diet_records : []; exerciseRecords.value = Array.isArray(d.exercise_records) ? d.exercise_records : []; if (d.diagnosis) { if (!patientName.value) patientName.value = d.diagnosis.patient_name || ""; if (!age.value) age.value = Number(d.diagnosis.age) || 0; if (!gender.value) gender.value = Number(d.diagnosis.gender) || 0; if (!patientId.value) patientId.value = Number(d.diagnosis.patient_id) || 0; } } else { bloodRecords.value = []; dietRecords.value = []; exerciseRecords.value = []; if (winRes == null ? void 0 : winRes.msg) showUserToast(winRes.msg); } if (noteRes && noteRes.code === 1) { const list = Array.isArray(noteRes.data) ? noteRes.data : []; trackingNotes.value = list.filter((it) => visibleDates.value.includes(String((it == null ? void 0 : it.note_date) || ""))); } else { trackingNotes.value = []; } await fetchDietAiRecommend(false); } catch (e) { common_vendor.index.showToast({ title: "加载失败,请稍后再试", icon: "none" }); } finally { loading.value = false; await common_vendor.nextTick$1(); scheduleChartRedraw(); if (ttsAutoPlay.value && !recordOverlayOpen.value) { const token = ++ttsAutoToken; setTimeout(() => { if (token === ttsAutoToken && !recordOverlayOpen.value) speakLatestSummary(); }, 350); } } } function onChangeRange(value) { if (rangeMode.value === value) return; rangeMode.value = value; fetchAll(); } async function goMorePage() { if (!diagnosisId.value) { const ok = await ensureCanRecordGlucose(); if (!ok || !diagnosisId.value) return; } common_vendor.index.navigateTo({ url: "/tongji/pages/more" }); } function buildTimeGreetingMeta(hour = (/* @__PURE__ */ new Date()).getHours()) { const h = Number(hour) || 0; if (h < 5) return { text: "夜深了", icon: "moon" }; if (h < 11) return { text: "早上好", icon: "sun" }; if (h < 13) return { text: "中午好", icon: "sun" }; if (h < 18) return { text: "下午好", icon: "sun" }; if (h < 22) return { text: "晚上好", icon: "sunset" }; return { text: "夜深了", icon: "moon" }; } const timeGreetingMeta = common_vendor.computed(() => buildTimeGreetingMeta()); function dayHasBloodRecord(key) { const b = bloodByDate.value[key]; if (!b) return false; return toNumber(b.fasting_blood_sugar) !== null || toNumber(b.postprandial_blood_sugar) !== null || toNumber(b.other_blood_sugar) !== null; } function dayCoverageLevel(key) { const b = bloodByDate.value[key]; if (!b) return 0; const fields = ["fasting_blood_sugar", "postprandial_blood_sugar", "other_blood_sugar"]; const score = fields.filter((f) => toNumber(b[f]) !== null).length; if (score === 0) return 0; if (score === 1) return 1; if (score === 2) return 2; return 3; } const todayChecked = common_vendor.computed(() => dayHasBloodRecord(todayStr.value)); common_vendor.computed(() => { const today = /* @__PURE__ */ new Date(); let count = 0; let startedFromYesterday = false; for (let i = 0; i < 90; i++) { const d = new Date(today); d.setDate(today.getDate() - i); const key = formatDate(d); const has = dayHasBloodRecord(key); if (has) { count++; } else { if (i === 0) { startedFromYesterday = true; continue; } break; } } return { days: count, startedFromYesterday }; }); const last7Dots = common_vendor.computed(() => { const arr = []; const today = /* @__PURE__ */ new Date(); const wkChars = ["日", "一", "二", "三", "四", "五", "六"]; for (let i = 6; i >= 0; i--) { const d = new Date(today); d.setDate(today.getDate() - i); const key = formatDate(d); arr.push({ date: key, label: wkChars[d.getDay()], isToday: i === 0, hasRecord: dayHasBloodRecord(key) }); } return arr; }); common_vendor.computed(() => last7Dots.value.filter((d) => d.hasRecord).length); function dayHasFastingRecord(key) { const b = bloodByDate.value[key]; return !!(b && toNumber(b.fasting_blood_sugar) !== null); } function dayHasPostprandialRecord(key) { const b = bloodByDate.value[key]; return !!(b && toNumber(b.postprandial_blood_sugar) !== null); } function dayIsCompleteRecord(key) { return dayHasFastingRecord(key) && dayHasPostprandialRecord(key); } common_vendor.computed(() => last7Dots.value.filter((d) => dayIsCompleteRecord(d.date)).length); const heatmapWeeks = common_vendor.computed(() => { const dates = chartDates.value; if (!dates || !dates.length) return []; const sorted = [...dates].sort(); const first = new Date(sorted[0]); const last = new Date(sorted[sorted.length - 1]); const firstDow = (first.getDay() + 6) % 7; const lastDow = (last.getDay() + 6) % 7; const gridStart = new Date(first); gridStart.setDate(first.getDate() - firstDow); const gridEnd = new Date(last); gridEnd.setDate(last.getDate() + (6 - lastDow)); const totalDays = Math.round((gridEnd - gridStart) / 864e5) + 1; const weeks = []; let cur = new Date(gridStart); for (let w = 0; w < Math.ceil(totalDays / 7); w++) { const week = []; for (let i = 0; i < 7; i++) { const key = formatDate(cur); const inRange = sorted.includes(key); week.push({ date: key, day: cur.getDate(), inRange, isToday: key === todayStr.value, level: inRange ? dayCoverageLevel(key) : -1 }); cur.setDate(cur.getDate() + 1); } weeks.push(week); } return weeks; }); common_vendor.computed(() => { let c = 0; for (const w of heatmapWeeks.value) for (const c2 of w) if (c2.inRange && c2.level > 0) c++; return c; }); common_vendor.computed(() => { let c = 0; for (const w of heatmapWeeks.value) for (const c2 of w) if (c2.inRange) c++; return c; }); common_vendor.computed(() => { const weeks = heatmapWeeks.value; if (!weeks.length) return ""; const counter = /* @__PURE__ */ new Map(); for (const w of weeks) { for (const c of w) { if (!c.inRange) continue; const [y2, m2] = c.date.split("-"); const key = `${y2}-${m2}`; counter.set(key, (counter.get(key) || 0) + 1); } } if (!counter.size) { const first = weeks[0][0].date.split("-"); return `${Number(first[0])}年${Number(first[1])}月`; } let best = ""; let bestCount = -1; for (const [k, v] of counter) { if (v > bestCount) { best = k; bestCount = v; } } const [y, m] = best.split("-"); return `${Number(y)}年${Number(m)}月`; }); const todayText = common_vendor.computed(() => { const d = /* @__PURE__ */ new Date(); const m = String(d.getMonth() + 1).padStart(2, "0"); const day = String(d.getDate()).padStart(2, "0"); const weekdays = ["周日", "周一", "周二", "周三", "周四", "周五", "周六"]; return `${d.getFullYear()}-${m}-${day} ${weekdays[d.getDay()]}`; }); const emptyInputForm = () => ({ visible: false, loading: false, submitting: false, id: 0, fasting_blood_sugar: "", postprandial_blood_sugar: "", other_blood_sugar: "", remark: "" }); const inputForm = common_vendor.ref(emptyInputForm()); function prepareRecordOverlay() { canvasCtx = null; canvasNode = null; ttsStop(); } function onInputField(field, e) { var _a; const val = ((_a = e == null ? void 0 : e.detail) == null ? void 0 : _a.value) ?? ""; inputForm.value[field] = val; } async function openInputForm(skipEnsure = false) { const token = common_vendor.index.getStorageSync("token"); if (!token) { showUserToast("请先登录后再录入"); return; } if (!skipEnsure) { const can = await ensureCanRecordGlucose(); if (!can) return; } if (!diagnosisId.value) { showUserToast("请先授权手机号"); return; } prepareRecordOverlay(); inputForm.value = { ...emptyInputForm(), visible: true, loading: true }; try { const res = await proxy.apiUrl({ url: "/api/tcm/dailyTodayBloodRecord", method: "GET", data: { diagnosis_id: diagnosisId.value } }, false); if (res && res.code === 1 && res.data && res.data.record) { const r = res.data.record; inputForm.value.id = Number(r.id) || 0; inputForm.value.fasting_blood_sugar = numToStr(r.fasting_blood_sugar); inputForm.value.postprandial_blood_sugar = numToStr(r.postprandial_blood_sugar); inputForm.value.other_blood_sugar = numToStr(r.other_blood_sugar); inputForm.value.remark = String(r.remark || ""); } } catch (e) { } finally { inputForm.value.loading = false; } } function numToStr(v) { if (v === null || v === void 0 || v === "" || v === 0 || v === "0") return ""; if (typeof v === "object") return ""; return String(v); } function closeInputForm() { if (inputForm.value.submitting) return; inputForm.value.visible = false; common_vendor.nextTick$1(() => scheduleChartRedraw()); } const recordOverlayOpen = common_vendor.computed(() => inputForm.value.visible || phoneGateVisible.value); async function submitInputForm() { if (inputForm.value.submitting || inputForm.value.loading) return; const f = inputForm.value; const hasAny = [ f.fasting_blood_sugar, f.postprandial_blood_sugar, f.other_blood_sugar ].some((v) => v !== "" && v !== null && Number(v) > 0) || !!(f.remark && f.remark.trim()); if (!hasAny) { common_vendor.index.showToast({ title: "请至少填写一项数据", icon: "none" }); return; } inputForm.value.submitting = true; try { const res = await proxy.apiUrl({ url: "/api/tcm/dailySaveBloodRecord", method: "POST", data: { diagnosis_id: diagnosisId.value, fasting_blood_sugar: f.fasting_blood_sugar, postprandial_blood_sugar: f.postprandial_blood_sugar, other_blood_sugar: f.other_blood_sugar, remark: f.remark } }, false); if (res && res.code === 1) { showUserToast(res.msg || "已保存", { icon: "success" }); inputForm.value.visible = false; await fetchAll(); } else { showUserToast(res && res.msg || "保存失败"); } } catch (e) { common_vendor.index.showToast({ title: "网络异常,请稍后再试", icon: "none" }); } finally { inputForm.value.submitting = false; } } function deleteInputRecord() { if (!inputForm.value.id || inputForm.value.submitting) return; common_vendor.index.showModal({ title: "删除确认", content: "确定删除今天已录入的数据吗?删除后无法恢复。", confirmColor: "#dc2626", success: async (m) => { if (!m.confirm) return; inputForm.value.submitting = true; try { const res = await proxy.apiUrl({ url: "/api/tcm/dailyDeleteBloodRecord", method: "POST", data: { diagnosis_id: diagnosisId.value, id: inputForm.value.id } }, false); if (res && res.code === 1) { common_vendor.index.showToast({ title: "已删除", icon: "success" }); inputForm.value.visible = false; fetchAll(); } else { showUserToast(res && res.msg || "删除失败"); } } catch (e) { common_vendor.index.showToast({ title: "网络异常,请稍后再试", icon: "none" }); } finally { inputForm.value.submitting = false; } } }); } const ttsEnabled = common_vendor.ref(true); const ttsAutoPlay = common_vendor.ref(false); const ttsSpeaking = common_vendor.ref(false); let ttsAudioCtx = null; let ttsAutoToken = 0; function teardownTtsAudio() { if (ttsAudioCtx) { try { ttsAudioCtx.stop(); } catch (e) { } try { ttsAudioCtx.destroy && ttsAudioCtx.destroy(); } catch (e) { } ttsAudioCtx = null; } } function ttsStop() { teardownTtsAudio(); ttsSpeaking.value = false; } function normalizeTtsText(text) { if (text == null) return ""; if (typeof text === "string") return text.replace(/\s+/g, " ").trim(); if (Array.isArray(text)) { return text.map((item) => { if (typeof item === "string") return item; if (item && typeof item === "object") { return item.title || item.label || item.desc || item.msg || item.message || ""; } return formatUserMessage(item, ""); }).filter(Boolean).join(","); } if (typeof text === "object") { return text.title || text.label || text.desc || text.msg || text.message || ""; } return formatUserMessage(text, ""); } function ttsSpeak(text) { if (!ttsEnabled.value) return; const content = normalizeTtsText(text); if (!content) return; ttsStop(); try { const plugin = requirePlugin("WechatSI"); ttsSpeaking.value = true; plugin.textToSpeech({ lang: "zh_CN", tts: true, content, success: (res) => { if (!res || !res.filename) { ttsSpeaking.value = false; return; } teardownTtsAudio(); ttsAudioCtx = common_vendor.index.createInnerAudioContext(); ttsAudioCtx.src = res.filename; ttsAudioCtx.obeyMuteSwitch = false; ttsAudioCtx.onPlay(() => { ttsSpeaking.value = true; }); ttsAudioCtx.onEnded(() => { ttsSpeaking.value = false; }); ttsAudioCtx.onError(() => { ttsSpeaking.value = false; }); ttsAudioCtx.onStop(() => { ttsSpeaking.value = false; }); ttsAudioCtx.play(); }, fail: (err) => { ttsSpeaking.value = false; common_vendor.index.__f__("warn", "at tongji/pages/index.vue:2103", "WechatSI textToSpeech failed", err); common_vendor.index.showToast({ title: "语音不可用,请检查网络/插件", icon: "none", duration: 2e3 }); } }); return; } catch (e) { common_vendor.index.__f__("warn", "at tongji/pages/index.vue:2109", "WechatSI plugin not available", e); } showUserToast(content, { duration: 3200 }); } function readableNumber(v) { if (v === null || v === void 0 || v === "") return ""; return String(v).replace(/(\d+)\.(\d+)/g, (_, a, b) => `${a}点${b}`); } function buildLatestSummaryText() { const f = latestStat.value.fasting; const p = latestStat.value.postprandial; const o = latestStat.value.other; const head = `${patientName.value || "您"}的最新血糖情况:`; const lines = []; if (f && f.value !== "—") { let line = `空腹血糖 ${readableNumber(f.value)} 毫摩每升`; if (f.isHigh) line += ",偏高,请遵医嘱。"; else line += "。"; if (f.trend && f.trend.dir !== "flat") { line += `比上次${f.trend.dir === "up" ? "升高" : "下降"} ${readableNumber(f.trend.delta.toFixed(1))}。`; } lines.push(line); } if (p && p.value !== "—") { let line = `餐后血糖 ${readableNumber(p.value)} 毫摩每升`; if (p.isHigh) line += ",偏高,请注意饮食。"; else line += "。"; if (p.trend && p.trend.dir !== "flat") { line += `比上次${p.trend.dir === "up" ? "升高" : "下降"} ${readableNumber(p.trend.delta.toFixed(1))}。`; } lines.push(line); } if (o && o.value !== "—") { let line = `其他时段血糖 ${readableNumber(o.value)} 毫摩每升`; if (o.isHigh) line += ",偏高,请遵医嘱。"; else line += "。"; if (o.trend && o.trend.dir !== "flat") { line += `比上次${o.trend.dir === "up" ? "升高" : "下降"} ${readableNumber(o.trend.delta.toFixed(1))}。`; } lines.push(line); } if (!lines.length) { return `${patientName.value || "您"}近期暂无血糖记录。`; } return head + lines.join(" "); } function speakLatestSummary() { const text = buildLatestSummaryText(); if (text) ttsSpeak(text); } function ensureCanvas() { return new Promise((resolve) => { if (canvasCtx) { resolve(); return; } const query = common_vendor.index.createSelectorQuery().in(proxy); query.select("#bloodWaveChart").fields({ node: true, size: true }).exec((res) => { const item = res && res[0]; if (!item || !item.node) { resolve(); return; } canvasNode = item.node; canvasCtx = canvasNode.getContext("2d"); try { canvasDpr = common_vendor.index.getSystemInfoSync().pixelRatio || 1; } catch (e) { canvasDpr = 1; } canvasWidth = item.width; canvasHeight = item.height; canvasNode.width = canvasWidth * canvasDpr; canvasNode.height = canvasHeight * canvasDpr; canvasCtx.scale(canvasDpr, canvasDpr); resolve(); }); }); } let redrawScheduled = false; function scheduleChartRedraw() { if (redrawScheduled) return; redrawScheduled = true; setTimeout(async () => { redrawScheduled = false; await ensureCanvas(); drawChart(); }, 60); } function buildSeries(field) { return chartDates.value.map((date) => { const b = bloodByDate.value[date]; return b ? toNumber(b[field]) : null; }); } function computeYRange(...seriesList) { const values = seriesList.flat().filter((v) => v !== null); if (!values.length) return { yMin: 4, yMax: 12 }; let min = Math.min(...values); let max = Math.max(...values); const span = max - min; if (span < 2) { min = Math.max(0, min - 1); max = max + 1; } else { min = Math.max(0, min - span * 0.2); max = max + span * 0.2; } min = Math.max(2, Math.floor(min)); max = Math.min(28, Math.ceil(max)); if (max - min < 4) max = min + 4; return { yMin: min, yMax: max }; } function drawChart() { if (!canvasCtx || !canvasWidth || !canvasHeight) return; const ctx = canvasCtx; const w = canvasWidth; const h = canvasHeight; ctx.clearRect(0, 0, w, h); const padding = { left: 40, right: 18, top: 26, bottom: 36 }; const cw = w - padding.left - padding.right; const ch = h - padding.top - padding.bottom; const fastingSeries = buildSeries("fasting_blood_sugar"); const postSeries = buildSeries("postprandial_blood_sugar"); const n = chartDates.value.length; const threshold = getBloodSugarThresholds(age.value); const seriesDefs = [ { key: "fasting", data: fastingSeries, color: "#204E2B", fillTop: "rgba(32,78,43,0.18)", fillBottom: "rgba(32,78,43,0)", label: "空腹", highThreshold: threshold ? threshold.fasting : null }, { key: "postprandial", data: postSeries, color: "#D97706", fillTop: "rgba(217,119,6,0.18)", fillBottom: "rgba(217,119,6,0)", label: "餐后", highThreshold: threshold ? threshold.postprandial : null } ]; const visibleDefs = seriesDefs.filter((item) => chartSeriesVisible.value[item.key]); const rangeSources = visibleDefs.length ? visibleDefs.map((item) => item.data) : [fastingSeries, postSeries]; const { yMin, yMax } = computeYRange(...rangeSources); const valueToY = (v) => padding.top + ch * (1 - (v - yMin) / (yMax - yMin)); ctx.fillStyle = "#fbfcfd"; ctx.fillRect(padding.left, padding.top, cw, ch); if (threshold) { const yThr = valueToY(threshold.fasting); const top = Math.max(padding.top, Math.min(yThr, padding.top + ch)); if (top > padding.top) { const dangerGrad = ctx.createLinearGradient(0, padding.top, 0, top); dangerGrad.addColorStop(0, "rgba(254, 226, 226, 0.55)"); dangerGrad.addColorStop(1, "rgba(254, 226, 226, 0.15)"); ctx.fillStyle = dangerGrad; ctx.fillRect(padding.left, padding.top, cw, top - padding.top); } } ctx.strokeStyle = "#eef2f5"; ctx.lineWidth = 1; const yTicks = 4; for (let i = 0; i <= yTicks; i++) { const y = padding.top + ch * i / yTicks; ctx.beginPath(); ctx.moveTo(padding.left, y); ctx.lineTo(padding.left + cw, y); ctx.stroke(); } ctx.font = "bold 12px sans-serif"; ctx.fillStyle = "#64748b"; ctx.textAlign = "right"; ctx.textBaseline = "middle"; for (let i = 0; i <= yTicks; i++) { const y = padding.top + ch * i / yTicks; const v = yMax - (yMax - yMin) * i / yTicks; ctx.fillText(v.toFixed(1), padding.left - 8, y); } ctx.font = "bold 12px sans-serif"; ctx.fillStyle = "#475569"; ctx.textAlign = "center"; ctx.textBaseline = "top"; if (n > 0) { const maxLabels = n > 20 ? 5 : 6; const labelStep = Math.max(1, Math.ceil(n / maxLabels)); chartDates.value.forEach((date, i) => { if (i !== 0 && i !== n - 1 && i % labelStep !== 0) return; const x = n === 1 ? padding.left + cw / 2 : padding.left + cw * i / (n - 1); ctx.fillText(date.slice(5), x, padding.top + ch + 8); }); } if (threshold) { const y = valueToY(threshold.fasting); if (y >= padding.top && y <= padding.top + ch) { ctx.strokeStyle = "#fda4af"; ctx.lineWidth = 1; try { ctx.setLineDash([6, 5]); } catch (e) { } ctx.beginPath(); ctx.moveTo(padding.left, y); ctx.lineTo(padding.left + cw, y); ctx.stroke(); try { ctx.setLineDash([]); } catch (e) { } ctx.font = "bold 11px sans-serif"; ctx.fillStyle = "#dc2626"; ctx.textAlign = "left"; ctx.textBaseline = "middle"; ctx.fillText(`空腹阈 ${threshold.fasting}`, padding.left + 6, y - 9); } } const xAt = (i) => n === 1 ? padding.left + cw / 2 : padding.left + cw * i / (n - 1); const coordByKey = { fasting: [], postprandial: [] }; const showDots = n <= 10; seriesDefs.forEach((meta) => { const projected = meta.data.map((v, i) => ({ x: xAt(i), y: v === null ? null : valueToY(v), value: v })); coordByKey[meta.key] = projected; if (!chartSeriesVisible.value[meta.key]) return; const segments = []; let cur = []; projected.forEach((p) => { if (p.y !== null) cur.push(p); else if (cur.length) { segments.push(cur); cur = []; } }); if (cur.length) segments.push(cur); segments.forEach((seg) => { if (seg.length === 1) { ctx.fillStyle = meta.color; ctx.beginPath(); ctx.arc(seg[0].x, seg[0].y, 4, 0, Math.PI * 2); ctx.fill(); return; } const drawPath = () => { ctx.beginPath(); ctx.moveTo(seg[0].x, seg[0].y); for (let i = 0; i < seg.length - 1; i++) { const p0 = seg[i - 1] || seg[i]; const p1 = seg[i]; const p2 = seg[i + 1]; const p3 = seg[i + 2] || seg[i + 1]; const cp1x = p1.x + (p2.x - p0.x) / 6; const cp1y = p1.y + (p2.y - p0.y) / 6; const cp2x = p2.x - (p3.x - p1.x) / 6; const cp2y = p2.y - (p3.y - p1.y) / 6; ctx.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, p2.x, p2.y); } }; drawPath(); ctx.lineTo(seg[seg.length - 1].x, padding.top + ch); ctx.lineTo(seg[0].x, padding.top + ch); ctx.closePath(); const grad = ctx.createLinearGradient(0, padding.top, 0, padding.top + ch); grad.addColorStop(0, meta.fillTop); grad.addColorStop(1, meta.fillBottom); ctx.fillStyle = grad; ctx.fill(); drawPath(); ctx.strokeStyle = meta.color; ctx.lineWidth = 2.4; ctx.lineCap = "round"; ctx.lineJoin = "round"; ctx.stroke(); if (showDots) { seg.forEach((p) => { ctx.beginPath(); ctx.arc(p.x, p.y, 3, 0, Math.PI * 2); ctx.fillStyle = "#ffffff"; ctx.fill(); ctx.strokeStyle = meta.color; ctx.lineWidth = 1.8; ctx.stroke(); }); } }); let maxIdx = -1; let maxVal = -Infinity; projected.forEach((p, i) => { if (p.value != null && p.value > maxVal) { maxVal = p.value; maxIdx = i; } }); if (maxIdx >= 0) { const p = projected[maxIdx]; const isHigh = meta.highThreshold != null && p.value >= meta.highThreshold; ctx.beginPath(); ctx.arc(p.x, p.y, 5, 0, Math.PI * 2); ctx.fillStyle = isHigh ? "#dc2626" : meta.color; ctx.fill(); ctx.strokeStyle = "#ffffff"; ctx.lineWidth = 2.5; ctx.stroke(); const labelText = String(p.value); ctx.font = "bold 12px sans-serif"; const textWidth = ctx.measureText(labelText).width; const padX = 8; const padY = 5; const boxWidth = textWidth + padX * 2; const boxHeight = 14 + padY * 2; let labelX = p.x; let labelAbove = true; if (p.y - 12 - boxHeight - 4 < padding.top) labelAbove = false; let labelY = labelAbove ? p.y - 12 - boxHeight / 2 : p.y + 12 + boxHeight / 2; if (labelX - boxWidth / 2 < padding.left + 2) labelX = padding.left + boxWidth / 2 + 2; if (labelX + boxWidth / 2 > padding.left + cw - 2) labelX = padding.left + cw - boxWidth / 2 - 2; ctx.fillStyle = isHigh ? "#dc2626" : meta.color; ctx.fillRect(labelX - boxWidth / 2, labelY - boxHeight / 2, boxWidth, boxHeight); ctx.fillStyle = "#ffffff"; ctx.textAlign = "center"; ctx.textBaseline = "middle"; ctx.fillText(labelText, labelX, labelY); } }); chartCoords = { padding, cw, ch, n, fasting: coordByKey.fasting, postprandial: coordByKey.postprandial }; } function toggleChartSeries(key) { if (key !== "fasting" && key !== "postprandial") return; chartSeriesVisible.value[key] = !chartSeriesVisible.value[key]; hoverInfo.value = null; scheduleChartRedraw(); } function onChartTouch(e) { if (!chartCoords || !canvasWidth) return; if (!chartDates.value.length) return; let touchX = 0; let touchY = 0; if (e && e.touches && e.touches[0]) { touchX = e.touches[0].x ?? e.touches[0].clientX ?? 0; touchY = e.touches[0].y ?? e.touches[0].clientY ?? 0; } const { padding, cw, n } = chartCoords; if (touchX < padding.left || touchX > padding.left + cw) { return; } const ratio = n <= 1 ? 0 : (touchX - padding.left) / cw; let idx = Math.round(ratio * (n - 1)); if (idx < 0) idx = 0; if (idx > n - 1) idx = n - 1; const date = chartDates.value[idx]; const fp = chartSeriesVisible.value.fasting ? chartCoords.fasting[idx] : null; const pp = chartSeriesVisible.value.postprandial ? chartCoords.postprandial[idx] : null; const anchorX = (fp == null ? void 0 : fp.x) ?? (pp == null ? void 0 : pp.x) ?? padding.left + cw * (idx / Math.max(1, n - 1)); const left = Math.max(8, Math.min(canvasWidth - 130, anchorX - 60)); const top = Math.max(4, touchY - 70); hoverInfo.value = { date: date.slice(5), fasting: (fp == null ? void 0 : fp.value) ?? null, postprandial: (pp == null ? void 0 : pp.value) ?? null, left, top }; if (hoverTimer) clearTimeout(hoverTimer); hoverTimer = setTimeout(() => { hoverInfo.value = null; }, 2500); } common_vendor.watch(rangeMode, () => { scheduleChartRedraw(); }); function readUserContext() { try { const userData = common_vendor.index.getStorageSync("userData"); if (userData && userData.diagnosis) { if (!patientId.value) patientId.value = Number(userData.diagnosis.patient_id) || 0; if (!diagnosisId.value) diagnosisId.value = Number(userData.diagnosis.id) || 0; if (!patientName.value) patientName.value = userData.diagnosis.patient_name || ""; if (!age.value) age.value = Number(userData.diagnosis.age) || 0; if (!gender.value) gender.value = Number(userData.diagnosis.gender) || 0; } } catch (e) { } } async function bootstrap(options) { options = options || {}; const inviteCode = String(options.invite_code || "").trim(); if (options.from === "share" && inviteCode) { authChecking.value = false; await bootstrapInviteViewer(inviteCode); return; } isInviteViewer.value = false; authChecking.value = true; const passedDiagnosisId = Number(options.diagnosis_id || options.id || 0); Number(options.patient_id || 0); options.patient_name ? decodeURIComponent(String(options.patient_name)) : ""; Number(options.age) || 0; Number(options.gender) || 0; const loggedIn = await ensureLoggedIn(); if (!loggedIn || !hasAuthToken()) { authChecking.value = false; showUserToast("登录失败,请稍后重试"); return; } readUserContext(); const list = await fetchCardList(); if (Array.isArray(list) && list.length > 0) { let target = null; if (passedDiagnosisId) { target = list.find((c) => Number(c.id) === Number(passedDiagnosisId)); } if (!target) target = list[0]; await applyCard(target); } else { diagnosisId.value = 0; patientId.value = 0; patientName.value = ""; age.value = 0; gender.value = 0; readUserMobile(); if (userMobile.value) { await ensureDailyContextByPhone(); } } authChecking.value = false; if (diagnosisId.value) { await fetchAll(); } } common_vendor.onLoad((options) => { bootstrap(options); }); common_vendor.onShow(() => { if (authChecking.value) return; common_vendor.nextTick$1(() => scheduleChartRedraw()); }); common_vendor.onPullDownRefresh(async () => { if (isInviteViewer.value) { const code = invitePreview.value.invite_code; if (code) await bootstrapInviteViewer(code); } else if (await ensureLoggedIn()) { await fetchAll(); } common_vendor.index.stopPullDownRefresh(); }); common_vendor.onHide(() => { ttsStop(); }); common_vendor.onUnload(() => { ttsStop(); }); const isInviteViewer = common_vendor.ref(false); const inviteLoading = common_vendor.ref(false); const inviteError = common_vendor.ref(""); const invitePreview = common_vendor.ref({}); const inviteLiking = common_vendor.ref(false); const inviteLikeNickname = common_vendor.ref("家人"); const inviteHeartBurst = common_vendor.ref(false); const familyNicknameOptions = ["家人", "亲友", "老伴", "子女"]; function hapticLight() { try { common_vendor.index.vibrateShort({ type: "light" }); } catch (e) { } } function getViewerKey() { try { let key = common_vendor.index.getStorageSync(VIEWER_KEY_STORAGE); if (!key) { key = `v_${Date.now()}_${Math.random().toString(36).slice(2, 12)}`; common_vendor.index.setStorageSync(VIEWER_KEY_STORAGE, key); } return String(key).slice(0, 64); } catch (e) { return `v_${Date.now()}`; } } const inviteTreeLevel = common_vendor.computed(() => Number(invitePreview.value.tree_level) || 0); const inviteDailyRecords = common_vendor.computed(() => { const list = invitePreview.value.daily_records; return Array.isArray(list) ? list : []; }); function formatInviteSugar(v) { if (v == null || v === "") return "—"; return String(v); } const INVITE_TREE_WHISPERS = [ "Ta 正在努力控糖,您的鼓励很重要。", "好习惯比完美数值更珍贵,一起加油。", "每天记一笔,就是在照顾未来的自己。", "点赞一下,让 Ta 知道家人在身边。" ]; function onInviteTreeWhisper() { const line = INVITE_TREE_WHISPERS[Math.floor(Math.random() * INVITE_TREE_WHISPERS.length)]; showUserToast(line, { duration: 2800 }); hapticLight(); } async function bootstrapInviteViewer(inviteCode) { isInviteViewer.value = true; inviteLoading.value = true; inviteError.value = ""; invitePreview.value = {}; inviteHeartBurst.value = false; try { const res = await proxy.apiUrl({ url: "/api/tcm/dailySharePreview", method: "GET", data: { invite_code: inviteCode, viewer_key: getViewerKey() } }, false); if (res && res.code === 1 && res.data) { invitePreview.value = res.data; } else { inviteError.value = formatUserMessage(res && res.msg, "邀请码无效或已过期"); } } catch (e) { inviteError.value = "加载失败,请稍后再试"; } finally { inviteLoading.value = false; } } async function onFamilyLike() { const code = invitePreview.value.invite_code; if (!code || inviteLiking.value) return; if (invitePreview.value.liked_by_me) { showUserToast("您今天已经点过赞啦"); return; } inviteLiking.value = true; try { const res = await proxy.apiUrl({ url: "/api/tcm/dailyFamilyLike", method: "POST", data: { invite_code: code, viewer_key: getViewerKey(), nickname: inviteLikeNickname.value } }, false); if (res && res.code === 1 && res.data) { const data = res.data; const alreadyLiked = !!data.already_liked; invitePreview.value = { ...invitePreview.value, like_count: Number(data.like_count) || 0, liked_by_me: true }; if (alreadyLiked) { showUserToast(data.praise_message || "您今天已经点过赞啦"); return; } inviteHeartBurst.value = true; setTimeout(() => { inviteHeartBurst.value = false; }, 900); hapticLight(); triggerCelebrate("鼓励已送达", data.praise_message || "谢谢您的点赞"); } else { showUserToast(res && res.msg || "点赞失败"); } } catch (e) { showUserToast("点赞失败,请稍后再试"); } finally { inviteLiking.value = false; } } return (_ctx, _cache) => { return common_vendor.e({ a: isInviteViewer.value }, isInviteViewer.value ? common_vendor.e({ b: common_vendor.p({ name: "view", size: "md", color: "#FFFFFF" }), c: common_vendor.t(invitePreview.value.viewer_notice || "近7日稳糖记录"), d: common_vendor.t(invitePreview.value.expires_hint || "邀请码仅今日有效"), e: invitePreview.value.patient_label }, invitePreview.value.patient_label ? { f: common_vendor.p({ name: "users", size: "sm", color: "#A5F3FC" }), g: common_vendor.t(invitePreview.value.patient_label) } : {}, { h: inviteLoading.value }, inviteLoading.value ? {} : invitePreview.value.invite_code ? common_vendor.e({ j: common_vendor.p({ name: "ticket", size: "md", color: "#204E2B" }), k: common_vendor.t(invitePreview.value.invite_code), l: common_vendor.p({ level: inviteTreeLevel.value, size: "md" }), m: common_vendor.o(onInviteTreeWhisper, "87"), n: common_vendor.t(invitePreview.value.tree_title || "控糖树"), o: common_vendor.t(invitePreview.value.tree_desc || ""), p: common_vendor.t(invitePreview.value.week_label || ""), q: common_vendor.p({ name: "calendar", size: "sm", color: "#204E2B" }), r: common_vendor.t(invitePreview.value.record_days), s: common_vendor.p({ name: "check-circle", size: "sm", color: "#386641" }), t: common_vendor.t(invitePreview.value.complete_days), v: common_vendor.p({ name: "flame", size: "sm", color: "#EA580C" }), w: common_vendor.t(invitePreview.value.streak_days), x: invitePreview.value.quote }, invitePreview.value.quote ? { y: common_vendor.t(invitePreview.value.quote) } : {}, { z: common_vendor.p({ name: "glucose", size: "md", color: "#386641" }), A: !inviteDailyRecords.value.length }, !inviteDailyRecords.value.length ? { B: common_vendor.p({ name: "minus", size: "lg", color: "#94A3B8" }) } : { C: common_vendor.f(inviteDailyRecords.value, (day, idx, i0) => { return common_vendor.e({ a: day.has_record ? 1 : "", b: idx < inviteDailyRecords.value.length - 1 }, idx < inviteDailyRecords.value.length - 1 ? {} : {}, { c: common_vendor.t(day.date_label), d: common_vendor.t(day.weekday), e: day.has_record }, day.has_record ? common_vendor.e({ f: common_vendor.t(formatInviteSugar(day.fasting)), g: day.fasting_high ? 1 : "", h: day.fasting != null }, day.fasting != null ? {} : {}, { i: day.fasting_high }, day.fasting_high ? { j: "612eeee9-9-" + i0, k: common_vendor.p({ name: "alert-triangle", size: "sm", color: "#DC2626" }) } : {}, { l: common_vendor.t(formatInviteSugar(day.postprandial)), m: day.postprandial_high ? 1 : "", n: day.postprandial != null }, day.postprandial != null ? {} : {}, { o: day.postprandial_high }, day.postprandial_high ? { p: "612eeee9-10-" + i0, q: common_vendor.p({ name: "alert-triangle", size: "sm", color: "#DC2626" }) } : {}, { r: day.bp_text }, day.bp_text ? common_vendor.e({ s: common_vendor.t(day.bp_text), t: day.bp_high ? 1 : "", v: day.bp_high }, day.bp_high ? { w: "612eeee9-11-" + i0, x: common_vendor.p({ name: "alert-triangle", size: "sm", color: "#DC2626" }) } : {}) : {}) : { y: "612eeee9-12-" + i0, z: common_vendor.p({ name: "minus", size: "sm", color: "#94A3B8" }) }, { A: day.date, B: !day.has_record ? 1 : "", C: idx === inviteDailyRecords.value.length - 1 ? 1 : "" }); }) }, { D: common_vendor.p({ name: "heart", size: "md", color: "#386641" }), E: common_vendor.t(invitePreview.value.like_count || 0), F: common_vendor.f(familyNicknameOptions, (n, k0, i0) => { return { a: common_vendor.t(n), b: n, c: inviteLikeNickname.value === n ? 1 : "", d: common_vendor.o(($event) => inviteLikeNickname.value = n, n) }; }), G: !invitePreview.value.liked_by_me }, !invitePreview.value.liked_by_me ? { H: common_vendor.p({ name: "heart", size: "md", color: "#FFFFFF" }) } : {}, { I: common_vendor.t(invitePreview.value.liked_by_me ? "今日已点赞,谢谢您的鼓励" : "送 Ta 一份鼓励"), J: invitePreview.value.liked_by_me ? 1 : "", K: inviteLiking.value ? 1 : "", L: inviteHeartBurst.value ? 1 : "", M: common_vendor.o(onFamilyLike, "5e"), N: common_vendor.p({ name: "activity", size: "sm", color: "#64748B" }) }) : { O: common_vendor.p({ name: "alert-triangle", size: "xl", color: "#DC2626" }), P: common_vendor.t(inviteError.value || "邀请码无效或已过期") }, { i: invitePreview.value.invite_code }) : {}, { Q: authChecking.value && !isInviteViewer.value }, authChecking.value && !isInviteViewer.value ? {} : {}, { R: !isInviteViewer.value && !authChecking.value }, !isInviteViewer.value && !authChecking.value ? common_vendor.e({ S: common_vendor.t(timeGreetingMeta.value.text), T: common_vendor.t(patientName.value || "您好"), U: common_vendor.t(todayChecked.value ? "今日血糖已记录" : "今日还没记血糖"), V: common_vendor.n(todayChecked.value ? "is-done" : "is-pending"), W: cards.value.length > 1 }, cards.value.length > 1 ? { X: common_vendor.f(cards.value, (card, k0, i0) => { return { a: common_vendor.t(card.patient_name || "就诊卡"), b: card.id, c: Number(card.id) === Number(diagnosisId.value) ? 1 : "", d: common_vendor.o(($event) => onSelectCard(card), card.id) }; }) } : {}, { Y: common_vendor.p({ name: "plus", size: "lg", color: "#FFFFFF" }), Z: common_vendor.o(($event) => openInputForm(), "0b"), aa: common_vendor.p({ name: ttsSpeaking.value ? "pause" : "volume", size: "md", color: "#204E2B" }), ab: common_vendor.t(ttsSpeaking.value ? "停止朗读" : "朗读血糖"), ac: ttsSpeaking.value ? 1 : "", ad: !ttsEnabled.value ? 1 : "", ae: common_vendor.o(($event) => ttsSpeaking.value ? ttsStop() : speakLatestSummary(), "0e"), af: diagnosisId.value }, diagnosisId.value ? common_vendor.e({ ag: common_vendor.t(rangeText.value), ah: !chartSeriesVisible.value.fasting ? 1 : "", ai: common_vendor.o(($event) => toggleChartSeries("fasting"), "91"), aj: !chartSeriesVisible.value.postprandial ? 1 : "", ak: common_vendor.o(($event) => toggleChartSeries("postprandial"), "df"), al: bloodHasData.value && bloodHighDayCount.value > 0 }, bloodHasData.value && bloodHighDayCount.value > 0 ? { am: common_vendor.t(bloodHighDayCount.value), an: common_vendor.t(bloodNormalDayCount.value), ao: common_vendor.t(bloodRecordDayCount.value) } : {}, { ap: !recordOverlayOpen.value }, !recordOverlayOpen.value ? { aq: common_vendor.o(onChartTouch, "28"), ar: common_vendor.o(onChartTouch, "83") } : {}, { as: recordOverlayOpen.value }, recordOverlayOpen.value ? {} : {}, { at: !bloodHasData.value && !loading.value && !recordOverlayOpen.value }, !bloodHasData.value && !loading.value && !recordOverlayOpen.value ? {} : {}, { av: hoverInfo.value && !recordOverlayOpen.value }, hoverInfo.value && !recordOverlayOpen.value ? common_vendor.e({ aw: common_vendor.t(hoverInfo.value.date), ax: hoverInfo.value.fasting != null }, hoverInfo.value.fasting != null ? { ay: common_vendor.t(hoverInfo.value.fasting) } : {}, { az: hoverInfo.value.postprandial != null }, hoverInfo.value.postprandial != null ? { aA: common_vendor.t(hoverInfo.value.postprandial) } : {}, { aB: hoverInfo.value.left + "px", aC: hoverInfo.value.top + "px" }) : {}, { aD: common_vendor.f(rangeOptions, (opt, k0, i0) => { return { a: common_vendor.t(opt.label), b: opt.value, c: rangeMode.value === opt.value ? 1 : "", d: common_vendor.o(($event) => onChangeRange(opt.value), opt.value) }; }) }) : {}, { aE: common_vendor.t(elderFasting.value.label), aF: common_vendor.t(elderFasting.value.value), aG: elderFasting.value.value !== "—" }, elderFasting.value.value !== "—" ? {} : {}, { aH: elderFasting.value.isHigh }, elderFasting.value.isHigh ? {} : {}, { aI: elderFasting.value.isHigh ? 1 : "", aJ: common_vendor.t(elderPostprandial.value.label), aK: common_vendor.t(elderPostprandial.value.value), aL: elderPostprandial.value.value !== "—" }, elderPostprandial.value.value !== "—" ? {} : {}, { aM: elderPostprandial.value.isHigh }, elderPostprandial.value.isHigh ? {} : {}, { aN: elderPostprandial.value.isHigh ? 1 : "", aO: common_vendor.o(goMorePage, "ee"), aP: diagnosisId.value }, diagnosisId.value ? common_vendor.e({ aQ: common_vendor.p({ name: "sparkles", size: "md", color: "#ffffff" }), aR: common_vendor.unref(dietAiLoading) ? 1 : "", aS: common_vendor.p({ name: "refresh", size: "sm", color: "#ffffff" }), aT: common_vendor.t(common_vendor.unref(dietAiLoading) ? "生成中" : "换一换"), aU: common_vendor.unref(dietAiLoading) ? 1 : "", aV: common_vendor.o((...args) => common_vendor.unref(refreshDietAiRecommend) && common_vendor.unref(refreshDietAiRecommend)(...args), "8d"), aW: common_vendor.unref(dietAiLoading) && !common_vendor.unref(hasDietAiMealContent) && !common_vendor.unref(dietAiStreaming) && !common_vendor.unref(dietAiReplacing) }, common_vendor.unref(dietAiLoading) && !common_vendor.unref(hasDietAiMealContent) && !common_vendor.unref(dietAiStreaming) && !common_vendor.unref(dietAiReplacing) ? { aX: common_vendor.f(3, (n, k0, i0) => { return { a: "sk-" + n }; }) } : common_vendor.e({ aY: common_vendor.unref(dietAiStreaming) }, common_vendor.unref(dietAiStreaming) ? {} : {}, { aZ: common_vendor.p({ name: "sun", size: "sm", color: "#ffffff" }), ba: common_vendor.t(common_vendor.unref(dietAiRecommend).breakfast || (common_vendor.unref(dietAiLoading) ? "…" : "—")), bb: common_vendor.unref(dietAiLoading) && common_vendor.unref(dietAiStreamField) === "breakfast" }, common_vendor.unref(dietAiLoading) && common_vendor.unref(dietAiStreamField) === "breakfast" ? {} : {}, { bc: common_vendor.unref(dietAiRecommend).drinks || common_vendor.unref(dietAiLoading) && common_vendor.unref(dietAiStreamField) === "drinks" }, common_vendor.unref(dietAiRecommend).drinks || common_vendor.unref(dietAiLoading) && common_vendor.unref(dietAiStreamField) === "drinks" ? common_vendor.e({ bd: common_vendor.p({ name: "droplet", size: "sm", color: "#ffffff" }), be: common_vendor.t(common_vendor.unref(dietAiRecommend).drinks || "…"), bf: common_vendor.unref(dietAiLoading) && common_vendor.unref(dietAiStreamField) === "drinks" }, common_vendor.unref(dietAiLoading) && common_vendor.unref(dietAiStreamField) === "drinks" ? {} : {}) : {}, { bg: common_vendor.p({ name: "sunset", size: "sm", color: "#ffffff" }), bh: common_vendor.t(common_vendor.unref(dietAiRecommend).lunch || (common_vendor.unref(dietAiLoading) ? "…" : "—")), bi: common_vendor.unref(dietAiLoading) && common_vendor.unref(dietAiStreamField) === "lunch" }, common_vendor.unref(dietAiLoading) && common_vendor.unref(dietAiStreamField) === "lunch" ? {} : {}, { bj: common_vendor.p({ name: "moon", size: "sm", color: "#ffffff" }), bk: common_vendor.t(common_vendor.unref(dietAiRecommend).dinner || (common_vendor.unref(dietAiLoading) ? "…" : "—")), bl: common_vendor.unref(dietAiLoading) && common_vendor.unref(dietAiStreamField) === "dinner" }, common_vendor.unref(dietAiLoading) && common_vendor.unref(dietAiStreamField) === "dinner" ? {} : {}, { bm: common_vendor.unref(dietAiRecommend).tips || common_vendor.unref(dietAiLoading) && common_vendor.unref(dietAiStreamField) === "tips" }, common_vendor.unref(dietAiRecommend).tips || common_vendor.unref(dietAiLoading) && common_vendor.unref(dietAiStreamField) === "tips" ? common_vendor.e({ bn: common_vendor.p({ name: "info", size: "sm", color: "#386641" }), bo: common_vendor.t(common_vendor.unref(dietAiRecommend).tips || "…"), bp: common_vendor.unref(dietAiLoading) && common_vendor.unref(dietAiStreamField) === "tips" }, common_vendor.unref(dietAiLoading) && common_vendor.unref(dietAiStreamField) === "tips" ? {} : {}) : {}, { bq: common_vendor.unref(dietAiRecommend).avoid && common_vendor.unref(dietAiRecommend).avoid.length }, common_vendor.unref(dietAiRecommend).avoid && common_vendor.unref(dietAiRecommend).avoid.length ? { br: common_vendor.p({ name: "alert-triangle", size: "sm", color: "#b91c1c" }), bs: common_vendor.f(common_vendor.unref(dietAiRecommend).avoid, (item, idx, i0) => { return { a: common_vendor.t(item), b: "avoid-" + idx }; }) } : {}, { bt: !common_vendor.unref(dietAiLoading) }, !common_vendor.unref(dietAiLoading) ? { bv: common_vendor.o((...args) => common_vendor.unref(applyDietAiToForm) && common_vendor.unref(applyDietAiToForm)(...args), "df"), bw: common_vendor.o((...args) => common_vendor.unref(openDietForm) && common_vendor.unref(openDietForm)(...args), "1f") } : {}, { bx: common_vendor.unref(dietAiStreaming) ? 1 : "" }), { by: dietExercise.value }, dietExercise.value ? common_vendor.e({ bz: common_vendor.p({ name: "activity", size: "sm", color: "#ffffff" }), bA: common_vendor.t(dietExercise.value.level_label), bB: common_vendor.n("lv-" + dietExercise.value.level), bC: dietExercise.value.headline }, dietExercise.value.headline ? { bD: common_vendor.t(dietExercise.value.headline) } : {}, { bE: common_vendor.f(dietExercise.value.items, (it, idx, i0) => { return { a: common_vendor.t(idx + 1), b: common_vendor.t(it), c: "ex-" + idx }; }), bF: dietExercise.value.intensity }, dietExercise.value.intensity ? { bG: common_vendor.p({ name: "flame", size: "sm", color: "#d97706" }), bH: common_vendor.t(dietExercise.value.intensity) } : {}, { bI: dietExercise.value.note }, dietExercise.value.note ? { bJ: common_vendor.t(dietExercise.value.note) } : {}, { bK: common_vendor.n("lv-" + dietExercise.value.level) }) : {}, { bL: common_vendor.unref(dietAiAskText), bM: common_vendor.o((...args) => common_vendor.unref(onDietAiAskInput) && common_vendor.unref(onDietAiAskInput)(...args), "95"), bN: common_vendor.o((...args) => common_vendor.unref(askDietAiFood) && common_vendor.unref(askDietAiFood)(...args), "4b"), bO: !common_vendor.unref(dietAiAsking) }, !common_vendor.unref(dietAiAsking) ? { bP: common_vendor.p({ name: "sparkles", size: "sm", color: "#ffffff" }) } : {}, { bQ: common_vendor.t(common_vendor.unref(dietAiAsking) ? "…" : "问 AI"), bR: common_vendor.unref(dietAiAsking) ? 1 : "", bS: common_vendor.o((...args) => common_vendor.unref(askDietAiFood) && common_vendor.unref(askDietAiFood)(...args), "e7"), bT: common_vendor.unref(dietAiAsking) || common_vendor.unref(dietAiAskResult).advice }, common_vendor.unref(dietAiAsking) || common_vendor.unref(dietAiAskResult).advice ? common_vendor.e({ bU: common_vendor.unref(dietAiAskResult).level_label }, common_vendor.unref(dietAiAskResult).level_label ? { bV: common_vendor.t(common_vendor.unref(dietAiAskResult).level_label), bW: common_vendor.n("lv-" + (common_vendor.unref(dietAiAskResult).level || "unknown")) } : {}, { bX: common_vendor.t(common_vendor.unref(dietAiAskResult).advice || (common_vendor.unref(dietAiAsking) ? "正在想…" : "")), bY: common_vendor.unref(dietAiAsking) }, common_vendor.unref(dietAiAsking) ? {} : {}, { bZ: common_vendor.unref(dietAiAskResult).portion }, common_vendor.unref(dietAiAskResult).portion ? { ca: common_vendor.t(common_vendor.unref(dietAiAskResult).portion) } : {}, { cb: common_vendor.n("lv-" + (common_vendor.unref(dietAiAskResult).level || "unknown")) }) : {}, { cc: hasDietAnalysis.value }, hasDietAnalysis.value ? { cd: common_vendor.p({ name: "activity", size: "sm", color: "#386641" }), ce: common_vendor.f(dietAnalysisList.value, (s, i, i0) => { return common_vendor.e({ a: common_vendor.t(s.label), b: s.record_days > 0 }, s.record_days > 0 ? { c: common_vendor.t(s.compliance), d: common_vendor.n(dietRateClass(s.compliance)), e: common_vendor.t(s.high_days), f: s.high_days > 0 ? 1 : "", g: common_vendor.t(dietAvgText(s.fasting_avg)), h: common_vendor.t(dietAvgText(s.postprandial_avg)), i: common_vendor.t(s.record_days) } : { j: "612eeee9-31-" + i0, k: common_vendor.p({ name: "minus", size: "sm", color: "#94A3B8" }) }, { l: "an-" + i }); }) } : {}, { cf: common_vendor.unref(dietAiRecommend).rules_summary || common_vendor.unref(dietAiRecommend).disclaimer }, common_vendor.unref(dietAiRecommend).rules_summary || common_vendor.unref(dietAiRecommend).disclaimer ? common_vendor.e({ cg: common_vendor.unref(dietAiRecommend).rules_summary }, common_vendor.unref(dietAiRecommend).rules_summary ? { ch: common_vendor.t(common_vendor.unref(dietAiRecommend).rules_summary) } : {}, { ci: common_vendor.unref(dietAiRecommend).disclaimer }, common_vendor.unref(dietAiRecommend).disclaimer ? { cj: common_vendor.t(common_vendor.unref(dietAiRecommend).disclaimer) } : {}) : {}) : {}, { ck: phoneGateVisible.value }, phoneGateVisible.value ? { cl: common_vendor.o(closePhoneGate, "fe"), cm: phoneGateSex.value === 1 ? 1 : "", cn: common_vendor.o(($event) => phoneGateSex.value = 1, "2b"), co: phoneGateSex.value === 2 ? 1 : "", cp: common_vendor.o(($event) => phoneGateSex.value = 2, "aa"), cq: phoneBinding.value, cr: phoneBinding.value || !phoneGateSex.value, cs: common_vendor.o(onPhoneGateAuthorize, "ef"), ct: common_vendor.o(() => { }, "f6"), cv: common_vendor.o(closePhoneGate, "8a") } : {}, { cw: inputForm.value.visible }, inputForm.value.visible ? common_vendor.e({ cx: common_vendor.t(inputForm.value.id ? "修改今日血糖" : "录入今日血糖"), cy: common_vendor.t(todayText.value), cz: common_vendor.t(patientName.value || "本人"), cA: common_vendor.o(closeInputForm, "5d"), cB: inputForm.value.loading }, inputForm.value.loading ? {} : { cC: inputForm.value.fasting_blood_sugar, cD: common_vendor.o(($event) => onInputField("fasting_blood_sugar", $event), "0e"), cE: inputForm.value.postprandial_blood_sugar, cF: common_vendor.o(($event) => onInputField("postprandial_blood_sugar", $event), "7e"), cG: inputForm.value.other_blood_sugar, cH: common_vendor.o(($event) => onInputField("other_blood_sugar", $event), "a1"), cI: inputForm.value.remark, cJ: common_vendor.o(($event) => onInputField("remark", $event), "bd") }, { cK: inputForm.value.id }, inputForm.value.id ? { cL: inputForm.value.submitting ? 1 : "", cM: common_vendor.o(deleteInputRecord, "d3") } : {}, { cN: common_vendor.t(inputForm.value.submitting ? "提交中…" : inputForm.value.id ? "保存修改" : "提交录入"), cO: inputForm.value.submitting || inputForm.value.loading ? 1 : "", cP: common_vendor.o(submitInputForm, "ec"), cQ: common_vendor.o(() => { }, "c3"), cR: common_vendor.o(closeInputForm, "b5") }) : {}) : {}, { cS: isInviteViewer.value ? 1 : "" }); }; } }; const MiniProgramPage = /* @__PURE__ */ common_vendor._export_sfc(_sfc_main, [["__scopeId", "data-v-612eeee9"]]); _sfc_main.__runtimeHooks = 2; wx.createPage(MiniProgramPage); //# sourceMappingURL=../../../.sourcemap/mp-weixin/tongji/pages/index.js.map