diff --git a/src/components/UserInfo/index.scss b/src/components/UserInfo/index.scss index dfe55a1..d8feca9 100644 --- a/src/components/UserInfo/index.scss +++ b/src/components/UserInfo/index.scss @@ -210,7 +210,8 @@ gap: 8px; flex-wrap: wrap; - .tag_item { + .tag_item, + .button_edit { display: flex; align-items: center; gap: 4px; @@ -224,11 +225,7 @@ .tag_icon { width: 12px; height: 12px; - /* Frame 1912054928 */ - - - } .tag_text { @@ -240,15 +237,59 @@ color: #000000; } } + + .button_edit { + font-family: 'PingFang SC'; + font-weight: 500; + font-size: 11px; + line-height: 1.8em; + letter-spacing: -2.1%; + color: rgba(60, 60, 67, 0.6); + display: flex; + align-items: center; + position: relative; + padding-right: 20px; + + &::before, &::after { + content: ''; + width: 6px; + height: 1px; + display: inline-block; + background-color: rgba(60, 60, 67, 0.6); + position: absolute; + right: 12px; + transform: rotate(45deg); + margin-left: 4px; + } + &::after { + transform: rotate(-45deg); + translate: 4.2px 0; + } + } } - .bio_text { - font-family: 'PingFang SC'; - font-weight: 400; - font-size: 14px; - line-height: 1.571em; - color: rgba(0, 0, 0, 0.65); - white-space: pre-line; + .personal_profile { + .personal_profile_edit { + display: flex; + align-items: center; + gap: 4px; + cursor: pointer; + + .edit_icon { + width: 16px; + height: 16px; + } + } + + .bio_text { + font-family: 'PingFang SC'; + font-weight: 400; + font-size: 14px; + line-height: 1.571em; + color: rgba(0, 0, 0, 0.65); + white-space: pre-line; + } + } } } diff --git a/src/components/UserInfo/index.tsx b/src/components/UserInfo/index.tsx index 2cc71f1..3515970 100644 --- a/src/components/UserInfo/index.tsx +++ b/src/components/UserInfo/index.tsx @@ -1,8 +1,11 @@ -import React from 'react'; +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'; + // 用户信息接口 export interface UserInfo { id: string; @@ -21,9 +24,10 @@ export interface UserInfo { ntrp_level: string; phone?: string; gender?: string; - + bio?: string, latitude?: string, longitude?: string, + birthday?: string, } @@ -35,6 +39,7 @@ interface UserInfoCardProps { on_follow?: () => void; on_message?: () => void; on_share?: () => void; + set_user_info?: (info: UserInfo) => void; } @@ -51,8 +56,64 @@ export const UserInfoCard: React.FC = ({ is_following = false, on_follow, on_message, - on_share + on_share, + set_user_info, }) => { + console.log("用户信息xx:", user_info); + // 编辑个人简介弹窗状态 + const [edit_modal_visible, setEditModalVisible] = useState(false); + const [editing_field, setEditingField] = useState(''); + + // 表单状态 + const [form_data, setFormData] = useState({...user_info}); + + // 处理编辑弹窗 + const handle_open_edit_modal = (field: string) => { + if (field === 'nickname') { + // 手动输入 + setEditingField(field); + setEditModalVisible(true); + } else { + setEditingField(field); + setEditModalVisible(true); + } + }; + const handle_edit_modal_save = async (value: string) => { + try { + // 调用更新用户信息接口,只传递修改的字段 + const update_data = { [editing_field]: value }; + await UserService.update_user_info(update_data); + + // 更新本地状态 + setFormData(prev => { + const updated = { ...prev, [editing_field]: value }; + typeof set_user_info === 'function' && set_user_info(updated); + return updated; + }); + + // 关闭弹窗 + setEditModalVisible(false); + setEditingField(''); + + // 显示成功提示 + Taro.showToast({ + title: '保存成功', + icon: 'success' + }); + } catch (error) { + console.error('保存失败:', error); + Taro.showToast({ + title: '保存失败', + icon: 'error' + }); + } + }; + + const handle_edit_modal_cancel = () => { + setEditModalVisible(false); + setEditingField(''); + }; + return ( {/* 头像和基本信息 */} @@ -130,7 +191,6 @@ export const UserInfoCard: React.FC = ({ - {user_info.gender === "0" && ( = ({ src={require('../../static/userInfo/female.svg')} /> )} - - - - {user_info.ntrp_level || '未设置'} - - - {user_info.occupation || '未设置'} - - - - {user_info.location || '未设置'} + { + !user_info.gender && ( + + 选择性别 + + ) + } + {user_info.ntrp_level ? + + {/* */} + {user_info.ntrp_level} + : + + 测测你的NTRP水平 + + } + {user_info.occupation ? + + {user_info.occupation} + : + + 选择职业 + + } + {user_info.location ? + + {/* */} + {user_info.location} + : + + 选择地区 + + } + + + { + user_info.personal_profile ? ( + {user_info.personal_profile} + ) : ( + handle_open_edit_modal('personal_profile')}> + + 点击添加简介,让更多人了解你 + + ) + } - {user_info.personal_profile} + + {/* 编辑个人简介弹窗 */} + ); }; diff --git a/src/config/api.ts b/src/config/api.ts index 0ab74ab..1be3372 100644 --- a/src/config/api.ts +++ b/src/config/api.ts @@ -11,7 +11,8 @@ export const API_CONFIG = { FOLLOW: '/user/follow', UNFOLLOW: '/user/unfollow', HOSTED_GAMES: '/user/games', - PARTICIPATED_GAMES: '/user/participated' + PARTICIPATED_GAMES: '/user/participated', + PARSE_PHONE: '/user/parse_phone', }, // 文件上传接口 diff --git a/src/services/userService.ts b/src/services/userService.ts index afb3ea2..cb3aa57 100644 --- a/src/services/userService.ts +++ b/src/services/userService.ts @@ -28,6 +28,9 @@ interface UserDetailData { last_login_time: string; create_time: string; last_modify_time: string; + personal_profile: string; + occupation: string; + birthday: string; stats: { followers_count: number; following_count: number; @@ -226,12 +229,13 @@ export class UserService { participated: userData.stats?.participated_games_count || 0 }, - personal_profile: '', + personal_profile: userData.personal_profile || '', location: userData.city + userData.district|| '', - occupation: '', + occupation: userData.occupation || '', ntrp_level: '', phone: userData.phone || '', - gender: userData.gender || '' + gender: userData.gender || '', + birthday: userData.birthday || '', }; } else { throw new Error(response.message || '获取用户信息失败'); @@ -449,6 +453,24 @@ export class UserService { return require('../static/userInfo/default_avatar.svg'); } } + + // 解析用户手机号 + static async parse_phone(phone_code: string): Promise { + try { + const response = await httpService.post<{ phone: string }>(API_CONFIG.USER.PARSE_PHONE, { phone_code }, { + showLoading: true, + loadingText: '获取手机号中...' + }); + if (response.code === 0) { + return response.data.phone || ''; + } else { + throw new Error(response.message || '获取手机号失败'); + } + } catch (error) { + console.error('获取手机号失败:', error); + return ''; + } + } } // 从 loginService 移过来的用户相关方法 diff --git a/src/static/userInfo/info_edit.svg b/src/static/userInfo/info_edit.svg new file mode 100644 index 0000000..33b0741 --- /dev/null +++ b/src/static/userInfo/info_edit.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/user_pages/edit/index.scss b/src/user_pages/edit/index.scss index 28022cb..b9d3061 100644 --- a/src/user_pages/edit/index.scss +++ b/src/user_pages/edit/index.scss @@ -145,12 +145,13 @@ padding: 10px 12px; min-height: 44px; box-sizing: border-box; + gap: 20px; .item_left { display: flex; align-items: center; gap: 8px; - flex: 1; + flex-shrink: 0; .item_icon { width: 16px; @@ -172,6 +173,7 @@ gap: 8px; flex: 1; justify-content: flex-end; + overflow: hidden; .item_input { flex: 1; @@ -184,6 +186,7 @@ border: none; background: transparent; outline: none; + min-width: 0; &::placeholder { color: rgba(0, 0, 0, 0.4); @@ -196,6 +199,11 @@ font-size: 14px; line-height: 1.71em; color: #000000; + flex: 1; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + text-align: right; } .bio_textarea { @@ -222,6 +230,26 @@ height: 14px; opacity: 0.2; } + + Button { + padding: 0; + font-family: 'PingFang SC'; + font-weight: 600; + font-size: 14px; + line-height: 1.71em; + color: #000000; + border: none; + flex: 1; + text-align: right; + background-color: unset; + &.placeholer { + font-weight: 400; + color: rgba(60, 60, 67, 0.3); + } + &:after { + border: none; + } + } } .divider { diff --git a/src/user_pages/edit/index.tsx b/src/user_pages/edit/index.tsx index 5916367..7bb01fc 100644 --- a/src/user_pages/edit/index.tsx +++ b/src/user_pages/edit/index.tsx @@ -1,5 +1,5 @@ import React, { useState, useEffect } from 'react'; -import { View, Text, Image, ScrollView, Picker, Input } from '@tarojs/components'; +import { View, Text, Image, ScrollView, Picker, Input, Button } from '@tarojs/components'; import Taro from '@tarojs/taro'; import './index.scss'; import { UserInfo } from '@/components/UserInfo'; @@ -67,7 +67,7 @@ const EditProfilePage: React.FC = () => { ntrp_level: user_data.ntrp_level || 'NTRP 4.0', phone: user_data.phone || '', gender: user_data.gender || '', - birthday: '2000-01-01' // 默认生日,实际应该从用户数据获取 + birthday: user_data.birthday || '', // 默认生日,实际应该从用户数据获取 }); } catch (error) { console.error('加载用户信息失败:', error); @@ -180,9 +180,7 @@ const EditProfilePage: React.FC = () => { // 处理性别选择 const handle_gender_change = (e: any) => { const gender_value = e.detail.value; - // 使用工具函数转换:页面选择器值(0/1) -> 数据库值('0'/'1') - const gender_db_value = gender_value === 0 ? '0' : '1'; - handle_field_edit('gender', gender_db_value); + handle_field_edit('gender', gender_value); }; // 处理生日选择 @@ -191,6 +189,17 @@ const EditProfilePage: React.FC = () => { handle_field_edit('birthday', birthday_value); }; + // NTRP水平输入 - 实时更新本地状态 + const handle_ntrp_level_input = (e: any) => { + const ntrp_level_value = e.detail.value; + setFormData(prev => ({ ...prev, ntrp_level: ntrp_level_value })); + } + // NTRP水平输入 - 失去焦点时保存到服务器 + const handle_ntrp_level_blur = (e: any) => { + const ntrp_level_value = e.detail.value; + handle_field_edit('ntrp_level', ntrp_level_value); + } + // 处理职业输入 - 实时更新本地状态 const handle_occupation_input = (e: any) => { const occupation_value = e.detail.value; @@ -215,17 +224,17 @@ const EditProfilePage: React.FC = () => { handle_field_edit('location', location_value); }; - // 处理手机号输入 - 实时更新本地状态 - const handle_phone_input = (e: any) => { - const phone_value = e.detail.value; - setFormData(prev => ({ ...prev, phone: phone_value })); - }; + // // 处理手机号输入 - 实时更新本地状态 + // const handle_phone_input = (e: any) => { + // const phone_value = e.detail.value; + // setFormData(prev => ({ ...prev, phone: phone_value })); + // }; - // 处理手机号输入 - 失去焦点时保存到服务器 - const handle_phone_blur = (e: any) => { - const phone_value = e.detail.value; - handle_field_edit('phone', phone_value); - }; + // // 处理手机号输入 - 失去焦点时保存到服务器 + // const handle_phone_blur = (e: any) => { + // const phone_value = e.detail.value; + // handle_field_edit('phone', phone_value); + // }; // 处理退出登录 @@ -246,6 +255,29 @@ const EditProfilePage: React.FC = () => { }); }; + const onGetPhoneNumber = async (e) => { + if (!e.detail || !e.detail.code) { + Taro.showToast({ + title: '获取手机号失败,请重试', + icon: 'none', + duration: 2000 + }); + return; + } + console.log('用户手机号信息aaa:', e) + try { + const phone = await UserService.parse_phone(e.detail.code); + handle_field_edit('phone', phone); + } catch (e) { + console.error('解析手机号失败:', e); + Taro.showToast({ + title: '解析手机号失败,请重试', + icon: 'none', + duration: 2000 + }); + } + } + return ( {/* 导航栏 */} @@ -345,7 +377,7 @@ const EditProfilePage: React.FC = () => { - {form_data.personal_profile || '介绍一下自己'} + {form_data.personal_profile.replace(/\n/g, ' ') || '介绍一下自己'} @@ -370,6 +402,7 @@ const EditProfilePage: React.FC = () => { onInput={handle_location_input} onBlur={handle_location_blur} /> + @@ -381,7 +414,14 @@ const EditProfilePage: React.FC = () => { NTRP 水平 - {form_data.ntrp_level} + {/* {form_data.ntrp_level} */} + @@ -401,6 +441,7 @@ const EditProfilePage: React.FC = () => { onInput={handle_occupation_input} onBlur={handle_occupation_blur} /> + @@ -415,14 +456,16 @@ const EditProfilePage: React.FC = () => { 手机 - + /> */} + + diff --git a/src/user_pages/myself/index.tsx b/src/user_pages/myself/index.tsx index b392c3f..319fe74 100644 --- a/src/user_pages/myself/index.tsx +++ b/src/user_pages/myself/index.tsx @@ -1,6 +1,6 @@ import React, { useState, useEffect } from "react"; import { View, Text, Image, ScrollView } from "@tarojs/components"; -import Taro from "@tarojs/taro"; +import Taro, { useDidShow } from "@tarojs/taro"; import "./index.scss"; import GuideBar from "@/components/GuideBar"; import { UserInfoCard, UserInfo } from "@/components/UserInfo/index"; @@ -33,6 +33,7 @@ const MyselfPage: React.FC = () => { location: "加载中...", occupation: "加载中...", ntrp_level: "NTRP 3.0", + personal_profile: "加载中...", }); // 球局记录状态 @@ -77,9 +78,13 @@ const MyselfPage: React.FC = () => { }; // 页面加载时获取数据 - useEffect(() => { - load_user_data(); - }, [user_id]); + // useEffect(() => { + // load_user_data(); + // }, [user_id]); + + useDidShow(() => { + load_user_data(); // 确保从编辑页面返回时刷新数据 + }); // 切换标签页时重新加载球局数据 useEffect(() => { @@ -157,6 +162,7 @@ const MyselfPage: React.FC = () => { is_current_user={is_current_user} is_following={is_following} on_follow={handle_follow} + set_user_info={set_user_info} /> )} {/* 球局订单和收藏功能 */} @@ -208,6 +214,7 @@ const MyselfPage: React.FC = () => { loading={loading} error={null} reload={load_game_data} + loadMoreMatches={() => { }} />