feat: 详情页联调
This commit is contained in:
@@ -16,6 +16,8 @@
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 100;
|
||||
overflow: hidden;
|
||||
background-color: rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.detail-navigator {
|
||||
@@ -63,12 +65,26 @@
|
||||
left: 0;
|
||||
top: 0;
|
||||
background-size: cover;
|
||||
filter: blur(40px);
|
||||
transform: scale(1.5);
|
||||
// filter: blur(40px);
|
||||
// transform: scale(1.5);
|
||||
z-index: -2;
|
||||
width: calc(100% + 20px);
|
||||
height: calc(100% + 20px);
|
||||
margin: -10px;
|
||||
// width: calc(100% + 20px);
|
||||
// height: calc(100% + 20px);
|
||||
// margin: -10px;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: -1;
|
||||
background: linear-gradient(180deg, rgba(0, 0, 0, 0.80) 0%, rgba(0, 0, 0, 0.40) 100%);
|
||||
backdrop-filter: blur(100px);
|
||||
}
|
||||
}
|
||||
|
||||
.detail-page-bg-text {
|
||||
@@ -215,7 +231,6 @@
|
||||
display: flex;
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
padding-bottom: 6px;
|
||||
box-sizing: border-box;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
@@ -225,6 +240,7 @@
|
||||
background: rgba(255, 255, 255, 0.25);
|
||||
overflow: hidden;
|
||||
color: #FFF;
|
||||
background: #536272;
|
||||
|
||||
.month {
|
||||
width: 100%;
|
||||
@@ -235,20 +251,21 @@
|
||||
box-sizing: border-box;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.08);
|
||||
// border-bottom: 1px solid rgba(255, 255, 255, 0.08);
|
||||
background: #7B828B;
|
||||
}
|
||||
|
||||
.day {
|
||||
display: flex;
|
||||
width: 48px;
|
||||
padding-bottom: 6px;
|
||||
height: 30px;
|
||||
// padding-bottom: 6px;
|
||||
box-sizing: border-box;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
// border: 0.5px solid rgba(255, 255, 255, 0.08);
|
||||
// background: rgba(255, 255, 255, 0.25);
|
||||
// background-color: #536272;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -334,7 +351,7 @@
|
||||
align-items: center;
|
||||
overflow: hidden;
|
||||
// border: 0.5px solid rgba(255, 255, 255, 0.08);
|
||||
background: rgba(255, 255, 255, 0.25);
|
||||
// background: rgba(255, 255, 255, 0.25);
|
||||
|
||||
&-image {
|
||||
width: 20px;
|
||||
@@ -399,7 +416,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
&-detail {
|
||||
&-venue {
|
||||
padding: 24px 15px 0;
|
||||
box-sizing: border-box;
|
||||
|
||||
@@ -408,7 +425,7 @@
|
||||
height: 31px;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
gap: 4px;
|
||||
gap: 8px;
|
||||
padding-bottom: 6px;
|
||||
color: #FFF;
|
||||
text-overflow: ellipsis;
|
||||
@@ -419,9 +436,15 @@
|
||||
line-height: 24px;
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
|
||||
|
||||
&-notice-icon {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
.venue-reserve-status {
|
||||
display: inline-flex;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
.venue-reserve-screenshot {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -461,6 +484,51 @@
|
||||
line-height: 24px; /* 160% */
|
||||
}
|
||||
}
|
||||
|
||||
.venue-screenshot-title {
|
||||
display: flex;
|
||||
padding: 18px 20px 10px 20px;
|
||||
align-items: center;
|
||||
align-self: stretch;
|
||||
font-family: "PingFang SC";
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
line-height: 24px; /* 150% */
|
||||
letter-spacing: -0.23px;
|
||||
}
|
||||
|
||||
.venue-screenshot-scroll-view {
|
||||
max-height: calc(100vh - 260px);
|
||||
overflow-y: auto;
|
||||
padding-bottom: 40px;
|
||||
|
||||
.venue-screenshot-image-list {
|
||||
width: 100%;
|
||||
padding: 0 16px;
|
||||
box-sizing: border-box;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 10px 10px;
|
||||
|
||||
.venue-screenshot-image-item {
|
||||
aspect-ratio: 1/1;
|
||||
border-radius: 9px;
|
||||
border: 1px solid rgba(0, 0, 0, 0.12);
|
||||
box-sizing: border-box;
|
||||
background: rgba(0, 0, 0, 0.06);
|
||||
margin: 0;
|
||||
position: relative;
|
||||
|
||||
.venue-screenshot-image-item-image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 9px;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-gameplay-requirements {
|
||||
@@ -591,7 +659,7 @@
|
||||
.participants-list-item {
|
||||
display: flex;
|
||||
width: 108px;
|
||||
padding: 16px 12px 10px 12px;
|
||||
padding: 16px 4px 10px 4px;
|
||||
box-sizing: border-box;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
@@ -608,6 +676,7 @@
|
||||
}
|
||||
|
||||
&-name {
|
||||
width: 100%;
|
||||
color: rgba(255, 255, 255, 0.85);
|
||||
text-align: center;
|
||||
font-feature-settings: 'liga' off, 'clig' off;
|
||||
@@ -616,6 +685,9 @@
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
line-height: 24px; /* 184.615% */
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
&-level {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { useState, useRef, useImperativeHandle, forwardRef } from 'react'
|
||||
import { View, Text, Image, Map, ScrollView } from '@tarojs/components'
|
||||
import { Avatar, Popover } from '@nutui/nutui-react-taro'
|
||||
import { Avatar, Popover, ImagePreview } from '@nutui/nutui-react-taro'
|
||||
import Taro, { useRouter, useShareAppMessage, useShareTimeline, useDidShow } from '@tarojs/taro'
|
||||
import dayjs from 'dayjs'
|
||||
import 'dayjs/locale/zh-cn'
|
||||
@@ -86,7 +86,6 @@ function StickyButton(props) {
|
||||
const { publisher_id, match_status, price } = detail || {}
|
||||
|
||||
const role = Number(publisher_id) === id ? 'ownner' : 'visitor'
|
||||
console.log(match_status, role)
|
||||
return (
|
||||
<View className="sticky-bottom-bar">
|
||||
<View className="sticky-bottom-bar-share-and-comment">
|
||||
@@ -214,117 +213,196 @@ function GameInfo(props) {
|
||||
)
|
||||
}
|
||||
|
||||
function Index() {
|
||||
// 使用Zustand store
|
||||
// const userStats = useUserStats()
|
||||
// const { incrementRequestCount, resetUserStats } = useUserActions()
|
||||
// 场馆信息
|
||||
function VenueInfo(props) {
|
||||
const { detail } = props
|
||||
const [visible, setVisible] = useState(false)
|
||||
const { venue_description, venue_description_tag = [], venue_image_list = [] } = detail
|
||||
|
||||
const [current, setCurrent] = useState(0)
|
||||
// const [textColor, setTextColor] = useState<string []>([])
|
||||
const [detail, setDetail] = useState<any>(null)
|
||||
const { params } = useRouter()
|
||||
const [currentLocation, setCurrentLocation] = useState<[number, number]>([0, 0])
|
||||
const { id, autoShare, from } = params
|
||||
const { fetchUserInfo, updateUserInfo } = useUserActions()
|
||||
|
||||
console.group('params')
|
||||
console.log(params)
|
||||
console.groupEnd()
|
||||
|
||||
// 本地状态管理
|
||||
const [loading, setLoading] = useState(false)
|
||||
const sharePopupRef = useRef<any>(null)
|
||||
|
||||
// 页面加载时获取数据
|
||||
// useEffect(() => {
|
||||
// fetchDetail()
|
||||
// calcBgMainColors()
|
||||
// }, [])
|
||||
|
||||
useDidShow(async () => {
|
||||
await updateLocation()
|
||||
await fetchUserInfo()
|
||||
await fetchDetail()
|
||||
// calcBgMainColors()
|
||||
})
|
||||
|
||||
const updateLocation = async () => {
|
||||
try {
|
||||
const location = await getCurrentLocation()
|
||||
setCurrentLocation([location.latitude, location.longitude])
|
||||
await updateUserInfo({ latitude: location.latitude, longitude: location.longitude })
|
||||
console.log('用户位置更新成功')
|
||||
} catch (error) {
|
||||
console.error('用户位置更新失败', error)
|
||||
}
|
||||
function showScreenShot() {
|
||||
setVisible(true)
|
||||
}
|
||||
function onClose() {
|
||||
setVisible(false)
|
||||
}
|
||||
|
||||
const fetchDetail = async () => {
|
||||
const res = await DetailService.getDetail(243/* Number(id) */)
|
||||
if (res.code === 0) {
|
||||
console.log(res.data)
|
||||
setDetail(res.data)
|
||||
}
|
||||
}
|
||||
|
||||
// const calcBgMainColors = async () => {
|
||||
// const textcolors: string[] = []
|
||||
// // for (const index in images) {
|
||||
// // const { textColor } = await getTextColorOnImage(images[index])
|
||||
// // textcolors[index] = textColor
|
||||
// // }
|
||||
// if (detail?.image_list?.length > 0) {
|
||||
// const { textColor } = await getTextColorOnImage(detail.image_list[0])
|
||||
// textcolors[0] = textColor
|
||||
// }
|
||||
// setColors(textcolors)
|
||||
// }
|
||||
|
||||
function handleShare() {
|
||||
sharePopupRef.current.show()
|
||||
}
|
||||
|
||||
const handleJoinGame = () => {
|
||||
Taro.navigateTo({
|
||||
url: `/pages/orderCheck/index?gameId=${243/* id */}`,
|
||||
function previewImage(current_url) {
|
||||
Taro.previewImage({
|
||||
current: current_url,
|
||||
urls: venue_image_list.map(c => c.url),
|
||||
})
|
||||
}
|
||||
return (
|
||||
<View className='detail-page-content-venue'>
|
||||
{/* venue detail title and venue ordered status */}
|
||||
<View className='venue-detail-title'>
|
||||
<Text>场馆详情</Text>
|
||||
{venue_image_list?.length > 0 ?
|
||||
<>
|
||||
<Text>·</Text>
|
||||
<View className="venue-reserve-status" onClick={showScreenShot}>
|
||||
<Text>已订场</Text>
|
||||
<Image className="venue-reserve-screenshot" src={img.ICON_DETAIL_ARROW_RIGHT} />
|
||||
</View>
|
||||
</>
|
||||
:
|
||||
''
|
||||
}
|
||||
</View>
|
||||
{/* venue detail content */}
|
||||
<View className='venue-detail-content'>
|
||||
{/* venue detail tags */}
|
||||
<View className='venue-detail-content-tags'>
|
||||
{insertDotInTags(venue_description_tag).map((tag, index) => (
|
||||
<View key={index} className='venue-detail-content-tags-tag'>
|
||||
<Text>{tag}</Text>
|
||||
</View>
|
||||
))}
|
||||
</View>
|
||||
{/* venue remarks */}
|
||||
<View className='venue-detail-content-remarks'>
|
||||
<Text>{venue_description}</Text>
|
||||
</View>
|
||||
</View>
|
||||
<CommonPopup
|
||||
visible={visible}
|
||||
onClose={onClose}
|
||||
round
|
||||
hideFooter
|
||||
position='bottom'
|
||||
zIndex={1001}
|
||||
>
|
||||
<View className="venue-screenshot-title">预定截图</View>
|
||||
<ScrollView
|
||||
scrollY
|
||||
className="venue-screenshot-scroll-view"
|
||||
>
|
||||
<View className="venue-screenshot-image-list">
|
||||
{venue_image_list.map(item => {
|
||||
return (
|
||||
<View className="venue-screenshot-image-item" onClick={previewImage.bind(null, item.url)}>
|
||||
<Image className="venue-screenshot-image-item-image" src={item.url} />
|
||||
</View>
|
||||
)
|
||||
})}
|
||||
</View>
|
||||
</ScrollView>
|
||||
</CommonPopup>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
const tags = [{
|
||||
name: '🕙 急招',
|
||||
icon: '',
|
||||
}, {
|
||||
name: '🔥 本周热门',
|
||||
icon: '',
|
||||
}, {
|
||||
name: '🎉 新活动',
|
||||
icon: '',
|
||||
}, {
|
||||
name: '官方组织',
|
||||
icon: '',
|
||||
}]
|
||||
function genNTRPRequirementText(min, max) {
|
||||
if (min && max) {
|
||||
return `${min} - ${max} 之间`
|
||||
} else if (max) {
|
||||
return `${max} 以上`
|
||||
}
|
||||
return '没有要求'
|
||||
}
|
||||
// 玩法要求
|
||||
function GamePlayAndRequirement(props) {
|
||||
const { detail: { skill_level_min, skill_level_max, play_type, game_type } } = props
|
||||
|
||||
const detailTags = ['室内', '硬地', '2号场', '有停车场', '有淋浴间', '有更衣室']
|
||||
const requirements = [
|
||||
{
|
||||
title: 'NTRP水平要求',
|
||||
desc: genNTRPRequirementText(skill_level_min, skill_level_max),
|
||||
},
|
||||
{
|
||||
title: '活动玩法',
|
||||
desc: play_type || '-',
|
||||
},
|
||||
{
|
||||
title: '人员构成',
|
||||
desc: game_type || '-',
|
||||
}
|
||||
]
|
||||
return (
|
||||
<View className='detail-page-content-gameplay-requirements'>
|
||||
{/* title */}
|
||||
<View className="gameplay-requirements-title">
|
||||
<Text>玩法要求</Text>
|
||||
</View>
|
||||
{/* requirements */}
|
||||
<View className='gameplay-requirements'>
|
||||
{requirements.map((item, index) => (
|
||||
<View key={index} className='gameplay-requirements-item'>
|
||||
<Text className='gameplay-requirements-item-title'>{item.title}</Text>
|
||||
<Text className='gameplay-requirements-item-desc'>{item.desc}</Text>
|
||||
</View>
|
||||
))}
|
||||
</View>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
const { title, longitude, latitude } = detail || {}
|
||||
// 参与者
|
||||
function Participants(props) {
|
||||
const { detail = {} } = props
|
||||
const participants = detail.participants || []
|
||||
const organizer_id = Number(detail.publisher_id)
|
||||
return (
|
||||
<View className='detail-page-content-participants'>
|
||||
<View className='participants-title'>
|
||||
<Text>参与者</Text>
|
||||
<Text>·</Text>
|
||||
<Text>剩余空位 3</Text>
|
||||
</View>
|
||||
<View className='participants-list'>
|
||||
{/* application */}
|
||||
<View className='participants-list-application' onClick={() => { Taro.showToast({ title: 'To be continued', icon: 'none' }) }}>
|
||||
<Image className='participants-list-application-icon' src={img.ICON_DETAIL_APPLICATION_ADD} />
|
||||
<Text className='participants-list-application-text'>申请加入</Text>
|
||||
</View>
|
||||
{/* participants list */}
|
||||
<ScrollView className='participants-list-scroll' scrollX>
|
||||
<View className='participants-list-scroll-content' style={{ width: `${participants.length * 103 + (participants.length - 1) * 8}px` }}>
|
||||
{participants.map((participant) => {
|
||||
const { user: { avatar_url, nickname, level, id: participant_user_id } } = participant
|
||||
const role = participant_user_id === organizer_id ? '组织者' : '参与者'
|
||||
return (
|
||||
<View key={participant.id} className='participants-list-item'>
|
||||
<Avatar className='participants-list-item-avatar' src={avatar_url} />
|
||||
<Text className='participants-list-item-name'>{nickname || '未知'}</Text>
|
||||
<Text className='participants-list-item-level'>{level || '未知'}</Text>
|
||||
<Text className='participants-list-item-role'>{role}</Text>
|
||||
</View>
|
||||
)
|
||||
})}
|
||||
</View>
|
||||
</ScrollView>
|
||||
</View>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
console.log(longitude, latitude, 2222)
|
||||
|
||||
const requirements = [{
|
||||
title: 'NTRP水平要求',
|
||||
desc: '2.0 - 4.5 之间',
|
||||
}, {
|
||||
title: '活动玩法',
|
||||
desc: '双打',
|
||||
}, {
|
||||
title: '人员构成',
|
||||
desc: '个人球局 · 组织者参与活动',
|
||||
}]
|
||||
|
||||
const participants = detail?.participants || []
|
||||
|
||||
const supplementalNotesTags = ['仅限男生', '装备自备', '其他']
|
||||
function SupplementalNotes(props) {
|
||||
const { detail: { description, description_tag = [] } } = props
|
||||
return (
|
||||
<View className='detail-page-content-supplemental-notes'>
|
||||
<View className='supplemental-notes-title'>
|
||||
<Text>补充说明</Text>
|
||||
</View>
|
||||
<View className='supplemental-notes-content'>
|
||||
{/* supplemental notes tags */}
|
||||
<View className='supplemental-notes-content-tags'>
|
||||
{insertDotInTags(description_tag).map((tag, index) => (
|
||||
<View key={index} className='supplemental-notes-content-tags-tag'>
|
||||
<Text>{tag}</Text>
|
||||
</View>
|
||||
))}
|
||||
</View>
|
||||
{/* supplemental notes content */}
|
||||
<View className='supplemental-notes-content-text'>
|
||||
<Text>{description}</Text>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
function OrganizerInfo(props) {
|
||||
const recommendGames = [
|
||||
{
|
||||
title: '黄浦日场对拉',
|
||||
@@ -366,6 +444,140 @@ function Index() {
|
||||
playType: '双打',
|
||||
},
|
||||
]
|
||||
return (
|
||||
<View className='detail-page-content-organizer-recommend-games'>
|
||||
{/* orgnizer title */}
|
||||
<View className='organizer-title'>
|
||||
<Text>组织者</Text>
|
||||
</View>
|
||||
{/* organizer avatar and name */}
|
||||
<View className='organizer-avatar-name'>
|
||||
<Avatar className='organizer-avatar-name-avatar' src="https://img.yzcdn.cn/vant/cat.jpeg" />
|
||||
<View className='organizer-avatar-name-message'>
|
||||
<Text className='organizer-avatar-name-message-name'>Light</Text>
|
||||
<View className='organizer-avatar-name-message-stats'>
|
||||
<Text>已组织 8 次</Text>
|
||||
<View className='organizer-avatar-name-message-stats-separator' />
|
||||
<Text>NTRP 3.5</Text>
|
||||
</View>
|
||||
</View>
|
||||
<View className="organizer-actions">
|
||||
<View className="organizer-actions-follow">
|
||||
<Image className='organizer-actions-follow-icon' src={img.ICON_DETAIL_APPLICATION_ADD} />
|
||||
<Text className='organizer-actions-follow-text'>关注</Text>
|
||||
</View>
|
||||
<View className="organizer-actions-comment">
|
||||
<Image className='organizer-actions-comment-icon' src={img.ICON_DETAIL_COMMENT} />
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
{/* recommend games by organizer */}
|
||||
<View className='organizer-recommend-games'>
|
||||
<View className='organizer-recommend-games-title'>
|
||||
<Text>TA的更多活动</Text>
|
||||
<Image className='organizer-recommend-games-title-arrow' src={img.ICON_DETAIL_ARROW_RIGHT} />
|
||||
</View>
|
||||
<ScrollView className='recommend-games-list' scrollX>
|
||||
<View className='recommend-games-list-content'>
|
||||
{recommendGames.map((game, index) => (
|
||||
<View key={index} className='recommend-games-list-item'>
|
||||
{/* game title */}
|
||||
<View className='recommend-games-list-item-title'>
|
||||
<Text>{game.title}</Text>
|
||||
<Image className='recommend-games-list-item-title-arrow' src={img.ICON_DETAIL_ARROW_RIGHT} />
|
||||
</View>
|
||||
{/* game time and range */}
|
||||
<View className='recommend-games-list-item-time-range'>
|
||||
<Text>{game.time}</Text>
|
||||
<Text>{game.timeLength}</Text>
|
||||
</View>
|
||||
{/* game location、vunue、distance */}
|
||||
<View className='recommend-games-list-item-location-venue-distance'>
|
||||
<Text>{game.venue}</Text>
|
||||
<Text>·</Text>
|
||||
<Text>{game.veuneType}</Text>
|
||||
<Text>·</Text>
|
||||
<Text>{game.distance}</Text>
|
||||
</View>
|
||||
{/* organizer avatar、applications、level requirements、play type */}
|
||||
<View className='recommend-games-list-item-addon'>
|
||||
<Avatar className='recommend-games-list-item-addon-avatar' src={game.avatar} />
|
||||
<View className='recommend-games-list-item-addon-message'>
|
||||
<View className='recommend-games-list-item-addon-message-applications'>
|
||||
<Text>报名人数 {game.checkedApplications}/{game.applications}</Text>
|
||||
</View>
|
||||
<View className='recommend-games-list-item-addon-message-level-requirements'>
|
||||
<Text>{game.levelRequirements}</Text>
|
||||
</View>
|
||||
<View className='recommend-games-list-item-addon-message-play-type'>
|
||||
<Text>{game.playType}</Text>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
))}
|
||||
</View>
|
||||
</ScrollView>
|
||||
</View>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
function Index() {
|
||||
const [detail, setDetail] = useState<any>({})
|
||||
const { params } = useRouter()
|
||||
const [currentLocation, setCurrentLocation] = useState<[number, number]>([0, 0])
|
||||
const { id, from } = params
|
||||
const { fetchUserInfo, updateUserInfo } = useUserActions()
|
||||
|
||||
const sharePopupRef = useRef<any>(null)
|
||||
|
||||
useDidShow(async () => {
|
||||
await updateLocation()
|
||||
await fetchUserInfo()
|
||||
await fetchDetail()
|
||||
})
|
||||
|
||||
const updateLocation = async () => {
|
||||
try {
|
||||
const location = await getCurrentLocation()
|
||||
setCurrentLocation([location.latitude, location.longitude])
|
||||
await updateUserInfo({ latitude: location.latitude, longitude: location.longitude })
|
||||
} catch (error) {
|
||||
console.error('用户位置更新失败', error)
|
||||
}
|
||||
}
|
||||
|
||||
const fetchDetail = async () => {
|
||||
const res = await DetailService.getDetail(243/* Number(id) */)
|
||||
if (res.code === 0) {
|
||||
setDetail(res.data)
|
||||
}
|
||||
}
|
||||
|
||||
function handleShare() {
|
||||
sharePopupRef.current.show()
|
||||
}
|
||||
|
||||
const handleJoinGame = () => {
|
||||
Taro.navigateTo({
|
||||
url: `/pages/orderCheck/index?gameId=${243/* id */}`,
|
||||
})
|
||||
}
|
||||
|
||||
const tags = [{
|
||||
name: '🕙 急招',
|
||||
icon: '',
|
||||
}, {
|
||||
name: '🔥 本周热门',
|
||||
icon: '',
|
||||
}, {
|
||||
name: '🎉 新活动',
|
||||
icon: '',
|
||||
}, {
|
||||
name: '官方组织',
|
||||
icon: '',
|
||||
}]
|
||||
|
||||
function handleBack() {
|
||||
const pages = Taro.getCurrentPages()
|
||||
@@ -380,6 +592,8 @@ function Index() {
|
||||
|
||||
|
||||
console.log('detail', detail)
|
||||
const backgroundImage = detail?.image_list?.[0] ? { backgroundImage: `url(${detail?.image_list?.[0]})` } : {}
|
||||
|
||||
return (
|
||||
<View className='detail-page'>
|
||||
{/* custom navbar */}
|
||||
@@ -393,8 +607,7 @@ function Index() {
|
||||
</View>
|
||||
</View>
|
||||
</view>
|
||||
<View className='detail-page-bg' style={detail?.image_list?.[0] ? { backgroundImage: `url(${detail?.image_list?.[0]})` } : {}} />
|
||||
<View className='detail-page-bg-text' />
|
||||
<View className='detail-page-bg' style={backgroundImage} />
|
||||
{/* swiper */}
|
||||
<View className="detail-swiper-container">
|
||||
<View className="detail-swiper-scroll-container">
|
||||
@@ -413,29 +626,6 @@ function Index() {
|
||||
}
|
||||
</View>
|
||||
</View>
|
||||
{/* <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> */}
|
||||
{/* content */}
|
||||
<View className='detail-page-content'>
|
||||
{/* avatar and tags */}
|
||||
@@ -455,186 +645,20 @@ function Index() {
|
||||
</View>
|
||||
{/* title */}
|
||||
<View className='detail-page-content-title'>
|
||||
<Text className='detail-page-content-title-text'>{title}</Text>
|
||||
<Text className='detail-page-content-title-text'>{detail.title}</Text>
|
||||
</View>
|
||||
{/* Date and Place and weather */}
|
||||
<GameInfo detail={detail} currentLocation={currentLocation} />
|
||||
{/* detail */}
|
||||
<View className='detail-page-content-detail'>
|
||||
{/* venue detail title and venue ordered status */}
|
||||
<View className='venue-detail-title'>
|
||||
<Text>场馆详情</Text>
|
||||
<Text>·</Text>
|
||||
<Text>已订场</Text>
|
||||
<Popover
|
||||
title="场地预定截图"
|
||||
description={<View>
|
||||
<Image src="https://img.yzcdn.cn/vant/cat.jpeg" />
|
||||
</View>}
|
||||
location='top'
|
||||
visible={false}
|
||||
>
|
||||
<Image className='venue-detail-title-notice-icon' src={img.ICON_DETAIL_NOTICE} />
|
||||
</Popover>
|
||||
</View>
|
||||
{/* venue detail content */}
|
||||
<View className='venue-detail-content'>
|
||||
{/* venue detail tags */}
|
||||
<View className='venue-detail-content-tags'>
|
||||
{insertDotInTags(detailTags).map((tag, index) => (
|
||||
<View key={index} className='venue-detail-content-tags-tag'>
|
||||
<Text>{tag}</Text>
|
||||
</View>
|
||||
))}
|
||||
</View>
|
||||
{/* venue remarks */}
|
||||
<View className='venue-detail-content-remarks'>
|
||||
<Text>其他这是用户在场地补充描述里自己写的东西啦啦啦啦啦啦啦啦啦啦啦啦</Text>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
<VenueInfo detail={detail} />
|
||||
{/* gameplay requirements */}
|
||||
<View className='detail-page-content-gameplay-requirements'>
|
||||
{/* title */}
|
||||
<View className="gameplay-requirements-title">
|
||||
<Text>玩法要求</Text>
|
||||
</View>
|
||||
{/* requirements */}
|
||||
<View className='gameplay-requirements'>
|
||||
{requirements.map((item, index) => (
|
||||
<View key={index} className='gameplay-requirements-item'>
|
||||
<Text className='gameplay-requirements-item-title'>{item.title}</Text>
|
||||
<Text className='gameplay-requirements-item-desc'>{item.desc}</Text>
|
||||
</View>
|
||||
))}
|
||||
</View>
|
||||
</View>
|
||||
<GamePlayAndRequirement detail={detail} />
|
||||
{/* participants */}
|
||||
<View className='detail-page-content-participants'>
|
||||
<View className='participants-title'>
|
||||
<Text>参与者</Text>
|
||||
<Text>·</Text>
|
||||
<Text>剩余空位 3</Text>
|
||||
</View>
|
||||
<View className='participants-list'>
|
||||
{/* application */}
|
||||
<View className='participants-list-application' onClick={() => { Taro.showToast({ title: 'To be continued', icon: 'none' }) }}>
|
||||
<Image className='participants-list-application-icon' src={img.ICON_DETAIL_APPLICATION_ADD} />
|
||||
<Text className='participants-list-application-text'>申请加入</Text>
|
||||
</View>
|
||||
{/* participants list */}
|
||||
<ScrollView className='participants-list-scroll' scrollX>
|
||||
<View className='participants-list-scroll-content' style={{ width: `${participants.length * 103 + (participants.length - 1) * 8}px` }}>
|
||||
{participants.map((participant) => (
|
||||
<View key={participant.id} className='participants-list-item'>
|
||||
{/* <Avatar className='participants-list-item-avatar' src={participant.user.avatar_url} /> */}
|
||||
{/* network image mock random */}
|
||||
<Avatar className='participants-list-item-avatar' src={`https://picsum.photos/800/600?random=${participant.id}`} />
|
||||
<Text className='participants-list-item-name'>{participant.user.nickname || '未知'}</Text>
|
||||
<Text className='participants-list-item-level'>{participant.level || '未知'}</Text>
|
||||
<Text className='participants-list-item-role'>{participant.role || '参与者'}</Text>
|
||||
</View>
|
||||
))}
|
||||
</View>
|
||||
</ScrollView>
|
||||
</View>
|
||||
</View>
|
||||
<Participants detail={detail} />
|
||||
{/* supplemental notes */}
|
||||
<View className='detail-page-content-supplemental-notes'>
|
||||
<View className='supplemental-notes-title'>
|
||||
<Text>补充说明</Text>
|
||||
</View>
|
||||
<View className='supplemental-notes-content'>
|
||||
{/* supplemental notes tags */}
|
||||
<View className='supplemental-notes-content-tags'>
|
||||
{insertDotInTags(supplementalNotesTags).map((tag, index) => (
|
||||
<View key={index} className='supplemental-notes-content-tags-tag'>
|
||||
<Text>{tag}</Text>
|
||||
</View>
|
||||
))}
|
||||
</View>
|
||||
{/* supplemental notes content */}
|
||||
<View className='supplemental-notes-content-text'>
|
||||
<Text>其他这是用户在补充说明里自己写的东西啦啦啦啦啦啦啦啦啦啦啦啦其他这是用户在补充说明里自己写的东西啦啦啦啦啦啦啦啦啦啦啦啦</Text>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
<SupplementalNotes detail={detail} />
|
||||
{/* organizer and recommend games by organizer */}
|
||||
<View className='detail-page-content-organizer-recommend-games'>
|
||||
{/* orgnizer title */}
|
||||
<View className='organizer-title'>
|
||||
<Text>组织者</Text>
|
||||
</View>
|
||||
{/* organizer avatar and name */}
|
||||
<View className='organizer-avatar-name'>
|
||||
<Avatar className='organizer-avatar-name-avatar' src="https://img.yzcdn.cn/vant/cat.jpeg" />
|
||||
<View className='organizer-avatar-name-message'>
|
||||
<Text className='organizer-avatar-name-message-name'>Light</Text>
|
||||
<View className='organizer-avatar-name-message-stats'>
|
||||
<Text>已组织 8 次</Text>
|
||||
<View className='organizer-avatar-name-message-stats-separator' />
|
||||
<Text>NTRP 3.5</Text>
|
||||
</View>
|
||||
</View>
|
||||
<View className="organizer-actions">
|
||||
<View className="organizer-actions-follow">
|
||||
<Image className='organizer-actions-follow-icon' src={img.ICON_DETAIL_APPLICATION_ADD} />
|
||||
<Text className='organizer-actions-follow-text'>关注</Text>
|
||||
</View>
|
||||
<View className="organizer-actions-comment">
|
||||
<Image className='organizer-actions-comment-icon' src={img.ICON_DETAIL_COMMENT} />
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
{/* recommend games by organizer */}
|
||||
<View className='organizer-recommend-games'>
|
||||
<View className='organizer-recommend-games-title'>
|
||||
<Text>TA的更多活动</Text>
|
||||
<Image className='organizer-recommend-games-title-arrow' src={img.ICON_DETAIL_ARROW_RIGHT} />
|
||||
</View>
|
||||
<ScrollView className='recommend-games-list' scrollX>
|
||||
<View className='recommend-games-list-content'>
|
||||
{recommendGames.map((game, index) => (
|
||||
<View key={index} className='recommend-games-list-item'>
|
||||
{/* game title */}
|
||||
<View className='recommend-games-list-item-title'>
|
||||
<Text>{game.title}</Text>
|
||||
<Image className='recommend-games-list-item-title-arrow' src={img.ICON_DETAIL_ARROW_RIGHT} />
|
||||
</View>
|
||||
{/* game time and range */}
|
||||
<View className='recommend-games-list-item-time-range'>
|
||||
<Text>{game.time}</Text>
|
||||
<Text>{game.timeLength}</Text>
|
||||
</View>
|
||||
{/* game location、vunue、distance */}
|
||||
<View className='recommend-games-list-item-location-venue-distance'>
|
||||
<Text>{game.venue}</Text>
|
||||
<Text>·</Text>
|
||||
<Text>{game.veuneType}</Text>
|
||||
<Text>·</Text>
|
||||
<Text>{game.distance}</Text>
|
||||
</View>
|
||||
{/* organizer avatar、applications、level requirements、play type */}
|
||||
<View className='recommend-games-list-item-addon'>
|
||||
<Avatar className='recommend-games-list-item-addon-avatar' src={game.avatar} />
|
||||
<View className='recommend-games-list-item-addon-message'>
|
||||
<View className='recommend-games-list-item-addon-message-applications'>
|
||||
<Text>报名人数 {game.checkedApplications}/{game.applications}</Text>
|
||||
</View>
|
||||
<View className='recommend-games-list-item-addon-message-level-requirements'>
|
||||
<Text>{game.levelRequirements}</Text>
|
||||
</View>
|
||||
<View className='recommend-games-list-item-addon-message-play-type'>
|
||||
<Text>{game.playType}</Text>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
))}
|
||||
</View>
|
||||
</ScrollView>
|
||||
</View>
|
||||
</View>
|
||||
<OrganizerInfo detail={detail} />
|
||||
{/* sticky bottom action bar */}
|
||||
<StickyButton handleShare={handleShare} handleJoinGame={handleJoinGame} detail={detail} />
|
||||
{/* share popup */}
|
||||
|
||||
@@ -45,7 +45,6 @@ const LoginPage: React.FC = () => {
|
||||
|
||||
setTimeout(() => {
|
||||
if (redirect) {
|
||||
console.log('redirect:', decodeURIComponent(redirect))
|
||||
Taro.redirectTo({ url: decodeURIComponent(redirect) });
|
||||
} else {
|
||||
Taro.redirectTo({ url: '/pages/list/index' });
|
||||
|
||||
@@ -211,12 +211,13 @@ class HttpService {
|
||||
}
|
||||
|
||||
try {
|
||||
console.log(this.buildHeaders(config), 1111);
|
||||
const reqHeader = this.buildHeaders(config)
|
||||
this.log('info', 'HTTP REQ HEADER: ', reqHeader)
|
||||
const requestConfig = {
|
||||
url: fullUrl,
|
||||
method: method,
|
||||
data: method !== 'GET' ? data : undefined,
|
||||
header: this.buildHeaders(config),
|
||||
header: reqHeader,
|
||||
timeout: this.timeout
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,6 @@ export const useUser = create<UserState>()((set) => ({
|
||||
},
|
||||
updateUserInfo: async(userInfo: Partial<UserInfoType>) => {
|
||||
const res = await updateUserProfile(userInfo)
|
||||
console.log(res)
|
||||
set({ user: res.data })
|
||||
}
|
||||
}))
|
||||
|
||||
Reference in New Issue
Block a user