个人页点击昵称弹出修改昵称弹窗

This commit is contained in:
2025-11-18 17:23:37 +08:00
parent c8cf22507c
commit 5ecb352d1b
2 changed files with 83 additions and 26 deletions

View File

@@ -10,7 +10,7 @@ import { useUserActions } from "@/store/userStore";
import { UserInfoType } from "@/services/userService"; import { UserInfoType } from "@/services/userService";
import { useCities, useProfessions } from "@/store/pickerOptionsStore"; import { useCities, useProfessions } from "@/store/pickerOptionsStore";
import { formatNtrpDisplay } from "@/utils/helper"; import { formatNtrpDisplay } from "@/utils/helper";
import FamilyContext from '@/context'; import FamilyContext from "@/context";
// 用户信息接口 // 用户信息接口
// export interface UserInfo { // export interface UserInfo {
@@ -105,12 +105,22 @@ const UserInfoCardComponent: React.FC<UserInfoCardProps> = ({
}); });
useEffect(() => { useEffect(() => {
const visibles = [gender_picker_visible, location_picker_visible, ntrp_picker_visible, occupation_picker_visible] const visibles = [
const showGuideBar = visibles.every(item => !item) gender_picker_visible,
location_picker_visible,
ntrp_picker_visible,
occupation_picker_visible,
];
const showGuideBar = visibles.every((item) => !item);
if (showGuideBar) { if (showGuideBar) {
handleGrandchildTrigger(false) handleGrandchildTrigger(false);
} }
}, [gender_picker_visible, location_picker_visible, ntrp_picker_visible, occupation_picker_visible]) }, [
gender_picker_visible,
location_picker_visible,
ntrp_picker_visible,
occupation_picker_visible,
]);
// 职业数据 // 职业数据
const professions = useProfessions(); const professions = useProfessions();
@@ -142,7 +152,7 @@ const UserInfoCardComponent: React.FC<UserInfoCardProps> = ({
// }; // };
// 处理编辑弹窗 // 处理编辑弹窗
const handle_open_edit_modal = (field: string) => { const handle_open_edit_modal = (field: string) => {
handleGrandchildTrigger(true) handleGrandchildTrigger(true);
if (field === "gender") { if (field === "gender") {
setGenderPickerVisible(true); setGenderPickerVisible(true);
return; return;
@@ -161,11 +171,11 @@ const UserInfoCardComponent: React.FC<UserInfoCardProps> = ({
} }
if (field === "nickname") { if (field === "nickname") {
// 手动输入 // 手动输入
handleGrandchildTrigger(true) handleGrandchildTrigger(true);
setEditingField(field); setEditingField(field);
setEditModalVisible(true); setEditModalVisible(true);
} else { } else {
handleGrandchildTrigger(true) handleGrandchildTrigger(true);
setEditingField(field); setEditingField(field);
setEditModalVisible(true); setEditModalVisible(true);
} }
@@ -178,6 +188,10 @@ const UserInfoCardComponent: React.FC<UserInfoCardProps> = ({
await updateUserInfo({ [editing_field]: value }); await updateUserInfo({ [editing_field]: value });
set_form_data((prev) => {
return { ...prev, ...update_data };
});
// 更新本地状态 // 更新本地状态
// setFormData((prev) => { // setFormData((prev) => {
// const updated = { ...prev, [editing_field]: value }; // const updated = { ...prev, [editing_field]: value };
@@ -338,7 +352,14 @@ const UserInfoCardComponent: React.FC<UserInfoCardProps> = ({
/> />
</View> </View>
<View className="info_container"> <View className="info_container">
<Text className="nickname">{user_info.nickname || ""}</Text> <Text
className="nickname"
onClick={() => {
handle_open_edit_modal("nickname");
}}
>
{user_info.nickname || ""}
</Text>
<Text className="join_date">{user_info.join_date || ""}</Text> <Text className="join_date">{user_info.join_date || ""}</Text>
</View> </View>
{is_current_user && ( {is_current_user && (
@@ -472,7 +493,9 @@ const UserInfoCardComponent: React.FC<UserInfoCardProps> = ({
editable && handle_open_edit_modal("ntrp_level"); editable && handle_open_edit_modal("ntrp_level");
}} }}
> >
<Text className="tag_text">{`NTRP ${formatNtrpDisplay(user_info.ntrp_level)}`}</Text> <Text className="tag_text">{`NTRP ${formatNtrpDisplay(
user_info.ntrp_level
)}`}</Text>
</View> </View>
) : is_current_user ? ( ) : is_current_user ? (
<View <View
@@ -521,14 +544,14 @@ const UserInfoCardComponent: React.FC<UserInfoCardProps> = ({
</View> </View>
) : null} ) : null}
</View> </View>
<View className="personal_profile" <View
onClick={() => handle_open_edit_modal("personal_profile")}> className="personal_profile"
onClick={() => handle_open_edit_modal("personal_profile")}
>
{user_info.personal_profile ? ( {user_info.personal_profile ? (
<Text className="bio_text">{user_info.personal_profile}</Text> <Text className="bio_text">{user_info.personal_profile}</Text>
) : is_current_user ? ( ) : is_current_user ? (
<View <View className="personal_profile_edit">
className="personal_profile_edit"
>
<Image <Image
className="edit_icon" className="edit_icon"
src={require("../../static/userInfo/info_edit.svg")} src={require("../../static/userInfo/info_edit.svg")}
@@ -541,6 +564,25 @@ const UserInfoCardComponent: React.FC<UserInfoCardProps> = ({
{/* 编辑个人简介弹窗 */} {/* 编辑个人简介弹窗 */}
<EditModal <EditModal
visible={edit_modal_visible}
type={editing_field}
title={editing_field === "nickname" ? "编辑名字" : "编辑简介"}
placeholder={
editing_field === "nickname"
? "请输入您的名字"
: "介绍一下你的喜好,或者训练习惯"
}
initialValue={form_data[editing_field as keyof typeof form_data] || ""}
maxLength={editing_field === "nickname" ? 20 : 100}
onSave={handle_edit_modal_save}
onCancel={handle_edit_modal_cancel}
validationMessage={
editing_field === "nickname"
? "请填写 1-20 个字符"
: "请填写 2-100 个字符"
}
/>
{/* <EditModal
visible={edit_modal_visible} visible={edit_modal_visible}
type={editing_field} type={editing_field}
title="编辑简介" title="编辑简介"
@@ -550,7 +592,7 @@ const UserInfoCardComponent: React.FC<UserInfoCardProps> = ({
onSave={handle_edit_modal_save} onSave={handle_edit_modal_save}
onCancel={handle_edit_modal_cancel} onCancel={handle_edit_modal_cancel}
validationMessage="请填写 2-100 个字符" validationMessage="请填写 2-100 个字符"
/> /> */}
{/* 性别选择弹窗 */} {/* 性别选择弹窗 */}
{gender_picker_visible && ( {gender_picker_visible && (
<PopupPicker <PopupPicker
@@ -632,7 +674,10 @@ const UserInfoCardComponent: React.FC<UserInfoCardProps> = ({
}; };
// 自定义比较函数:只在关键 props 变化时重新渲染 // 自定义比较函数:只在关键 props 变化时重新渲染
const arePropsEqual = (prevProps: UserInfoCardProps, nextProps: UserInfoCardProps) => { const arePropsEqual = (
prevProps: UserInfoCardProps,
nextProps: UserInfoCardProps
) => {
// 使用 JSON.stringify 进行深度比较(注意:对于复杂对象可能有性能问题) // 使用 JSON.stringify 进行深度比较(注意:对于复杂对象可能有性能问题)
const prevUserInfoStr = JSON.stringify(prevProps.user_info); const prevUserInfoStr = JSON.stringify(prevProps.user_info);
const nextUserInfoStr = JSON.stringify(nextProps.user_info); const nextUserInfoStr = JSON.stringify(nextProps.user_info);
@@ -781,7 +826,8 @@ export const GameTabs: React.FC<GameTabsProps> = ({
<Text className="tab_text">{hosted_text}</Text> <Text className="tab_text">{hosted_text}</Text>
</View> </View>
<View <View
className={`tab_item ${active_tab === "participated" ? "active" : "" className={`tab_item ${
active_tab === "participated" ? "active" : ""
}`} }`}
onClick={() => on_tab_change("participated")} onClick={() => on_tab_change("participated")}
> >

View File

@@ -316,7 +316,11 @@ const EditProfilePage: React.FC = () => {
// 处理地区选择 // 处理地区选择
const handle_location_change = (e: any) => { const handle_location_change = (e: any) => {
if (!Array.isArray(e) || e.length < 3 || e.some((v) => v === undefined || v === null)) { if (
!Array.isArray(e) ||
e.length < 3 ||
e.some((v) => v === undefined || v === null)
) {
Taro.showToast({ Taro.showToast({
title: "请完整选择地区", title: "请完整选择地区",
icon: "none", icon: "none",
@@ -327,7 +331,7 @@ const EditProfilePage: React.FC = () => {
handle_field_edit({ handle_field_edit({
country: String(country ?? ""), country: String(country ?? ""),
province: String(province ?? ""), province: String(province ?? ""),
city: String(city ?? "") city: String(city ?? ""),
}); });
}; };
@@ -346,7 +350,11 @@ const EditProfilePage: React.FC = () => {
// 处理职业选择 // 处理职业选择
const handle_occupation_change = (e: any) => { const handle_occupation_change = (e: any) => {
if (!Array.isArray(e) || e.length === 0 || e.some((v) => v === undefined || v === null)) { if (
!Array.isArray(e) ||
e.length === 0 ||
e.some((v) => v === undefined || v === null)
) {
Taro.showToast({ Taro.showToast({
title: "请完整选择职业", title: "请完整选择职业",
icon: "none", icon: "none",
@@ -354,7 +362,10 @@ const EditProfilePage: React.FC = () => {
return; return;
} }
// 职业可能是多级联动,将所有选中的值用空格连接 // 职业可能是多级联动,将所有选中的值用空格连接
const occupation_value = e.map((v) => String(v ?? "")).filter(Boolean).join(" "); const occupation_value = e
.map((v) => String(v ?? ""))
.filter(Boolean)
.join(" ");
handle_field_edit("occupation", occupation_value); handle_field_edit("occupation", occupation_value);
}; };