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