feat(miniprogram): 访客首页轮播图接入公开 API + 文章列表替换核心功能区域
This commit is contained in:
@@ -339,6 +339,19 @@
|
||||
&--1 {
|
||||
background: linear-gradient(135deg, $pri-d 0%, $pri 60%, $pri-l 100%);
|
||||
}
|
||||
&--2 {
|
||||
background: linear-gradient(135deg, $acc 0%, #3D5A40 60%, $acc-l 100%);
|
||||
}
|
||||
&--3 {
|
||||
background: linear-gradient(135deg, #8B6F4E 0%, $wrn 60%, $wrn-l 100%);
|
||||
}
|
||||
}
|
||||
|
||||
.guest-slide-image {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.guest-slide:nth-child(2) .guest-slide-bg {
|
||||
@@ -397,14 +410,27 @@
|
||||
.guest-article-card {
|
||||
background: $card;
|
||||
border-radius: $r;
|
||||
padding: 16px 18px;
|
||||
overflow: hidden;
|
||||
box-shadow: $shadow-sm;
|
||||
display: flex;
|
||||
|
||||
&:active {
|
||||
opacity: 0.85;
|
||||
}
|
||||
}
|
||||
|
||||
.guest-article-cover {
|
||||
width: 100px;
|
||||
height: 80px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.guest-article-body {
|
||||
padding: 12px 14px;
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.guest-article-title {
|
||||
font-size: var(--tk-font-body-sm);
|
||||
font-weight: 600;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { View, Text, Swiper, SwiperItem } from '@tarojs/components';
|
||||
import { useState, useCallback } from 'react';
|
||||
import { View, Text, Swiper, SwiperItem, Image } from '@tarojs/components';
|
||||
import { useState } from 'react';
|
||||
import Taro, { useDidShow, usePullDownRefresh } from '@tarojs/taro';
|
||||
import { useAuthStore } from '../../stores/auth';
|
||||
import { useUIStore } from '../../stores/ui';
|
||||
@@ -12,6 +12,8 @@ import * as appointmentApi from '@/services/appointment';
|
||||
import * as followupApi from '@/services/followup';
|
||||
import { listPendingSuggestions, type AiSuggestionItem } from '@/services/ai-analysis';
|
||||
import { notificationService } from '@/services/notification';
|
||||
import { api } from '@/services/request';
|
||||
import type { Article } from '@/services/article';
|
||||
import './index.scss';
|
||||
|
||||
interface ReminderItem {
|
||||
@@ -21,15 +23,62 @@ interface ReminderItem {
|
||||
tag: string;
|
||||
}
|
||||
|
||||
interface PublicBanner {
|
||||
id: string;
|
||||
title?: string;
|
||||
subtitle?: string;
|
||||
image_url?: string;
|
||||
link_type?: string;
|
||||
link_target?: string;
|
||||
}
|
||||
|
||||
// ─── 访客首页 ───
|
||||
|
||||
const CAROUSEL_SLIDES = [
|
||||
{ id: 'slide-1', title: '专业血透中心', desc: '三甲级医护团队全程守护' },
|
||||
{ id: 'slide-2', title: '智慧健康管理', desc: 'AI 驱动个性化健康方案' },
|
||||
{ id: 'slide-3', title: '温馨就医环境', desc: '舒适安全的治疗体验' },
|
||||
const FALLBACK_SLIDES = [
|
||||
{ id: 'slide-1', title: '专业血透中心', desc: '三甲级医护团队全程守护', image_url: '' },
|
||||
{ id: 'slide-2', title: '智慧健康管理', desc: 'AI 驱动个性化健康方案', image_url: '' },
|
||||
{ id: 'slide-3', title: '温馨就医环境', desc: '舒适安全的治疗体验', image_url: '' },
|
||||
];
|
||||
|
||||
function GuestHome({ modeClass }: { modeClass: string }) {
|
||||
const [banners, setBanners] = useState<PublicBanner[]>([]);
|
||||
const [articles, setArticles] = useState<Article[]>([]);
|
||||
|
||||
useDidShow(() => {
|
||||
loadPublicData();
|
||||
});
|
||||
|
||||
const loadPublicData = async () => {
|
||||
const tenantId = Taro.getStorageSync('tenant_id');
|
||||
if (!tenantId) {
|
||||
setBanners(FALLBACK_SLIDES);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const [bannerData, articleData] = await Promise.allSettled([
|
||||
api.get<PublicBanner[]>('/public/banners', { tenant_id: tenantId }, 300_000),
|
||||
api.get<{ data: Article[]; total: number }>('/health/articles', {
|
||||
status: 'published',
|
||||
page_size: 4,
|
||||
}, 300_000),
|
||||
]);
|
||||
|
||||
if (bannerData.status === 'fulfilled' && bannerData.value?.length > 0) {
|
||||
setBanners(bannerData.value);
|
||||
} else {
|
||||
setBanners(FALLBACK_SLIDES);
|
||||
}
|
||||
|
||||
if (articleData.status === 'fulfilled' && articleData.value?.data?.length > 0) {
|
||||
setArticles(articleData.value.data);
|
||||
}
|
||||
} catch {
|
||||
setBanners(FALLBACK_SLIDES);
|
||||
}
|
||||
};
|
||||
|
||||
const slides = banners.length > 0 ? banners : FALLBACK_SLIDES;
|
||||
|
||||
return (
|
||||
<View className={`guest-page ${modeClass}`}>
|
||||
{/* 轮播图 */}
|
||||
@@ -43,36 +92,58 @@ function GuestHome({ modeClass }: { modeClass: string }) {
|
||||
interval={4000}
|
||||
duration={500}
|
||||
>
|
||||
{CAROUSEL_SLIDES.map((slide) => (
|
||||
<SwiperItem key={slide.id}>
|
||||
{slides.map((slide, idx) => (
|
||||
<SwiperItem key={slide.id || idx}>
|
||||
<View className='guest-slide'>
|
||||
<View className='guest-slide-bg guest-slide-bg--1' />
|
||||
{slide.image_url ? (
|
||||
<Image className='guest-slide-image' src={slide.image_url} mode='aspectFill' />
|
||||
) : (
|
||||
<View className={`guest-slide-bg guest-slide-bg--${(idx % 3) + 1}`} />
|
||||
)}
|
||||
<View className='guest-slide-content'>
|
||||
<Text className='guest-slide-title'>{slide.title}</Text>
|
||||
<Text className='guest-slide-desc'>{slide.desc}</Text>
|
||||
<Text className='guest-slide-desc'>{slide.subtitle || slide.desc}</Text>
|
||||
</View>
|
||||
</View>
|
||||
</SwiperItem>
|
||||
))}
|
||||
</Swiper>
|
||||
|
||||
{/* 功能亮点 */}
|
||||
{/* 推荐文章(替换原来的"核心功能"区域) */}
|
||||
<View className='guest-section'>
|
||||
<Text className='guest-section-title'>核心功能</Text>
|
||||
<View className='guest-articles'>
|
||||
<View className='guest-article-card'>
|
||||
<Text className='guest-article-title'>健康数据管理</Text>
|
||||
<Text className='guest-article-summary'>记录并追踪您的体征数据</Text>
|
||||
<Text className='guest-section-title'>健康资讯</Text>
|
||||
{articles.length > 0 ? (
|
||||
<View className='guest-articles'>
|
||||
{articles.map((article) => (
|
||||
<View className='guest-article-card' key={article.id}>
|
||||
{article.cover_image && (
|
||||
<Image className='guest-article-cover' src={article.cover_image} mode='aspectFill' />
|
||||
)}
|
||||
<View className='guest-article-body'>
|
||||
<Text className='guest-article-title'>{article.title}</Text>
|
||||
<Text className='guest-article-summary'>
|
||||
{article.summary || '点击查看详情'}
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
))}
|
||||
</View>
|
||||
<View className='guest-article-card'>
|
||||
<Text className='guest-article-title'>智能预约排班</Text>
|
||||
<Text className='guest-article-summary'>在线预约透析和治疗</Text>
|
||||
) : (
|
||||
<View className='guest-articles'>
|
||||
<View className='guest-article-card'>
|
||||
<Text className='guest-article-title'>健康数据管理</Text>
|
||||
<Text className='guest-article-summary'>记录并追踪您的体征数据</Text>
|
||||
</View>
|
||||
<View className='guest-article-card'>
|
||||
<Text className='guest-article-title'>智能预约排班</Text>
|
||||
<Text className='guest-article-summary'>在线预约透析和治疗</Text>
|
||||
</View>
|
||||
<View className='guest-article-card'>
|
||||
<Text className='guest-article-title'>AI 健康分析</Text>
|
||||
<Text className='guest-article-summary'>个性化健康趋势解读</Text>
|
||||
</View>
|
||||
</View>
|
||||
<View className='guest-article-card'>
|
||||
<Text className='guest-article-title'>AI 健康分析</Text>
|
||||
<Text className='guest-article-summary'>个性化健康趋势解读</Text>
|
||||
</View>
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
|
||||
{/* 底部登录引导 */}
|
||||
|
||||
Reference in New Issue
Block a user