初始化工程
This commit is contained in:
3
src/pages/index/index.config.ts
Normal file
3
src/pages/index/index.config.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export default definePageConfig({
|
||||
navigationBarTitleText: '首页'
|
||||
})
|
||||
261
src/pages/index/index.scss
Normal file
261
src/pages/index/index.scss
Normal file
@@ -0,0 +1,261 @@
|
||||
.index-page {
|
||||
padding: 20px;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
min-height: 100vh;
|
||||
|
||||
.page-header {
|
||||
text-align: center;
|
||||
margin-bottom: 24px;
|
||||
|
||||
.page-title {
|
||||
font-size: 28px;
|
||||
font-weight: bold;
|
||||
color: white;
|
||||
display: block;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.page-subtitle {
|
||||
font-size: 16px;
|
||||
color: rgba(255, 255, 255, 0.8);
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.user-card {
|
||||
background: white;
|
||||
border-radius: 16px;
|
||||
padding: 20px;
|
||||
margin-bottom: 20px;
|
||||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
|
||||
|
||||
.user-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16px;
|
||||
|
||||
.user-info {
|
||||
flex: 1;
|
||||
|
||||
.username {
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
display: block;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.user-level {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
display: block;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.join-date {
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.stats-section {
|
||||
background: white;
|
||||
border-radius: 16px;
|
||||
padding: 20px;
|
||||
margin-bottom: 20px;
|
||||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
|
||||
|
||||
.section-title {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
margin-bottom: 16px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
:global {
|
||||
.nut-cell {
|
||||
background: #f8f9fa;
|
||||
border-radius: 12px;
|
||||
margin-bottom: 8px;
|
||||
border: none;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.nut-cell__title {
|
||||
font-weight: 500;
|
||||
color: #555;
|
||||
}
|
||||
|
||||
.nut-cell__value {
|
||||
font-weight: bold;
|
||||
color: #007bff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.action-section {
|
||||
background: white;
|
||||
border-radius: 16px;
|
||||
padding: 20px;
|
||||
margin-bottom: 20px;
|
||||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
|
||||
|
||||
.section-title {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
margin-bottom: 16px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.button-group {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
|
||||
.custom-button {
|
||||
border-radius: 12px;
|
||||
font-weight: 500;
|
||||
height: 48px;
|
||||
border: none;
|
||||
margin-bottom: 12px;
|
||||
font-size: 16px;
|
||||
color: white;
|
||||
|
||||
&.primary-btn {
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
}
|
||||
|
||||
&.success-btn {
|
||||
background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
|
||||
}
|
||||
|
||||
&.warning-btn {
|
||||
background: linear-gradient(135deg, #fa709a 0%, #fee140 100%);
|
||||
}
|
||||
|
||||
&:disabled {
|
||||
opacity: 0.6;
|
||||
}
|
||||
}
|
||||
|
||||
// 保留 NutUI 按钮样式(备用)
|
||||
:global {
|
||||
.nut-button {
|
||||
border-radius: 12px;
|
||||
font-weight: 500;
|
||||
height: 48px;
|
||||
border: none;
|
||||
|
||||
&--primary {
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
}
|
||||
|
||||
&--success {
|
||||
background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
|
||||
}
|
||||
|
||||
&--warning {
|
||||
background: linear-gradient(135deg, #fa709a 0%, #fee140 100%);
|
||||
}
|
||||
|
||||
&:disabled {
|
||||
opacity: 0.6;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.loading-section {
|
||||
background: white;
|
||||
border-radius: 16px;
|
||||
padding: 20px;
|
||||
margin-bottom: 20px;
|
||||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
|
||||
text-align: center;
|
||||
|
||||
.loading-text {
|
||||
font-size: 16px;
|
||||
color: #666;
|
||||
margin-bottom: 12px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
:global {
|
||||
.nut-progress {
|
||||
.nut-progress-outer {
|
||||
background: #f0f0f0;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.nut-progress-inner {
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
border-radius: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tips-section {
|
||||
background: rgba(255, 255, 255, 0.95);
|
||||
border-radius: 16px;
|
||||
padding: 20px;
|
||||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
|
||||
|
||||
.tips-title {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
margin-bottom: 16px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.tips-content {
|
||||
.tip-item {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
line-height: 1.6;
|
||||
margin-bottom: 8px;
|
||||
display: block;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 响应式设计
|
||||
@media (max-width: 768px) {
|
||||
.index-page {
|
||||
padding: 16px;
|
||||
|
||||
.page-header {
|
||||
.page-title {
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
.page-subtitle {
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
.user-card,
|
||||
.stats-section,
|
||||
.action-section,
|
||||
.loading-section,
|
||||
.tips-section {
|
||||
padding: 16px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
293
src/pages/index/index.tsx
Normal file
293
src/pages/index/index.tsx
Normal file
@@ -0,0 +1,293 @@
|
||||
import React, { useState, useEffect } from 'react'
|
||||
import { View, Text, Button } from '@tarojs/components'
|
||||
import { Cell, Avatar, Progress } from '@nutui/nutui-react-taro'
|
||||
import Taro from '@tarojs/taro'
|
||||
// 导入API服务
|
||||
import demoApi from '../../services/demoApi'
|
||||
import commonApi from '../../services/commonApi'
|
||||
import {
|
||||
useUserStats,
|
||||
useUserActions
|
||||
} from '../../store/userStore'
|
||||
import './index.scss'
|
||||
|
||||
function Index() {
|
||||
// 使用Zustand store
|
||||
const userStats = useUserStats()
|
||||
const { incrementRequestCount, resetUserStats } = useUserActions()
|
||||
|
||||
// 本地状态管理
|
||||
const [loading, setLoading] = useState(false)
|
||||
const [userProfile, setUserProfile] = useState<any>(null)
|
||||
const [interests, setInterests] = useState<string[]>([])
|
||||
|
||||
// 页面加载时获取数据
|
||||
useEffect(() => {
|
||||
initializeData()
|
||||
}, [])
|
||||
|
||||
// 初始化数据
|
||||
const initializeData = async () => {
|
||||
try {
|
||||
// 获取推荐的兴趣爱好
|
||||
const interestsRes = await demoApi.getRecommendedInterests()
|
||||
if (interestsRes.success) {
|
||||
setInterests(interestsRes.data || [])
|
||||
}
|
||||
} catch (error) {
|
||||
console.log('获取初始数据失败:', error)
|
||||
}
|
||||
}
|
||||
|
||||
// 1. 获取用户信息 API 请求
|
||||
const handleGetUserProfile = async () => {
|
||||
console.log('获取用户信息...');
|
||||
setLoading(true)
|
||||
|
||||
try {
|
||||
const response = await demoApi.getUserProfile()
|
||||
|
||||
if (response.success) {
|
||||
setUserProfile(response.data)
|
||||
incrementRequestCount()
|
||||
|
||||
Taro.showToast({
|
||||
title: '获取用户信息成功',
|
||||
icon: 'success'
|
||||
})
|
||||
|
||||
console.log('用户信息:', response.data)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取用户信息失败:', error)
|
||||
Taro.showToast({
|
||||
title: '获取失败,使用模拟数据',
|
||||
icon: 'none'
|
||||
})
|
||||
|
||||
// 模拟数据
|
||||
setUserProfile({
|
||||
id: '123',
|
||||
nickname: '网球爱好者',
|
||||
avatar: '',
|
||||
gender: 'male',
|
||||
interests: interests.slice(0, 3)
|
||||
})
|
||||
incrementRequestCount()
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
}
|
||||
|
||||
// 2. 提交统计数据 API 请求
|
||||
const handleSubmitStats = async () => {
|
||||
console.log('提交统计数据...');
|
||||
setLoading(true)
|
||||
|
||||
try {
|
||||
const response = await commonApi.submitForm('userStats', [
|
||||
{
|
||||
type: 'userStats',
|
||||
data: {
|
||||
requestCount: userStats.requestCount,
|
||||
matchesCreated: userStats.matchesCreated,
|
||||
matchesJoined: userStats.matchesJoined,
|
||||
lastActiveTime: userStats.lastActiveTime,
|
||||
userId: userProfile?.id || 'guest'
|
||||
}
|
||||
}
|
||||
])
|
||||
|
||||
if (response.success) {
|
||||
incrementRequestCount()
|
||||
|
||||
Taro.showToast({
|
||||
title: '统计数据提交成功',
|
||||
icon: 'success'
|
||||
})
|
||||
|
||||
console.log('提交结果:', response.data)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('提交统计数据失败:', error)
|
||||
incrementRequestCount() // 即使失败也计数,用于演示
|
||||
|
||||
Taro.showToast({
|
||||
title: '网络模拟提交成功',
|
||||
icon: 'success'
|
||||
})
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
}
|
||||
|
||||
// 3. 提交反馈 API 请求
|
||||
const handleSubmitFeedback = async () => {
|
||||
console.log('提交用户反馈...');
|
||||
setLoading(true)
|
||||
|
||||
try {
|
||||
const response = await demoApi.submitFeedback({
|
||||
matchId: 'demo_match_' + Date.now(),
|
||||
rating: 5,
|
||||
recommend: 'yes',
|
||||
aspects: ['场地环境', '服务质量', '价格合理'],
|
||||
comments: `用户反馈 - 请求次数: ${userStats.requestCount + 1},体验良好!`
|
||||
})
|
||||
|
||||
if (response.success) {
|
||||
incrementRequestCount()
|
||||
|
||||
Taro.showToast({
|
||||
title: '反馈提交成功',
|
||||
icon: 'success'
|
||||
})
|
||||
|
||||
console.log('反馈结果:', response.data)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('提交反馈失败:', error)
|
||||
incrementRequestCount() // 即使失败也计数,用于演示
|
||||
|
||||
Taro.showToast({
|
||||
title: '网络模拟提交成功',
|
||||
icon: 'success'
|
||||
})
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
}
|
||||
|
||||
// 重置所有数据
|
||||
const handleResetAllData = () => {
|
||||
console.log('重置所有数据...');
|
||||
resetUserStats()
|
||||
setUserProfile(null)
|
||||
|
||||
Taro.showToast({
|
||||
title: '数据已重置',
|
||||
icon: 'success'
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<View className='index-page'>
|
||||
{/* 页面标题 */}
|
||||
<View className='page-header'>
|
||||
<Text className='page-title'>API 请求演示</Text>
|
||||
<Text className='page-subtitle'>真实网络请求功能测试</Text>
|
||||
</View>
|
||||
|
||||
{/* 用户信息卡片 */}
|
||||
<View className='user-card'>
|
||||
<View className='user-header'>
|
||||
<Avatar
|
||||
size="large"
|
||||
src={userProfile?.avatar || ''}
|
||||
style={{ backgroundColor: '#fa2c19' }}
|
||||
>
|
||||
{userProfile?.nickname?.charAt(0) || 'U'}
|
||||
</Avatar>
|
||||
<View className='user-info'>
|
||||
<Text className='username'>
|
||||
{userProfile?.nickname || '点击获取用户信息'}
|
||||
</Text>
|
||||
<Text className='user-level'>
|
||||
性别: {userProfile?.gender === 'male' ? '男' : userProfile?.gender === 'female' ? '女' : '未知'}
|
||||
</Text>
|
||||
<Text className='join-date'>
|
||||
兴趣: {userProfile?.interests?.join(', ') || '暂无'}
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{/* 统计数据 */}
|
||||
<View className='stats-section'>
|
||||
<Text className='section-title'>📊 API 请求统计</Text>
|
||||
|
||||
<Cell title="API 请求次数" extra={userStats.requestCount} />
|
||||
<Cell title="创建的比赛" extra={userStats.matchesCreated} />
|
||||
<Cell title="参加的比赛" extra={userStats.matchesJoined} />
|
||||
<Cell
|
||||
title="最后活跃时间"
|
||||
extra={new Date(userStats.lastActiveTime).toLocaleTimeString()}
|
||||
/>
|
||||
{interests.length > 0 && (
|
||||
<Cell
|
||||
title="推荐兴趣"
|
||||
extra={interests.slice(0, 2).join(', ')}
|
||||
/>
|
||||
)}
|
||||
</View>
|
||||
|
||||
{/* API 请求按钮区域 */}
|
||||
<View className='action-section'>
|
||||
<Text className='section-title'>🚀 API 请求功能</Text>
|
||||
|
||||
<View className='button-group'>
|
||||
<Button
|
||||
type="primary"
|
||||
loading={loading}
|
||||
onClick={handleGetUserProfile}
|
||||
disabled={loading}
|
||||
className="custom-button primary-btn"
|
||||
>
|
||||
{loading ? '请求中...' : '获取用户信息'}
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
type="default"
|
||||
loading={loading}
|
||||
onClick={handleSubmitStats}
|
||||
disabled={loading}
|
||||
className="custom-button success-btn"
|
||||
>
|
||||
{loading ? '提交中...' : '提交统计数据'}
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
type="default"
|
||||
loading={loading}
|
||||
onClick={handleSubmitFeedback}
|
||||
disabled={loading}
|
||||
className="custom-button warning-btn"
|
||||
>
|
||||
{loading ? '提交中...' : '提交用户反馈'}
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
type="warn"
|
||||
onClick={handleResetAllData}
|
||||
disabled={loading}
|
||||
className="custom-button warning-btn"
|
||||
>
|
||||
重置所有数据
|
||||
</Button>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{/* 实时进度显示 */}
|
||||
{loading && (
|
||||
<View className='loading-section'>
|
||||
<Text className='loading-text'>正在发送 API 请求...</Text>
|
||||
<Progress percent={100} animated />
|
||||
</View>
|
||||
)}
|
||||
|
||||
{/* 提示信息 */}
|
||||
<View className='tips-section'>
|
||||
<Text className='tips-title'>💡 API 功能说明</Text>
|
||||
<View className='tips-content'>
|
||||
<Text className='tip-item'>• "获取用户信息" - 调用用户资料 API</Text>
|
||||
<Text className='tip-item'>• "提交统计数据" - 发送统计到服务器</Text>
|
||||
<Text className='tip-item'>• "提交用户反馈" - 发送用户评价数据</Text>
|
||||
<Text className='tip-item'>• 所有请求都会增加 API 计数统计</Text>
|
||||
<Text className='tip-item'>• 请求失败时会自动使用模拟数据</Text>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
export default Index
|
||||
Reference in New Issue
Block a user