1
This commit is contained in:
128
config/env.ts
Normal file
128
config/env.ts
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
import Taro from '@tarojs/taro'
|
||||||
|
|
||||||
|
// 环境类型
|
||||||
|
export type EnvType = 'development' | 'production'
|
||||||
|
|
||||||
|
// 环境配置接口
|
||||||
|
export interface EnvConfig {
|
||||||
|
name: string
|
||||||
|
apiBaseURL: string
|
||||||
|
timeout: number
|
||||||
|
enableLog: boolean
|
||||||
|
enableMock: boolean
|
||||||
|
// 客服配置
|
||||||
|
customerService: {
|
||||||
|
corpId: string
|
||||||
|
serviceUrl: string
|
||||||
|
phoneNumber?: string
|
||||||
|
email?: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 各环境配置
|
||||||
|
const envConfigs: Record<EnvType, EnvConfig> = {
|
||||||
|
|
||||||
|
|
||||||
|
// 开发环境
|
||||||
|
development: {
|
||||||
|
name: '开发环境',
|
||||||
|
// apiBaseURL: 'https://tennis.bimwe.com',
|
||||||
|
apiBaseURL: 'http://localhost:9098',
|
||||||
|
timeout: 15000,
|
||||||
|
enableLog: true,
|
||||||
|
enableMock: false,
|
||||||
|
// 客服配置
|
||||||
|
customerService: {
|
||||||
|
corpId: 'ww51fc969e8b76af82', // 企业ID
|
||||||
|
serviceUrl: 'https://work.weixin.qq.com/kfid/kfc64085b93243c5c91',
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// 生产环境1
|
||||||
|
// production: {
|
||||||
|
// name: '生产环境1',
|
||||||
|
// apiBaseURL: 'https://tennis.bimwe.com',
|
||||||
|
// timeout: 10000,
|
||||||
|
// enableLog: false,
|
||||||
|
// enableMock: false,
|
||||||
|
// // 客服配置
|
||||||
|
// customerService: {
|
||||||
|
// corpId: 'ww51fc969e8b76af82', // 企业ID
|
||||||
|
// serviceUrl: 'https://work.weixin.qq.com/kfid/kfc64085b93243c5c91',
|
||||||
|
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
|
||||||
|
// 生产环境2
|
||||||
|
production: {
|
||||||
|
name: '生产环境2',
|
||||||
|
apiBaseURL: 'https://youchang.qiongjingtiyu.com',
|
||||||
|
timeout: 10000,
|
||||||
|
enableLog: false,
|
||||||
|
enableMock: false,
|
||||||
|
// 客服配置
|
||||||
|
customerService: {
|
||||||
|
corpId: 'ww9a2d9a5d9410c664', // 企业ID
|
||||||
|
serviceUrl: 'https://work.weixin.qq.com/kfid/kfcd355e162e0390684',
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取当前环境
|
||||||
|
export const getCurrentEnv = (): EnvType => {
|
||||||
|
// 在小程序环境中,使用默认逻辑判断环境
|
||||||
|
// 可以根据实际需要配置不同的判断逻辑
|
||||||
|
|
||||||
|
// 可以根据实际部署情况添加更多判断逻辑
|
||||||
|
// 比如通过 Taro.getEnv() 获取当前平台环境
|
||||||
|
|
||||||
|
const isProd = process.env.NODE_ENV === 'production'
|
||||||
|
if (isProd) {
|
||||||
|
return 'production'
|
||||||
|
} else {
|
||||||
|
return 'development'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取当前环境配置
|
||||||
|
export const getCurrentConfig = (): EnvConfig => {
|
||||||
|
const env = getCurrentEnv()
|
||||||
|
return envConfigs[env]
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取指定环境配置
|
||||||
|
export const getEnvConfig = (env: EnvType): EnvConfig => {
|
||||||
|
return envConfigs[env]
|
||||||
|
}
|
||||||
|
|
||||||
|
// 是否为开发环境
|
||||||
|
export const isDevelopment = (): boolean => {
|
||||||
|
return getCurrentEnv() === 'development'
|
||||||
|
}
|
||||||
|
|
||||||
|
// 是否为生产环境
|
||||||
|
export const isProduction = (): boolean => {
|
||||||
|
return getCurrentEnv() === 'production'
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// 环境配置调试信息
|
||||||
|
export const getEnvInfo = () => {
|
||||||
|
const config = getCurrentConfig()
|
||||||
|
return {
|
||||||
|
env: getCurrentEnv(),
|
||||||
|
config,
|
||||||
|
taroEnv: Taro.getEnv(),
|
||||||
|
platform: Taro.getEnv() === Taro.ENV_TYPE.WEAPP ? '微信小程序' :
|
||||||
|
Taro.getEnv() === Taro.ENV_TYPE.WEB ? 'Web' :
|
||||||
|
Taro.getEnv() === Taro.ENV_TYPE.RN ? 'React Native' : '未知'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 导出当前环境配置(方便直接使用)
|
||||||
|
export default getCurrentConfig()
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { View, Text, Button, Image } from "@tarojs/components";
|
import { View, Text, Button, Image } from "@tarojs/components";
|
||||||
import Taro, { useRouter } from "@tarojs/taro";
|
import Taro, { useRouter } from "@tarojs/taro";
|
||||||
|
import { GeneralNavbar } from "@/components";
|
||||||
import {
|
import {
|
||||||
wechat_auth_login,
|
wechat_auth_login,
|
||||||
save_login_state,
|
save_login_state,
|
||||||
@@ -171,6 +172,8 @@ const LoginPage: React.FC = () => {
|
|||||||
<View className="bg_overlay"></View>
|
<View className="bg_overlay"></View>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
|
<GeneralNavbar title="" showBack={true} showAvatar={false} onBack={handle_return_home} />
|
||||||
|
|
||||||
{/* 主要内容 */}
|
{/* 主要内容 */}
|
||||||
<View className="login_main_content">
|
<View className="login_main_content">
|
||||||
{/* 品牌区域 */}
|
{/* 品牌区域 */}
|
||||||
@@ -216,9 +219,9 @@ const LoginPage: React.FC = () => {
|
|||||||
<Text className="button_text">手机号快捷登录</Text>
|
<Text className="button_text">手机号快捷登录</Text>
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<View className="return_home_button link_button" onClick={handle_return_home}>
|
{/* <View className="return_home_button link_button" onClick={handle_return_home}>
|
||||||
<Text className="button_text">返回首页</Text>
|
<Text className="button_text">返回首页</Text>
|
||||||
</View>
|
</View> */}
|
||||||
|
|
||||||
{/* 用户协议复选框 */}
|
{/* 用户协议复选框 */}
|
||||||
<View className="terms_checkbox_section">
|
<View className="terms_checkbox_section">
|
||||||
|
|||||||
@@ -65,20 +65,22 @@ const MyselfPageContent: React.FC<MyselfPageContentProps> = ({ isActive = true }
|
|||||||
game_records: TennisMatch[]
|
game_records: TennisMatch[]
|
||||||
): { notEndGames: TennisMatch[]; finishedGames: TennisMatch[] } => {
|
): { notEndGames: TennisMatch[]; finishedGames: TennisMatch[] } => {
|
||||||
const now = new Date().getTime();
|
const now = new Date().getTime();
|
||||||
return game_records.reduce(
|
|
||||||
(result, cur) => {
|
// 使用for
|
||||||
let { end_time } = cur;
|
const notEndGames: TennisMatch[] = [];
|
||||||
end_time = end_time.replace(/\s/, "T");
|
const finishedGames: TennisMatch[] = [];
|
||||||
new Date(end_time).getTime() > now
|
for (const game of game_records) {
|
||||||
? result.notEndGames.push(cur)
|
const { end_time } = game;
|
||||||
: result.finishedGames.push(cur);
|
const end_time_str = end_time.replace(/\s/, "T");
|
||||||
return result;
|
new Date(end_time_str).getTime() > now
|
||||||
},
|
? notEndGames.push(game)
|
||||||
{
|
: finishedGames.push(game);
|
||||||
notEndGames: [] as TennisMatch[],
|
}
|
||||||
finishedGames: [] as TennisMatch[],
|
|
||||||
}
|
console.log("notEndGames", notEndGames);
|
||||||
);
|
|
||||||
|
return { notEndGames, finishedGames };
|
||||||
|
|
||||||
},
|
},
|
||||||
[]
|
[]
|
||||||
);
|
);
|
||||||
@@ -95,6 +97,8 @@ const MyselfPageContent: React.FC<MyselfPageContentProps> = ({ isActive = true }
|
|||||||
} else {
|
} else {
|
||||||
games_data = await UserService.get_participated_games(user_info.id);
|
games_data = await UserService.get_participated_games(user_info.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const sorted_games = games_data.sort((a, b) => {
|
const sorted_games = games_data.sort((a, b) => {
|
||||||
return (
|
return (
|
||||||
new Date(a.original_start_time.replace(/\s/, "T")).getTime() -
|
new Date(a.original_start_time.replace(/\s/, "T")).getTime() -
|
||||||
@@ -102,6 +106,8 @@ const MyselfPageContent: React.FC<MyselfPageContentProps> = ({ isActive = true }
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
const { notEndGames, finishedGames } = classifyGameRecords(sorted_games);
|
const { notEndGames, finishedGames } = classifyGameRecords(sorted_games);
|
||||||
|
console.log("notEndGames", notEndGames);
|
||||||
|
|
||||||
set_game_records(notEndGames);
|
set_game_records(notEndGames);
|
||||||
setEndedGameRecords(finishedGames);
|
setEndedGameRecords(finishedGames);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -250,17 +256,15 @@ const MyselfPageContent: React.FC<MyselfPageContentProps> = ({ isActive = true }
|
|||||||
<View className={styles.gameTabsSection}>
|
<View className={styles.gameTabsSection}>
|
||||||
<View className={styles.tabContainer}>
|
<View className={styles.tabContainer}>
|
||||||
<View
|
<View
|
||||||
className={`${styles.tabItem} ${
|
className={`${styles.tabItem} ${active_tab === "hosted" ? styles.active : ""
|
||||||
active_tab === "hosted" ? styles.active : ""
|
}`}
|
||||||
}`}
|
|
||||||
onClick={() => setActiveTab("hosted")}
|
onClick={() => setActiveTab("hosted")}
|
||||||
>
|
>
|
||||||
<Text className={styles.tabText}>我主办的</Text>
|
<Text className={styles.tabText}>我主办的</Text>
|
||||||
</View>
|
</View>
|
||||||
<View
|
<View
|
||||||
className={`${styles.tabItem} ${
|
className={`${styles.tabItem} ${active_tab === "participated" ? styles.active : ""
|
||||||
active_tab === "participated" ? styles.active : ""
|
}`}
|
||||||
}`}
|
|
||||||
onClick={() => setActiveTab("participated")}
|
onClick={() => setActiveTab("participated")}
|
||||||
>
|
>
|
||||||
<Text className={styles.tabText}>我参与的</Text>
|
<Text className={styles.tabText}>我参与的</Text>
|
||||||
@@ -281,7 +285,7 @@ const MyselfPageContent: React.FC<MyselfPageContentProps> = ({ isActive = true }
|
|||||||
btnImg="ICON_ADD"
|
btnImg="ICON_ADD"
|
||||||
reload={goPublish}
|
reload={goPublish}
|
||||||
isShowNoData={game_records.length === 0}
|
isShowNoData={game_records.length === 0}
|
||||||
loadMoreMatches={() => {}}
|
loadMoreMatches={() => { }}
|
||||||
collapse={true}
|
collapse={true}
|
||||||
style={{
|
style={{
|
||||||
paddingBottom: ended_game_records.length ? 0 : "90px",
|
paddingBottom: ended_game_records.length ? 0 : "90px",
|
||||||
@@ -308,7 +312,7 @@ const MyselfPageContent: React.FC<MyselfPageContentProps> = ({ isActive = true }
|
|||||||
error={null}
|
error={null}
|
||||||
errorImg="ICON_LIST_EMPTY_CARD"
|
errorImg="ICON_LIST_EMPTY_CARD"
|
||||||
isShowNoData={ended_game_records.length === 0}
|
isShowNoData={ended_game_records.length === 0}
|
||||||
loadMoreMatches={() => {}}
|
loadMoreMatches={() => { }}
|
||||||
collapse={true}
|
collapse={true}
|
||||||
style={{ paddingBottom: "90px", overflow: "hidden" }}
|
style={{ paddingBottom: "90px", overflow: "hidden" }}
|
||||||
listLoadErrorWrapperHeight="fit-content"
|
listLoadErrorWrapperHeight="fit-content"
|
||||||
|
|||||||
@@ -249,7 +249,7 @@ const CommentReply = () => {
|
|||||||
<View className="comment-left">
|
<View className="comment-left">
|
||||||
<Image
|
<Image
|
||||||
className="user-avatar"
|
className="user-avatar"
|
||||||
src={item.user_avatar || "https://img.yzcdn.cn/vant/cat.jpeg"}
|
src={item.user_avatar }
|
||||||
mode="aspectFill"
|
mode="aspectFill"
|
||||||
onClick={(e) => handleUserClick(e, item.user_id)}
|
onClick={(e) => handleUserClick(e, item.user_id)}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -151,6 +151,7 @@ interface BackendGameData {
|
|||||||
longitude: string;
|
longitude: string;
|
||||||
venue_type: string;
|
venue_type: string;
|
||||||
surface_type: string;
|
surface_type: string;
|
||||||
|
distance_km: string;
|
||||||
};
|
};
|
||||||
participants: {
|
participants: {
|
||||||
user: {
|
user: {
|
||||||
@@ -206,7 +207,7 @@ export class UserService {
|
|||||||
latitude = parseFloat(game.venue_dtl.latitude) || latitude;
|
latitude = parseFloat(game.venue_dtl.latitude) || latitude;
|
||||||
longitude = parseFloat(game.venue_dtl.longitude) || longitude;
|
longitude = parseFloat(game.venue_dtl.longitude) || longitude;
|
||||||
}
|
}
|
||||||
const distance = this.calculate_distance(latitude, longitude);
|
|
||||||
|
|
||||||
// 处理地点信息 - 优先使用venue_dtl中的信息
|
// 处理地点信息 - 优先使用venue_dtl中的信息
|
||||||
let location = game.location_name || game.location || "未知地点";
|
let location = game.location_name || game.location || "未知地点";
|
||||||
@@ -227,7 +228,7 @@ export class UserService {
|
|||||||
original_start_time: game.start_time,
|
original_start_time: game.start_time,
|
||||||
end_time: game.end_time || "",
|
end_time: game.end_time || "",
|
||||||
location: location,
|
location: location,
|
||||||
distance_km: parseFloat(distance.replace("km", "")) || 0,
|
distance_km: game.venue_dtl?.distance_km ,
|
||||||
current_players: registered_count,
|
current_players: registered_count,
|
||||||
max_players: max_count,
|
max_players: max_count,
|
||||||
skill_level_min: parseInt(game.skill_level_min) || 0,
|
skill_level_min: parseInt(game.skill_level_min) || 0,
|
||||||
@@ -303,20 +304,7 @@ export class UserService {
|
|||||||
return `${date_str} ${time_str}`;
|
return `${date_str} ${time_str}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 计算距离(模拟实现,实际需要根据用户位置计算)
|
|
||||||
private static calculate_distance(
|
|
||||||
latitude: number,
|
|
||||||
longitude: number
|
|
||||||
): string {
|
|
||||||
if (latitude === 0 && longitude === 0) {
|
|
||||||
return "未知距离";
|
|
||||||
}
|
|
||||||
|
|
||||||
// 这里应该根据用户当前位置计算实际距离
|
|
||||||
// 暂时返回模拟距离
|
|
||||||
const distances = ["1.2km", "2.5km", "3.8km", "5.1km", "7.3km"];
|
|
||||||
return distances[Math.floor(Math.random() * distances.length)];
|
|
||||||
}
|
|
||||||
// 获取用户信息
|
// 获取用户信息
|
||||||
static async get_user_info(user_id?: string): Promise<UserInfo> {
|
static async get_user_info(user_id?: string): Promise<UserInfo> {
|
||||||
try {
|
try {
|
||||||
|
|||||||
Reference in New Issue
Block a user