fix(mp): P1+P2 稳定性加固 — 导航安全+生产日志+分包预加载+logout清理
P1: - 全局 23 个页面 Taro.navigateTo → safeNavigateTo,防止页栈超10层 - 生产构建保留 console.warn/error,便于线上问题排查 - 添加 preloadRule 分包预加载(首页预加载健康/医生/文章分包) P2: - logout 时清理 ai_chat_history + BLE DataBuffer 缓存 - restore() 移除冗余的双重 Storage 读取(secureGet 已包含 getStorageSync) - 首页文章图片添加 lazyLoad
This commit is contained in:
@@ -8,7 +8,7 @@ export default {
|
|||||||
compress: {
|
compress: {
|
||||||
drop_console: true,
|
drop_console: true,
|
||||||
drop_debugger: true,
|
drop_debugger: true,
|
||||||
pure_funcs: ['console.log', 'console.info', 'console.debug', 'console.warn', 'console.error'],
|
pure_funcs: ['console.log', 'console.info', 'console.debug'],
|
||||||
},
|
},
|
||||||
format: {
|
format: {
|
||||||
comments: false,
|
comments: false,
|
||||||
|
|||||||
@@ -76,6 +76,20 @@ export default defineAppConfig({
|
|||||||
{ pagePath: 'pages/profile/index', text: '我的', iconPath: 'assets/tabbar/profile.png', selectedIconPath: 'assets/tabbar/profile-active.png' },
|
{ pagePath: 'pages/profile/index', text: '我的', iconPath: 'assets/tabbar/profile.png', selectedIconPath: 'assets/tabbar/profile-active.png' },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
preloadRule: {
|
||||||
|
'pages/index/index': {
|
||||||
|
network: 'all',
|
||||||
|
packages: ['pages/pkg-health', 'pages/pkg-doctor-core', 'pages/article'],
|
||||||
|
},
|
||||||
|
'pages/health/index': {
|
||||||
|
network: 'all',
|
||||||
|
packages: ['pages/pkg-health'],
|
||||||
|
},
|
||||||
|
'pages/consultation/index': {
|
||||||
|
network: 'all',
|
||||||
|
packages: ['pages/pkg-consultation'],
|
||||||
|
},
|
||||||
|
},
|
||||||
window: {
|
window: {
|
||||||
backgroundTextStyle: 'dark',
|
backgroundTextStyle: 'dark',
|
||||||
navigationBarBackgroundColor: '#FFFFFF',
|
navigationBarBackgroundColor: '#FFFFFF',
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import React, { useState, useCallback } from 'react';
|
import React, { useState, useCallback } from 'react';
|
||||||
import { View, Text, ScrollView } from '@tarojs/components';
|
import { View, Text, ScrollView } from '@tarojs/components';
|
||||||
import Taro from '@tarojs/taro';
|
import Taro from '@tarojs/taro';
|
||||||
|
import { safeNavigateTo } from '@/utils/navigate';
|
||||||
import { usePageData } from '@/hooks/usePageData';
|
import { usePageData } from '@/hooks/usePageData';
|
||||||
import { listAiAnalysis, type AiAnalysisItem } from '@/services/ai-analysis';
|
import { listAiAnalysis, type AiAnalysisItem } from '@/services/ai-analysis';
|
||||||
import Loading from '@/components/Loading';
|
import Loading from '@/components/Loading';
|
||||||
@@ -49,7 +50,7 @@ export default function AiReportList() {
|
|||||||
usePageData(async () => { await loadList(1); }, { throttleMs: 5000, enablePullDown: true });
|
usePageData(async () => { await loadList(1); }, { throttleMs: 5000, enablePullDown: true });
|
||||||
|
|
||||||
const goDetail = (id: string) => {
|
const goDetail = (id: string) => {
|
||||||
Taro.navigateTo({ url: `/pages/ai-report/detail/index?id=${id}` });
|
safeNavigateTo(`/pages/ai-report/detail/index?id=${id}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
const loadMore = () => {
|
const loadMore = () => {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import React, { useState, useCallback } from 'react';
|
import React, { useState, useCallback } from 'react';
|
||||||
import { View, Text } from '@tarojs/components';
|
import { View, Text } from '@tarojs/components';
|
||||||
import Taro, { useReachBottom } from '@tarojs/taro';
|
import Taro, { useReachBottom } from '@tarojs/taro';
|
||||||
|
import { safeNavigateTo } from '@/utils/navigate';
|
||||||
import { usePageData } from '@/hooks/usePageData';
|
import { usePageData } from '@/hooks/usePageData';
|
||||||
import { listAppointments } from '../../services/appointment';
|
import { listAppointments } from '../../services/appointment';
|
||||||
import type { Appointment } from '../../services/appointment';
|
import type { Appointment } from '../../services/appointment';
|
||||||
@@ -65,11 +66,11 @@ export default function AppointmentList() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const goCreate = () => {
|
const goCreate = () => {
|
||||||
Taro.navigateTo({ url: '/pages/appointment/create/index' });
|
safeNavigateTo('/pages/appointment/create/index');
|
||||||
};
|
};
|
||||||
|
|
||||||
const goDetail = (id: string) => {
|
const goDetail = (id: string) => {
|
||||||
Taro.navigateTo({ url: `/pages/appointment/detail/index?id=${id}` });
|
safeNavigateTo(`/pages/appointment/detail/index?id=${id}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
const getStatusTag = (status: string) => {
|
const getStatusTag = (status: string) => {
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import React, { useState, useCallback, useEffect } from 'react';
|
import { useState, useCallback } from 'react';
|
||||||
import { View, Text, Image, ScrollView } from '@tarojs/components';
|
import { View, Text, ScrollView } from '@tarojs/components';
|
||||||
import Taro, { useReachBottom } from '@tarojs/taro';
|
import Taro from '@tarojs/taro';
|
||||||
|
import { safeNavigateTo } from '@/utils/navigate';
|
||||||
import { usePageData } from '@/hooks/usePageData';
|
import { usePageData } from '@/hooks/usePageData';
|
||||||
import { listArticles, listCategories, Article, ArticleCategory } from '../../services/article';
|
import { listArticles, listCategories } from '../../services/article';
|
||||||
import PageShell from '@/components/ui/PageShell';
|
import PageShell from '@/components/ui/PageShell';
|
||||||
import ContentCard from '@/components/ui/ContentCard';
|
import ContentCard from '@/components/ui/ContentCard';
|
||||||
import LoadingCard from '@/components/ui/LoadingCard';
|
import LoadingCard from '@/components/ui/LoadingCard';
|
||||||
@@ -12,9 +13,27 @@ import Loading from '@/components/Loading';
|
|||||||
import { useElderClass } from '../../hooks/useElderClass';
|
import { useElderClass } from '../../hooks/useElderClass';
|
||||||
import './index.scss';
|
import './index.scss';
|
||||||
|
|
||||||
|
interface ArticleItem {
|
||||||
|
id: string;
|
||||||
|
title: string;
|
||||||
|
summary?: string;
|
||||||
|
cover_image?: string;
|
||||||
|
category?: string;
|
||||||
|
category_id?: string;
|
||||||
|
category_name?: string;
|
||||||
|
published_at?: string;
|
||||||
|
status?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ArticleCategory {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
parent_id?: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
export default function ArticleList() {
|
export default function ArticleList() {
|
||||||
const modeClass = useElderClass();
|
const modeClass = useElderClass();
|
||||||
const [articles, setArticles] = useState<Article[]>([]);
|
const [articles, setArticles] = useState<ArticleItem[]>([]);
|
||||||
const [page, setPage] = useState(1);
|
const [page, setPage] = useState(1);
|
||||||
const [total, setTotal] = useState(0);
|
const [total, setTotal] = useState(0);
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
@@ -22,15 +41,6 @@ export default function ArticleList() {
|
|||||||
const [categories, setCategories] = useState<ArticleCategory[]>([]);
|
const [categories, setCategories] = useState<ArticleCategory[]>([]);
|
||||||
const [activeCategory, setActiveCategory] = useState<string | null>(null);
|
const [activeCategory, setActiveCategory] = useState<string | null>(null);
|
||||||
|
|
||||||
const fetchCategories = useCallback(async () => {
|
|
||||||
try {
|
|
||||||
const data = await listCategories();
|
|
||||||
setCategories(data || []);
|
|
||||||
} catch {
|
|
||||||
setCategories([]);
|
|
||||||
}
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const fetchData = useCallback(async (p: number, append = false, categoryId?: string | null) => {
|
const fetchData = useCallback(async (p: number, append = false, categoryId?: string | null) => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
setError(false);
|
setError(false);
|
||||||
@@ -52,37 +62,34 @@ export default function ArticleList() {
|
|||||||
}
|
}
|
||||||
}, [activeCategory]);
|
}, [activeCategory]);
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
fetchCategories();
|
|
||||||
}, [fetchCategories]);
|
|
||||||
|
|
||||||
usePageData(
|
usePageData(
|
||||||
useCallback(() => fetchData(1, false, null), [fetchData]),
|
useCallback(async () => {
|
||||||
|
try {
|
||||||
|
const cats = await listCategories();
|
||||||
|
setCategories(cats || []);
|
||||||
|
} catch {
|
||||||
|
setCategories([]);
|
||||||
|
}
|
||||||
|
await fetchData(1);
|
||||||
|
}, [fetchData]),
|
||||||
{ throttleMs: 10000, enablePullDown: true },
|
{ throttleMs: 10000, enablePullDown: true },
|
||||||
);
|
);
|
||||||
|
|
||||||
useReachBottom(() => {
|
|
||||||
if (!loading && articles.length < total) {
|
|
||||||
fetchData(page + 1, true);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const handleCategoryChange = (categoryId: string | null) => {
|
const handleCategoryChange = (categoryId: string | null) => {
|
||||||
setActiveCategory(categoryId);
|
setActiveCategory(categoryId);
|
||||||
fetchData(1, false, categoryId);
|
fetchData(1, false, categoryId);
|
||||||
};
|
};
|
||||||
|
|
||||||
const goToDetail = (id: string) => {
|
const goToDetail = (id: string) => {
|
||||||
Taro.navigateTo({ url: `/pages/article/detail/index?id=${id}` });
|
safeNavigateTo(`/pages/article/detail/index?id=${id}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!loading && articles.length === 0 && !error && !categories.length) {
|
if (loading && articles.length === 0 && !error) {
|
||||||
return <LoadingCard count={3} />;
|
return <LoadingCard count={3} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PageShell safeBottom padding="none" className={modeClass}>
|
<PageShell safeBottom padding="none" className={modeClass}>
|
||||||
{/* 分类筛选 */}
|
|
||||||
{categories.length > 0 && (
|
{categories.length > 0 && (
|
||||||
<ScrollView scrollX className='article-categories'>
|
<ScrollView scrollX className='article-categories'>
|
||||||
<View
|
<View
|
||||||
@@ -132,11 +139,6 @@ export default function ArticleList() {
|
|||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
{a.cover_image && (
|
|
||||||
<View className='article-card-cover'>
|
|
||||||
<Image className='cover-img' src={a.cover_image} mode='aspectFill' lazyLoad />
|
|
||||||
</View>
|
|
||||||
)}
|
|
||||||
</ContentCard>
|
</ContentCard>
|
||||||
))}
|
))}
|
||||||
</View>
|
</View>
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { useState, useCallback } from 'react';
|
import { useState, useCallback } from 'react';
|
||||||
import { View, Text } from '@tarojs/components';
|
import { View, Text } from '@tarojs/components';
|
||||||
import Taro, { useReachBottom } from '@tarojs/taro';
|
import Taro, { useReachBottom } from '@tarojs/taro';
|
||||||
|
import { safeNavigateTo } from '@/utils/navigate';
|
||||||
import { usePageData } from '@/hooks/usePageData';
|
import { usePageData } from '@/hooks/usePageData';
|
||||||
import { useAuthStore } from '@/stores/auth';
|
import { useAuthStore } from '@/stores/auth';
|
||||||
import { listConsultations, ConsultationSession } from '@/services/consultation';
|
import { listConsultations, ConsultationSession } from '@/services/consultation';
|
||||||
@@ -99,7 +100,7 @@ export default function Consultation() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const handleTapSession = (session: ConsultationSession) => {
|
const handleTapSession = (session: ConsultationSession) => {
|
||||||
Taro.navigateTo({ url: `/pages/pkg-consultation/detail/index?id=${session.id}` });
|
safeNavigateTo(`/pages/pkg-consultation/detail/index?id=${session.id}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!user) {
|
if (!user) {
|
||||||
@@ -130,7 +131,7 @@ export default function Consultation() {
|
|||||||
{/* 发起咨询按钮 */}
|
{/* 发起咨询按钮 */}
|
||||||
<View
|
<View
|
||||||
className='consultation-create-btn'
|
className='consultation-create-btn'
|
||||||
onClick={() => Taro.navigateTo({ url: '/pages/consultation/create/index' })}
|
onClick={() => safeNavigateTo('/pages/consultation/create/index')}
|
||||||
>
|
>
|
||||||
<Text className='consultation-create-btn-text'>发起咨询</Text>
|
<Text className='consultation-create-btn-text'>发起咨询</Text>
|
||||||
</View>
|
</View>
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { View, Text, Input } from '@tarojs/components';
|
import { View, Text, Input } from '@tarojs/components';
|
||||||
import Taro from '@tarojs/taro';
|
import Taro from '@tarojs/taro';
|
||||||
|
import { safeNavigateTo } from '@/utils/navigate';
|
||||||
import { useAuthStore } from '../../stores/auth';
|
import { useAuthStore } from '../../stores/auth';
|
||||||
import { useElderClass } from '../../hooks/useElderClass';
|
import { useElderClass } from '../../hooks/useElderClass';
|
||||||
import { findThreshold, inputVitalSign, type HealthThreshold } from '../../services/health';
|
import { findThreshold, inputVitalSign, type HealthThreshold } from '../../services/health';
|
||||||
@@ -173,9 +174,9 @@ export default function Health() {
|
|||||||
<View className='ai-suggestion-card' onClick={() => {
|
<View className='ai-suggestion-card' onClick={() => {
|
||||||
const first = aiSuggestions[0];
|
const first = aiSuggestions[0];
|
||||||
if (first?.suggestion_type === 'appointment') {
|
if (first?.suggestion_type === 'appointment') {
|
||||||
Taro.navigateTo({ url: `/pages/appointment/create/index` });
|
safeNavigateTo(`/pages/appointment/create/index`);
|
||||||
} else if (first?.suggestion_type === 'followup') {
|
} else if (first?.suggestion_type === 'followup') {
|
||||||
Taro.navigateTo({ url: '/pages/pkg-profile/followups/index' });
|
safeNavigateTo('/pages/pkg-profile/followups/index');
|
||||||
} else {
|
} else {
|
||||||
Taro.switchTab({ url: '/pages/health/index' });
|
Taro.switchTab({ url: '/pages/health/index' });
|
||||||
}
|
}
|
||||||
@@ -326,7 +327,7 @@ export default function Health() {
|
|||||||
</View>
|
</View>
|
||||||
|
|
||||||
<ContentCard
|
<ContentCard
|
||||||
onPress={() => Taro.navigateTo({ url: '/pages/article/index' })}
|
onPress={() => safeNavigateTo('/pages/article/index')}
|
||||||
>
|
>
|
||||||
<Text className='article-entry-text'>最新健康资讯 ›</Text>
|
<Text className='article-entry-text'>最新健康资讯 ›</Text>
|
||||||
</ContentCard>
|
</ContentCard>
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { View, Text, Swiper, SwiperItem, Image } from '@tarojs/components';
|
import { View, Text, Swiper, SwiperItem, Image } from '@tarojs/components';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import Taro, { useDidShow, useDidHide } from '@tarojs/taro';
|
import Taro, { useDidShow, useDidHide } from '@tarojs/taro';
|
||||||
|
import { safeNavigateTo } from '@/utils/navigate';
|
||||||
import { useAuthStore } from '../../stores/auth';
|
import { useAuthStore } from '../../stores/auth';
|
||||||
import { useUIStore } from '../../stores/ui';
|
import { useUIStore } from '../../stores/ui';
|
||||||
import { navigateToLogin } from '../../utils/navigate';
|
import { navigateToLogin } from '../../utils/navigate';
|
||||||
@@ -120,12 +121,12 @@ function GuestHome({ modeClass }: { modeClass: string }) {
|
|||||||
{articles.map((article) => (
|
{articles.map((article) => (
|
||||||
<ContentCard
|
<ContentCard
|
||||||
key={article.id}
|
key={article.id}
|
||||||
onPress={() => Taro.navigateTo({ url: `/pages/article/detail/index?id=${article.id}` })}
|
onPress={() => safeNavigateTo(`/pages/article/detail/index?id=${article.id}`)}
|
||||||
activeFeedback="opacity"
|
activeFeedback="opacity"
|
||||||
padding="none"
|
padding="none"
|
||||||
>
|
>
|
||||||
{article.cover_image && (
|
{article.cover_image && (
|
||||||
<Image className='guest-article-cover' src={article.cover_image} mode='aspectFill' />
|
<Image className='guest-article-cover' src={article.cover_image} mode='aspectFill' lazyLoad />
|
||||||
)}
|
)}
|
||||||
<View className='guest-article-body'>
|
<View className='guest-article-body'>
|
||||||
<Text className='guest-article-title'>{article.title}</Text>
|
<Text className='guest-article-title'>{article.title}</Text>
|
||||||
@@ -229,7 +230,7 @@ function HomeDashboard({ modeClass }: { modeClass: string }) {
|
|||||||
return (
|
return (
|
||||||
<ContentCard
|
<ContentCard
|
||||||
key={item.label}
|
key={item.label}
|
||||||
onPress={() => Taro.navigateTo({ url: `/pages/pkg-health/trend/index?indicator=${item.indicator}` })}
|
onPress={() => safeNavigateTo(`/pages/pkg-health/trend/index?indicator=${item.indicator}`)}
|
||||||
activeFeedback="opacity"
|
activeFeedback="opacity"
|
||||||
>
|
>
|
||||||
<Text className='vital-label'>{item.label}</Text>
|
<Text className='vital-label'>{item.label}</Text>
|
||||||
@@ -259,8 +260,8 @@ function HomeDashboard({ modeClass }: { modeClass: string }) {
|
|||||||
key={r.id}
|
key={r.id}
|
||||||
className={`reminder-item ${i > 0 ? 'reminder-item-border' : ''}`}
|
className={`reminder-item ${i > 0 ? 'reminder-item-border' : ''}`}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (r.type === 'appointment') Taro.navigateTo({ url: '/pages/appointment/index' });
|
if (r.type === 'appointment') safeNavigateTo('/pages/appointment/index');
|
||||||
else if (r.type === 'followup') Taro.navigateTo({ url: `/pages/pkg-profile/followups/detail/index?id=${r.id}` });
|
else if (r.type === 'followup') safeNavigateTo(`/pages/pkg-profile/followups/detail/index?id=${r.id}`);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Text className='reminder-tag'>{r.tag}</Text>
|
<Text className='reminder-tag'>{r.tag}</Text>
|
||||||
@@ -275,7 +276,7 @@ function HomeDashboard({ modeClass }: { modeClass: string }) {
|
|||||||
<View className='action-btn action-primary' onClick={() => Taro.switchTab({ url: '/pages/health/index' })}>
|
<View className='action-btn action-primary' onClick={() => Taro.switchTab({ url: '/pages/health/index' })}>
|
||||||
<Text className='action-btn-text'>记录体征</Text>
|
<Text className='action-btn-text'>记录体征</Text>
|
||||||
</View>
|
</View>
|
||||||
<View className='action-btn action-outline' onClick={() => Taro.navigateTo({ url: '/pages/appointment/create/index' })}>
|
<View className='action-btn action-outline' onClick={() => safeNavigateTo('/pages/appointment/create/index')}>
|
||||||
<Text className='action-btn-text'>预约挂号</Text>
|
<Text className='action-btn-text'>预约挂号</Text>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { View, Text, Input, Button } from '@tarojs/components';
|
import { View, Text, Input, Button } from '@tarojs/components';
|
||||||
import Taro from '@tarojs/taro';
|
import Taro from '@tarojs/taro';
|
||||||
|
import { safeNavigateTo } from '@/utils/navigate';
|
||||||
import { useAuthStore } from '../../stores/auth';
|
import { useAuthStore } from '../../stores/auth';
|
||||||
import './index.scss';
|
import './index.scss';
|
||||||
|
|
||||||
@@ -191,9 +192,9 @@ export default function Login() {
|
|||||||
</View>
|
</View>
|
||||||
<Text className="agreement-text">
|
<Text className="agreement-text">
|
||||||
登录即同意
|
登录即同意
|
||||||
<Text className="agreement-link" onClick={() => Taro.navigateTo({ url: '/pages/legal/user-agreement' })}>《用户协议》</Text>
|
<Text className="agreement-link" onClick={() => safeNavigateTo('/pages/legal/user-agreement')}>《用户协议》</Text>
|
||||||
和
|
和
|
||||||
<Text className="agreement-link" onClick={() => Taro.navigateTo({ url: '/pages/legal/privacy-policy' })}>《隐私政策》</Text>
|
<Text className="agreement-link" onClick={() => safeNavigateTo('/pages/legal/privacy-policy')}>《隐私政策》</Text>
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import React, { useState, useCallback } from 'react';
|
import React, { useState, useCallback } from 'react';
|
||||||
import { View, Text } from '@tarojs/components';
|
import { View, Text } from '@tarojs/components';
|
||||||
import Taro, { useReachBottom } from '@tarojs/taro';
|
import Taro, { useReachBottom } from '@tarojs/taro';
|
||||||
|
import { safeNavigateTo } from '@/utils/navigate';
|
||||||
import { usePageData } from '@/hooks/usePageData';
|
import { usePageData } from '@/hooks/usePageData';
|
||||||
import { listProducts } from '../../services/points';
|
import { listProducts } from '../../services/points';
|
||||||
import type { PointsProduct } from '../../services/points';
|
import type { PointsProduct } from '../../services/points';
|
||||||
@@ -132,7 +133,7 @@ export default function Mall() {
|
|||||||
Taro.showToast({ title: '已兑完', icon: 'none' });
|
Taro.showToast({ title: '已兑完', icon: 'none' });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Taro.navigateTo({ url: `/pages/pkg-mall/exchange/index?product_id=${item.id}` });
|
safeNavigateTo(`/pages/pkg-mall/exchange/index?product_id=${item.id}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
const balance = account?.balance ?? 0;
|
const balance = account?.balance ?? 0;
|
||||||
@@ -145,7 +146,7 @@ export default function Mall() {
|
|||||||
text='请先完善个人档案'
|
text='请先完善个人档案'
|
||||||
hint='建档后即可使用积分商城、签到等功能'
|
hint='建档后即可使用积分商城、签到等功能'
|
||||||
actionText='去建档'
|
actionText='去建档'
|
||||||
onAction={() => Taro.navigateTo({ url: '/pages/pkg-profile/family-add/index' })}
|
onAction={() => safeNavigateTo('/pages/pkg-profile/family-add/index')}
|
||||||
/>
|
/>
|
||||||
</PageShell>
|
</PageShell>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { useState, useCallback } from 'react';
|
import { useState, useCallback } from 'react';
|
||||||
import { View, Text } from '@tarojs/components';
|
import { View, Text } from '@tarojs/components';
|
||||||
import Taro, { useRouter } from '@tarojs/taro';
|
import Taro, { useRouter } from '@tarojs/taro';
|
||||||
|
import { safeNavigateTo } from '@/utils/navigate';
|
||||||
import { usePageData } from '@/hooks/usePageData';
|
import { usePageData } from '@/hooks/usePageData';
|
||||||
import {
|
import {
|
||||||
getDialysisRecord, reviewDialysisRecord,
|
getDialysisRecord, reviewDialysisRecord,
|
||||||
@@ -167,9 +168,7 @@ export default function DialysisDetail() {
|
|||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
{record.status === 'draft' && (
|
{record.status === 'draft' && (
|
||||||
<View className='action-btn action-btn--secondary' onClick={() => Taro.navigateTo({
|
<View className='action-btn action-btn--secondary' onClick={() => safeNavigateTo(`/pages/pkg-doctor-clinical/dialysis/create/index?id=${id}&version=${record.version}`)}>
|
||||||
url: `/pages/pkg-doctor-clinical/dialysis/create/index?id=${id}&version=${record.version}`,
|
|
||||||
})}>
|
|
||||||
<Text className='action-btn__text'>编辑</Text>
|
<Text className='action-btn__text'>编辑</Text>
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { useState, useEffect, useCallback, useRef } from 'react';
|
import { useState, useEffect, useCallback, useRef } from 'react';
|
||||||
import { View, Text } from '@tarojs/components';
|
import { View, Text } from '@tarojs/components';
|
||||||
import Taro, { useRouter } from '@tarojs/taro';
|
import Taro, { useRouter } from '@tarojs/taro';
|
||||||
|
import { safeNavigateTo } from '@/utils/navigate';
|
||||||
import { usePageData } from '@/hooks/usePageData';
|
import { usePageData } from '@/hooks/usePageData';
|
||||||
import { listLabReports, type LabReportItem } from '@/services/doctor/labReport';
|
import { listLabReports, type LabReportItem } from '@/services/doctor/labReport';
|
||||||
import { listPatients } from '@/services/doctor/patient';
|
import { listPatients } from '@/services/doctor/patient';
|
||||||
@@ -99,9 +100,7 @@ export default function ReportList() {
|
|||||||
{reports.map((r) => (
|
{reports.map((r) => (
|
||||||
<ContentCard
|
<ContentCard
|
||||||
key={r.id}
|
key={r.id}
|
||||||
onPress={() => Taro.navigateTo({
|
onPress={() => safeNavigateTo(`/pages/pkg-doctor-clinical/report/detail/index?patientId=${currentPatientId}&id=${r.id}`)}
|
||||||
url: `/pages/pkg-doctor-clinical/report/detail/index?patientId=${currentPatientId}&id=${r.id}`,
|
|
||||||
})}
|
|
||||||
>
|
>
|
||||||
<View className="report-card__header">
|
<View className="report-card__header">
|
||||||
<Text className="report-card__type">{r.report_type}</Text>
|
<Text className="report-card__type">{r.report_type}</Text>
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { useState, useEffect, useCallback, useRef } from 'react';
|
import { useState, useEffect, useCallback, useRef } from 'react';
|
||||||
import { View, Text } from '@tarojs/components';
|
import { View, Text } from '@tarojs/components';
|
||||||
import Taro, { useRouter } from '@tarojs/taro';
|
import Taro, { useRouter } from '@tarojs/taro';
|
||||||
|
import { safeNavigateTo } from '@/utils/navigate';
|
||||||
import { usePageData } from '@/hooks/usePageData';
|
import { usePageData } from '@/hooks/usePageData';
|
||||||
import { listFollowUpTasks, type FollowUpTask } from '@/services/doctor/followup';
|
import { listFollowUpTasks, type FollowUpTask } from '@/services/doctor/followup';
|
||||||
import PageShell from '@/components/ui/PageShell';
|
import PageShell from '@/components/ui/PageShell';
|
||||||
@@ -106,7 +107,7 @@ export default function FollowUpList() {
|
|||||||
{tasks.map((task) => (
|
{tasks.map((task) => (
|
||||||
<ContentCard
|
<ContentCard
|
||||||
key={task.id}
|
key={task.id}
|
||||||
onPress={() => Taro.navigateTo({ url: `/pages/pkg-doctor-core/followup/detail/index?id=${task.id}` })}
|
onPress={() => safeNavigateTo(`/pages/pkg-doctor-core/followup/detail/index?id=${task.id}`)}
|
||||||
>
|
>
|
||||||
<View className="task-card__header">
|
<View className="task-card__header">
|
||||||
<Text className="task-card__type">{getTypeLabel(task.follow_up_type)}</Text>
|
<Text className="task-card__type">{getTypeLabel(task.follow_up_type)}</Text>
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { useState, useMemo, useCallback } from 'react';
|
import { useState, useMemo, useCallback } from 'react';
|
||||||
import { View, Text, Input } from '@tarojs/components';
|
import { View, Text, Input } from '@tarojs/components';
|
||||||
import Taro from '@tarojs/taro';
|
import Taro from '@tarojs/taro';
|
||||||
|
import { safeNavigateTo } from '@/utils/navigate';
|
||||||
import { useAuthStore } from '@/stores/auth';
|
import { useAuthStore } from '@/stores/auth';
|
||||||
import { useDoctorClass } from '@/hooks/useDoctorClass';
|
import { useDoctorClass } from '@/hooks/useDoctorClass';
|
||||||
import { usePageData } from '@/hooks/usePageData';
|
import { usePageData } from '@/hooks/usePageData';
|
||||||
@@ -93,7 +94,7 @@ export default function DoctorHome() {
|
|||||||
usePageData(loadDashboard, { throttleMs: 10000 });
|
usePageData(loadDashboard, { throttleMs: 10000 });
|
||||||
|
|
||||||
const handleCardClick = (card: CardConfig) => {
|
const handleCardClick = (card: CardConfig) => {
|
||||||
Taro.navigateTo({ url: card.route });
|
safeNavigateTo(card.route);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleLogout = () => {
|
const handleLogout = () => {
|
||||||
@@ -123,7 +124,7 @@ export default function DoctorHome() {
|
|||||||
<View className='doctor-home__alert'>
|
<View className='doctor-home__alert'>
|
||||||
<Text className='doctor-home__alert-icon'>!</Text>
|
<Text className='doctor-home__alert-icon'>!</Text>
|
||||||
<Text className='doctor-home__alert-text'>{alertCount} 位患者体征异常</Text>
|
<Text className='doctor-home__alert-text'>{alertCount} 位患者体征异常</Text>
|
||||||
<Text className='doctor-home__alert-link' onClick={() => Taro.navigateTo({ url: '/pages/pkg-doctor-clinical/alerts/index' })}>查看 →</Text>
|
<Text className='doctor-home__alert-link' onClick={() => safeNavigateTo('/pages/pkg-doctor-clinical/alerts/index')}>查看 →</Text>
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
@@ -131,7 +132,7 @@ export default function DoctorHome() {
|
|||||||
<Input
|
<Input
|
||||||
className='doctor-home__search-input'
|
className='doctor-home__search-input'
|
||||||
placeholder='搜索患者姓名...'
|
placeholder='搜索患者姓名...'
|
||||||
onFocus={() => Taro.navigateTo({ url: '/pages/pkg-doctor-core/patients/index' })}
|
onFocus={() => safeNavigateTo('/pages/pkg-doctor-core/patients/index')}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
@@ -176,7 +177,7 @@ export default function DoctorHome() {
|
|||||||
<View
|
<View
|
||||||
key={action.route}
|
key={action.route}
|
||||||
className='quick-action'
|
className='quick-action'
|
||||||
onClick={() => Taro.navigateTo({ url: action.route })}
|
onClick={() => safeNavigateTo(action.route)}
|
||||||
>
|
>
|
||||||
<View className='quick-action__icon-wrap'>
|
<View className='quick-action__icon-wrap'>
|
||||||
<Text className='quick-action__initial'>{action.initial}</Text>
|
<Text className='quick-action__initial'>{action.initial}</Text>
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { useState, useCallback } from 'react';
|
import { useState, useCallback } from 'react';
|
||||||
import { View, Text } from '@tarojs/components';
|
import { View, Text } from '@tarojs/components';
|
||||||
import Taro, { useRouter } from '@tarojs/taro';
|
import Taro, { useRouter } from '@tarojs/taro';
|
||||||
|
import { safeNavigateTo } from '@/utils/navigate';
|
||||||
import { usePageData } from '@/hooks/usePageData';
|
import { usePageData } from '@/hooks/usePageData';
|
||||||
import { getPatient, getHealthSummary, type PatientDetail, type HealthSummary } from '@/services/doctor/patient';
|
import { getPatient, getHealthSummary, type PatientDetail, type HealthSummary } from '@/services/doctor/patient';
|
||||||
import Loading from '@/components/Loading';
|
import Loading from '@/components/Loading';
|
||||||
@@ -127,7 +128,7 @@ export default function PatientDetail() {
|
|||||||
<Text className='section-title'>近期化验</Text>
|
<Text className='section-title'>近期化验</Text>
|
||||||
<View
|
<View
|
||||||
className='lab-item'
|
className='lab-item'
|
||||||
onClick={() => Taro.navigateTo({ url: `/pages/pkg-doctor-clinical/report/detail/index?patientId=${patientId}&id=${summary.latest_lab_report!.id}` })}
|
onClick={() => safeNavigateTo(`/pages/pkg-doctor-clinical/report/detail/index?patientId=${patientId}&id=${summary.latest_lab_report!.id}`)}
|
||||||
>
|
>
|
||||||
<View className='lab-item__header'>
|
<View className='lab-item__header'>
|
||||||
<Text className='lab-item__type'>{summary.latest_lab_report.report_type}</Text>
|
<Text className='lab-item__type'>{summary.latest_lab_report.report_type}</Text>
|
||||||
@@ -144,10 +145,10 @@ export default function PatientDetail() {
|
|||||||
<ContentCard>
|
<ContentCard>
|
||||||
<Text className='section-title'>操作</Text>
|
<Text className='section-title'>操作</Text>
|
||||||
<View className='action-buttons'>
|
<View className='action-buttons'>
|
||||||
<View className='action-btn' onClick={() => Taro.navigateTo({ url: `/pages/pkg-doctor-clinical/report/index?patientId=${patientId}` })}>
|
<View className='action-btn' onClick={() => safeNavigateTo(`/pages/pkg-doctor-clinical/report/index?patientId=${patientId}`)}>
|
||||||
<Text>查看化验报告</Text>
|
<Text>查看化验报告</Text>
|
||||||
</View>
|
</View>
|
||||||
<View className='action-btn' onClick={() => Taro.navigateTo({ url: `/pages/pkg-doctor-core/followup/index?patientId=${patientId}` })}>
|
<View className='action-btn' onClick={() => safeNavigateTo(`/pages/pkg-doctor-core/followup/index?patientId=${patientId}`)}>
|
||||||
<Text>随访记录</Text>
|
<Text>随访记录</Text>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { useState, useEffect, useCallback, useRef } from 'react';
|
import { useState, useEffect, useCallback, useRef } from 'react';
|
||||||
import { View, Text } from '@tarojs/components';
|
import { View, Text } from '@tarojs/components';
|
||||||
import Taro, { useReachBottom } from '@tarojs/taro';
|
import Taro, { useReachBottom } from '@tarojs/taro';
|
||||||
|
import { safeNavigateTo } from '@/utils/navigate';
|
||||||
import { usePageData } from '@/hooks/usePageData';
|
import { usePageData } from '@/hooks/usePageData';
|
||||||
import { listPatients, listPatientTags, type PatientItem, type PatientTag } from '@/services/doctor/patient';
|
import { listPatients, listPatientTags, type PatientItem, type PatientTag } from '@/services/doctor/patient';
|
||||||
import PageShell from '@/components/ui/PageShell';
|
import PageShell from '@/components/ui/PageShell';
|
||||||
@@ -118,7 +119,7 @@ export default function PatientList() {
|
|||||||
{patients.map((p) => (
|
{patients.map((p) => (
|
||||||
<ContentCard
|
<ContentCard
|
||||||
key={p.id}
|
key={p.id}
|
||||||
onPress={() => Taro.navigateTo({ url: `/pages/pkg-doctor-core/patients/detail/index?id=${p.id}` })}
|
onPress={() => safeNavigateTo(`/pages/pkg-doctor-core/patients/detail/index?id=${p.id}`)}
|
||||||
>
|
>
|
||||||
<View className="patient-card__header">
|
<View className="patient-card__header">
|
||||||
<Text className="patient-card__name">{p.name}</Text>
|
<Text className="patient-card__name">{p.name}</Text>
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import React, { useState, useCallback } from 'react';
|
import React, { useState, useCallback } from 'react';
|
||||||
import { View, Text } from '@tarojs/components';
|
import { View, Text } from '@tarojs/components';
|
||||||
import Taro from '@tarojs/taro';
|
import Taro from '@tarojs/taro';
|
||||||
|
import { safeNavigateTo } from '@/utils/navigate';
|
||||||
import { usePageData } from '@/hooks/usePageData';
|
import { usePageData } from '@/hooks/usePageData';
|
||||||
import { listPatientAlerts, type Alert } from '@/services/alert';
|
import { listPatientAlerts, type Alert } from '@/services/alert';
|
||||||
import { useAuthStore } from '@/stores/auth';
|
import { useAuthStore } from '@/stores/auth';
|
||||||
@@ -82,7 +83,7 @@ export default function PatientAlerts() {
|
|||||||
if (!currentPatient) {
|
if (!currentPatient) {
|
||||||
return (
|
return (
|
||||||
<PageShell padding="none" className={modeClass}>
|
<PageShell padding="none" className={modeClass}>
|
||||||
<ErrorState text='请先完善个人档案' onRetry={() => Taro.navigateTo({ url: '/pages/pkg-profile/family-add/index' })} />
|
<ErrorState text='请先完善个人档案' onRetry={() => safeNavigateTo('/pages/pkg-profile/family-add/index')} />
|
||||||
</PageShell>
|
</PageShell>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { useState, useCallback } from 'react';
|
import { useState, useCallback } from 'react';
|
||||||
import { View, Text, Input, Picker } from '@tarojs/components';
|
import { View, Text, Input, Picker } from '@tarojs/components';
|
||||||
import Taro from '@tarojs/taro';
|
import Taro from '@tarojs/taro';
|
||||||
|
import { safeNavigateTo } from '@/utils/navigate';
|
||||||
import { usePageData } from '@/hooks/usePageData';
|
import { usePageData } from '@/hooks/usePageData';
|
||||||
import { num, validateStr } from '@/utils/validate';
|
import { num, validateStr } from '@/utils/validate';
|
||||||
import { inputVitalSign, getHealthThresholds, findThreshold, DEFAULT_THRESHOLDS, type HealthThreshold } from '../../../services/health';
|
import { inputVitalSign, getHealthThresholds, findThreshold, DEFAULT_THRESHOLDS, type HealthThreshold } from '../../../services/health';
|
||||||
@@ -193,7 +194,7 @@ export default function HealthInput() {
|
|||||||
</View>
|
</View>
|
||||||
|
|
||||||
{/* 从设备同步入口 */}
|
{/* 从设备同步入口 */}
|
||||||
<View className='input-sync-entry' onClick={() => Taro.navigateTo({ url: '/pages/pkg-health/device-sync/index?returnTo=input' })}>
|
<View className='input-sync-entry' onClick={() => safeNavigateTo('/pages/pkg-health/device-sync/index?returnTo=input')}>
|
||||||
<Text className='input-sync-entry-text'>从设备同步</Text>
|
<Text className='input-sync-entry-text'>从设备同步</Text>
|
||||||
<Text className='input-sync-entry-hint'>蓝牙连接设备自动获取数据</Text>
|
<Text className='input-sync-entry-hint'>蓝牙连接设备自动获取数据</Text>
|
||||||
</View>
|
</View>
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import React, { useState, useCallback } from 'react';
|
import React, { useState, useCallback } from 'react';
|
||||||
import { View, Text } from '@tarojs/components';
|
import { View, Text } from '@tarojs/components';
|
||||||
import Taro, { useReachBottom } from '@tarojs/taro';
|
import Taro, { useReachBottom } from '@tarojs/taro';
|
||||||
|
import { safeNavigateTo } from '@/utils/navigate';
|
||||||
import { usePageData } from '@/hooks/usePageData';
|
import { usePageData } from '@/hooks/usePageData';
|
||||||
import { getCachedPatientId } from '@/services/request';
|
import { getCachedPatientId } from '@/services/request';
|
||||||
import { listDialysisPrescriptions } from '@/services/dialysis';
|
import { listDialysisPrescriptions } from '@/services/dialysis';
|
||||||
@@ -68,7 +69,7 @@ export default function DialysisPrescriptionList() {
|
|||||||
<View
|
<View
|
||||||
className='prescription-card'
|
className='prescription-card'
|
||||||
key={p.id}
|
key={p.id}
|
||||||
onClick={() => Taro.navigateTo({ url: `/pages/pkg-profile/dialysis-prescriptions/detail/index?id=${p.id}` })}
|
onClick={() => safeNavigateTo(`/pages/pkg-profile/dialysis-prescriptions/detail/index?id=${p.id}`)}
|
||||||
>
|
>
|
||||||
<View className='prescription-card-top'>
|
<View className='prescription-card-top'>
|
||||||
<Text className='prescription-model'>{p.dialyzer_model || '未指定型号'}</Text>
|
<Text className='prescription-model'>{p.dialyzer_model || '未指定型号'}</Text>
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import React, { useState, useCallback } from 'react';
|
import React, { useState, useCallback } from 'react';
|
||||||
import { View, Text } from '@tarojs/components';
|
import { View, Text } from '@tarojs/components';
|
||||||
import Taro, { useReachBottom } from '@tarojs/taro';
|
import Taro, { useReachBottom } from '@tarojs/taro';
|
||||||
|
import { safeNavigateTo } from '@/utils/navigate';
|
||||||
import { usePageData } from '@/hooks/usePageData';
|
import { usePageData } from '@/hooks/usePageData';
|
||||||
import { getCachedPatientId } from '@/services/request';
|
import { getCachedPatientId } from '@/services/request';
|
||||||
import { listDialysisRecords } from '@/services/dialysis';
|
import { listDialysisRecords } from '@/services/dialysis';
|
||||||
@@ -76,7 +77,7 @@ export default function DialysisRecordList() {
|
|||||||
<View
|
<View
|
||||||
className='record-card'
|
className='record-card'
|
||||||
key={r.id}
|
key={r.id}
|
||||||
onClick={() => Taro.navigateTo({ url: `/pages/pkg-profile/dialysis-records/detail/index?id=${r.id}` })}
|
onClick={() => safeNavigateTo(`/pages/pkg-profile/dialysis-records/detail/index?id=${r.id}`)}
|
||||||
>
|
>
|
||||||
<View className='record-card-top'>
|
<View className='record-card-top'>
|
||||||
<Text className={`type-tag ${ti.cls}`}>{ti.label}</Text>
|
<Text className={`type-tag ${ti.cls}`}>{ti.label}</Text>
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import React, { useState, useCallback } from 'react';
|
import React, { useState, useCallback } from 'react';
|
||||||
import { View, Text } from '@tarojs/components';
|
import { View, Text } from '@tarojs/components';
|
||||||
import Taro from '@tarojs/taro';
|
import Taro from '@tarojs/taro';
|
||||||
|
import { safeNavigateTo } from '@/utils/navigate';
|
||||||
import { usePageData } from '@/hooks/usePageData';
|
import { usePageData } from '@/hooks/usePageData';
|
||||||
import { listPatients, Patient } from '../../../services/patient';
|
import { listPatients, Patient } from '../../../services/patient';
|
||||||
import { useAuthStore } from '../../../stores/auth';
|
import { useAuthStore } from '../../../stores/auth';
|
||||||
@@ -42,12 +43,12 @@ export default function FamilyList() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const goToAdd = () => {
|
const goToAdd = () => {
|
||||||
Taro.navigateTo({ url: '/pages/pkg-profile/family-add/index' });
|
safeNavigateTo('/pages/pkg-profile/family-add/index');
|
||||||
};
|
};
|
||||||
|
|
||||||
const goToEdit = (patient: Patient) => {
|
const goToEdit = (patient: Patient) => {
|
||||||
Taro.setStorageSync('edit_patient', patient);
|
Taro.setStorageSync('edit_patient', patient);
|
||||||
Taro.navigateTo({ url: `/pages/pkg-profile/family-add/index?id=${patient.id}` });
|
safeNavigateTo(`/pages/pkg-profile/family-add/index?id=${patient.id}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
const genderText = (g?: string) => {
|
const genderText = (g?: string) => {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import React, { useState, useCallback } from 'react';
|
import React, { useState, useCallback } from 'react';
|
||||||
import { View, Text } from '@tarojs/components';
|
import { View, Text } from '@tarojs/components';
|
||||||
import Taro from '@tarojs/taro';
|
import Taro from '@tarojs/taro';
|
||||||
|
import { safeNavigateTo } from '@/utils/navigate';
|
||||||
import { usePageData } from '@/hooks/usePageData';
|
import { usePageData } from '@/hooks/usePageData';
|
||||||
import { listTasks, FollowUpTask } from '../../../services/followup';
|
import { listTasks, FollowUpTask } from '../../../services/followup';
|
||||||
import EmptyState from '../../../components/EmptyState';
|
import EmptyState from '../../../components/EmptyState';
|
||||||
@@ -45,7 +46,7 @@ export default function MyFollowUps() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const goToDetail = (id: string) => {
|
const goToDetail = (id: string) => {
|
||||||
Taro.navigateTo({ url: `/pages/pkg-profile/followups/detail/index?id=${id}` });
|
safeNavigateTo(`/pages/pkg-profile/followups/detail/index?id=${id}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
const getStatusClass = (status: string) => {
|
const getStatusClass = (status: string) => {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import React, { useState, useCallback } from 'react';
|
import React, { useState, useCallback } from 'react';
|
||||||
import { View, Text } from '@tarojs/components';
|
import { View, Text } from '@tarojs/components';
|
||||||
import Taro, { useReachBottom } from '@tarojs/taro';
|
import Taro, { useReachBottom } from '@tarojs/taro';
|
||||||
|
import { safeNavigateTo } from '@/utils/navigate';
|
||||||
import { usePageData } from '@/hooks/usePageData';
|
import { usePageData } from '@/hooks/usePageData';
|
||||||
import { getCachedPatientId } from '@/services/request';
|
import { getCachedPatientId } from '@/services/request';
|
||||||
import { listReports, LabReport } from '../../../services/report';
|
import { listReports, LabReport } from '../../../services/report';
|
||||||
@@ -49,7 +50,7 @@ export default function MyReports() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const goToDetail = (id: string) => {
|
const goToDetail = (id: string) => {
|
||||||
Taro.navigateTo({ url: `/pages/pkg-profile/reports/detail/index?id=${id}` });
|
safeNavigateTo(`/pages/pkg-profile/reports/detail/index?id=${id}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
const formatStatus = (report: LabReport) => {
|
const formatStatus = (report: LabReport) => {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { View, Text } from '@tarojs/components';
|
import { View, Text } from '@tarojs/components';
|
||||||
import Taro from '@tarojs/taro';
|
import Taro from '@tarojs/taro';
|
||||||
|
import { safeNavigateTo } from '@/utils/navigate';
|
||||||
import { useAuthStore } from '../../../stores/auth';
|
import { useAuthStore } from '../../../stores/auth';
|
||||||
import { invalidateHeadersCache, clearRequestCache } from '@/services/request';
|
import { invalidateHeadersCache, clearRequestCache } from '@/services/request';
|
||||||
import { useElderClass } from '../../../hooks/useElderClass';
|
import { useElderClass } from '../../../hooks/useElderClass';
|
||||||
@@ -51,7 +52,7 @@ export default function Settings() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handlePrivacy = () => {
|
const handlePrivacy = () => {
|
||||||
Taro.navigateTo({ url: '/pages/legal/privacy-policy' });
|
safeNavigateTo('/pages/legal/privacy-policy');
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleLogout = () => {
|
const handleLogout = () => {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { View, Text } from '@tarojs/components';
|
import { View, Text } from '@tarojs/components';
|
||||||
import Taro from '@tarojs/taro';
|
import Taro from '@tarojs/taro';
|
||||||
|
import { safeNavigateTo } from '@/utils/navigate';
|
||||||
import { useState, useCallback } from 'react';
|
import { useState, useCallback } from 'react';
|
||||||
import { useAuthStore } from '../../stores/auth';
|
import { useAuthStore } from '../../stores/auth';
|
||||||
import { usePointsStore } from '../../stores/points';
|
import { usePointsStore } from '../../stores/points';
|
||||||
@@ -113,7 +114,7 @@ export default function Profile() {
|
|||||||
if (item.isSwitchTab) {
|
if (item.isSwitchTab) {
|
||||||
Taro.switchTab({ url: item.path });
|
Taro.switchTab({ url: item.path });
|
||||||
} else {
|
} else {
|
||||||
Taro.navigateTo({ url: item.path });
|
safeNavigateTo(item.path);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -188,7 +189,7 @@ export default function Profile() {
|
|||||||
<ContentCard
|
<ContentCard
|
||||||
padding="none"
|
padding="none"
|
||||||
margin="none"
|
margin="none"
|
||||||
onPress={() => Taro.navigateTo({ url: '/pages/pkg-profile/notifications/index' })}
|
onPress={() => safeNavigateTo('/pages/pkg-profile/notifications/index')}
|
||||||
>
|
>
|
||||||
<View className='menu-item'>
|
<View className='menu-item'>
|
||||||
<View className='menu-icon menu-icon--pri-l'>
|
<View className='menu-icon menu-icon--pri-l'>
|
||||||
|
|||||||
@@ -81,12 +81,12 @@ export const useAuthStore = create<AuthState>((set, get) => ({
|
|||||||
restore: () => {
|
restore: () => {
|
||||||
// 利用内存缓存避免重复 Storage IPC + JSON.parse
|
// 利用内存缓存避免重复 Storage IPC + JSON.parse
|
||||||
try {
|
try {
|
||||||
const userData = secureGet('user_data') || Taro.getStorageSync('user_data') || '';
|
const userData = secureGet('user_data');
|
||||||
if (userData !== cachedUserJson) {
|
if (userData !== cachedUserJson) {
|
||||||
cachedUserJson = userData;
|
cachedUserJson = userData;
|
||||||
cachedUserObj = userData ? JSON.parse(userData) : null;
|
cachedUserObj = userData ? JSON.parse(userData) : null;
|
||||||
}
|
}
|
||||||
const rolesData = secureGet('user_roles') || Taro.getStorageSync('user_roles') || '';
|
const rolesData = secureGet('user_roles');
|
||||||
if (rolesData !== cachedRolesJson) {
|
if (rolesData !== cachedRolesJson) {
|
||||||
cachedRolesJson = rolesData;
|
cachedRolesJson = rolesData;
|
||||||
cachedRolesObj = rolesData ? JSON.parse(rolesData) : [];
|
cachedRolesObj = rolesData ? JSON.parse(rolesData) : [];
|
||||||
@@ -252,6 +252,14 @@ export const useAuthStore = create<AuthState>((set, get) => ({
|
|||||||
Taro.removeStorageSync('current_patient_id');
|
Taro.removeStorageSync('current_patient_id');
|
||||||
Taro.removeStorageSync('analytics_queue');
|
Taro.removeStorageSync('analytics_queue');
|
||||||
Taro.removeStorageSync('edit_patient');
|
Taro.removeStorageSync('edit_patient');
|
||||||
|
Taro.removeStorageSync('ai_chat_history');
|
||||||
|
// 清理 BLE DataBuffer 缓存(key 格式:ble_buffer_{patientId}_{bucket})
|
||||||
|
const storageInfo = Taro.getStorageInfoSync();
|
||||||
|
storageInfo.keys.forEach((key) => {
|
||||||
|
if (key.startsWith('ble_buffer_') || key.startsWith('last_ble_sync')) {
|
||||||
|
Taro.removeStorageSync(key);
|
||||||
|
}
|
||||||
|
});
|
||||||
resetAllStores();
|
resetAllStores();
|
||||||
set({ user: null, roles: [], currentPatient: null, patients: [] });
|
set({ user: null, roles: [], currentPatient: null, patients: [] });
|
||||||
Taro.reLaunch({ url: '/pages/index/index' });
|
Taro.reLaunch({ url: '/pages/index/index' });
|
||||||
|
|||||||
Reference in New Issue
Block a user