feat(miniapp): SERS 教程入口与季节性防控提醒展示
This commit is contained in:
@@ -46,6 +46,8 @@ export const listDiseases = () => get<Disease[]>('/knowledge/diseases');
|
|||||||
export const getDisease = (id: string) => get<Disease>(`/knowledge/diseases/${id}`);
|
export const getDisease = (id: string) => get<Disease>(`/knowledge/diseases/${id}`);
|
||||||
export const listAIGuides = () => get<KnowledgeArticle[]>('/knowledge/articles', { kind: 'ai_guide' });
|
export const listAIGuides = () => get<KnowledgeArticle[]>('/knowledge/articles', { kind: 'ai_guide' });
|
||||||
export const listLAMPGuides = () => get<KnowledgeArticle[]>('/knowledge/articles', { kind: 'lamp_guide' });
|
export const listLAMPGuides = () => get<KnowledgeArticle[]>('/knowledge/articles', { kind: 'lamp_guide' });
|
||||||
|
export const listSERSGuides = () => get<KnowledgeArticle[]>('/knowledge/articles', { kind: 'sers_guide' });
|
||||||
|
export const listSeasonalTips = () => get<KnowledgeArticle[]>('/knowledge/articles', { kind: 'seasonal_tip' });
|
||||||
export const getArticle = (id: string) => get<KnowledgeArticle>(`/knowledge/articles/${id}`);
|
export const getArticle = (id: string) => get<KnowledgeArticle>(`/knowledge/articles/${id}`);
|
||||||
export const getStageHints = (stage?: string) =>
|
export const getStageHints = (stage?: string) =>
|
||||||
get<StageHint[]>('/knowledge/stage-hints', stage ? { stage } : undefined);
|
get<StageHint[]>('/knowledge/stage-hints', stage ? { stage } : undefined);
|
||||||
|
|||||||
@@ -130,6 +130,47 @@
|
|||||||
margin-top: 4rpx;
|
margin-top: 4rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.seasonCard {
|
||||||
|
background: linear-gradient(135deg, $color-primary 0%, $color-primary-dark 100%);
|
||||||
|
border-radius: $radius-lg;
|
||||||
|
padding: $spacing-lg;
|
||||||
|
box-shadow: $shadow-card;
|
||||||
|
margin-bottom: $spacing-md;
|
||||||
|
}
|
||||||
|
|
||||||
|
.seasonHeader {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: $spacing-sm;
|
||||||
|
margin-bottom: $spacing-sm;
|
||||||
|
}
|
||||||
|
|
||||||
|
.seasonBadge {
|
||||||
|
font-size: $font-size-xs;
|
||||||
|
color: $color-primary;
|
||||||
|
background: rgba(255, 255, 255, 0.9);
|
||||||
|
padding: 4rpx $spacing-sm;
|
||||||
|
border-radius: $radius-round;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.seasonTitle {
|
||||||
|
font-size: $font-size-lg;
|
||||||
|
font-weight: $font-weight-semibold;
|
||||||
|
color: $color-text-white;
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.seasonContent {
|
||||||
|
display: block;
|
||||||
|
font-size: $font-size-sm;
|
||||||
|
color: rgba(255, 255, 255, 0.95);
|
||||||
|
line-height: $line-height-loose;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
word-break: break-all;
|
||||||
|
}
|
||||||
|
|
||||||
.diseaseList {
|
.diseaseList {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ import styles from './index.module.scss';
|
|||||||
import {
|
import {
|
||||||
listAIGuides,
|
listAIGuides,
|
||||||
listLAMPGuides,
|
listLAMPGuides,
|
||||||
|
listSERSGuides,
|
||||||
|
listSeasonalTips,
|
||||||
listDiseases,
|
listDiseases,
|
||||||
getStageHints,
|
getStageHints,
|
||||||
type Disease,
|
type Disease,
|
||||||
@@ -15,6 +17,7 @@ import {
|
|||||||
const GUIDE_LABELS: Record<string, string> = {
|
const GUIDE_LABELS: Record<string, string> = {
|
||||||
ai_guide: 'AI 解读',
|
ai_guide: 'AI 解读',
|
||||||
lamp_guide: 'LAMP 教程',
|
lamp_guide: 'LAMP 教程',
|
||||||
|
sers_guide: 'SERS 教程',
|
||||||
};
|
};
|
||||||
|
|
||||||
const STAGE_OPTIONS = [
|
const STAGE_OPTIONS = [
|
||||||
@@ -24,6 +27,14 @@ const STAGE_OPTIONS = [
|
|||||||
{ key: 'pupa', label: '蛹期' },
|
{ key: 'pupa', label: '蛹期' },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const currentSeason = (() => {
|
||||||
|
const m = new Date().getMonth() + 1;
|
||||||
|
if (m >= 3 && m <= 5) return '春季';
|
||||||
|
if (m >= 6 && m <= 8) return '夏季';
|
||||||
|
if (m >= 9 && m <= 11) return '秋季';
|
||||||
|
return '冬季';
|
||||||
|
})();
|
||||||
|
|
||||||
const CATEGORY_LABELS: Record<string, string> = {
|
const CATEGORY_LABELS: Record<string, string> = {
|
||||||
viral: '病毒性',
|
viral: '病毒性',
|
||||||
fungal: '真菌性',
|
fungal: '真菌性',
|
||||||
@@ -35,7 +46,7 @@ const CATEGORY_LABELS: Record<string, string> = {
|
|||||||
const KnowledgePage: React.FC = () => {
|
const KnowledgePage: React.FC = () => {
|
||||||
const [diseases, setDiseases] = useState<Disease[]>([]);
|
const [diseases, setDiseases] = useState<Disease[]>([]);
|
||||||
const [guides, setGuides] = useState<KnowledgeArticle[]>([]);
|
const [guides, setGuides] = useState<KnowledgeArticle[]>([]);
|
||||||
const [lampGuides, setLampGuides] = useState<KnowledgeArticle[]>([]);
|
const [seasonalTips, setSeasonalTips] = useState<KnowledgeArticle[]>([]);
|
||||||
const [stage, setStage] = useState('young');
|
const [stage, setStage] = useState('young');
|
||||||
const [stageHints, setStageHints] = useState<StageHint[]>([]);
|
const [stageHints, setStageHints] = useState<StageHint[]>([]);
|
||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
@@ -53,14 +64,16 @@ const KnowledgePage: React.FC = () => {
|
|||||||
|
|
||||||
const fetchData = useCallback(async () => {
|
const fetchData = useCallback(async () => {
|
||||||
try {
|
try {
|
||||||
const [diseaseRes, guideRes, lampRes] = await Promise.all([
|
const [diseaseRes, guideRes, lampRes, sersRes, seasonalRes] = await Promise.all([
|
||||||
listDiseases().catch(() => [] as Disease[]),
|
listDiseases().catch(() => [] as Disease[]),
|
||||||
listAIGuides().catch(() => [] as KnowledgeArticle[]),
|
listAIGuides().catch(() => [] as KnowledgeArticle[]),
|
||||||
listLAMPGuides().catch(() => [] as KnowledgeArticle[]),
|
listLAMPGuides().catch(() => [] as KnowledgeArticle[]),
|
||||||
|
listSERSGuides().catch(() => [] as KnowledgeArticle[]),
|
||||||
|
listSeasonalTips().catch(() => [] as KnowledgeArticle[]),
|
||||||
]);
|
]);
|
||||||
setDiseases(diseaseRes);
|
setDiseases(diseaseRes);
|
||||||
setGuides(guideRes);
|
setGuides([...guideRes, ...lampRes, ...sersRes]);
|
||||||
setLampGuides(lampRes);
|
setSeasonalTips(seasonalRes);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('[Knowledge] 数据加载失败:', err);
|
console.error('[Knowledge] 数据加载失败:', err);
|
||||||
Taro.showToast({
|
Taro.showToast({
|
||||||
@@ -85,7 +98,7 @@ const KnowledgePage: React.FC = () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const openGuide = (a: KnowledgeArticle) => {
|
const openGuide = (a: KnowledgeArticle) => {
|
||||||
Taro.navigateTo({ url: `/pages/knowledge/detail/index?kind=ai_guide&id=${a.id}` });
|
Taro.navigateTo({ url: `/pages/knowledge/detail/index?kind=article&id=${a.id}` });
|
||||||
};
|
};
|
||||||
|
|
||||||
const openDisease = (d: Disease) => {
|
const openDisease = (d: Disease) => {
|
||||||
@@ -105,17 +118,6 @@ const KnowledgePage: React.FC = () => {
|
|||||||
</View>
|
</View>
|
||||||
))}
|
))}
|
||||||
|
|
||||||
{lampGuides.map((a) => (
|
|
||||||
<View key={a.id} className={styles.guideCard} onClick={() => openGuide(a)}>
|
|
||||||
<View className={styles.guideHeader}>
|
|
||||||
<Text className={styles.guideBadge}>{GUIDE_LABELS[a.kind] || a.kind}</Text>
|
|
||||||
<Text className={styles.guideArrow}>›</Text>
|
|
||||||
</View>
|
|
||||||
<Text className={styles.guideTitle}>{a.title}</Text>
|
|
||||||
{a.summary ? <Text className={styles.guideSummary}>{a.summary}</Text> : null}
|
|
||||||
</View>
|
|
||||||
))}
|
|
||||||
|
|
||||||
<Text className={styles.sectionTitle}>饲养阶段风险提示</Text>
|
<Text className={styles.sectionTitle}>饲养阶段风险提示</Text>
|
||||||
<View className={styles.stageChips}>
|
<View className={styles.stageChips}>
|
||||||
{STAGE_OPTIONS.map((opt) => (
|
{STAGE_OPTIONS.map((opt) => (
|
||||||
@@ -153,6 +155,27 @@ const KnowledgePage: React.FC = () => {
|
|||||||
))
|
))
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
<Text className={styles.sectionTitle}>季节性防控提醒</Text>
|
||||||
|
{seasonalTips
|
||||||
|
.filter((t) => t.title.startsWith(currentSeason))
|
||||||
|
.map((t) => (
|
||||||
|
<View key={t.id} className={styles.seasonCard} onClick={() => openGuide(t)}>
|
||||||
|
<View className={styles.seasonHeader}>
|
||||||
|
<Text className={styles.seasonBadge}>当前 {currentSeason}</Text>
|
||||||
|
<Text className={styles.seasonTitle}>{t.title}</Text>
|
||||||
|
</View>
|
||||||
|
<Text className={styles.seasonContent}>{t.content}</Text>
|
||||||
|
</View>
|
||||||
|
))}
|
||||||
|
<View className={styles.diseaseList}>
|
||||||
|
{seasonalTips.map((t) => (
|
||||||
|
<View key={t.id} className={styles.guideCard} onClick={() => openGuide(t)}>
|
||||||
|
<Text className={styles.guideTitle}>{t.title}</Text>
|
||||||
|
{t.summary ? <Text className={styles.guideSummary}>{t.summary}</Text> : null}
|
||||||
|
</View>
|
||||||
|
))}
|
||||||
|
</View>
|
||||||
|
|
||||||
<Text className={styles.sectionTitle}>蚕病百科</Text>
|
<Text className={styles.sectionTitle}>蚕病百科</Text>
|
||||||
<View className={styles.diseaseList}>
|
<View className={styles.diseaseList}>
|
||||||
{diseases.map((d) => (
|
{diseases.map((d) => (
|
||||||
|
|||||||
Reference in New Issue
Block a user