Merge branch 'feat/liujie'
This commit is contained in:
@@ -54,6 +54,7 @@
|
|||||||
"@tarojs/shared": "4.1.5",
|
"@tarojs/shared": "4.1.5",
|
||||||
"@tarojs/taro": "4.1.5",
|
"@tarojs/taro": "4.1.5",
|
||||||
"dayjs": "^1.11.13",
|
"dayjs": "^1.11.13",
|
||||||
|
"qweather-icons": "^1.8.0",
|
||||||
"react": "^18.0.0",
|
"react": "^18.0.0",
|
||||||
"react-dom": "^18.0.0",
|
"react-dom": "^18.0.0",
|
||||||
"zustand": "^4.4.7"
|
"zustand": "^4.4.7"
|
||||||
|
|||||||
41
src/app.ts
41
src/app.ts
@@ -1,48 +1,47 @@
|
|||||||
import { Component, ReactNode } from 'react'
|
import { Component, ReactNode } from "react";
|
||||||
import './nutui-theme.scss'
|
import "./nutui-theme.scss";
|
||||||
import './app.scss'
|
import "./app.scss";
|
||||||
import { useDictionaryStore } from './store/dictionaryStore'
|
import "qweather-icons/font/qweather-icons.css";
|
||||||
import { useGlobalStore } from './store/global'
|
import { useDictionaryStore } from "./store/dictionaryStore";
|
||||||
|
import { useGlobalStore } from "./store/global";
|
||||||
|
|
||||||
// import { getNavbarHeight } from "@/utils/getNavbarHeight";
|
// import { getNavbarHeight } from "@/utils/getNavbarHeight";
|
||||||
|
|
||||||
interface AppProps {
|
interface AppProps {
|
||||||
children: ReactNode
|
children: ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
class App extends Component<AppProps> {
|
class App extends Component<AppProps> {
|
||||||
|
|
||||||
|
|
||||||
onLaunch() {
|
onLaunch() {
|
||||||
console.log('小程序启动,初始化逻辑写这里')
|
console.log("小程序启动,初始化逻辑写这里");
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
// 初始化字典数据
|
// 初始化字典数据
|
||||||
this.initDictionaryData()
|
this.initDictionaryData();
|
||||||
this.getNavBarHeight()
|
this.getNavBarHeight();
|
||||||
// this.getLocation()
|
// this.getLocation()
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidShow() { }
|
componentDidShow() {}
|
||||||
|
|
||||||
componentDidHide() { }
|
componentDidHide() {}
|
||||||
|
|
||||||
// 初始化字典数据
|
// 初始化字典数据
|
||||||
private async initDictionaryData() {
|
private async initDictionaryData() {
|
||||||
try {
|
try {
|
||||||
const { fetchDictionary } = useDictionaryStore.getState()
|
const { fetchDictionary } = useDictionaryStore.getState();
|
||||||
await fetchDictionary()
|
await fetchDictionary();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('初始化字典数据失败:', error)
|
console.error("初始化字典数据失败:", error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取导航高度
|
// 获取导航高度
|
||||||
getNavBarHeight = () => {
|
getNavBarHeight = () => {
|
||||||
const { getNavbarHeightInfo } = useGlobalStore.getState()
|
const { getNavbarHeightInfo } = useGlobalStore.getState();
|
||||||
getNavbarHeightInfo()
|
getNavbarHeightInfo();
|
||||||
}
|
};
|
||||||
|
|
||||||
// 获取位置信息
|
// 获取位置信息
|
||||||
// getLocation = () => {
|
// getLocation = () => {
|
||||||
@@ -52,8 +51,8 @@ class App extends Component<AppProps> {
|
|||||||
|
|
||||||
render() {
|
render() {
|
||||||
// this.props.children 是将要会渲染的页面
|
// this.props.children 是将要会渲染的页面
|
||||||
return this.props.children
|
return this.props.children;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default App
|
export default App;
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
import React, { useEffect, useState } from 'react'
|
import React, { useEffect, useState } from "react";
|
||||||
import Taro from '@tarojs/taro'
|
import { View } from "@tarojs/components";
|
||||||
import { check_login_status } from '@/services/loginService'
|
import Taro from "@tarojs/taro";
|
||||||
|
import { check_login_status } from "@/services/loginService";
|
||||||
|
|
||||||
|
|
||||||
export function getCurrentFullPath(): string {
|
export function getCurrentFullPath(): string {
|
||||||
const pages = Taro.getCurrentPages();
|
const pages = Taro.getCurrentPages();
|
||||||
@@ -31,18 +30,30 @@ export default function withAuth<P extends object>(
|
|||||||
const is_login = check_login_status();
|
const is_login = check_login_status();
|
||||||
setAuthed(is_login);
|
setAuthed(is_login);
|
||||||
|
|
||||||
if (!is_login) {
|
// if (!is_login) {
|
||||||
const currentPage = getCurrentFullPath();
|
// const currentPage = getCurrentFullPath();
|
||||||
// Taro.redirectTo({
|
// Taro.redirectTo({
|
||||||
// url: `/pages/login/index/index${
|
// url: `/pages/login/index/index${
|
||||||
// currentPage ? `?redirect=${encodeURIComponent(currentPage)}` : ''
|
// currentPage ? `?redirect=${encodeURIComponent(currentPage)}` : ""
|
||||||
// }`,
|
// }`,
|
||||||
// })
|
// });
|
||||||
}
|
// }
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
// if (!authed) {
|
// if (!authed) {
|
||||||
// return <View style={{ width: '100vh', height: '100vw', backgroundColor: 'white', position: 'fixed', top: 0, left: 0, zIndex: 999 }} /> // 空壳,避免 children 渲染出错
|
// return (
|
||||||
|
// <View
|
||||||
|
// style={{
|
||||||
|
// width: "100vh",
|
||||||
|
// height: "100vw",
|
||||||
|
// backgroundColor: "white",
|
||||||
|
// position: "fixed",
|
||||||
|
// top: 0,
|
||||||
|
// left: 0,
|
||||||
|
// zIndex: 999,
|
||||||
|
// }}
|
||||||
|
// />
|
||||||
|
// ); // 空壳,避免 children 渲染出错
|
||||||
// }
|
// }
|
||||||
|
|
||||||
return <WrappedComponent {...props} />;
|
return <WrappedComponent {...props} />;
|
||||||
|
|||||||
@@ -17,8 +17,8 @@ const envConfigs: Record<EnvType, EnvConfig> = {
|
|||||||
// 开发环境
|
// 开发环境
|
||||||
development: {
|
development: {
|
||||||
name: '开发环境',
|
name: '开发环境',
|
||||||
// apiBaseURL: 'https://sit.light120.com',
|
apiBaseURL: 'https://sit.light120.com',
|
||||||
apiBaseURL: 'http://localhost:9098',
|
// apiBaseURL: 'http://localhost:9098',
|
||||||
timeout: 15000,
|
timeout: 15000,
|
||||||
enableLog: true,
|
enableLog: true,
|
||||||
enableMock: true
|
enableMock: true
|
||||||
|
|||||||
@@ -1,5 +1,16 @@
|
|||||||
@use "~@/scss/images.scss" as img;
|
@use "~@/scss/images.scss" as img;
|
||||||
|
|
||||||
|
.errorTip {
|
||||||
|
width: 100vw;
|
||||||
|
height: 100vh;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-around;
|
||||||
|
flex-direction: column;
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
.container {
|
.container {
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
@@ -193,7 +204,9 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
align-self: stretch;
|
align-self: stretch;
|
||||||
color: #000;
|
color: #000;
|
||||||
font-feature-settings: 'liga' off, 'clig' off;
|
font-feature-settings:
|
||||||
|
"liga" off,
|
||||||
|
"clig" off;
|
||||||
font-family: "PingFang SC";
|
font-family: "PingFang SC";
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
@@ -205,7 +218,7 @@
|
|||||||
.summaryList {
|
.summaryList {
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
border: 1px solid rgba(0, 0, 0, 0.06);
|
border: 1px solid rgba(0, 0, 0, 0.06);
|
||||||
background: #FFF;
|
background: #fff;
|
||||||
box-shadow: 0 4px 36px 0 rgba(0, 0, 0, 0.06);
|
box-shadow: 0 4px 36px 0 rgba(0, 0, 0, 0.06);
|
||||||
|
|
||||||
.summaryItem {
|
.summaryItem {
|
||||||
@@ -218,8 +231,10 @@
|
|||||||
.title {
|
.title {
|
||||||
width: 120px;
|
width: 120px;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
color: rgba(60, 60, 67, 0.60);
|
color: rgba(60, 60, 67, 0.6);
|
||||||
font-feature-settings: 'liga' off, 'clig' off;
|
font-feature-settings:
|
||||||
|
"liga" off,
|
||||||
|
"clig" off;
|
||||||
font-family: "PingFang SC";
|
font-family: "PingFang SC";
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
@@ -229,7 +244,9 @@
|
|||||||
|
|
||||||
.content {
|
.content {
|
||||||
color: #000;
|
color: #000;
|
||||||
font-feature-settings: 'liga' off, 'clig' off;
|
font-feature-settings:
|
||||||
|
"liga" off,
|
||||||
|
"clig" off;
|
||||||
font-family: "PingFang SC";
|
font-family: "PingFang SC";
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
@@ -248,7 +265,9 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
align-self: stretch;
|
align-self: stretch;
|
||||||
color: #000;
|
color: #000;
|
||||||
font-feature-settings: 'liga' off, 'clig' off;
|
font-feature-settings:
|
||||||
|
"liga" off,
|
||||||
|
"clig" off;
|
||||||
font-family: "PingFang SC";
|
font-family: "PingFang SC";
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
@@ -260,7 +279,7 @@
|
|||||||
.policyList {
|
.policyList {
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
border: 1px solid rgba(0, 0, 0, 0.06);
|
border: 1px solid rgba(0, 0, 0, 0.06);
|
||||||
background: #FFF;
|
background: #fff;
|
||||||
box-shadow: 0 4px 36px 0 rgba(0, 0, 0, 0.06);
|
box-shadow: 0 4px 36px 0 rgba(0, 0, 0, 0.06);
|
||||||
|
|
||||||
.policyItem {
|
.policyItem {
|
||||||
@@ -269,7 +288,9 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
color: #000;
|
color: #000;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-feature-settings: 'liga' off, 'clig' off;
|
font-feature-settings:
|
||||||
|
"liga" off,
|
||||||
|
"clig" off;
|
||||||
font-family: "PingFang SC";
|
font-family: "PingFang SC";
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
@@ -280,7 +301,9 @@
|
|||||||
&:nth-child(1) {
|
&:nth-child(1) {
|
||||||
color: #000;
|
color: #000;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-feature-settings: 'liga' off, 'clig' off;
|
font-feature-settings:
|
||||||
|
"liga" off,
|
||||||
|
"clig" off;
|
||||||
font-family: "PingFang SC";
|
font-family: "PingFang SC";
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
@@ -289,7 +312,8 @@
|
|||||||
border: none;
|
border: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.time, .rule {
|
.time,
|
||||||
|
.rule {
|
||||||
width: 50%;
|
width: 50%;
|
||||||
padding: 10px 12px;
|
padding: 10px 12px;
|
||||||
}
|
}
|
||||||
@@ -314,7 +338,9 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
align-self: stretch;
|
align-self: stretch;
|
||||||
color: #000;
|
color: #000;
|
||||||
font-feature-settings: 'liga' off, 'clig' off;
|
font-feature-settings:
|
||||||
|
"liga" off,
|
||||||
|
"clig" off;
|
||||||
font-family: "PingFang SC";
|
font-family: "PingFang SC";
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
@@ -324,7 +350,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.content {
|
.content {
|
||||||
color: rgba(22, 24, 35, 0.60);
|
color: rgba(22, 24, 35, 0.6);
|
||||||
font-family: "PingFang SC";
|
font-family: "PingFang SC";
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
|
|||||||
@@ -3,8 +3,11 @@ import { View, Text, Button, Image } from "@tarojs/components";
|
|||||||
import Taro, { useDidShow, useRouter } from "@tarojs/taro";
|
import Taro, { useDidShow, useRouter } from "@tarojs/taro";
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
import { delay } from "@/utils";
|
import { delay } from "@/utils";
|
||||||
import orderService, { GameOrderRes } from "@/services/orderService";
|
import orderService, {
|
||||||
import detailService, { GameDetail } from "@/services/detailService";
|
GameOrderRes,
|
||||||
|
OrderStatus,
|
||||||
|
} from "@/services/orderService";
|
||||||
|
import detailService, { GameData } from "@/services/detailService";
|
||||||
import { withAuth } from "@/components";
|
import { withAuth } from "@/components";
|
||||||
import { calculateDistance, getCurrentLocation } from "@/utils";
|
import { calculateDistance, getCurrentLocation } from "@/utils";
|
||||||
import img from "@/config/images";
|
import img from "@/config/images";
|
||||||
@@ -111,7 +114,7 @@ function GameInfo(props) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function OrderMsg(props) {
|
function OrderMsg(props) {
|
||||||
const { detail, orderInfo } = props;
|
const { detail, checkOrderInfo } = props;
|
||||||
const {
|
const {
|
||||||
start_time,
|
start_time,
|
||||||
end_time,
|
end_time,
|
||||||
@@ -120,10 +123,10 @@ function OrderMsg(props) {
|
|||||||
wechat_contact,
|
wechat_contact,
|
||||||
price,
|
price,
|
||||||
} = detail;
|
} = detail;
|
||||||
const { order_info: { registrant_nickname } = {} } = orderInfo
|
const { order_info: { registrant_nickname } = {} } = checkOrderInfo;
|
||||||
const startTime = dayjs(start_time);
|
const startTime = dayjs(start_time);
|
||||||
const endTime = dayjs(end_time);
|
const endTime = dayjs(end_time);
|
||||||
const startYear = startTime.format('YYYY')
|
const startYear = startTime.format("YYYY");
|
||||||
const startMonth = startTime.format("M");
|
const startMonth = startTime.format("M");
|
||||||
const startDay = startTime.format("D");
|
const startDay = startTime.format("D");
|
||||||
const startDate = `${startYear}年${startMonth}月${startDay}日`;
|
const startDate = `${startYear}年${startMonth}月${startDay}日`;
|
||||||
@@ -157,32 +160,38 @@ function OrderMsg(props) {
|
|||||||
</View>
|
</View>
|
||||||
{/* 订单信息摘要 */}
|
{/* 订单信息摘要 */}
|
||||||
<View className={styles.summaryList}>
|
<View className={styles.summaryList}>
|
||||||
{
|
{summary.map((item, index) => (
|
||||||
summary.map((item, index) => (<View key={index} className={styles.summaryItem}>
|
<View key={index} className={styles.summaryItem}>
|
||||||
<Text className={styles.title}>{item.title}</Text>
|
<Text className={styles.title}>{item.title}</Text>
|
||||||
<Text className={styles.content}>{item.content}</Text>
|
<Text className={styles.content}>{item.content}</Text>
|
||||||
</View>))
|
</View>
|
||||||
}
|
))}
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function RefundPolicy(props) {
|
function RefundPolicy(props) {
|
||||||
const { orderInfo } = props
|
const { checkOrderInfo } = props;
|
||||||
const { refund_policy = [] } = orderInfo
|
const { refund_policy = [] } = checkOrderInfo;
|
||||||
const policyList = [{
|
const policyList = [
|
||||||
time: '申请退款时间',
|
{
|
||||||
rule: '退款规则',
|
time: "申请退款时间",
|
||||||
}, ...refund_policy.map((item, index) => {
|
rule: "退款规则",
|
||||||
const [, theTime] = item.application_time.split('undefined ')
|
},
|
||||||
const theTimeObj = dayjs(theTime)
|
...refund_policy.map((item, index) => {
|
||||||
const year = theTimeObj.format('YYYY')
|
const [, theTime] = item.application_time.split("undefined ");
|
||||||
const month = theTimeObj.format('M')
|
const theTimeObj = dayjs(theTime);
|
||||||
const day = theTimeObj.format('D')
|
const year = theTimeObj.format("YYYY");
|
||||||
const time = theTimeObj.format('HH:MM')
|
const month = theTimeObj.format("M");
|
||||||
return { time: `${year}年${month}月${day}日${time}${index === 0 ? '前' : '后'}`, rule: item.refund_rule }
|
const day = theTimeObj.format("D");
|
||||||
})]
|
const time = theTimeObj.format("HH:MM");
|
||||||
|
return {
|
||||||
|
time: `${year}年${month}月${day}日${time}${index === 0 ? "前" : "后"}`,
|
||||||
|
rule: item.refund_rule,
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
];
|
||||||
return (
|
return (
|
||||||
<View className={styles.refundPolicy}>
|
<View className={styles.refundPolicy}>
|
||||||
<View className={styles.moduleTitle}>
|
<View className={styles.moduleTitle}>
|
||||||
@@ -190,12 +199,12 @@ function RefundPolicy(props) {
|
|||||||
</View>
|
</View>
|
||||||
{/* 订单信息摘要 */}
|
{/* 订单信息摘要 */}
|
||||||
<View className={styles.policyList}>
|
<View className={styles.policyList}>
|
||||||
{
|
{policyList.map((item, index) => (
|
||||||
policyList.map((item, index) => (<View key={index} className={styles.policyItem}>
|
<View key={index} className={styles.policyItem}>
|
||||||
<View className={styles.time}>{item.time}</View>
|
<View className={styles.time}>{item.time}</View>
|
||||||
<View className={styles.rule}>{item.rule}</View>
|
<View className={styles.rule}>{item.rule}</View>
|
||||||
</View>))
|
</View>
|
||||||
}
|
))}
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
@@ -212,22 +221,43 @@ function Disclaimer() {
|
|||||||
|
|
||||||
const OrderCheck = () => {
|
const OrderCheck = () => {
|
||||||
const { params } = useRouter();
|
const { params } = useRouter();
|
||||||
const { id, gameId } = params;
|
const { id: stringId, gameId: stringGameId } = params;
|
||||||
const [detail, setDetail] = useState<GameDetail | {}>({});
|
const [id, gameId] = [Number(stringId), Number(stringGameId)];
|
||||||
|
const [detail, setDetail] = useState<GameData | {}>({});
|
||||||
const [location, setLocation] = useState<number[]>([0, 0]);
|
const [location, setLocation] = useState<number[]>([0, 0]);
|
||||||
const [orderInfo, setOrderInfo] = useState<GameOrderRes | {}>({})
|
const [checkOrderInfo, setCheckOrderInfo] = useState<GameOrderRes | {}>({});
|
||||||
|
const [orderDetail, setOrderDetail] = useState({});
|
||||||
|
|
||||||
useDidShow(async () => {
|
useDidShow(async () => {
|
||||||
const res = await detailService.getDetail(Number(gameId));
|
let gameDetail = {};
|
||||||
const orderRes = await orderService.getOrderInfo(Number(gameId))
|
if (id) {
|
||||||
setOrderInfo(orderRes.data)
|
const res = await orderService.getOrderDetail(id);
|
||||||
console.log(res);
|
|
||||||
if (res.code === 0) {
|
if (res.code === 0) {
|
||||||
setDetail(res.data);
|
setOrderDetail(res.data);
|
||||||
|
gameDetail = res.data.game_info;
|
||||||
}
|
}
|
||||||
|
} else if (gameId) {
|
||||||
|
const res = await detailService.getDetail(gameId);
|
||||||
|
if (res.code === 0) {
|
||||||
|
gameDetail = res.data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (gameDetail.id) {
|
||||||
|
setDetail(gameDetail);
|
||||||
|
onInit(gameDetail.id);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
async function checkOrder(gid) {
|
||||||
|
const orderRes = await orderService.getCheckOrderInfo(gid);
|
||||||
|
setCheckOrderInfo(orderRes.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function onInit(gid) {
|
||||||
|
checkOrder(gid);
|
||||||
const location = await getCurrentLocation();
|
const location = await getCurrentLocation();
|
||||||
setLocation([location.latitude, location.longitude]);
|
setLocation([location.latitude, location.longitude]);
|
||||||
});
|
}
|
||||||
|
|
||||||
//TODO: get order msg from id
|
//TODO: get order msg from id
|
||||||
const handlePay = async () => {
|
const handlePay = async () => {
|
||||||
@@ -235,9 +265,32 @@ const OrderCheck = () => {
|
|||||||
title: "支付中...",
|
title: "支付中...",
|
||||||
mask: true,
|
mask: true,
|
||||||
});
|
});
|
||||||
const res = await orderService.createOrder(Number(gameId));
|
let wxPayRes: any = {};
|
||||||
|
try {
|
||||||
|
if (orderDetail.game_info?.id) {
|
||||||
|
const res = await orderService.getUnpaidOrder(orderDetail.game_info.id);
|
||||||
if (res.code === 0) {
|
if (res.code === 0) {
|
||||||
const { payment_required, payment_params } = res.data;
|
wxPayRes = {
|
||||||
|
...res.data,
|
||||||
|
payment_required: res.data.has_unpaid_order,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const res = await orderService.createOrder(detail.id);
|
||||||
|
if (res.code === 0) {
|
||||||
|
wxPayRes = res.data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
Taro.hideLoading();
|
||||||
|
Taro.showToast({
|
||||||
|
title: "支付调用失败",
|
||||||
|
icon: "none",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { payment_required, payment_params } = wxPayRes;
|
||||||
if (payment_required) {
|
if (payment_required) {
|
||||||
const {
|
const {
|
||||||
timeStamp,
|
timeStamp,
|
||||||
@@ -272,19 +325,42 @@ const OrderCheck = () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
if (!id && !gameId) {
|
||||||
|
return (
|
||||||
|
<View className={styles.errorTip}>
|
||||||
|
<Text>异常订单</Text>
|
||||||
|
<Button
|
||||||
|
type="warn"
|
||||||
|
onClick={() => {
|
||||||
|
Taro.redirectTo({ url: "/pages/list/index" });
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
回到首页
|
||||||
|
</Button>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<View className={styles.container}>
|
<View className={styles.container}>
|
||||||
{/* Game Date and Address */}
|
{/* Game Date and Address */}
|
||||||
<GameInfo detail={detail} currentLocation={location} />
|
<GameInfo detail={detail} currentLocation={location} />
|
||||||
{/* Order message */}
|
{/* Order message */}
|
||||||
<OrderMsg detail={detail} orderInfo={orderInfo} />
|
<OrderMsg detail={detail} checkOrderInfo={checkOrderInfo} />
|
||||||
{/* Refund policy */}
|
{/* Refund policy */}
|
||||||
<RefundPolicy orderInfo={orderInfo} />
|
<RefundPolicy checkOrderInfo={checkOrderInfo} />
|
||||||
{/* Disclaimer */}
|
{/* Disclaimer */}
|
||||||
<Disclaimer />
|
<Disclaimer />
|
||||||
<Button className={styles.payButton} type="primary" onClick={handlePay}>支付</Button>
|
{!id ||
|
||||||
|
(orderDetail.order_status === OrderStatus.PENDING && (
|
||||||
|
<Button
|
||||||
|
className={styles.payButton}
|
||||||
|
type="primary"
|
||||||
|
onClick={handlePay}
|
||||||
|
>
|
||||||
|
{orderDetail.order_status === OrderStatus.PENDING ? "继续" : ""}支付
|
||||||
|
</Button>
|
||||||
|
))}
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
@use '~@/scss/images.scss' as img;
|
@use "~@/scss/images.scss" as img;
|
||||||
|
|
||||||
.detail-page {
|
.detail-page {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@@ -31,13 +31,14 @@
|
|||||||
color: #fff;
|
color: #fff;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
background: rgba(0, 0, 0, 0.10);
|
background: rgba(0, 0, 0, 0.1);
|
||||||
|
|
||||||
.detail-navigator-back {
|
.detail-navigator-back {
|
||||||
border-right: 1px solid #444;
|
border-right: 1px solid #444;
|
||||||
}
|
}
|
||||||
|
|
||||||
.detail-navigator-back, .detail-navigator-icon {
|
.detail-navigator-back,
|
||||||
|
.detail-navigator-icon {
|
||||||
height: 20px;
|
height: 20px;
|
||||||
width: 50%;
|
width: 50%;
|
||||||
|
|
||||||
@@ -75,14 +76,18 @@
|
|||||||
height: 100vh;
|
height: 100vh;
|
||||||
|
|
||||||
&::after {
|
&::after {
|
||||||
content: '';
|
content: "";
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
z-index: -1;
|
z-index: -1;
|
||||||
background: linear-gradient(180deg, rgba(0, 0, 0, 0.80) 0%, rgba(0, 0, 0, 0.40) 100%);
|
background: linear-gradient(
|
||||||
|
180deg,
|
||||||
|
rgba(0, 0, 0, 0.8) 0%,
|
||||||
|
rgba(0, 0, 0, 0.4) 100%
|
||||||
|
);
|
||||||
backdrop-filter: blur(100px);
|
backdrop-filter: blur(100px);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -141,7 +146,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.detail-page-content {
|
.detail-page-content {
|
||||||
|
|
||||||
&-avatar-tags {
|
&-avatar-tags {
|
||||||
padding: 20px 20px 0;
|
padding: 20px 20px 0;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
@@ -194,8 +198,10 @@
|
|||||||
|
|
||||||
&-text {
|
&-text {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
color: #FFF;
|
color: #fff;
|
||||||
font-feature-settings: 'liga' off, 'clig' off;
|
font-feature-settings:
|
||||||
|
"liga" off,
|
||||||
|
"clig" off;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
font-family: "PingFang SC";
|
font-family: "PingFang SC";
|
||||||
font-size: 22px;
|
font-size: 22px;
|
||||||
@@ -232,7 +238,7 @@
|
|||||||
// border: 0.5px solid rgba(255, 255, 255, 0.08);
|
// border: 0.5px solid rgba(255, 255, 255, 0.08);
|
||||||
background: rgba(255, 255, 255, 0.25);
|
background: rgba(255, 255, 255, 0.25);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
color: #FFF;
|
color: #fff;
|
||||||
background: #536272;
|
background: #536272;
|
||||||
|
|
||||||
.month {
|
.month {
|
||||||
@@ -245,7 +251,7 @@
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: 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;
|
background: #7b828b;
|
||||||
}
|
}
|
||||||
|
|
||||||
.day {
|
.day {
|
||||||
@@ -269,11 +275,13 @@
|
|||||||
justify-content: space-evenly;
|
justify-content: space-evenly;
|
||||||
gap: 4px;
|
gap: 4px;
|
||||||
align-self: stretch;
|
align-self: stretch;
|
||||||
color: #FFF;
|
color: #fff;
|
||||||
|
|
||||||
.date {
|
.date {
|
||||||
color: #FFF;
|
color: #fff;
|
||||||
font-feature-settings: 'liga' off, 'clig' off;
|
font-feature-settings:
|
||||||
|
"liga" off,
|
||||||
|
"clig" off;
|
||||||
font-family: "PingFang SC";
|
font-family: "PingFang SC";
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
@@ -282,8 +290,10 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.venue-time {
|
.venue-time {
|
||||||
color: rgba(255, 255, 255, 0.80);
|
color: rgba(255, 255, 255, 0.8);
|
||||||
font-feature-settings: 'liga' off, 'clig' off;
|
font-feature-settings:
|
||||||
|
"liga" off,
|
||||||
|
"clig" off;
|
||||||
font-family: "PingFang SC";
|
font-family: "PingFang SC";
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
@@ -302,18 +312,16 @@
|
|||||||
&-icon {
|
&-icon {
|
||||||
width: 20px;
|
width: 20px;
|
||||||
height: 20px;
|
height: 20px;
|
||||||
|
color: rgba(255, 255, 255, 0.8);
|
||||||
.weather-icon {
|
|
||||||
width: 20px;
|
|
||||||
height: 20px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
&-text-temperature {
|
&-text-temperature {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 12px;
|
gap: 12px;
|
||||||
color: rgba(255, 255, 255, 0.80);
|
color: rgba(255, 255, 255, 0.8);
|
||||||
font-feature-settings: 'liga' off, 'clig' off;
|
font-feature-settings:
|
||||||
|
"liga" off,
|
||||||
|
"clig" off;
|
||||||
font-family: "PingFang SC";
|
font-family: "PingFang SC";
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
@@ -338,7 +346,7 @@
|
|||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
padding: 14px;
|
padding: 14px;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
background: #4D5865;
|
background: #4d5865;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -364,9 +372,11 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 4px;
|
gap: 4px;
|
||||||
color: #FFF;
|
color: #fff;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-feature-settings: 'liga' off, 'clig' off;
|
font-feature-settings:
|
||||||
|
"liga" off,
|
||||||
|
"clig" off;
|
||||||
font-family: "PingFang SC";
|
font-family: "PingFang SC";
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
@@ -380,9 +390,11 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&-address {
|
&-address {
|
||||||
color: rgba(255, 255, 255, 0.80);
|
color: rgba(255, 255, 255, 0.8);
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-feature-settings: 'liga' off, 'clig' off;
|
font-feature-settings:
|
||||||
|
"liga" off,
|
||||||
|
"clig" off;
|
||||||
font-family: "PingFang SC";
|
font-family: "PingFang SC";
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
@@ -422,7 +434,7 @@
|
|||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
padding-bottom: 6px;
|
padding-bottom: 6px;
|
||||||
color: #FFF;
|
color: #fff;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
font-family: "PingFang SC";
|
font-family: "PingFang SC";
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
@@ -455,8 +467,10 @@
|
|||||||
|
|
||||||
&-tag {
|
&-tag {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
color: #FFF;
|
color: #fff;
|
||||||
font-feature-settings: 'liga' off, 'clig' off;
|
font-feature-settings:
|
||||||
|
"liga" off,
|
||||||
|
"clig" off;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
font-family: "PingFang SC";
|
font-family: "PingFang SC";
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
@@ -520,6 +534,7 @@
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
border-radius: 9px;
|
border-radius: 9px;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
object-fit: cover;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -532,10 +547,12 @@
|
|||||||
|
|
||||||
.gameplay-requirements-title {
|
.gameplay-requirements-title {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
color: #FFF;
|
color: #fff;
|
||||||
height: 24px;
|
height: 24px;
|
||||||
padding-bottom: 6px;
|
padding-bottom: 6px;
|
||||||
font-feature-settings: 'liga' off, 'clig' off;
|
font-feature-settings:
|
||||||
|
"liga" off,
|
||||||
|
"clig" off;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
font-family: "PingFang SC";
|
font-family: "PingFang SC";
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
@@ -559,8 +576,10 @@
|
|||||||
align-self: stretch;
|
align-self: stretch;
|
||||||
|
|
||||||
&-title {
|
&-title {
|
||||||
color: rgba(255, 255, 255, 0.80);
|
color: rgba(255, 255, 255, 0.8);
|
||||||
font-feature-settings: 'liga' off, 'clig' off;
|
font-feature-settings:
|
||||||
|
"liga" off,
|
||||||
|
"clig" off;
|
||||||
font-family: "PingFang SC";
|
font-family: "PingFang SC";
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
@@ -569,8 +588,10 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&-desc {
|
&-desc {
|
||||||
color: #FFF;
|
color: #fff;
|
||||||
font-feature-settings: 'liga' off, 'clig' off;
|
font-feature-settings:
|
||||||
|
"liga" off,
|
||||||
|
"clig" off;
|
||||||
font-family: "PingFang SC";
|
font-family: "PingFang SC";
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
@@ -590,8 +611,10 @@
|
|||||||
padding-bottom: 6px;
|
padding-bottom: 6px;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
color: #FFF;
|
color: #fff;
|
||||||
font-feature-settings: 'liga' off, 'clig' off;
|
font-feature-settings:
|
||||||
|
"liga" off,
|
||||||
|
"clig" off;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
font-family: "PingFang SC";
|
font-family: "PingFang SC";
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
@@ -620,7 +643,7 @@
|
|||||||
gap: 8px;
|
gap: 8px;
|
||||||
align-self: stretch;
|
align-self: stretch;
|
||||||
border-radius: 20px;
|
border-radius: 20px;
|
||||||
border: 1px dashed rgba(255, 255, 255, 0.20);
|
border: 1px dashed rgba(255, 255, 255, 0.2);
|
||||||
background: rgba(255, 255, 255, 0.16);
|
background: rgba(255, 255, 255, 0.16);
|
||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
|
|
||||||
@@ -630,8 +653,10 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&-text {
|
&-text {
|
||||||
color: rgba(255, 255, 255, 0.60);
|
color: rgba(255, 255, 255, 0.6);
|
||||||
font-feature-settings: 'liga' off, 'clig' off;
|
font-feature-settings:
|
||||||
|
"liga" off,
|
||||||
|
"clig" off;
|
||||||
font-family: "PingFang SC";
|
font-family: "PingFang SC";
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
@@ -661,7 +686,7 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 4px;
|
gap: 4px;
|
||||||
border-radius: 20px;
|
border-radius: 20px;
|
||||||
border: 0.5px solid rgba(255, 255, 255, 0.20);
|
border: 0.5px solid rgba(255, 255, 255, 0.2);
|
||||||
background: rgba(255, 255, 255, 0.16);
|
background: rgba(255, 255, 255, 0.16);
|
||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
|
|
||||||
@@ -674,7 +699,9 @@
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
color: rgba(255, 255, 255, 0.85);
|
color: rgba(255, 255, 255, 0.85);
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-feature-settings: 'liga' off, 'clig' off;
|
font-feature-settings:
|
||||||
|
"liga" off,
|
||||||
|
"clig" off;
|
||||||
font-family: "PingFang SC";
|
font-family: "PingFang SC";
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
@@ -688,7 +715,9 @@
|
|||||||
&-level {
|
&-level {
|
||||||
color: rgba(255, 255, 255, 0.45);
|
color: rgba(255, 255, 255, 0.45);
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-feature-settings: 'liga' off, 'clig' off;
|
font-feature-settings:
|
||||||
|
"liga" off,
|
||||||
|
"clig" off;
|
||||||
font-family: "PingFang SC";
|
font-family: "PingFang SC";
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
@@ -697,9 +726,11 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&-role {
|
&-role {
|
||||||
color: #FFF;
|
color: #fff;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-feature-settings: 'liga' off, 'clig' off;
|
font-feature-settings:
|
||||||
|
"liga" off,
|
||||||
|
"clig" off;
|
||||||
font-family: "PingFang SC";
|
font-family: "PingFang SC";
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
@@ -719,8 +750,10 @@
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
padding-bottom: 7px;
|
padding-bottom: 7px;
|
||||||
height: 24px;
|
height: 24px;
|
||||||
color: #FFF;
|
color: #fff;
|
||||||
font-feature-settings: 'liga' off, 'clig' off;
|
font-feature-settings:
|
||||||
|
"liga" off,
|
||||||
|
"clig" off;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
font-family: "PingFang SC";
|
font-family: "PingFang SC";
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
@@ -744,8 +777,10 @@
|
|||||||
|
|
||||||
&-tag {
|
&-tag {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
color: #FFF;
|
color: #fff;
|
||||||
font-feature-settings: 'liga' off, 'clig' off;
|
font-feature-settings:
|
||||||
|
"liga" off,
|
||||||
|
"clig" off;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
font-family: "PingFang SC";
|
font-family: "PingFang SC";
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
@@ -758,7 +793,9 @@
|
|||||||
&-text {
|
&-text {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
color: rgba(255, 255, 255, 0.65);
|
color: rgba(255, 255, 255, 0.65);
|
||||||
font-feature-settings: 'liga' off, 'clig' off;
|
font-feature-settings:
|
||||||
|
"liga" off,
|
||||||
|
"clig" off;
|
||||||
font-family: "PingFang SC";
|
font-family: "PingFang SC";
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
@@ -775,8 +812,10 @@
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
padding-bottom: 6px;
|
padding-bottom: 6px;
|
||||||
height: 24px;
|
height: 24px;
|
||||||
color: #FFF;
|
color: #fff;
|
||||||
font-feature-settings: 'liga' off, 'clig' off;
|
font-feature-settings:
|
||||||
|
"liga" off,
|
||||||
|
"clig" off;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
font-family: "PingFang SC";
|
font-family: "PingFang SC";
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
@@ -816,7 +855,7 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 5px;
|
gap: 5px;
|
||||||
color: rgba(255, 255, 255, 0.60);
|
color: rgba(255, 255, 255, 0.6);
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
@@ -826,7 +865,7 @@
|
|||||||
&-separator {
|
&-separator {
|
||||||
width: 1px;
|
width: 1px;
|
||||||
height: 10px;
|
height: 10px;
|
||||||
color: rgba(255, 255, 255, 0.20);
|
color: rgba(255, 255, 255, 0.2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -837,7 +876,8 @@
|
|||||||
gap: 8px;
|
gap: 8px;
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
|
|
||||||
.organizer-actions-follow, .organizer-actions-comment {
|
.organizer-actions-follow,
|
||||||
|
.organizer-actions-comment {
|
||||||
display: flex;
|
display: flex;
|
||||||
height: 32px;
|
height: 32px;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
@@ -857,7 +897,7 @@
|
|||||||
.organizer-actions-follow {
|
.organizer-actions-follow {
|
||||||
padding: 8px 12px 8px;
|
padding: 8px 12px 8px;
|
||||||
&-text {
|
&-text {
|
||||||
color: #FFF;
|
color: #fff;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
@@ -913,7 +953,7 @@
|
|||||||
gap: 6px;
|
gap: 6px;
|
||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
border-radius: 20px;
|
border-radius: 20px;
|
||||||
border: 1px solid rgba(33, 178, 0, 0.20);
|
border: 1px solid rgba(33, 178, 0, 0.2);
|
||||||
background: rgba(255, 255, 255, 0.16);
|
background: rgba(255, 255, 255, 0.16);
|
||||||
padding: 12px 0 12px 15px;
|
padding: 12px 0 12px 15px;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
@@ -953,7 +993,9 @@
|
|||||||
gap: 2px;
|
gap: 2px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
color: rgba(255, 255, 255, 0.45);
|
color: rgba(255, 255, 255, 0.45);
|
||||||
font-feature-settings: 'liga' off, 'clig' off;
|
font-feature-settings:
|
||||||
|
"liga" off,
|
||||||
|
"clig" off;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
font-family: "PingFang SC";
|
font-family: "PingFang SC";
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
@@ -976,7 +1018,9 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
gap: 4px;
|
gap: 4px;
|
||||||
|
|
||||||
&-applications, &-level-requirements, &-play-type {
|
&-applications,
|
||||||
|
&-level-requirements,
|
||||||
|
&-play-type {
|
||||||
color: rgba(255, 255, 255, 0.85);
|
color: rgba(255, 255, 255, 0.85);
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
@@ -1024,7 +1068,7 @@
|
|||||||
gap: 16px;
|
gap: 16px;
|
||||||
border-radius: 16px;
|
border-radius: 16px;
|
||||||
border: 1px solid rgba(255, 255, 255, 0.06);
|
border: 1px solid rgba(255, 255, 255, 0.06);
|
||||||
background: #FFF;
|
background: #fff;
|
||||||
|
|
||||||
.sticky-bottom-bar-share {
|
.sticky-bottom-bar-share {
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -1049,7 +1093,7 @@
|
|||||||
&-separator {
|
&-separator {
|
||||||
width: 1px;
|
width: 1px;
|
||||||
height: 24px;
|
height: 24px;
|
||||||
background: rgba(0, 0, 0, 0.10);
|
background: rgba(0, 0, 0, 0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
.sticky-bottom-bar-comment {
|
.sticky-bottom-bar-comment {
|
||||||
@@ -1085,7 +1129,7 @@
|
|||||||
flex: 1 0 0;
|
flex: 1 0 0;
|
||||||
border-radius: 16px;
|
border-radius: 16px;
|
||||||
border: 1px solid rgba(0, 0, 0, 0.06);
|
border: 1px solid rgba(0, 0, 0, 0.06);
|
||||||
background: #FFF;
|
background: #fff;
|
||||||
|
|
||||||
&-price {
|
&-price {
|
||||||
font-family: "PoetsenOne";
|
font-family: "PoetsenOne";
|
||||||
@@ -1130,4 +1174,3 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ import {
|
|||||||
DisplayConditionType,
|
DisplayConditionType,
|
||||||
} from "@/components/NTRPEvaluatePopup";
|
} from "@/components/NTRPEvaluatePopup";
|
||||||
import DetailService, { MATCH_STATUS } from "@/services/detailService";
|
import DetailService, { MATCH_STATUS } from "@/services/detailService";
|
||||||
|
import * as LoginService from "@/services/loginService";
|
||||||
|
import OrderService from "@/services/orderService";
|
||||||
import { getCurrentLocation, calculateDistance } from "@/utils/locationUtils";
|
import { getCurrentLocation, calculateDistance } from "@/utils/locationUtils";
|
||||||
import { useUserInfo, useUserActions } from "@/store/userStore";
|
import { useUserInfo, useUserActions } from "@/store/userStore";
|
||||||
import img from "@/config/images";
|
import img from "@/config/images";
|
||||||
@@ -218,10 +220,16 @@ function navto(url) {
|
|||||||
function StickyButton(props) {
|
function StickyButton(props) {
|
||||||
const { handleShare, handleJoinGame, detail } = props;
|
const { handleShare, handleJoinGame, detail } = props;
|
||||||
const ntrpRef = useRef(null);
|
const ntrpRef = useRef(null);
|
||||||
const userInfo = useUserInfo();
|
// const userInfo = useUserInfo();
|
||||||
const { id } = userInfo;
|
// const { id } = userInfo;
|
||||||
const { publisher_id, match_status, price, user_action_status, end_time } =
|
const {
|
||||||
detail || {};
|
id,
|
||||||
|
publisher_id,
|
||||||
|
match_status,
|
||||||
|
price,
|
||||||
|
user_action_status,
|
||||||
|
end_time,
|
||||||
|
} = detail || {};
|
||||||
|
|
||||||
function handleSelfEvaluate() {
|
function handleSelfEvaluate() {
|
||||||
// TODO: 打开自评弹窗
|
// TODO: 打开自评弹窗
|
||||||
@@ -266,7 +274,14 @@ function StickyButton(props) {
|
|||||||
} else if (can_pay) {
|
} else if (can_pay) {
|
||||||
return {
|
return {
|
||||||
text: "继续支付",
|
text: "继续支付",
|
||||||
action: handleJoinGame,
|
action: async () => {
|
||||||
|
const res = await OrderService.getUnpaidOrder(id);
|
||||||
|
if (res.code === 0) {
|
||||||
|
Taro.navigateTo({
|
||||||
|
url: `/mod_user/orderDetail/index?id=${res.data.order_info.order_id}`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
};
|
};
|
||||||
} else if (can_substitute) {
|
} else if (can_substitute) {
|
||||||
return {
|
return {
|
||||||
@@ -323,7 +338,7 @@ function StickyButton(props) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const role = Number(publisher_id) === id ? "ownner" : "visitor";
|
// const role = Number(publisher_id) === id ? "ownner" : "visitor";
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View className="sticky-bottom-bar">
|
<View className="sticky-bottom-bar">
|
||||||
@@ -359,8 +374,17 @@ function StickyButton(props) {
|
|||||||
// 球局信息
|
// 球局信息
|
||||||
function GameInfo(props) {
|
function GameInfo(props) {
|
||||||
const { detail, currentLocation } = props;
|
const { detail, currentLocation } = props;
|
||||||
const { latitude, longitude, location, location_name, start_time, end_time } =
|
const {
|
||||||
detail || {};
|
latitude,
|
||||||
|
longitude,
|
||||||
|
location,
|
||||||
|
location_name,
|
||||||
|
start_time,
|
||||||
|
end_time,
|
||||||
|
weather = [{}],
|
||||||
|
} = detail || {};
|
||||||
|
|
||||||
|
const [{ iconDay, tempMax, tempMin }] = weather;
|
||||||
|
|
||||||
const openMap = () => {
|
const openMap = () => {
|
||||||
Taro.openLocation({
|
Taro.openLocation({
|
||||||
@@ -374,7 +398,9 @@ function GameInfo(props) {
|
|||||||
|
|
||||||
const [c_latitude, c_longitude] = currentLocation;
|
const [c_latitude, c_longitude] = currentLocation;
|
||||||
const distance =
|
const distance =
|
||||||
calculateDistance(c_latitude, c_longitude, latitude, longitude) / 1000;
|
latitude && longitude
|
||||||
|
? calculateDistance(c_latitude, c_longitude, latitude, longitude) / 1000
|
||||||
|
: 0;
|
||||||
|
|
||||||
const startTime = dayjs(start_time);
|
const startTime = dayjs(start_time);
|
||||||
const endTime = dayjs(end_time);
|
const endTime = dayjs(end_time);
|
||||||
@@ -409,11 +435,16 @@ function GameInfo(props) {
|
|||||||
<View className="detail-page-content-game-info-date-weather-weather">
|
<View className="detail-page-content-game-info-date-weather-weather">
|
||||||
{/* Weather icon */}
|
{/* Weather icon */}
|
||||||
<View className="detail-page-content-game-info-date-weather-weather-icon">
|
<View className="detail-page-content-game-info-date-weather-weather-icon">
|
||||||
<Image className="weather-icon" src={img.ICON_WEATHER_SUN} />
|
{/*<Image className="weather-icon" src={img.ICON_WEATHER_SUN} />*/}
|
||||||
|
<i className={`qi-${iconDay}`}></i>
|
||||||
</View>
|
</View>
|
||||||
{/* Weather text and temperature */}
|
{/* Weather text and temperature */}
|
||||||
<View className="detail-page-content-game-info-date-weather-weather-text-temperature">
|
<View className="detail-page-content-game-info-date-weather-weather-text-temperature">
|
||||||
<Text>28℃ - 32℃</Text>
|
{tempMin && tempMax && (
|
||||||
|
<Text>
|
||||||
|
{tempMin}℃ - {tempMax}℃
|
||||||
|
</Text>
|
||||||
|
)}
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
@@ -431,6 +462,7 @@ function GameInfo(props) {
|
|||||||
{/* location message */}
|
{/* location message */}
|
||||||
<View className="location-message-text">
|
<View className="location-message-text">
|
||||||
{/* venue name and distance */}
|
{/* venue name and distance */}
|
||||||
|
{distance ? (
|
||||||
<View
|
<View
|
||||||
className="location-message-text-name-distance"
|
className="location-message-text-name-distance"
|
||||||
onClick={openMap}
|
onClick={openMap}
|
||||||
@@ -443,6 +475,9 @@ function GameInfo(props) {
|
|||||||
src={img.ICON_DETAIL_ARROW_RIGHT}
|
src={img.ICON_DETAIL_ARROW_RIGHT}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
|
) : (
|
||||||
|
""
|
||||||
|
)}
|
||||||
{/* venue address */}
|
{/* venue address */}
|
||||||
<View className="location-message-text-address">
|
<View className="location-message-text-address">
|
||||||
<Text>{location || "-"}</Text>
|
<Text>{location || "-"}</Text>
|
||||||
@@ -454,8 +489,8 @@ function GameInfo(props) {
|
|||||||
{longitude && latitude && (
|
{longitude && latitude && (
|
||||||
<Map
|
<Map
|
||||||
className="location-map-map"
|
className="location-map-map"
|
||||||
longitude={longitude}
|
longitude={c_longitude}
|
||||||
latitude={latitude}
|
latitude={c_latitude}
|
||||||
markers={[
|
markers={[
|
||||||
{
|
{
|
||||||
id: 1,
|
id: 1,
|
||||||
@@ -468,7 +503,7 @@ function GameInfo(props) {
|
|||||||
]}
|
]}
|
||||||
includePoints={[
|
includePoints={[
|
||||||
{ latitude, longitude },
|
{ latitude, longitude },
|
||||||
{ latitude: currentLocation[0], longitude: currentLocation[1] },
|
{ latitude: c_latitude, longitude: c_longitude },
|
||||||
]}
|
]}
|
||||||
includePadding={{ left: 50, right: 50, top: 50, bottom: 50 }}
|
includePadding={{ left: 50, right: 50, top: 50, bottom: 50 }}
|
||||||
onError={() => {}}
|
onError={() => {}}
|
||||||
@@ -580,7 +615,7 @@ function genNTRPRequirementText(min, max) {
|
|||||||
} else if (max) {
|
} else if (max) {
|
||||||
return `${max} 以上`;
|
return `${max} 以上`;
|
||||||
}
|
}
|
||||||
return '-'
|
return "-";
|
||||||
}
|
}
|
||||||
// 玩法要求
|
// 玩法要求
|
||||||
function GamePlayAndRequirement(props) {
|
function GamePlayAndRequirement(props) {
|
||||||
@@ -627,23 +662,34 @@ function GamePlayAndRequirement(props) {
|
|||||||
function Participants(props) {
|
function Participants(props) {
|
||||||
const { detail = {}, handleJoinGame } = props;
|
const { detail = {}, handleJoinGame } = props;
|
||||||
const participants = detail.participants || [];
|
const participants = detail.participants || [];
|
||||||
const { participant_count, max_participants, user_action_status = {} } = detail
|
const {
|
||||||
const { can_join } = user_action_status
|
participant_count,
|
||||||
const leftCount = max_participants - participant_count
|
max_participants,
|
||||||
|
user_action_status = {},
|
||||||
|
} = detail;
|
||||||
|
const { can_join, can_pay, can_substitute, is_substituting, waiting_start } =
|
||||||
|
user_action_status;
|
||||||
|
const showApplicationEntry =
|
||||||
|
[can_pay, can_substitute, is_substituting, waiting_start].every(
|
||||||
|
(item) => !item,
|
||||||
|
) && can_join;
|
||||||
|
const leftCount = max_participants - participant_count;
|
||||||
const organizer_id = Number(detail.publisher_id);
|
const organizer_id = Number(detail.publisher_id);
|
||||||
return (
|
return (
|
||||||
<View className="detail-page-content-participants">
|
<View className="detail-page-content-participants">
|
||||||
<View className="participants-title">
|
<View className="participants-title">
|
||||||
<Text>参与者</Text>
|
<Text>参与者</Text>
|
||||||
<Text>·</Text>
|
<Text>·</Text>
|
||||||
<Text>{leftCount > 0 ? `剩余空位 ${leftCount}` : '已满员'}</Text>
|
<Text>{leftCount > 0 ? `剩余空位 ${leftCount}` : "已满员"}</Text>
|
||||||
</View>
|
</View>
|
||||||
|
{participant_count > 0 || showApplicationEntry ? (
|
||||||
<View className="participants-list">
|
<View className="participants-list">
|
||||||
{/* application */}
|
{/* application */}
|
||||||
{can_join && <View
|
{showApplicationEntry && (
|
||||||
|
<View
|
||||||
className="participants-list-application"
|
className="participants-list-application"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
handleJoinGame()
|
handleJoinGame();
|
||||||
// Taro.showToast({ title: "To be continued", icon: "none" });
|
// Taro.showToast({ title: "To be continued", icon: "none" });
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@@ -651,8 +697,11 @@ function Participants(props) {
|
|||||||
className="participants-list-application-icon"
|
className="participants-list-application-icon"
|
||||||
src={img.ICON_DETAIL_APPLICATION_ADD}
|
src={img.ICON_DETAIL_APPLICATION_ADD}
|
||||||
/>
|
/>
|
||||||
<Text className="participants-list-application-text">申请加入</Text>
|
<Text className="participants-list-application-text">
|
||||||
</View>}
|
申请加入
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
)}
|
||||||
{/* participants list */}
|
{/* participants list */}
|
||||||
<ScrollView className="participants-list-scroll" scrollX>
|
<ScrollView className="participants-list-scroll" scrollX>
|
||||||
<View
|
<View
|
||||||
@@ -663,7 +712,12 @@ function Participants(props) {
|
|||||||
>
|
>
|
||||||
{participants.map((participant) => {
|
{participants.map((participant) => {
|
||||||
const {
|
const {
|
||||||
user: { avatar_url, nickname, level, id: participant_user_id },
|
user: {
|
||||||
|
avatar_url,
|
||||||
|
nickname,
|
||||||
|
level,
|
||||||
|
id: participant_user_id,
|
||||||
|
},
|
||||||
} = participant;
|
} = participant;
|
||||||
const role =
|
const role =
|
||||||
participant_user_id === organizer_id ? "组织者" : "参与者";
|
participant_user_id === organizer_id ? "组织者" : "参与者";
|
||||||
@@ -686,6 +740,9 @@ function Participants(props) {
|
|||||||
</View>
|
</View>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
</View>
|
</View>
|
||||||
|
) : (
|
||||||
|
""
|
||||||
|
)}
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -717,48 +774,86 @@ function SupplementalNotes(props) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function genRecommendGames(games, location, avatar) {
|
||||||
|
return games.map((item) => {
|
||||||
|
const {
|
||||||
|
id,
|
||||||
|
title,
|
||||||
|
start_time,
|
||||||
|
end_time,
|
||||||
|
court_type,
|
||||||
|
location_name,
|
||||||
|
current_players,
|
||||||
|
max_players,
|
||||||
|
latitude,
|
||||||
|
longitude,
|
||||||
|
skill_level_max,
|
||||||
|
skill_level_min,
|
||||||
|
play_type,
|
||||||
|
} = item;
|
||||||
|
const [c_latitude, c_longitude] = location;
|
||||||
|
const distance =
|
||||||
|
calculateDistance(c_latitude, c_longitude, latitude, longitude) / 1000;
|
||||||
|
const startTime = dayjs(start_time);
|
||||||
|
const endTime = dayjs(end_time);
|
||||||
|
return {
|
||||||
|
id,
|
||||||
|
title,
|
||||||
|
time: startTime.format("YYYY-MM-DD HH:MM"),
|
||||||
|
timeLength: endTime.diff(startTime, "hour"),
|
||||||
|
venue: location_name,
|
||||||
|
venueType: court_type,
|
||||||
|
distance: `${distance.toFixed(2)}km`,
|
||||||
|
avatar,
|
||||||
|
applications: max_players,
|
||||||
|
checkedApplications: current_players,
|
||||||
|
levelRequirements: `NTRP ${genNTRPRequirementText(skill_level_min, skill_level_max)}`,
|
||||||
|
playType: play_type,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function OrganizerInfo(props) {
|
function OrganizerInfo(props) {
|
||||||
const recommendGames = [
|
const {
|
||||||
{
|
userInfo,
|
||||||
title: "黄浦日场对拉",
|
currentLocation: location,
|
||||||
time: "2025-08-25 9:00",
|
onUpdateUserInfo = () => {},
|
||||||
timeLength: "2小时",
|
} = props;
|
||||||
venue: "上海体育场",
|
const {
|
||||||
veuneType: "室外",
|
id,
|
||||||
distance: "1.2km",
|
nickname,
|
||||||
avatar: "https://img.yzcdn.cn/vant/cat.jpeg",
|
avatar_url,
|
||||||
applications: 10,
|
is_following,
|
||||||
checkedApplications: 3,
|
ntrp_level,
|
||||||
levelRequirements: "NTRP 3.5",
|
stats: { hosted_games_count } = {},
|
||||||
playType: "双打",
|
ongoing_games = [],
|
||||||
},
|
} = userInfo;
|
||||||
{
|
|
||||||
title: "黄浦夜场对拉",
|
const myInfo = useUserInfo();
|
||||||
time: "2025-08-25 19:00",
|
const { id: my_id } = myInfo as LoginService.UserInfoType;
|
||||||
timeLength: "2小时",
|
|
||||||
venue: "上海体育场",
|
const recommendGames = genRecommendGames(ongoing_games, location, avatar_url);
|
||||||
veuneType: "室外",
|
|
||||||
distance: "1.2km",
|
const toggleFollow = async (follow) => {
|
||||||
avatar: "https://img.yzcdn.cn/vant/cat.jpeg",
|
try {
|
||||||
applications: 10,
|
if (follow) {
|
||||||
checkedApplications: 3,
|
await LoginService.unFollowUser(id);
|
||||||
levelRequirements: "NTRP 3.5",
|
} else {
|
||||||
playType: "双打",
|
await LoginService.followUser(id);
|
||||||
},
|
}
|
||||||
{
|
onUpdateUserInfo();
|
||||||
title: "黄浦全天对拉",
|
Taro.showToast({
|
||||||
time: "2025-08-25 9:00",
|
title: `${nickname} ${follow ? "已取消关注" : "已关注"}`,
|
||||||
timeLength: "12小时",
|
icon: "success",
|
||||||
venue: "上海体育场",
|
});
|
||||||
veuneType: "室外",
|
} catch (e) {
|
||||||
distance: "1.2km",
|
Taro.showToast({
|
||||||
avatar: "https://img.yzcdn.cn/vant/cat.jpeg",
|
title: `${nickname} ${follow ? "取消关注失败" : "关注失败"}`,
|
||||||
applications: 10,
|
icon: "error",
|
||||||
checkedApplications: 3,
|
});
|
||||||
levelRequirements: "NTRP 3.5",
|
}
|
||||||
playType: "双打",
|
};
|
||||||
},
|
|
||||||
];
|
|
||||||
return (
|
return (
|
||||||
<View className="detail-page-content-organizer-recommend-games">
|
<View className="detail-page-content-organizer-recommend-games">
|
||||||
{/* orgnizer title */}
|
{/* orgnizer title */}
|
||||||
@@ -767,26 +862,36 @@ function OrganizerInfo(props) {
|
|||||||
</View>
|
</View>
|
||||||
{/* organizer avatar and name */}
|
{/* organizer avatar and name */}
|
||||||
<View className="organizer-avatar-name">
|
<View className="organizer-avatar-name">
|
||||||
<Avatar
|
<Avatar className="organizer-avatar-name-avatar" src={avatar_url} />
|
||||||
className="organizer-avatar-name-avatar"
|
|
||||||
src="https://img.yzcdn.cn/vant/cat.jpeg"
|
|
||||||
/>
|
|
||||||
<View className="organizer-avatar-name-message">
|
<View className="organizer-avatar-name-message">
|
||||||
<Text className="organizer-avatar-name-message-name">Light</Text>
|
<Text className="organizer-avatar-name-message-name">{nickname}</Text>
|
||||||
<View className="organizer-avatar-name-message-stats">
|
<View className="organizer-avatar-name-message-stats">
|
||||||
<Text>已组织 8 次</Text>
|
<Text>已组织 {hosted_games_count} 次</Text>
|
||||||
<View className="organizer-avatar-name-message-stats-separator" />
|
<View className="organizer-avatar-name-message-stats-separator" />
|
||||||
<Text>NTRP 3.5</Text>
|
<Text>NTRP {ntrp_level || "初学者"}</Text>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
<View className="organizer-actions">
|
<View className="organizer-actions">
|
||||||
<View className="organizer-actions-follow">
|
{my_id === id ? (
|
||||||
|
""
|
||||||
|
) : (
|
||||||
|
<View
|
||||||
|
className="organizer-actions-follow"
|
||||||
|
onClick={toggleFollow.bind(null, is_following)}
|
||||||
|
>
|
||||||
|
{is_following ? (
|
||||||
|
<Text className="organizer-actions-follow-text">取消关注</Text>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
<Image
|
<Image
|
||||||
className="organizer-actions-follow-icon"
|
className="organizer-actions-follow-icon"
|
||||||
src={img.ICON_DETAIL_APPLICATION_ADD}
|
src={img.ICON_DETAIL_APPLICATION_ADD}
|
||||||
/>
|
/>
|
||||||
<Text className="organizer-actions-follow-text">关注</Text>
|
<Text className="organizer-actions-follow-text">关注</Text>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</View>
|
</View>
|
||||||
|
)}
|
||||||
<View className="organizer-actions-comment">
|
<View className="organizer-actions-comment">
|
||||||
<Image
|
<Image
|
||||||
className="organizer-actions-comment-icon"
|
className="organizer-actions-comment-icon"
|
||||||
@@ -797,7 +902,7 @@ function OrganizerInfo(props) {
|
|||||||
</View>
|
</View>
|
||||||
{/* recommend games by organizer */}
|
{/* recommend games by organizer */}
|
||||||
<View className="organizer-recommend-games">
|
<View className="organizer-recommend-games">
|
||||||
<View className="organizer-recommend-games-title">
|
<View className="organizer-recommend-games-title" onClick={() => {}}>
|
||||||
<Text>TA的更多活动</Text>
|
<Text>TA的更多活动</Text>
|
||||||
<Image
|
<Image
|
||||||
className="organizer-recommend-games-title-arrow"
|
className="organizer-recommend-games-title-arrow"
|
||||||
@@ -825,7 +930,7 @@ function OrganizerInfo(props) {
|
|||||||
<View className="recommend-games-list-item-location-venue-distance">
|
<View className="recommend-games-list-item-location-venue-distance">
|
||||||
<Text>{game.venue}</Text>
|
<Text>{game.venue}</Text>
|
||||||
<Text>·</Text>
|
<Text>·</Text>
|
||||||
<Text>{game.veuneType}</Text>
|
<Text>{game.venueType}</Text>
|
||||||
<Text>·</Text>
|
<Text>·</Text>
|
||||||
<Text>{game.distance}</Text>
|
<Text>{game.distance}</Text>
|
||||||
</View>
|
</View>
|
||||||
@@ -865,26 +970,31 @@ function Index() {
|
|||||||
0, 0,
|
0, 0,
|
||||||
]);
|
]);
|
||||||
const { id, from } = params;
|
const { id, from } = params;
|
||||||
const { fetchUserInfo, updateUserInfo } = useUserActions();
|
const [userInfo, setUserInfo] = useState({}); // 组织者的userInfo
|
||||||
|
const { fetchUserInfo } = useUserActions(); // 获取登录用户的userInfo
|
||||||
|
|
||||||
const sharePopupRef = useRef<any>(null);
|
const sharePopupRef = useRef<any>(null);
|
||||||
|
|
||||||
useDidShow(async () => {
|
useDidShow(async () => {
|
||||||
await updateLocation();
|
await updateLocation();
|
||||||
await fetchUserInfo();
|
await fetchUserInfo();
|
||||||
await fetchDetail();
|
// await fetchDetail();
|
||||||
});
|
});
|
||||||
|
|
||||||
const updateLocation = async () => {
|
const updateLocation = async () => {
|
||||||
try {
|
try {
|
||||||
const location = await getCurrentLocation()
|
const { address, ...location } = await getCurrentLocation();
|
||||||
setCurrentLocation([location.latitude, location.longitude])
|
setCurrentLocation([location.latitude, location.longitude]);
|
||||||
|
|
||||||
// 使用 userStore 中的统一位置更新方法
|
// 使用 userStore 中的统一位置更新方法
|
||||||
await updateUserInfo({ latitude: location.latitude, longitude: location.longitude })
|
// await updateUserInfo({ latitude: location.latitude, longitude: location.longitude })
|
||||||
|
await DetailService.updateLocation({
|
||||||
|
latitude: Number(location.latitude),
|
||||||
|
longitude: Number(location.longitude),
|
||||||
|
});
|
||||||
|
|
||||||
// 位置更新后,重新获取详情页数据(因为距离等信息可能发生变化)
|
// 位置更新后,重新获取详情页数据(因为距离等信息可能发生变化)
|
||||||
await fetchDetail()
|
await fetchDetail();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("用户位置更新失败", error);
|
console.error("用户位置更新失败", error);
|
||||||
}
|
}
|
||||||
@@ -895,9 +1005,22 @@ function Index() {
|
|||||||
const res = await DetailService.getDetail(Number(id));
|
const res = await DetailService.getDetail(Number(id));
|
||||||
if (res.code === 0) {
|
if (res.code === 0) {
|
||||||
setDetail(res.data);
|
setDetail(res.data);
|
||||||
|
fetchUserInfoById(res.data.publisher_id);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const onUpdateUserInfo = () => {
|
||||||
|
fetchUserInfoById(detail.publisher_id);
|
||||||
|
};
|
||||||
|
|
||||||
|
async function fetchUserInfoById(user_id) {
|
||||||
|
const userDetailInfo = await LoginService.getUserInfoById(Number(user_id));
|
||||||
|
if (userDetailInfo.code === 0) {
|
||||||
|
// console.log(userDetailInfo.data);
|
||||||
|
setUserInfo(userDetailInfo.data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function handleShare() {
|
function handleShare() {
|
||||||
sharePopupRef.current.show();
|
sharePopupRef.current.show();
|
||||||
}
|
}
|
||||||
@@ -965,7 +1088,12 @@ function Index() {
|
|||||||
{/* supplemental notes */}
|
{/* supplemental notes */}
|
||||||
<SupplementalNotes detail={detail} />
|
<SupplementalNotes detail={detail} />
|
||||||
{/* organizer and recommend games by organizer */}
|
{/* organizer and recommend games by organizer */}
|
||||||
<OrganizerInfo detail={detail} />
|
<OrganizerInfo
|
||||||
|
detail={detail}
|
||||||
|
userInfo={userInfo}
|
||||||
|
currentLocation={currentLocation}
|
||||||
|
onUpdateUserInfo={onUpdateUserInfo}
|
||||||
|
/>
|
||||||
{/* sticky bottom action bar */}
|
{/* sticky bottom action bar */}
|
||||||
<StickyButton
|
<StickyButton
|
||||||
handleShare={handleShare}
|
handleShare={handleShare}
|
||||||
|
|||||||
@@ -1,47 +1,120 @@
|
|||||||
import httpService from './httpService'
|
import httpService from "./httpService";
|
||||||
import type { ApiResponse } from './httpService'
|
import type { ApiResponse } from "./httpService";
|
||||||
|
|
||||||
// 用户接口
|
interface VenueImage {
|
||||||
export interface GameDetail {
|
id: string;
|
||||||
id: number,
|
url: string;
|
||||||
title: string,
|
}
|
||||||
venue_id: number,
|
|
||||||
creator_id: number,
|
interface Weather {
|
||||||
game_date: string,
|
fxDate: string;
|
||||||
start_time: string,
|
tempMax: string;
|
||||||
end_time: string,
|
tempMin: string;
|
||||||
max_participants: number,
|
iconDay: string;
|
||||||
current_participants: number,
|
textDay: string;
|
||||||
ntrp_level: string,
|
iconNight: string;
|
||||||
play_style: string,
|
textNight: string;
|
||||||
description: string,
|
humidity: string;
|
||||||
status: string,
|
}
|
||||||
created_at: string,
|
|
||||||
updated_at: string,
|
interface UserActionStatus {
|
||||||
|
can_assess: boolean;
|
||||||
|
can_join: boolean;
|
||||||
|
can_substitute: boolean;
|
||||||
|
can_pay: boolean;
|
||||||
|
waiting_start: boolean;
|
||||||
|
is_substituting: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GameData {
|
||||||
|
image_list: string[];
|
||||||
|
description_tag: string[];
|
||||||
|
start_time: string;
|
||||||
|
end_time: string;
|
||||||
|
venue_description_tag: string[];
|
||||||
|
venue_image_list: VenueImage[];
|
||||||
|
remark_tag: string[];
|
||||||
|
create_time: string;
|
||||||
|
last_modify_time: string;
|
||||||
|
id: number;
|
||||||
|
title: string;
|
||||||
|
description: string;
|
||||||
|
game_type: string;
|
||||||
|
play_type: string;
|
||||||
|
publisher_id: string;
|
||||||
|
venue_id: string;
|
||||||
|
max_players: number;
|
||||||
|
current_players: number;
|
||||||
|
price: string;
|
||||||
|
price_mode: string;
|
||||||
|
court_type: string;
|
||||||
|
court_surface: string;
|
||||||
|
gender_limit: string;
|
||||||
|
skill_level_min: string;
|
||||||
|
skill_level_max: string;
|
||||||
|
is_urgent: string;
|
||||||
|
is_substitute_supported: string;
|
||||||
|
max_substitute_players: number;
|
||||||
|
current_substitute_count: number;
|
||||||
|
is_wechat_contact: number;
|
||||||
|
wechat_contact: string;
|
||||||
|
privacy_level: string;
|
||||||
|
member_visibility: string;
|
||||||
|
match_status: number;
|
||||||
|
venue_description: string;
|
||||||
|
location_name: string;
|
||||||
|
location: string;
|
||||||
|
latitude: number;
|
||||||
|
longitude: number;
|
||||||
|
deadline_hours: number;
|
||||||
|
remark: string;
|
||||||
|
venue_dtl: any | null;
|
||||||
|
formal_members: any[];
|
||||||
|
substitute_members: any[];
|
||||||
|
participants: any[];
|
||||||
|
participant_count: number;
|
||||||
|
max_participants: number;
|
||||||
|
weather: Weather[];
|
||||||
|
user_action_status: UserActionStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum MATCH_STATUS {
|
export enum MATCH_STATUS {
|
||||||
NOT_STARTED = 0, // 未开始
|
NOT_STARTED = 0, // 未开始
|
||||||
IN_PROGRESS = 1, //进行中
|
IN_PROGRESS = 1, //进行中
|
||||||
FINISHED = 2 //已结束
|
FINISHED = 2, //已结束
|
||||||
}
|
}
|
||||||
|
|
||||||
// 响应接口
|
export interface UpdateLocationRes {
|
||||||
export interface Response {
|
latitude: number;
|
||||||
code: string
|
longitude: number;
|
||||||
message: string
|
country: string;
|
||||||
data: GameDetail
|
province: string;
|
||||||
|
city: string;
|
||||||
|
district: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 发布球局类
|
// 发布球局类
|
||||||
class GameDetailService {
|
class GameDetailService {
|
||||||
// 用户登录
|
// 用户登录
|
||||||
async getDetail(id: number): Promise<ApiResponse<Response>> {
|
async getDetail(id: number): Promise<ApiResponse<GameData>> {
|
||||||
return httpService.post('/games/detail', { id }, {
|
return httpService.post(
|
||||||
|
"/games/detail",
|
||||||
|
{ id },
|
||||||
|
{
|
||||||
showLoading: true,
|
showLoading: true,
|
||||||
})
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async updateLocation(location: {
|
||||||
|
latitude: number;
|
||||||
|
longitude: number;
|
||||||
|
}): Promise<ApiResponse<UpdateLocationRes>> {
|
||||||
|
return httpService.post("/user/update_location", location, {
|
||||||
|
showLoading: true,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 导出认证服务实例
|
// 导出认证服务实例
|
||||||
export default new GameDetailService()
|
export default new GameDetailService();
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import Taro from "@tarojs/taro";
|
import Taro from "@tarojs/taro";
|
||||||
import httpService, { ApiResponse } from "./httpService";
|
import httpService, { ApiResponse } from "./httpService";
|
||||||
import tokenManager from '../utils/tokenManager';
|
import tokenManager from "../utils/tokenManager";
|
||||||
import { useUser } from '@/store/userStore';
|
import { useUser } from "@/store/userStore";
|
||||||
|
|
||||||
// 微信用户信息接口
|
// 微信用户信息接口
|
||||||
export interface WechatUserInfo {
|
export interface WechatUserInfo {
|
||||||
@@ -49,7 +49,7 @@ export interface UserStats {
|
|||||||
export interface PhoneLoginParams {
|
export interface PhoneLoginParams {
|
||||||
phone: string;
|
phone: string;
|
||||||
verification_code: string;
|
verification_code: string;
|
||||||
user_code: string
|
user_code: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface UserInfoType {
|
export interface UserInfoType {
|
||||||
@@ -105,7 +105,7 @@ export const wechat_auth_login = async (
|
|||||||
try {
|
try {
|
||||||
await useUser.getState().fetchUserInfo();
|
await useUser.getState().fetchUserInfo();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('更新用户信息到 store 失败:', error);
|
console.error("更新用户信息到 store 失败:", error);
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -158,7 +158,7 @@ export const phone_auth_login = async (
|
|||||||
try {
|
try {
|
||||||
await useUser.getState().fetchUserInfo();
|
await useUser.getState().fetchUserInfo();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('更新用户信息到 store 失败:', error);
|
console.error("更新用户信息到 store 失败:", error);
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -410,4 +410,40 @@ export const updateUserPhone = async (payload: ChangePhoneParams) => {
|
|||||||
console.error("更新用户手机号失败:", error);
|
console.error("更新用户手机号失败:", error);
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
// 获取指定用户信息
|
||||||
|
export const getUserInfoById = async (id) => {
|
||||||
|
try {
|
||||||
|
const response = await httpService.post("/user/detail_by_id", { id });
|
||||||
|
return response;
|
||||||
|
} catch (error) {
|
||||||
|
console.error("获取用户信息失败:", error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 关注用户
|
||||||
|
export const followUser = async (following_id) => {
|
||||||
|
try {
|
||||||
|
const response = await httpService.post("/wch_users/follow", {
|
||||||
|
following_id,
|
||||||
|
});
|
||||||
|
return response;
|
||||||
|
} catch (error) {
|
||||||
|
console.error("关注失败:", error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 取消关注用户
|
||||||
|
export const unFollowUser = async (following_id) => {
|
||||||
|
try {
|
||||||
|
const response = await httpService.post("/wch_users/unfollow", {
|
||||||
|
following_id,
|
||||||
|
});
|
||||||
|
return response;
|
||||||
|
} catch (error) {
|
||||||
|
console.error("取消关注失败:", error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,90 +1,125 @@
|
|||||||
import httpService from './httpService'
|
import httpService from "./httpService";
|
||||||
import type { ApiResponse } from './httpService'
|
import type { ApiResponse } from "./httpService";
|
||||||
import { requestPayment } from '@tarojs/taro'
|
|
||||||
|
|
||||||
export interface SignType {
|
export interface SignType {
|
||||||
/** 仅在微信支付 v2 版本接口适用 */
|
/** 仅在微信支付 v2 版本接口适用 */
|
||||||
MD5
|
MD5;
|
||||||
/** 仅在微信支付 v2 版本接口适用 */
|
/** 仅在微信支付 v2 版本接口适用 */
|
||||||
'HMAC-SHA256'
|
"HMAC-SHA256";
|
||||||
/** 仅在微信支付 v3 版本接口适用 */
|
/** 仅在微信支付 v3 版本接口适用 */
|
||||||
RSA
|
RSA;
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum OrderStatus {
|
||||||
|
PENDING = 0,
|
||||||
|
PAID,
|
||||||
|
FINISHED,
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface PayMentParams {
|
export interface PayMentParams {
|
||||||
order_id: number,
|
order_id: number;
|
||||||
order_no: string,
|
order_no: string;
|
||||||
status: number,
|
status: number;
|
||||||
appId: string,
|
appId: string;
|
||||||
timeStamp: string,
|
timeStamp: string;
|
||||||
nonceStr: string,
|
nonceStr: string;
|
||||||
package: string,
|
package: string;
|
||||||
signType: keyof SignType,
|
signType: keyof SignType;
|
||||||
paySign: string
|
paySign: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 用户接口
|
// 用户接口
|
||||||
export interface OrderResponse {
|
export interface OrderResponse {
|
||||||
participant_id: number,
|
participant_id: number;
|
||||||
payment_required: boolean,
|
payment_required: boolean;
|
||||||
payment_params: PayMentParams
|
payment_params: PayMentParams;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface OrderInfo {
|
export interface OrderInfo {
|
||||||
time: string
|
time: string;
|
||||||
address: string
|
address: string;
|
||||||
registrant_nickname: string
|
registrant_nickname: string;
|
||||||
registrant_phone: string
|
registrant_phone: string;
|
||||||
cost: string
|
cost: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface RefundPolicy {
|
export interface RefundPolicy {
|
||||||
application_time: string
|
application_time: string;
|
||||||
refund_rule: string
|
refund_rule: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface GameStatus {
|
export interface GameStatus {
|
||||||
current_players: number
|
current_players: number;
|
||||||
max_players: number
|
max_players: number;
|
||||||
is_full: boolean
|
is_full: boolean;
|
||||||
can_join: boolean
|
can_join: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface GameDetails {
|
export interface GameDetails {
|
||||||
game_id: number
|
game_id: number;
|
||||||
game_title: string
|
game_title: string;
|
||||||
game_description: string
|
game_description: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface GameOrderRes {
|
export interface GameOrderRes {
|
||||||
order_info: OrderInfo
|
order_info: OrderInfo;
|
||||||
refund_policy: RefundPolicy[]
|
refund_policy: RefundPolicy[];
|
||||||
notice: string
|
notice: string;
|
||||||
game_status: GameStatus
|
game_status: GameStatus;
|
||||||
game_details: GameDetails
|
game_details: GameDetails;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// 发布球局类
|
// 发布球局类
|
||||||
class OrderService {
|
class OrderService {
|
||||||
// 查询订单列表
|
// 查询订单列表
|
||||||
async getOrderList() {
|
async getOrderList() {
|
||||||
return httpService.post('/user/orders', {}, { showLoading: true })
|
return httpService.post("/user/orders", {}, { showLoading: true });
|
||||||
}
|
|
||||||
// 创建订单
|
|
||||||
async createOrder(game_id: number): Promise<ApiResponse<OrderResponse>> {
|
|
||||||
return httpService.post('/payment/create_order', { game_id }, {
|
|
||||||
showLoading: true,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async getOrderInfo(game_id: number): Promise<ApiResponse<GameOrderRes>> {
|
// 获取订单详情
|
||||||
return httpService.post('/payment/check_order', { game_id }, {
|
async getOrderDetail(order_id: number): Promise<ApiResponse<any>> {
|
||||||
|
return httpService.post(
|
||||||
|
"/payment/order_details",
|
||||||
|
{ order_id },
|
||||||
|
{
|
||||||
showLoading: true,
|
showLoading: true,
|
||||||
})
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建订单
|
||||||
|
async createOrder(game_id: number): Promise<ApiResponse<OrderResponse>> {
|
||||||
|
return httpService.post(
|
||||||
|
"/payment/create_order",
|
||||||
|
{ game_id },
|
||||||
|
{
|
||||||
|
showLoading: true,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查订单信息
|
||||||
|
async getCheckOrderInfo(game_id: number): Promise<ApiResponse<GameOrderRes>> {
|
||||||
|
return httpService.post(
|
||||||
|
"/payment/check_order",
|
||||||
|
{ game_id },
|
||||||
|
{
|
||||||
|
showLoading: true,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取未支付订单
|
||||||
|
async getUnpaidOrder(game_id: number): Promise<ApiResponse<any>> {
|
||||||
|
return httpService.post(
|
||||||
|
"/payment/get_unpaid_order",
|
||||||
|
{ game_id },
|
||||||
|
{
|
||||||
|
showLoading: true,
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 导出认证服务实例
|
// 导出认证服务实例
|
||||||
export default new OrderService()
|
export default new OrderService();
|
||||||
|
|||||||
@@ -8333,6 +8333,11 @@ quick-lru@^4.0.1:
|
|||||||
resolved "https://registry.npmmirror.com/quick-lru/-/quick-lru-4.0.1.tgz#5b8878f113a58217848c6482026c73e1ba57727f"
|
resolved "https://registry.npmmirror.com/quick-lru/-/quick-lru-4.0.1.tgz#5b8878f113a58217848c6482026c73e1ba57727f"
|
||||||
integrity sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==
|
integrity sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==
|
||||||
|
|
||||||
|
qweather-icons@^1.8.0:
|
||||||
|
version "1.8.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/qweather-icons/-/qweather-icons-1.8.0.tgz#25eb2714d68daf13c06032c082f720e6734c4ecb"
|
||||||
|
integrity sha512-Ti7KGrWXSV7e5HMpjPhDYua8hwC3t0nScNOSQ3kLPehsOja5cioZw8bcKi7jeAGBlVLrgAkLla5xVEYlH1s5Jw==
|
||||||
|
|
||||||
randombytes@^2.1.0:
|
randombytes@^2.1.0:
|
||||||
version "2.1.0"
|
version "2.1.0"
|
||||||
resolved "https://registry.npmmirror.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a"
|
resolved "https://registry.npmmirror.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a"
|
||||||
|
|||||||
Reference in New Issue
Block a user