feat(miniprogram): 初始化 Taro 4 + React 小程序项目
- 手动创建 Taro 4.2 + React 18 + TypeScript 项目骨架 - 配置 webpack5 编译、SCSS 样式、医疗清新主题 - 实现 API 请求层(JWT 自动注入 + token 刷新) - 实现 auth store(微信登录 + 手机号绑定 + 就诊人管理) - 实现登录页(微信一键登录 + 手机号授权绑定) - 实现首页(问候栏 + 今日健康卡片 + 快捷服务 + 即将到来) - 实现我的页面(个人信息 + 功能菜单 + 退出登录) - 健康/预约/资讯占位页 - TabBar 5 个入口:首页/健康/预约/资讯/我的
This commit is contained in:
122
apps/miniprogram/src/pages/index/index.scss
Normal file
122
apps/miniprogram/src/pages/index/index.scss
Normal file
@@ -0,0 +1,122 @@
|
||||
@import '../../styles/variables.scss';
|
||||
|
||||
.index-page {
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
|
||||
.greeting-bar {
|
||||
background: linear-gradient(135deg, $pri 0%, $pri-d 100%);
|
||||
padding: 40px 32px 60px;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.greeting-text {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.greeting-hello {
|
||||
font-size: 36px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.greeting-name {
|
||||
font-size: 36px;
|
||||
font-weight: bold;
|
||||
margin-left: 12px;
|
||||
}
|
||||
|
||||
.greeting-date {
|
||||
font-size: 24px;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.health-card {
|
||||
background: $card;
|
||||
border-radius: $r;
|
||||
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08);
|
||||
margin: -30px 24px 24px;
|
||||
padding: 28px;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 30px;
|
||||
font-weight: bold;
|
||||
color: $tx;
|
||||
margin-bottom: 20px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.health-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.health-item {
|
||||
background: $bg;
|
||||
border-radius: $r-sm;
|
||||
padding: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.health-label {
|
||||
font-size: 24px;
|
||||
color: $tx2;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.health-value {
|
||||
font-size: 36px;
|
||||
font-weight: bold;
|
||||
color: $pri;
|
||||
display: block;
|
||||
margin: 8px 0 4px;
|
||||
}
|
||||
|
||||
.health-unit {
|
||||
font-size: 22px;
|
||||
color: $tx3;
|
||||
}
|
||||
|
||||
.quick-services {
|
||||
margin: 0 24px 24px;
|
||||
}
|
||||
|
||||
.service-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.service-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 20px 0;
|
||||
}
|
||||
|
||||
.service-icon {
|
||||
font-size: 48px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.service-label {
|
||||
font-size: 24px;
|
||||
color: $tx2;
|
||||
}
|
||||
|
||||
.upcoming {
|
||||
margin: 0 24px;
|
||||
}
|
||||
|
||||
.empty-hint {
|
||||
background: $card;
|
||||
border-radius: $r;
|
||||
padding: 40px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.empty-text {
|
||||
font-size: 26px;
|
||||
color: $tx3;
|
||||
}
|
||||
85
apps/miniprogram/src/pages/index/index.tsx
Normal file
85
apps/miniprogram/src/pages/index/index.tsx
Normal file
@@ -0,0 +1,85 @@
|
||||
import { View, Text } from '@tarojs/components';
|
||||
import Taro, { useDidShow } from '@tarojs/taro';
|
||||
import { useAuthStore } from '../../stores/auth';
|
||||
import './index.scss';
|
||||
|
||||
export default function Index() {
|
||||
const { user, restore } = useAuthStore();
|
||||
|
||||
useDidShow(() => {
|
||||
restore();
|
||||
});
|
||||
|
||||
const greeting = () => {
|
||||
const h = new Date().getHours();
|
||||
if (h < 6) return '凌晨好';
|
||||
if (h < 12) return '上午好';
|
||||
if (h < 14) return '中午好';
|
||||
if (h < 18) return '下午好';
|
||||
return '晚上好';
|
||||
};
|
||||
|
||||
return (
|
||||
<View className='index-page'>
|
||||
{/* 问候栏 */}
|
||||
<View className='greeting-bar'>
|
||||
<View className='greeting-text'>
|
||||
<Text className='greeting-hello'>{greeting()}</Text>
|
||||
<Text className='greeting-name'>{user?.display_name || '用户'}</Text>
|
||||
</View>
|
||||
<Text className='greeting-date'>
|
||||
{new Date().toLocaleDateString('zh-CN', { month: 'long', day: 'numeric', weekday: 'short' })}
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
{/* 今日健康卡片 */}
|
||||
<View className='health-card'>
|
||||
<Text className='section-title'>今日健康</Text>
|
||||
<View className='health-grid'>
|
||||
{[
|
||||
{ label: '血压', value: '--/--', unit: 'mmHg', status: '' },
|
||||
{ label: '心率', value: '--', unit: 'bpm', status: '' },
|
||||
{ label: '血糖', value: '--', unit: 'mmol/L', status: '' },
|
||||
{ label: '体重', value: '--', unit: 'kg', status: '' },
|
||||
].map((item) => (
|
||||
<View className='health-item' key={item.label}>
|
||||
<Text className='health-label'>{item.label}</Text>
|
||||
<Text className='health-value'>{item.value}</Text>
|
||||
<Text className='health-unit'>{item.unit}</Text>
|
||||
</View>
|
||||
))}
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{/* 快捷服务 */}
|
||||
<View className='quick-services'>
|
||||
<Text className='section-title'>快捷服务</Text>
|
||||
<View className='service-grid'>
|
||||
{[
|
||||
{ label: '录数据', icon: '📝', path: '/pages/health/index' },
|
||||
{ label: '预约', icon: '📅', path: '/pages/appointment/index' },
|
||||
{ label: '报告', icon: '📋', path: '/pages/profile/index' },
|
||||
{ label: '随访', icon: '💬', path: '/pages/profile/index' },
|
||||
].map((item) => (
|
||||
<View
|
||||
className='service-item'
|
||||
key={item.label}
|
||||
onClick={() => Taro.switchTab({ url: item.path })}
|
||||
>
|
||||
<Text className='service-icon'>{item.icon}</Text>
|
||||
<Text className='service-label'>{item.label}</Text>
|
||||
</View>
|
||||
))}
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{/* 即将到来 */}
|
||||
<View className='upcoming'>
|
||||
<Text className='section-title'>即将到来</Text>
|
||||
<View className='empty-hint'>
|
||||
<Text className='empty-text'>暂无即将到来的预约</Text>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user