Merge branch 'feat/liujie'
This commit is contained in:
4
src/pages/detail/index.config.ts
Normal file
4
src/pages/detail/index.config.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export default definePageConfig({
|
||||
navigationBarTitleText: '球局详情',
|
||||
navigationStyle: 'custom',
|
||||
})
|
||||
102
src/pages/detail/index.scss
Normal file
102
src/pages/detail/index.scss
Normal file
@@ -0,0 +1,102 @@
|
||||
@use '~@/scss/images.scss' as img;
|
||||
|
||||
.detail-page {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
.custom-navbar {
|
||||
height: 56px; /* 通常与原生导航栏高度一致 */
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
// background-color: #fff;
|
||||
color: #000;
|
||||
padding-top: 36px; /* 适配状态栏 */
|
||||
}
|
||||
|
||||
.detail-navigator {
|
||||
height: 30px;
|
||||
width: 80px;
|
||||
border-radius: 15px;
|
||||
position: absolute;
|
||||
left: 12px;
|
||||
border: 1px solid #888;
|
||||
box-sizing: border-box;
|
||||
color: #fff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.detail-navigator-back {
|
||||
border-right: 1px solid #444;
|
||||
}
|
||||
|
||||
.detail-navigator-back, .detail-navigator-icon {
|
||||
height: 20px;
|
||||
width: 50%;
|
||||
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
||||
& > .detail-navigator-back-icon {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
& > .detail-navigator-logo-icon {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.detail-page-bg {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
background-size: cover;
|
||||
filter: blur(40px);
|
||||
transform: scale(1.5);
|
||||
z-index: -2;
|
||||
width: calc(100% + 20px);
|
||||
height: calc(100% + 20px);
|
||||
margin: -10px;
|
||||
}
|
||||
|
||||
.detail-page-bg-text {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
z-index: -1;
|
||||
background-color: rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.detail-swiper {
|
||||
height: 240px;
|
||||
margin-top: 15px;
|
||||
margin-left: 15px;
|
||||
}
|
||||
|
||||
.detail-swiper-item {
|
||||
overflow: visible;
|
||||
height: 100%;
|
||||
|
||||
.detail-swiper-item-image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 12px;
|
||||
transition: transform 0.5s;
|
||||
}
|
||||
}
|
||||
|
||||
.detail-text {
|
||||
font-size: 40rpx;
|
||||
margin-top: 20px;
|
||||
transition: color 0.3s ease-in;
|
||||
}
|
||||
}
|
||||
110
src/pages/detail/index.tsx
Normal file
110
src/pages/detail/index.tsx
Normal file
@@ -0,0 +1,110 @@
|
||||
import React, { useState, useEffect } from 'react'
|
||||
import { View, Text, Button, Swiper, SwiperItem, Image } 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 img from '../../config/images'
|
||||
import { getTextColorOnImage } from '../../utils/processImage'
|
||||
import './index.scss'
|
||||
|
||||
const images = [
|
||||
'http://bimwe.oss-cn-shanghai.aliyuncs.com/front/ball/images/1a35ebbf-2361-44da-b338-7608561d0b31.png',
|
||||
'http://bimwe.oss-cn-shanghai.aliyuncs.com/front/ball/images/cf5a82ba-90af-4138-a1b3-9119adcde9e0.png',
|
||||
'http://bimwe.oss-cn-shanghai.aliyuncs.com/front/ball/images/49d7cdf0-b03c-4a0f-91c6-e7778080cfcd.png'
|
||||
]
|
||||
|
||||
|
||||
|
||||
function Index() {
|
||||
// 使用Zustand store
|
||||
// const userStats = useUserStats()
|
||||
// const { incrementRequestCount, resetUserStats } = useUserActions()
|
||||
|
||||
const [current, setCurrent] = useState(0)
|
||||
const [colors, setColors] = useState<string []>([])
|
||||
|
||||
// 本地状态管理
|
||||
const [loading, setLoading] = useState(false)
|
||||
const [userProfile, setUserProfile] = useState<any>(null)
|
||||
const [interests, setInterests] = useState<string[]>([])
|
||||
|
||||
// 页面加载时获取数据
|
||||
useEffect(() => {
|
||||
initializeData()
|
||||
calcBgMainColors()
|
||||
}, [])
|
||||
|
||||
// 初始化数据
|
||||
const initializeData = async () => {
|
||||
try {
|
||||
// 获取推荐的兴趣爱好
|
||||
const interestsRes = await demoApi.getRecommendedInterests()
|
||||
if (interestsRes.success) {
|
||||
setInterests(interestsRes.data || [])
|
||||
}
|
||||
} catch (error) {
|
||||
console.log('获取初始数据失败:', error)
|
||||
}
|
||||
}
|
||||
|
||||
const calcBgMainColors = async () => {
|
||||
const textcolors: string[] = []
|
||||
for (const index in images) {
|
||||
const { textColor } = await getTextColorOnImage(images[index])
|
||||
textcolors[index] = textColor
|
||||
}
|
||||
setColors(textcolors)
|
||||
}
|
||||
|
||||
return (
|
||||
<View className='detail-page'>
|
||||
<view className="custom-navbar">
|
||||
<View className='detail-navigator'>
|
||||
<View className='detail-navigator-back'>
|
||||
<Image className='detail-navigator-back-icon' src={img.ICON_ARROW_LEFT} />
|
||||
</View>
|
||||
<View className='detail-navigator-icon'>
|
||||
<Image className='detail-navigator-logo-icon' src={img.ICON_LOGO_GO} />
|
||||
</View>
|
||||
</View>
|
||||
{/* <view className="navbar-title">我的自定义标题</view> */}
|
||||
</view>
|
||||
<View className='detail-page-bg' style={{ backgroundImage: `url(${images[current]})` }} />
|
||||
<View className='detail-page-bg-text' />
|
||||
<Swiper
|
||||
className='detail-swiper'
|
||||
indicatorDots={false}
|
||||
circular
|
||||
nextMargin="20px"
|
||||
onChange={(e) => { setCurrent(e.detail.current) }}
|
||||
>
|
||||
{images.map((imageUrl, index) => (
|
||||
<SwiperItem
|
||||
key={index}
|
||||
className='detail-swiper-item'
|
||||
>
|
||||
<Image
|
||||
src={imageUrl}
|
||||
mode="aspectFill"
|
||||
className='detail-swiper-item-image'
|
||||
style={{
|
||||
transform: index !== current ? 'scale(0.8) translateX(-12%)' : 'scale(0.95)', // 前后图缩小
|
||||
}}
|
||||
/>
|
||||
</SwiperItem>
|
||||
))}
|
||||
</Swiper>
|
||||
<Text className='detail-text' style={{ color: colors[current] }}>
|
||||
Five feet from the bed was an earthen wall that had suffered from numerous cracks due to the passage of time. From the other side of the wall came the nagging voice of his mother and the occasional deep breathing of his father who was smoking his pipe.
|
||||
</Text>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
export default Index
|
||||
@@ -5,8 +5,8 @@ import Taro from '@tarojs/taro'
|
||||
// 导入API服务
|
||||
import demoApi from '../../services/demoApi'
|
||||
import commonApi from '../../services/commonApi'
|
||||
import {
|
||||
useUserStats,
|
||||
import {
|
||||
useUserStats,
|
||||
useUserActions
|
||||
} from '../../store/userStore'
|
||||
import './index.scss'
|
||||
@@ -15,7 +15,7 @@ function Index() {
|
||||
// 使用Zustand store
|
||||
const userStats = useUserStats()
|
||||
const { incrementRequestCount, resetUserStats } = useUserActions()
|
||||
|
||||
|
||||
// 本地状态管理
|
||||
const [loading, setLoading] = useState(false)
|
||||
const [userProfile, setUserProfile] = useState<any>(null)
|
||||
@@ -43,19 +43,19 @@ function Index() {
|
||||
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) {
|
||||
@@ -64,7 +64,7 @@ function Index() {
|
||||
title: '获取失败,使用模拟数据',
|
||||
icon: 'none'
|
||||
})
|
||||
|
||||
|
||||
// 模拟数据
|
||||
setUserProfile({
|
||||
id: '123',
|
||||
@@ -83,7 +83,7 @@ function Index() {
|
||||
const handleSubmitStats = async () => {
|
||||
console.log('提交统计数据...');
|
||||
setLoading(true)
|
||||
|
||||
|
||||
try {
|
||||
const response = await commonApi.submitForm('userStats', [
|
||||
{
|
||||
@@ -97,21 +97,21 @@ function Index() {
|
||||
}
|
||||
}
|
||||
])
|
||||
|
||||
|
||||
if (response.success) {
|
||||
incrementRequestCount()
|
||||
|
||||
|
||||
Taro.showToast({
|
||||
title: '统计数据提交成功',
|
||||
icon: 'success'
|
||||
})
|
||||
|
||||
|
||||
console.log('提交结果:', response.data)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('提交统计数据失败:', error)
|
||||
incrementRequestCount() // 即使失败也计数,用于演示
|
||||
|
||||
|
||||
Taro.showToast({
|
||||
title: '网络模拟提交成功',
|
||||
icon: 'success'
|
||||
@@ -125,7 +125,7 @@ function Index() {
|
||||
const handleSubmitFeedback = async () => {
|
||||
console.log('提交用户反馈...');
|
||||
setLoading(true)
|
||||
|
||||
|
||||
try {
|
||||
const response = await demoApi.submitFeedback({
|
||||
matchId: 'demo_match_' + Date.now(),
|
||||
@@ -134,21 +134,21 @@ function Index() {
|
||||
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'
|
||||
@@ -163,7 +163,7 @@ function Index() {
|
||||
console.log('重置所有数据...');
|
||||
resetUserStats()
|
||||
setUserProfile(null)
|
||||
|
||||
|
||||
Taro.showToast({
|
||||
title: '数据已重置',
|
||||
icon: 'success'
|
||||
@@ -181,9 +181,9 @@ function Index() {
|
||||
{/* 用户信息卡片 */}
|
||||
<View className='user-card'>
|
||||
<View className='user-header'>
|
||||
<Avatar
|
||||
size="large"
|
||||
src={userProfile?.avatar || ''}
|
||||
<Avatar
|
||||
size="large"
|
||||
src={userProfile?.avatar || ''}
|
||||
style={{ backgroundColor: '#fa2c19' }}
|
||||
>
|
||||
{userProfile?.nickname?.charAt(0) || 'U'}
|
||||
@@ -205,17 +205,17 @@ function Index() {
|
||||
{/* 统计数据 */}
|
||||
<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="最后活跃时间"
|
||||
<Cell
|
||||
title="最后活跃时间"
|
||||
extra={new Date(userStats.lastActiveTime).toLocaleTimeString()}
|
||||
/>
|
||||
{interests.length > 0 && (
|
||||
<Cell
|
||||
title="推荐兴趣"
|
||||
<Cell
|
||||
title="推荐兴趣"
|
||||
extra={interests.slice(0, 2).join(', ')}
|
||||
/>
|
||||
)}
|
||||
@@ -224,10 +224,10 @@ function Index() {
|
||||
{/* API 请求按钮区域 */}
|
||||
<View className='action-section'>
|
||||
<Text className='section-title'>🚀 API 请求功能</Text>
|
||||
|
||||
|
||||
<View className='button-group'>
|
||||
<Button
|
||||
type="primary"
|
||||
<Button
|
||||
type="primary"
|
||||
loading={loading}
|
||||
onClick={handleGetUserProfile}
|
||||
disabled={loading}
|
||||
@@ -236,8 +236,8 @@ function Index() {
|
||||
{loading ? '请求中...' : '获取用户信息'}
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
type="default"
|
||||
<Button
|
||||
type="default"
|
||||
loading={loading}
|
||||
onClick={handleSubmitStats}
|
||||
disabled={loading}
|
||||
@@ -246,8 +246,8 @@ function Index() {
|
||||
{loading ? '提交中...' : '提交统计数据'}
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
type="default"
|
||||
<Button
|
||||
type="default"
|
||||
loading={loading}
|
||||
onClick={handleSubmitFeedback}
|
||||
disabled={loading}
|
||||
@@ -256,8 +256,8 @@ function Index() {
|
||||
{loading ? '提交中...' : '提交用户反馈'}
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
type="warn"
|
||||
<Button
|
||||
type="warn"
|
||||
onClick={handleResetAllData}
|
||||
disabled={loading}
|
||||
className="custom-button warning-btn"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { useState, useEffect } from 'react'
|
||||
import { View, Text } from '@tarojs/components'
|
||||
import { ImageUpload, Range, TimeSelector, TextareaTag, NumberInterval, TitleTextarea, FormSwitch } from '../../components'
|
||||
import { ImageUpload, Range, TimeSelector, TextareaTag, NumberInterval, TitleTextarea, FormSwitch, UploadCover } from '../../components'
|
||||
import FormBasicInfo from './components/FormBasicInfo'
|
||||
import { type CoverImage } from '../../components/index.types'
|
||||
import { FormFieldConfig, FieldType } from '../../config/formSchema/publishBallFormSchema'
|
||||
@@ -22,18 +22,22 @@ const componentMap = {
|
||||
[FieldType.WECHATCONTACT]: WechatSwitch,
|
||||
}
|
||||
|
||||
const PublishForm: React.FC<{
|
||||
formData: PublishBallFormData,
|
||||
onChange: (key: keyof PublishBallFormData, value: any, index?: number) => void,
|
||||
const PublishForm: React.FC<{
|
||||
formData: PublishBallFormData,
|
||||
onChange: (key: keyof PublishBallFormData, value: any, index?: number) => void,
|
||||
optionsConfig: FormFieldConfig[] }> = ({ formData, onChange, optionsConfig }) => {
|
||||
const [coverImages, setCoverImages] = useState<CoverImage[]>([])
|
||||
|
||||
|
||||
// 字典数据相关
|
||||
const { getDictionaryValue } = useDictionaryActions()
|
||||
|
||||
// 处理封面图片变化
|
||||
const handleCoverImagesChange = (images: CoverImage[]) => {
|
||||
setCoverImages(images)
|
||||
const handleCoverImagesChange = (fn: (images: CoverImage[]) => CoverImage[]) => {
|
||||
if (fn instanceof Function) {
|
||||
setCoverImages(fn(coverImages))
|
||||
} else {
|
||||
setCoverImages(fn)
|
||||
}
|
||||
}
|
||||
|
||||
// 更新表单数据
|
||||
@@ -70,7 +74,7 @@ const PublishForm: React.FC<{
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 如果是补充要求,从字典获取选项
|
||||
if (item.prop === 'descriptionInfo') {
|
||||
const descriptionOptions = getDictionaryOptions('publishing_requirements', [])
|
||||
@@ -79,7 +83,7 @@ const PublishForm: React.FC<{
|
||||
options: descriptionOptions
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return item
|
||||
})
|
||||
}
|
||||
@@ -93,7 +97,7 @@ const PublishForm: React.FC<{
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// 获取动态表单配置
|
||||
const dynamicConfig = getDynamicFormConfig()
|
||||
@@ -112,8 +116,8 @@ const PublishForm: React.FC<{
|
||||
}
|
||||
if (item.type === FieldType.UPLOADIMAGE) {
|
||||
/* 活动封面 */
|
||||
return <ImageUpload
|
||||
images={coverImages}
|
||||
return <UploadCover
|
||||
value={coverImages}
|
||||
onChange={handleCoverImagesChange}
|
||||
{...item.props}
|
||||
/>
|
||||
@@ -154,7 +158,7 @@ const PublishForm: React.FC<{
|
||||
value={formData[item.prop]}
|
||||
onChange={(value) => updateFormData(item.prop as keyof PublishBallFormData, value)}
|
||||
{...optionProps}
|
||||
placeholder={item.placeholder}
|
||||
placeholder={item.placeholder}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
Reference in New Issue
Block a user