From 25e9b310a6bba72a8747a1de3cadddfcfda6175d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E6=9D=B0?= Date: Sat, 6 Sep 2025 18:55:07 +0800 Subject: [PATCH 1/2] =?UTF-8?q?feat:=20=E6=94=AF=E4=BB=98=E8=AE=A2?= =?UTF-8?q?=E5=8D=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/detail/index.tsx | 208 +++++++++++++++++++-------------- src/pages/orderCheck/index.tsx | 63 ++++++++-- src/services/detailService.ts | 6 + src/services/orderService.ts | 46 ++++++++ 4 files changed, 222 insertions(+), 101 deletions(-) create mode 100644 src/services/orderService.ts diff --git a/src/pages/detail/index.tsx b/src/pages/detail/index.tsx index 8be0e4c..4137f70 100644 --- a/src/pages/detail/index.tsx +++ b/src/pages/detail/index.tsx @@ -2,10 +2,12 @@ import React, { useState, useEffect, useRef, useImperativeHandle, forwardRef } f import { View, Text, Button, Swiper, SwiperItem, Image, Map, ScrollView } from '@tarojs/components' import { Cell, Avatar, Progress, Popover } from '@nutui/nutui-react-taro' import Taro, { useRouter, useShareAppMessage, useShareTimeline, useDidShow } from '@tarojs/taro' +import dayjs, { locale } from 'dayjs' +import 'dayjs/locale/zh-cn' // 导入API服务 -import DetailService from '../../services/detailService' +import DetailService, { MATCH_STATUS} from '../../services/detailService' import { updateUserProfile, get_user_info } from '../../services/loginService' -import { getCurrentLocation } from '../../utils/locationUtils' +import { getCurrentLocation, calculateDistance } from '../../utils/locationUtils' import { useUserInfo, useUserActions, @@ -15,6 +17,8 @@ import { getTextColorOnImage } from '../../utils' import './index.scss' import { CommonPopup } from '@/components' +dayjs.locale('zh-cn') + 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', @@ -96,10 +100,10 @@ function StickyButton(props) { const { handleShare, handleJoinGame, detail } = props const userInfo = useUserInfo() const { id } = userInfo - const { publisher_id, status } = detail || {} + const { publisher_id, match_status, price } = detail || {} const role = Number(publisher_id) === id ? 'ownner' : 'visitor' - console.log(status, role) + console.log(match_status, role) return ( @@ -117,7 +121,110 @@ function StickyButton(props) { 🎾 立即加入 - ¥ 65 + ¥ {price} + + + + ) +} + +// 球局信息 +function GameInfo(props) { + const { detail, currentLocation } = props + const { latitude, longitude, location, location_name, start_time, end_time } = detail || {} + + const openMap = () => { + Taro.openLocation({ + latitude, // 纬度(必填) + longitude, // 经度(必填) + name: location_name, // 位置名(可选) + address: location, // 地址详情(可选) + scale: 15, // 地图缩放级别(1-28) + }) + } + + const [c_latitude, c_longitude] = currentLocation + const distance = calculateDistance(c_latitude, c_longitude, latitude, longitude) / 1000 + + const startTime = dayjs(start_time) + const endTime = dayjs(end_time) + const game_length = endTime.diff(startTime, 'minutes') / 60 + + const startMonth = startTime.format('M') + const startDay = startTime.format('D') + const theDayOfWeek = startTime.format('dddd') + const startDate = `${startMonth}月${startDay}日 ${theDayOfWeek}` + const gameRange = `${startTime.format('HH:mm')} - ${endTime.format('HH:mm')}` + + + return ( + + {/* Date and Weather */} + + {/* Calendar and Date time */} + + {/* Calendar */} + + {startMonth}月 + {startDay} + + {/* Date time */} + + {startDate} + {gameRange} ({game_length}小时) + + + {/* Weather */} + + {/* Weather icon */} + + + + {/* Weather text and temperature */} + + 28℃ - 32℃ + + + + {/* Place */} + + {/* venue location message */} + + {/* location icon */} + + + + {/* location message */} + + {/* venue name and distance */} + + {location_name || '-'} + · + {distance.toFixed(1)}km + + + {/* venue address */} + + {location || '-'} + + + + {/* venue map */} + + {longitude && latitude && ( + {}} + // hide business msg + showLocation + theme='dark' + /> + )} @@ -133,11 +240,13 @@ function Index() { // const [textColor, setTextColor] = useState([]) const [detail, setDetail] = useState(null) const { params } = useRouter() - const [currentLocation, setCurrentLocation] = useState([0, 0]) + const [currentLocation, setCurrentLocation] = useState<[number, number]>([0, 0]) const { id, autoShare, from } = params const { fetchUserInfo, updateUserInfo } = useUserActions() - console.log('from', from) + console.group('params') + console.log(params) + console.groupEnd() // 本地状态管理 const [loading, setLoading] = useState(false) @@ -168,7 +277,7 @@ function Index() { } const fetchDetail = async () => { - const res = await DetailService.getDetail(242/* Number(id) */) + const res = await DetailService.getDetail(243/* Number(id) */) if (res.code === 0) { console.log(res.data) setDetail(res.data) @@ -192,19 +301,9 @@ function Index() { sharePopupRef.current.show() } - const openMap = () => { - Taro.openLocation({ - latitude: detail?.longitude, // 纬度(必填) - longitude: detail?.latitude, // 经度(必填) - name: '上海体育场', // 位置名(可选) - address: '上海市徐汇区肇嘉浜路128号', // 地址详情(可选) - scale: 15, // 地图缩放级别(1-28) - }) - } - const handleJoinGame = () => { Taro.navigateTo({ - url: `/pages/orderCheck/index?id=${id}`, + url: `/pages/orderCheck/index?gameId=${243/* id */}`, }) } @@ -364,76 +463,7 @@ function Index() { {title} {/* Date and Place and weather */} - - {/* Date and Weather */} - - {/* Calendar and Date time */} - - {/* Calendar */} - - 3月 - 25 - - {/* Date time */} - - 3月25日 周一 - 19:00-21:00 (2小时) - - - {/* Weather */} - - {/* Weather icon */} - - - - {/* Weather text and temperature */} - - 28℃ - 32℃ - - - - {/* Place */} - - {/* venue location message */} - - {/* location icon */} - - - - {/* location message */} - - {/* venue name and distance */} - - 上海体育场 - · - 1.2km - - - {/* venue address */} - - 上海市徐汇区肇嘉浜路128号 - - - - {/* venue map */} - - {longitude && latitude && ( - {}} - // hide business msg - showLocation - theme='dark' - /> - )} - - - + {/* detail */} {/* venue detail title and venue ordered status */} diff --git a/src/pages/orderCheck/index.tsx b/src/pages/orderCheck/index.tsx index 7a32e62..5f3c231 100644 --- a/src/pages/orderCheck/index.tsx +++ b/src/pages/orderCheck/index.tsx @@ -1,28 +1,67 @@ -import React from 'react' +import React, { useState } from 'react' import { View, Text, Button } from '@tarojs/components' -import Taro from '@tarojs/taro' +import Taro, { useDidShow, useRouter } from '@tarojs/taro' import { delay } from '@/utils' +import orderService from '@/services/orderService' +import detailService, { GameDetail } from '@/services/detailService' const OrderCheck = () => { + const { params } = useRouter() + const { id, gameId } = params + const [detail ,setDetail] = useState({}) + + useDidShow(async () => { + const res = await detailService.getDetail(Number(gameId)) + console.log(res) + if (res.code === 0) { + setDetail(res.data) + } + }) + + //TODO: get order msg from id const handlePay = async () => { Taro.showLoading({ title: '支付中...', mask: true }) - await delay(2000) - Taro.hideLoading() - Taro.showToast({ - title: '支付成功', - icon: 'success' - }) - await delay(1000) - Taro.navigateBack({ - delta: 1 - }) + const res = await orderService.createOrder(Number(gameId)) + if (res.code === 0) { + const { payment_required, payment_params } = res.data + if (payment_required) { + const { timeStamp, nonceStr, package: package_, signType, paySign } = payment_params + await Taro.requestPayment({ + timeStamp, + nonceStr, + package: package_, + signType, + paySign, + success: async () => { + Taro.hideLoading() + Taro.showToast({ + title: '支付成功', + icon: 'success' + }) + await delay(1000) + Taro.navigateBack({ + delta: 1 + }) + }, + fail: () => { + Taro.hideLoading() + Taro.showToast({ + title: '支付失败', + icon: 'none' + }) + } + }) + } + } } return ( OrderCheck + 球局名称:{detail?.title || '-'} + 价格:¥{detail?.price || '-'} ) diff --git a/src/services/detailService.ts b/src/services/detailService.ts index e971bf0..6313e36 100644 --- a/src/services/detailService.ts +++ b/src/services/detailService.ts @@ -20,6 +20,12 @@ export interface GameDetail { updated_at: string, } +export enum MATCH_STATUS { + NOT_STARTED = 0, // 未开始 + IN_PROGRESS = 1, //进行中 + FINISHED = 2 //已结束 +} + // 响应接口 export interface Response { code: string diff --git a/src/services/orderService.ts b/src/services/orderService.ts new file mode 100644 index 0000000..d51b269 --- /dev/null +++ b/src/services/orderService.ts @@ -0,0 +1,46 @@ +import httpService from './httpService' +import type { ApiResponse } from './httpService' +import { requestPayment } from '@tarojs/taro' + +export interface SignType { + /** 仅在微信支付 v2 版本接口适用 */ + MD5 + /** 仅在微信支付 v2 版本接口适用 */ + 'HMAC-SHA256' + /** 仅在微信支付 v3 版本接口适用 */ + RSA +} + +export interface PayMentParams { + order_id: number, + order_no: string, + status: number, + appId: string, + timeStamp: string, + nonceStr: string, + package: string, + signType: keyof SignType, + paySign: string +} + +// 用户接口 +export interface OrderResponse { + participant_id: number, + payment_required: boolean, + payment_params: PayMentParams +} + +// 发布球局类 +class OrderService { + // 用户登录 + async createOrder(game_id: number): Promise> { + return httpService.post('/payment/create_order', { game_id }, { + showLoading: true, + }) + } + + // async getOrderInfo() +} + +// 导出认证服务实例 +export default new OrderService() \ No newline at end of file From 28efb5a69024b36e4f2ebf99a15f13e7934fa4ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E6=9D=B0?= Date: Sat, 6 Sep 2025 20:32:47 +0800 Subject: [PATCH 2/2] style: fix style --- src/components/UploadCover/index.scss | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/components/UploadCover/index.scss b/src/components/UploadCover/index.scss index ff76d06..e16b3a0 100644 --- a/src/components/UploadCover/index.scss +++ b/src/components/UploadCover/index.scss @@ -121,6 +121,18 @@ align-items: center; border-bottom: 1px solid rgba(0, 0, 0, 0.12); + .upload-source-popup-item-text { + width: 100%; + height: 56px; + padding: 16px 24px; + box-sizing: border-box; + font-size: 14px; + font-style: normal; + font-weight: 500; + line-height: 24px; + text-align: center; + } + &:last-child { border-bottom: none; }