细节优化

This commit is contained in:
2025-12-01 11:37:59 +08:00
parent f389397227
commit 675ecb536d
7 changed files with 101 additions and 68 deletions

View File

@@ -18,11 +18,10 @@ import styles from "./index.module.scss";
function NTRPTestEntryCard(props: { function NTRPTestEntryCard(props: {
type: EvaluateScene; type: EvaluateScene;
evaluateCallback?: EvaluateCallback; evaluateCallback?: EvaluateCallback;
callback?: (flag) => void;
}) { }) {
const [testFlag, setTestFlag] = useState(false); const [testFlag, setTestFlag] = useState(false);
const [hasTestInLastMonth, setHasTestInLastMonth] = useState(false); const [hasTestInLastMonth, setHasTestInLastMonth] = useState(false);
const { type, evaluateCallback, callback } = props; const { type, evaluateCallback } = props;
const userInfo = useUserInfo(); const userInfo = useUserInfo();
const { setCallback } = useEvaluate(); const { setCallback } = useEvaluate();
const { fetchUserInfo } = useUserActions(); const { fetchUserInfo } = useUserActions();
@@ -42,7 +41,6 @@ function NTRPTestEntryCard(props: {
if (res.code === 0) { if (res.code === 0) {
setTestFlag(res.data.has_test_record); setTestFlag(res.data.has_test_record);
setHasTestInLastMonth(res.data.has_test_in_last_month); setHasTestInLastMonth(res.data.has_test_in_last_month);
callback?.(res.data.has_test_in_last_month);
} }
}; };
init(); init();

View File

@@ -31,6 +31,7 @@ interface PickerProps {
onConfirm?: (options: PickerOption[], values: (string | number)[]) => void; onConfirm?: (options: PickerOption[], values: (string | number)[]) => void;
onChange?: (value: (string | number)[]) => void; onChange?: (value: (string | number)[]) => void;
style?: React.CSSProperties; style?: React.CSSProperties;
ntrpTested?: boolean;
} }
const PopupPicker = ({ const PopupPicker = ({
@@ -48,16 +49,17 @@ const PopupPicker = ({
options = [], options = [],
type = null, type = null,
style, style,
ntrpTested,
}: PickerProps) => { }: PickerProps) => {
const [defaultValue, setDefaultValue] = useState<(string | number)[]>([]); const [defaultValue, setDefaultValue] = useState<(string | number)[]>([]);
const [defaultOptions, setDefaultOptions] = useState<PickerOption[][]>([]); const [defaultOptions, setDefaultOptions] = useState<PickerOption[][]>([]);
const [pickerCurrentValue, setPickerCurrentValue] = useState<(string | number)[]>(value); const [pickerCurrentValue, setPickerCurrentValue] =
const [tested, setTested] = useState(false) useState<(string | number)[]>(value);
const changePicker = (options: any[], values: any, columnIndex: number) => { const changePicker = (options: any[], values: any, columnIndex: number) => {
// 更新 Picker 的当前值 // 更新 Picker 的当前值
setPickerCurrentValue(values); setPickerCurrentValue(values);
if (onChange) { if (onChange) {
console.log("picker onChange", columnIndex, values, options); console.log("picker onChange", columnIndex, values, options);
if ( if (
@@ -84,7 +86,10 @@ const PopupPicker = ({
}; };
// 处理 Picker 的确认事件,获取当前选中的值 // 处理 Picker 的确认事件,获取当前选中的值
const handlePickerConfirm = (options: PickerOption[], values: (string | number)[]) => { const handlePickerConfirm = (
options: PickerOption[],
values: (string | number)[]
) => {
setPickerCurrentValue(values); setPickerCurrentValue(values);
setDefaultValue(values); setDefaultValue(values);
}; };
@@ -127,9 +132,6 @@ const PopupPicker = ({
} }
} }
}, [visible, value]); }, [visible, value]);
const callback = (tested: boolean) => {
setTested(tested)
}
return ( return (
<> <>
<CommonPopup <CommonPopup
@@ -146,9 +148,9 @@ const PopupPicker = ({
zIndex={1000} zIndex={1000}
style={style} style={style}
> >
{type === "ntrp" && !tested && ( {type === "ntrp" && !ntrpTested && (
<View className={styles.evaluateCardWrap}> <View className={styles.evaluateCardWrap}>
<NTRPTestEntryCard callback={(flag) => callback(flag)} type={EvaluateScene.userEdit} /> <NTRPTestEntryCard type={EvaluateScene.userEdit} />
</View> </View>
// <View className={`${styles["examination-btn"]}}`}> // <View className={`${styles["examination-btn"]}}`}>
// <View className={`${styles["text-container"]}}`}> // <View className={`${styles["text-container"]}}`}>

View File

@@ -11,6 +11,7 @@ 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 { useGlobalState } from "@/store/global"; import { useGlobalState } from "@/store/global";
import evaluateService from "@/services/evaluateService";
// 用户信息接口 // 用户信息接口
// export interface UserInfo { // export interface UserInfo {
@@ -78,6 +79,7 @@ const UserInfoCardComponent: React.FC<UserInfoCardProps> = ({
}) => { }) => {
const { setShowGuideBar } = useGlobalState(); const { setShowGuideBar } = useGlobalState();
const { updateUserInfo } = useUserActions(); const { updateUserInfo } = useUserActions();
const [ntrpTested, setNtrpTested] = useState(false);
// 使用 useRef 记录上一次的 user_info只在真正变化时打印 // 使用 useRef 记录上一次的 user_info只在真正变化时打印
const prevUserInfoRef = useRef<Partial<UserInfoType>>(); const prevUserInfoRef = useRef<Partial<UserInfoType>>();
@@ -90,6 +92,14 @@ const UserInfoCardComponent: React.FC<UserInfoCardProps> = ({
console.log("UserInfoCard 用户信息变化:", user_info); console.log("UserInfoCard 用户信息变化:", user_info);
prevUserInfoRef.current = user_info; prevUserInfoRef.current = user_info;
} }
const getLastResult = async () => {
// 获取测试结果
const res = await evaluateService.getLastResult();
if (res.code === 0) {
setNtrpTested(res.data.has_test_in_last_month);
}
};
getLastResult();
}, [user_info]); }, [user_info]);
// 编辑个人简介弹窗状态 // 编辑个人简介弹窗状态
@@ -651,6 +661,7 @@ const UserInfoCardComponent: React.FC<UserInfoCardProps> = ({
<PopupPicker <PopupPicker
showHeader={true} showHeader={true}
title="选择 NTRP 自评水平" title="选择 NTRP 自评水平"
ntrpTested={ntrpTested}
options={[ options={[
[ [
{ text: "1.5", value: "1.5" }, { text: "1.5", value: "1.5" },
@@ -660,6 +671,7 @@ const UserInfoCardComponent: React.FC<UserInfoCardProps> = ({
{ text: "3.5", value: "3.5" }, { text: "3.5", value: "3.5" },
{ text: "4.0", value: "4.0" }, { text: "4.0", value: "4.0" },
{ text: "4.5", value: "4.5" }, { text: "4.5", value: "4.5" },
{ text: "4.5+", value: "4.5+" },
], ],
]} ]}
type="ntrp" type="ntrp"
@@ -668,7 +680,7 @@ const UserInfoCardComponent: React.FC<UserInfoCardProps> = ({
setvisible={setNtrpPickerVisible} setvisible={setNtrpPickerVisible}
value={ value={
!form_data.ntrp_level || form_data.ntrp_level === "0" !form_data.ntrp_level || form_data.ntrp_level === "0"
? ["3.0"] ? ["2.5"]
: [form_data.ntrp_level] : [form_data.ntrp_level]
} }
onChange={handle_ntrp_level_change} onChange={handle_ntrp_level_change}

View File

@@ -150,7 +150,11 @@ const MyselfPageContent: React.FC = () => {
// }; // };
return ( return (
<ScrollView scrollY refresherBackground="#FAFAFA" className={styles.myselfPage}> <ScrollView
scrollY
refresherBackground="#FAFAFA"
className={styles.myselfPage}
>
<View <View
className={styles.myselfPageContentMain} className={styles.myselfPageContentMain}
style={{ paddingTop: `${totalHeight}px` }} style={{ paddingTop: `${totalHeight}px` }}
@@ -235,7 +239,7 @@ const MyselfPageContent: React.FC = () => {
collapse={true} collapse={true}
style={{ paddingBottom: 0, overflow: "hidden" }} style={{ paddingBottom: 0, overflow: "hidden" }}
listLoadErrorWrapperHeight="267px" listLoadErrorWrapperHeight="267px"
listLoadErrorWidth="100%" listLoadErrorWidth="320px"
listLoadErrorHeight="152px" listLoadErrorHeight="152px"
defaultShowNum={3} defaultShowNum={3}
/> />
@@ -256,7 +260,7 @@ const MyselfPageContent: React.FC = () => {
collapse={true} collapse={true}
style={{ paddingBottom: "90px", overflow: "hidden" }} style={{ paddingBottom: "90px", overflow: "hidden" }}
listLoadErrorWrapperHeight="220px" listLoadErrorWrapperHeight="220px"
listLoadErrorWidth="100%" listLoadErrorWidth="320px"
listLoadErrorHeight="152px" listLoadErrorHeight="152px"
defaultShowNum={3} defaultShowNum={3}
/> />

View File

@@ -1,17 +1,13 @@
// 编辑资料页面样式 // 编辑资料页面样式
.edit_profile_page { .edit_profile_page {
height: 100vh; // position: relative; height: 100vh; // position: relative;
background: radial-gradient(circle at 50% 0, background: radial-gradient(
/* 光晕圆心在顶部中间 */ circle at 50% 0,
rgba(191, 255, 239, 0.9) 0px, /* 光晕圆心在顶部中间 */ rgba(191, 255, 239, 0.9) 0px,
/* 中间更深的浅蓝 */ /* 中间更深的浅蓝 */ rgba(191, 255, 239, 0.5) 200px,
rgba(191, 255, 239, 0.5) 200px, /* 100px 处开始淡化 */ #fafafa 300px,
/* 100px 处开始淡化 */ /* 到 200px 变成白色 */ #fafafa 100% /* 200px 以下全白 */
#fafafa 300px, );
/* 到 200px 变成白色 */
#fafafa 100%
/* 200px 以下全白 */
);
position: relative; position: relative;
// overflow: hidden; // overflow: hidden;
box-sizing: border-box; box-sizing: border-box;
@@ -56,7 +52,7 @@
display: flex; display: flex;
justify-content: center; justify-content: center;
&>.detail-navigator-back-icon { & > .detail-navigator-back-icon {
width: 32px; width: 32px;
height: 32px; height: 32px;
} }
@@ -353,7 +349,7 @@
} }
&.group { &.group {
border: 1px solid rgba(0, 0, 0, 0.06); border: 0.5pt solid rgba(0, 0, 0, 0.06);
border-radius: 16px; border-radius: 16px;
overflow: hidden; overflow: hidden;
@@ -368,7 +364,7 @@
} }
&:first-child { &:first-child {
border-bottom: 1px solid rgba(0, 0, 0, 0.06); border-bottom: 0.5pt solid rgba(0, 0, 0, 0.06);
} }
} }
} }
@@ -389,4 +385,4 @@
color: rgba(0, 0, 0, 0.6); color: rgba(0, 0, 0, 0.6);
} }
} }
} }

View File

@@ -7,12 +7,13 @@ import { UserService, PickerOption } from "@/services/userService";
import { clear_login_state } from "@/services/loginService"; import { clear_login_state } from "@/services/loginService";
import { convert_db_gender_to_display } from "@/utils/genderUtils"; import { convert_db_gender_to_display } from "@/utils/genderUtils";
import { EditModal, GeneralNavbar } from "@/components"; import { EditModal, GeneralNavbar } from "@/components";
import img from "@/config/images"; // import img from "@/config/images";
import CommonDialog from "@/components/CommonDialog"; import CommonDialog from "@/components/CommonDialog";
import { useUserActions, useUserInfo } from "@/store/userStore"; import { useUserActions, useUserInfo } 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 { handleCustomerService } from "@/services/userService"; import { handleCustomerService } from "@/services/userService";
import evaluateService from "@/services/evaluateService";
const EditProfilePage: React.FC = () => { const EditProfilePage: React.FC = () => {
const { updateUserInfo } = useUserActions(); const { updateUserInfo } = useUserActions();
@@ -57,6 +58,8 @@ const EditProfilePage: React.FC = () => {
// 城市数据 // 城市数据
const cities = useCities(); const cities = useCities();
const [ntrpTested, setNtrpTested] = useState<boolean>(false);
// 监听store中的用户信息变化同步到表单状态 // 监听store中的用户信息变化同步到表单状态
useEffect(() => { useEffect(() => {
if (user_info && Object.keys(user_info).length > 0) { if (user_info && Object.keys(user_info).length > 0) {
@@ -74,6 +77,15 @@ const EditProfilePage: React.FC = () => {
city: info?.city ?? "", city: info?.city ?? "",
}); });
} }
const getLastResult = async () => {
// 获取测试结果
const res = await evaluateService.getLastResult();
if (res.code === 0) {
setNtrpTested(res.data.has_test_in_last_month);
}
};
getLastResult();
}, [user_info]); }, [user_info]);
// 页面加载时初始化数据 // 页面加载时初始化数据
@@ -695,9 +707,9 @@ const EditProfilePage: React.FC = () => {
> >
{form_data.phone {form_data.phone
? form_data.phone.replace( ? form_data.phone.replace(
/(\d{3})(\d{4})(\d{4})/, /(\d{3})(\d{4})(\d{4})/,
"$1 $2 $3" "$1 $2 $3"
) )
: "未绑定"} : "未绑定"}
</Button> </Button>
<Image <Image
@@ -822,6 +834,7 @@ const EditProfilePage: React.FC = () => {
showHeader={true} showHeader={true}
title="选择 NTRP 自评水平" title="选择 NTRP 自评水平"
confirmText="保存" confirmText="保存"
ntrpTested={ntrpTested}
options={[ options={[
[ [
{ text: "1.5", value: "1.5" }, { text: "1.5", value: "1.5" },
@@ -831,6 +844,7 @@ const EditProfilePage: React.FC = () => {
{ text: "3.5", value: "3.5" }, { text: "3.5", value: "3.5" },
{ text: "4.0", value: "4.0" }, { text: "4.0", value: "4.0" },
{ text: "4.5", value: "4.5" }, { text: "4.5", value: "4.5" },
{ text: "4.5+", value: "4.5+" },
], ],
]} ]}
type="ntrp" type="ntrp"
@@ -838,7 +852,7 @@ const EditProfilePage: React.FC = () => {
visible={ntrp_picker_visible} visible={ntrp_picker_visible}
setvisible={setNtrpPickerVisible} setvisible={setNtrpPickerVisible}
value={ value={
form_data.ntrp_level === "0" ? ["3.0"] : [form_data.ntrp_level] form_data.ntrp_level === "0" ? ["2.5"] : [form_data.ntrp_level]
} }
onChange={handle_ntrp_level_change} onChange={handle_ntrp_level_change}
/> />

View File

@@ -96,8 +96,9 @@ const OtherUserPage: React.FC = () => {
nickname: userData.nickname || "", nickname: userData.nickname || "",
avatar_url: userData.avatar_url || "", avatar_url: userData.avatar_url || "",
join_date: userData.subscribe_time join_date: userData.subscribe_time
? `${new Date(userData.subscribe_time).getFullYear()}${new Date(userData.subscribe_time).getMonth() + 1 ? `${new Date(userData.subscribe_time).getFullYear()}${
}月加入` new Date(userData.subscribe_time).getMonth() + 1
}月加入`
: "", : "",
stats: { stats: {
following_count: userData.stats?.following_count || 0, following_count: userData.stats?.following_count || 0,
@@ -132,35 +133,35 @@ const OtherUserPage: React.FC = () => {
}, [user_id]); }, [user_id]);
// 分类球局数据(使用 useCallback 包装,避免每次渲染都创建新函数) // 分类球局数据(使用 useCallback 包装,避免每次渲染都创建新函数)
const classifyGameRecords = useCallback(( const classifyGameRecords = useCallback(
game_records: GameRecord[] (
): { notEndGames: GameRecord[]; finishedGames: GameRecord[] } => { game_records: GameRecord[]
const now = new Date().getTime(); ): { notEndGames: GameRecord[]; finishedGames: GameRecord[] } => {
return game_records.reduce( const now = new Date().getTime();
(result, cur) => { return game_records.reduce(
let { end_time } = cur; (result, cur) => {
end_time = end_time.replace(/\s/, "T"); let { end_time } = cur;
new Date(end_time).getTime() > now end_time = end_time.replace(/\s/, "T");
? result.notEndGames.push(cur) new Date(end_time).getTime() > now
: result.finishedGames.push(cur); ? result.notEndGames.push(cur)
return result; : result.finishedGames.push(cur);
}, return result;
{ },
notEndGames: [] as GameRecord[], {
finishedGames: [] as GameRecord[], notEndGames: [] as GameRecord[],
} finishedGames: [] as GameRecord[],
); }
}, []); );
},
[]
);
// 加载球局数据(使用 useCallback 包装,避免每次渲染都创建新函数) // 加载球局数据(使用 useCallback 包装,避免每次渲染都创建新函数)
const load_game_data = useCallback(async () => { const load_game_data = useCallback(async () => {
if (!user_id) return; if (!user_id) return;
try { try {
set_loading(true); set_loading(true);
const games_data = await UserService.get_user_games( const games_data = await UserService.get_user_games(user_id, active_tab);
user_id,
active_tab
);
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() -
@@ -214,7 +215,9 @@ const OtherUserPage: React.FC = () => {
const handle_send_message = useCallback(() => { const handle_send_message = useCallback(() => {
if (!user_info.id) return; if (!user_info.id) return;
Taro.navigateTo({ Taro.navigateTo({
url: `/mode_user/message/chat/index?user_id=${user_info.id}&nickname=${user_info.nickname || ""}`, url: `/mode_user/message/chat/index?user_id=${user_info.id}&nickname=${
user_info.nickname || ""
}`,
}); });
}, [user_info.id, user_info.nickname]); }, [user_info.id, user_info.nickname]);
@@ -237,7 +240,11 @@ const OtherUserPage: React.FC = () => {
// }; // };
return ( return (
<ScrollView scrollY className="other_user_page" refresherBackground="#FAFAFA"> <ScrollView
scrollY
className="other_user_page"
refresherBackground="#FAFAFA"
>
{/* <CustomNavbar> {/* <CustomNavbar>
<View className="navbar_content"> <View className="navbar_content">
<View className="navbar_back" onClick={() => Taro.navigateBack()}> <View className="navbar_back" onClick={() => Taro.navigateBack()}>
@@ -303,11 +310,11 @@ const OtherUserPage: React.FC = () => {
isShowNoData={game_records.length === 0} isShowNoData={game_records.length === 0}
errorImg="ICON_LIST_EMPTY_CARD" errorImg="ICON_LIST_EMPTY_CARD"
emptyText="暂无球局信息" emptyText="暂无球局信息"
loadMoreMatches={() => { }} loadMoreMatches={() => {}}
collapse={true} collapse={true}
style={{ paddingBottom: 0, overflow: "hidden" }} style={{ paddingBottom: 0, overflow: "hidden" }}
listLoadErrorWrapperHeight="267px" listLoadErrorWrapperHeight="267px"
listLoadErrorWidth="100%" listLoadErrorWidth="320px"
listLoadErrorHeight="152px" listLoadErrorHeight="152px"
defaultShowNum={3} defaultShowNum={3}
/> />
@@ -346,11 +353,11 @@ const OtherUserPage: React.FC = () => {
isShowNoData={ended_game_records.length === 0} isShowNoData={ended_game_records.length === 0}
errorImg="ICON_LIST_EMPTY_CARD" errorImg="ICON_LIST_EMPTY_CARD"
emptyText="暂无球局信息" emptyText="暂无球局信息"
loadMoreMatches={() => { }} loadMoreMatches={() => {}}
collapse={true} collapse={true}
style={{ paddingBottom: "90px", overflow: "hidden" }} style={{ paddingBottom: "90px", overflow: "hidden" }}
listLoadErrorWrapperHeight="220px" listLoadErrorWrapperHeight="220px"
listLoadErrorWidth="100%" listLoadErrorWidth="320px"
listLoadErrorHeight="152px" listLoadErrorHeight="152px"
defaultShowNum={3} defaultShowNum={3}
/> />