他人页

This commit is contained in:
2025-09-15 17:30:48 +08:00
parent 91636855aa
commit 7a0bc71f9f
10 changed files with 227 additions and 167 deletions

View File

@@ -1,10 +1,10 @@
import React, { useState } from 'react';
import Taro from '@tarojs/taro';
import { View, Text, Image, Button } from '@tarojs/components';
import './index.scss';
import React, { useState } from "react";
import Taro from "@tarojs/taro";
import { View, Text, Image, Button } from "@tarojs/components";
import "./index.scss";
import { EditModal } from '@/components';
import { UserService } from '@/services/userService';
import { EditModal } from "@/components";
import { UserService } from "@/services/userService";
// 用户信息接口
export interface UserInfo {
@@ -33,7 +33,6 @@ export interface UserInfo {
ongoing_games?: string[];
}
// 用户信息卡片组件属性
interface UserInfoCardProps {
user_info: UserInfo;
@@ -45,11 +44,10 @@ interface UserInfoCardProps {
set_user_info?: (info: UserInfo) => void;
}
// 处理编辑用户信息
const on_edit = () => {
Taro.navigateTo({
url: '/user_pages/edit/index'
url: "/user_pages/edit/index",
});
};
// 用户信息卡片组件
@@ -62,17 +60,17 @@ export const UserInfoCard: React.FC<UserInfoCardProps> = ({
on_share,
set_user_info,
}) => {
console.log("用户信息:", user_info);
console.log("UserInfoCard 用户信息:", user_info);
// 编辑个人简介弹窗状态
const [edit_modal_visible, setEditModalVisible] = useState(false);
const [editing_field, setEditingField] = useState<string>('');
const [editing_field, setEditingField] = useState<string>("");
// 表单状态
const [form_data, setFormData] = useState<UserInfo>({...user_info});
const [form_data, setFormData] = useState<UserInfo>({ ...user_info });
// 处理编辑弹窗
const handle_open_edit_modal = (field: string) => {
if (field === 'nickname') {
if (field === "nickname") {
// 手动输入
setEditingField(field);
setEditModalVisible(true);
@@ -88,33 +86,33 @@ export const UserInfoCard: React.FC<UserInfoCardProps> = ({
await UserService.update_user_info(update_data);
// 更新本地状态
setFormData(prev => {
setFormData((prev) => {
const updated = { ...prev, [editing_field]: value };
typeof set_user_info === 'function' && set_user_info(updated);
typeof set_user_info === "function" && set_user_info(updated);
return updated;
});
// 关闭弹窗
setEditModalVisible(false);
setEditingField('');
setEditingField("");
// 显示成功提示
Taro.showToast({
title: '保存成功',
icon: 'success'
title: "保存成功",
icon: "success",
});
} catch (error) {
console.error('保存失败:', error);
console.error("保存失败:", error);
Taro.showToast({
title: '保存失败',
icon: 'error'
title: "保存失败",
icon: "error",
});
}
};
const handle_edit_modal_cancel = () => {
setEditModalVisible(false);
setEditingField('');
setEditingField("");
};
return (
@@ -128,11 +126,14 @@ export const UserInfoCard: React.FC<UserInfoCardProps> = ({
<Text className="nickname">{user_info.nickname}</Text>
<Text className="join_date">{user_info.join_date}</Text>
</View>
<View className='tag_item' onClick={on_edit}>
<Image
className="tag_icon"
src={require('../../static/userInfo/edit.svg')}
/> </View>
{is_current_user && (
<View className="tag_item" onClick={on_edit}>
<Image
className="tag_icon"
src={require("../../static/userInfo/edit.svg")}
/>
</View>
)}
</View>
{/* 统计数据 */}
@@ -159,15 +160,17 @@ export const UserInfoCard: React.FC<UserInfoCardProps> = ({
{/* 只有非当前用户才显示关注按钮 */}
{!is_current_user && on_follow && (
<Button
className={`follow_button ${is_following ? 'following' : ''}`}
className={`follow_button ${is_following ? "following" : ""}`}
onClick={on_follow}
>
<Image
className="button_icon"
src={require('../../static/userInfo/plus.svg')}
src={require(is_following
? "@/static/userInfo/following.svg"
: "@/static/userInfo/unfollow.svg")}
/>
<Text className="button_text">
{is_following ? '已关注' : '关注'}
{is_following ? "已关注" : "关注"}
</Text>
</Button>
)}
@@ -176,7 +179,7 @@ export const UserInfoCard: React.FC<UserInfoCardProps> = ({
<Button className="message_button" onClick={on_message}>
<Image
className="button_icon"
src={require('../../static/userInfo/message.svg')}
src={require("@/static/userInfo/chat.svg")}
/>
</Button>
)}
@@ -193,74 +196,69 @@ export const UserInfoCard: React.FC<UserInfoCardProps> = ({
{/* 标签和简介 */}
<View className="tags_bio_section">
<View className="tags_container">
<View className="tag_item">
{user_info.gender === "0" && (
<Image
className="tag_icon"
src={require('../../static/userInfo/male.svg')}
/>
)}
{user_info.gender === "1" && (
<Image
className="tag_icon"
src={require('../../static/userInfo/female.svg')}
/>
)}
{
!user_info.gender && (
<View className='button_edit'>
<Text></Text>
</View>
)
}
</View>
{user_info.ntrp_level ?
{user_info.gender ? (
<View className="tag_item">
{user_info.gender === "0" && (
<Image
className="tag_icon"
src={require("../../static/userInfo/male.svg")}
/>
)}
{user_info.gender === "1" && (
<Image
className="tag_icon"
src={require("../../static/userInfo/female.svg")}
/>
)}
</View>
) : is_current_user ? (
<View className="button_edit">
<Text></Text>
</View>
) : null}
{user_info.ntrp_level ? (
<View className="tag_item">
{/* <Image
className="tag_icon"
src={require('../../static/userInfo/level.svg')}
/> */}
<Text className="tag_text">{user_info.ntrp_level}</Text>
</View> :
</View>
) : is_current_user ? (
<View className="button_edit">
<Text>NTRP水平</Text>
</View>
}
{user_info.occupation ?
) : null}
{user_info.occupation ? (
<View className="tag_item">
<Text className="tag_text">{user_info.occupation}</Text>
</View> :
</View>
) : is_current_user ? (
<View className="button_edit">
<Text></Text>
</View>
}
{user_info.location ?
) : null}
{user_info.location ? (
<View className="tag_item">
{/* <Image
className="tag_icon"
src={require('../../static/userInfo/location.svg')}
/> */}
<Text className="tag_text">{user_info.location}</Text>
</View> :
</View>
) : is_current_user ? (
<View className="button_edit">
<Text></Text>
</View>
}
) : null}
</View>
<View className="personal_profile">
{
user_info.personal_profile ? (
<Text className="bio_text">{user_info.personal_profile}</Text>
) : (
<View className='personal_profile_edit' onClick={() => handle_open_edit_modal('personal_profile')}>
<Image
className="edit_icon"
src={require('../../static/userInfo/info_edit.svg')}
/>
<Text className="bio_text"></Text>
</View>
)
}
{user_info.personal_profile ? (
<Text className="bio_text">{user_info.personal_profile}</Text>
) : is_current_user ? (
<View
className="personal_profile_edit"
onClick={() => handle_open_edit_modal("personal_profile")}
>
<Image
className="edit_icon"
src={require("../../static/userInfo/info_edit.svg")}
/>
<Text className="bio_text"></Text>
</View>
) : null}
</View>
</View>
@@ -268,13 +266,13 @@ export const UserInfoCard: React.FC<UserInfoCardProps> = ({
<EditModal
visible={edit_modal_visible}
type={editing_field}
title='编辑简介'
placeholder='介绍一下你的喜好,或者训练习惯'
initialValue={form_data['personal_profile'] || ''}
title="编辑简介"
placeholder="介绍一下你的喜好,或者训练习惯"
initialValue={form_data["personal_profile"] || ""}
maxLength={100}
onSave={handle_edit_modal_save}
onCancel={handle_edit_modal_cancel}
validationMessage='请填写 2-100 个字符'
validationMessage="请填写 2-100 个字符"
/>
</View>
);
@@ -298,7 +296,7 @@ export interface GameRecord {
current_participants: number;
level_range: string;
game_type: string;
images: string[];
image_list: string[];
}
// 球局卡片组件属性
@@ -312,20 +310,17 @@ interface GameCardProps {
export const GameCard: React.FC<GameCardProps> = ({
game,
on_click,
on_participant_click
on_participant_click,
}) => {
return (
<View
className="game_card"
onClick={() => on_click(game.id)}
>
<View className="game_card" onClick={() => on_click(game.id)}>
{/* 球局标题和类型 */}
<View className="game_header">
<Text className="game_title">{game.title}</Text>
<View className="game_type_icon">
<Image
className="type_icon"
src={require('../../static/userInfo/tennis.svg')}
src={require("../../static/userInfo/tennis.svg")}
/>
</View>
</View>
@@ -348,12 +343,8 @@ export const GameCard: React.FC<GameCardProps> = ({
{/* 球局图片 */}
<View className="game_images">
{game.images.map((image, index) => (
<Image
key={index}
className="game_image"
src={image}
/>
{game.image_list.map((image, index) => (
<Image key={index} className="game_image" src={image} />
))}
</View>
@@ -361,7 +352,7 @@ export const GameCard: React.FC<GameCardProps> = ({
<View className="game_tags">
<View className="participants_info">
<View className="avatars">
{game.participants.map((participant, index) => (
{game.participants?.map((participant, index) => (
<Image
key={index}
className="participant_avatar"
@@ -394,8 +385,8 @@ export const GameCard: React.FC<GameCardProps> = ({
// 球局标签页组件属性
interface GameTabsProps {
active_tab: 'hosted' | 'participated';
on_tab_change: (tab: 'hosted' | 'participated') => void;
active_tab: "hosted" | "participated";
on_tab_change: (tab: "hosted" | "participated") => void;
is_current_user: boolean;
}
@@ -403,21 +394,29 @@ interface GameTabsProps {
export const GameTabs: React.FC<GameTabsProps> = ({
active_tab,
on_tab_change,
is_current_user
is_current_user,
}) => {
const hosted_text = is_current_user ? '我主办的' : '他主办的';
const participated_text = is_current_user ? '我参与的' : '他参与的';
const hosted_text = is_current_user ? "我主办的" : "主办球局";
const participated_text = is_current_user ? "我参与的" : "参与球局";
return (
<View className="game_tabs_section">
<View className="tab_container">
<View className={`tab_item ${active_tab === 'hosted' ? 'active' : ''}`} onClick={() => on_tab_change('hosted')}>
<View
className={`tab_item ${active_tab === "hosted" ? "active" : ""}`}
onClick={() => on_tab_change("hosted")}
>
<Text className="tab_text">{hosted_text}</Text>
</View>
<View className={`tab_item ${active_tab === 'participated' ? 'active' : ''}`} onClick={() => on_tab_change('participated')}>
<View
className={`tab_item ${
active_tab === "participated" ? "active" : ""
}`}
onClick={() => on_tab_change("participated")}
>
<Text className="tab_text">{participated_text}</Text>
</View>
</View>
</View>
);
};
};