This commit is contained in:
张成
2025-09-07 10:21:27 +08:00
parent 4c36986ade
commit 9830cd4b2d
4 changed files with 223 additions and 63 deletions

View File

@@ -17,52 +17,7 @@
overflow-y: auto; overflow-y: auto;
padding: 15px; padding: 15px;
// 头部操作栏
.header_section {
display: flex;
align-items: center;
justify-content: space-between;
padding: 10px 0 20px;
margin-bottom: 20px;
.back_button {
width: 40px;
height: 40px;
background: transparent;
border: none;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
.back_icon {
width: 24px;
height: 24px;
}
}
.page_title {
font-family: 'PingFang SC';
font-weight: 600;
font-size: 18px;
line-height: 1.4em;
color: #000000;
}
.save_button {
background: transparent;
border: none;
cursor: pointer;
.save_text {
font-family: 'PingFang SC';
font-weight: 600;
font-size: 16px;
line-height: 1.4em;
color: #000000;
}
}
}
// 头像编辑区域 // 头像编辑区域
.avatar_section { .avatar_section {
@@ -71,6 +26,7 @@
align-items: center; align-items: center;
gap: 12px; gap: 12px;
margin-bottom: 30px; margin-bottom: 30px;
margin-top: 98px;
.avatar_container { .avatar_container {
position: relative; position: relative;

View File

@@ -152,19 +152,6 @@ const EditProfilePage: React.FC = () => {
</View> </View>
) : ( ) : (
<> <>
{/* 头部操作栏 */}
<View className="header_section">
<Button className="back_button" onClick={handle_back}>
<Image
className="back_icon"
src={require('../../../static/detail/icon-arrow-left.svg')}
/>
</Button>
<Text className="page_title"></Text>
<Button className="save_button" onClick={handle_save}>
<Text className="save_text"></Text>
</Button>
</View>
{/* 头像编辑区域 */} {/* 头像编辑区域 */}
<View className="avatar_section"> <View className="avatar_section">
@@ -173,7 +160,7 @@ const EditProfilePage: React.FC = () => {
<View className="avatar_overlay"> <View className="avatar_overlay">
<Image <Image
className="upload_icon" className="upload_icon"
src={require('../../../static/publishBall/icon-upload.svg')} src={require('../../../static/userinfo/icon_upload.svg')}
/> />
</View> </View>
</View> </View>

View File

@@ -83,8 +83,166 @@ interface UploadResponseData {
}; };
} }
// 后端球局数据接口
interface BackendGameData {
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;
start_time: string;
end_time: string;
location_name: string | null;
location: string;
latitude?: number;
longitude?: number;
image_list?: string[];
description_tag?: string[];
venue_description_tag?: string[];
venue_image_list?: Array<{ id: string; url: string }>;
participant_count: number;
max_participants: number;
participant_info?: {
id: number;
status: string;
payment_status: string;
joined_at: string;
deposit_amount: number;
join_message: string;
skill_level: string;
contact_info: string;
};
venue_dtl?: {
id: number;
name: string;
address: string;
latitude: string;
longitude: string;
venue_type: string;
surface_type: string;
};
}
// 用户服务类 // 用户服务类
export class UserService { export class UserService {
// 数据转换函数将后端数据转换为ListContainer期望的格式
private static transform_game_data(backend_data: BackendGameData[]): any[] {
return backend_data.map(game => {
// 处理时间格式
const start_time = new Date(game.start_time);
const date_time = this.format_date_time(start_time);
// 处理技能等级
const skill_level = this.format_skill_level(game.skill_level_min, game.skill_level_max);
// 处理图片数组 - 兼容两种数据格式
let images: string[] = [];
if (game.image_list && game.image_list.length > 0) {
images = game.image_list.filter(img => img && img.trim() !== '');
} else if (game.venue_image_list && game.venue_image_list.length > 0) {
images = game.venue_image_list
.filter(img => img && img.url && img.url.trim() !== '')
.map(img => img.url);
}
// 处理距离 - 优先使用venue_dtl中的坐标其次使用game中的坐标
let latitude = game.latitude || 0;
let longitude = game.longitude || 0;
if (game.venue_dtl) {
latitude = parseFloat(game.venue_dtl.latitude) || latitude;
longitude = parseFloat(game.venue_dtl.longitude) || longitude;
}
const distance = this.calculate_distance(latitude, longitude);
// 处理地点信息 - 优先使用venue_dtl中的信息
let location = game.location_name || game.location || '未知地点';
if (game.venue_dtl && game.venue_dtl.name) {
location = game.venue_dtl.name;
}
// 处理人数统计 - 兼容不同的字段名
const registered_count = game.current_players || game.participant_count || 0;
const max_count = game.max_players || game.max_participants || 0;
return {
id: game.id,
title: game.title || '未命名球局',
dateTime: date_time,
location: location,
distance: distance,
registeredCount: registered_count,
maxCount: max_count,
skillLevel: skill_level,
matchType: game.play_type || '不限',
images: images,
shinei: game.court_type || '未知'
};
});
}
// 格式化时间显示
private static format_date_time(start_time: Date): string {
const now = new Date();
const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
const tomorrow = new Date(today.getTime() + 24 * 60 * 60 * 1000);
const day_after_tomorrow = new Date(today.getTime() + 2 * 24 * 60 * 60 * 1000);
const start_date = new Date(start_time.getFullYear(), start_time.getMonth(), start_time.getDate());
let date_str = '';
if (start_date.getTime() === today.getTime()) {
date_str = '今天';
} else if (start_date.getTime() === tomorrow.getTime()) {
date_str = '明天';
} else if (start_date.getTime() === day_after_tomorrow.getTime()) {
date_str = '后天';
} else {
const weekdays = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'];
date_str = weekdays[start_time.getDay()];
}
const time_str = `${start_time.getHours().toString().padStart(2, '0')}:${start_time.getMinutes().toString().padStart(2, '0')}`;
return `${date_str} ${time_str}`;
}
// 格式化技能等级
private static format_skill_level(min: string, max: string): string {
const min_num = parseInt(min) || 0;
const max_num = parseInt(max) || 0;
if (min_num === 0 && max_num === 0) {
return '不限';
}
if (min_num === max_num) {
return `${min_num}.0`;
}
return `${min_num}.0-${max_num}.0`;
}
// 计算距离(模拟实现,实际需要根据用户位置计算)
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 {
@@ -157,13 +315,14 @@ export class UserService {
}); });
if (response.code === 0) { if (response.code === 0) {
return response.data.rows || []; // 使用数据转换函数将后端数据转换为ListContainer期望的格式
return this.transform_game_data(response.data.rows || []);
} else { } else {
throw new Error(response.message || '获取主办球局失败'); throw new Error(response.message || '获取主办球局失败');
} }
} catch (error) { } catch (error) {
console.error('获取主办球局失败:', error); console.error('获取主办球局失败:', error);
// 返回模拟数据 // 返回符合ListContainer data格式的模拟数据
return [ return [
{ {
id: 1, id: 1,
@@ -181,6 +340,22 @@ export class UserService {
require('../static/userInfo/game3.svg') require('../static/userInfo/game3.svg')
], ],
shinei: '室外' shinei: '室外'
},
{
id: 5,
title: '新手友好局',
dateTime: '周日 下午2点',
location: '徐汇网球中心',
distance: '1.8km',
registeredCount: 4,
maxCount: 6,
skillLevel: '1.5-2.0',
matchType: '双打',
images: [
require('../static/userInfo/game1.svg'),
require('../static/userInfo/game2.svg')
],
shinei: '室外'
} }
]; ];
} }
@@ -197,13 +372,14 @@ export class UserService {
}); });
if (response.code === 0) { if (response.code === 0) {
return response.data.rows || []; // 使用数据转换函数将后端数据转换为ListContainer期望的格式
return this.transform_game_data(response.data.rows || []);
} else { } else {
throw new Error(response.message || '获取参与球局失败'); throw new Error(response.message || '获取参与球局失败');
} }
} catch (error) { } catch (error) {
console.error('获取参与球局失败:', error); console.error('获取参与球局失败:', error);
// 返回模拟数据 // 返回符合ListContainer data格式的模拟数据
return [ return [
{ {
id: 2, id: 2,
@@ -220,6 +396,38 @@ export class UserService {
require('../static/userInfo/game3.svg') require('../static/userInfo/game3.svg')
], ],
shinei: '室内' shinei: '室内'
},
{
id: 3,
title: '晨练单打',
dateTime: '明天(周五) 早上7点',
location: '浦东网球俱乐部',
distance: '2.8km',
registeredCount: 1,
maxCount: 2,
skillLevel: '2.5-3.0',
matchType: '单打',
images: [
require('../static/userInfo/game1.svg')
],
shinei: '室外'
},
{
id: 4,
title: '夜场混双',
dateTime: '今晚 晚上8点',
location: '虹桥网球中心',
distance: '4.1km',
registeredCount: 3,
maxCount: 4,
skillLevel: '3.5-4.0',
matchType: '混双',
images: [
require('../static/userInfo/game1.svg'),
require('../static/userInfo/game2.svg'),
require('../static/userInfo/game3.svg')
],
shinei: '室内'
} }
]; ];
} }

View File

@@ -0,0 +1,9 @@
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="32" height="32" rx="16" fill="black"/>
<rect x="0.25" y="0.25" width="31.5" height="31.5" rx="15.75" stroke="black" stroke-opacity="0.06" stroke-width="0.5"/>
<path d="M22.6666 16C22.6666 15.6318 22.3681 15.3333 21.9999 15.3333C21.6317 15.3333 21.3333 15.6318 21.3333 16H22.6666ZM15.9999 10.6667C16.3681 10.6667 16.6666 10.3682 16.6666 10C16.6666 9.63182 16.3681 9.33334 15.9999 9.33334V10.6667ZM20.9999 21.3333H10.9999V22.6667H20.9999V21.3333ZM10.6666 21V11H9.33325V21H10.6666ZM21.3333 16V21H22.6666V16H21.3333ZM10.9999 10.6667H15.9999V9.33334H10.9999V10.6667ZM10.9999 21.3333C10.8158 21.3333 10.6666 21.1841 10.6666 21H9.33325C9.33325 21.9205 10.0794 22.6667 10.9999 22.6667V21.3333ZM20.9999 22.6667C21.9204 22.6667 22.6666 21.9205 22.6666 21H21.3333C21.3333 21.1841 21.184 21.3333 20.9999 21.3333V22.6667ZM10.6666 11C10.6666 10.8159 10.8158 10.6667 10.9999 10.6667V9.33334C10.0794 9.33334 9.33325 10.0795 9.33325 11H10.6666Z" fill="white"/>
<path d="M10 19.6667L13.5644 16.3993C13.813 16.1714 14.1926 16.1651 14.4487 16.3846L18.6667 20" stroke="white" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M17.3333 18.3333L18.9244 16.7422C19.159 16.5076 19.5304 16.4812 19.7958 16.6803L21.9999 18.3333" stroke="white" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M18 12H22" stroke="white" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M20 10V14" stroke="white" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB