This commit is contained in:
张成
2025-11-08 21:44:23 +08:00
8 changed files with 152 additions and 38 deletions

View File

@@ -1,5 +1,5 @@
import React, { useState, useEffect } from "react";
import Taro from "@tarojs/taro";
import Taro, { useDidShow } from "@tarojs/taro";
import { View, Text, Image, Button } from "@tarojs/components";
import "./index.scss";
@@ -48,6 +48,7 @@ interface UserInfoCardProps {
on_message?: () => void;
on_share?: () => void;
set_user_info?: (info: Partial<UserInfoType>) => void;
onTab?: (tab) => void;
}
// 处理编辑用户信息
@@ -65,6 +66,7 @@ export const UserInfoCard: React.FC<UserInfoCardProps> = ({
on_message,
on_share,
set_user_info,
onTab,
}) => {
const { updateUserInfo } = useUserActions();
console.log("UserInfoCard 用户信息:", user_info);
@@ -78,9 +80,11 @@ export const UserInfoCard: React.FC<UserInfoCardProps> = ({
useState(false);
// 表单状态
const [form_data] = useState<Partial<UserInfoType>>({
...user_info,
});
const [form_data, set_form_data] = useState<Partial<UserInfoType>>({});
useDidShow(() => {
set_form_data({ ...user_info })
})
// 职业数据
const professions = useProfessions();
@@ -181,6 +185,9 @@ export const UserInfoCard: React.FC<UserInfoCardProps> = ({
!Array.isArray(field)
) {
await updateUserInfo({ ...field });
set_form_data((prev) => {
return { ...prev, ...field }
})
// 更新本地状态
// setFormData((prev) => ({ ...prev, ...field }));
// setUserInfo((prev) => ({ ...prev, ...field }));
@@ -188,6 +195,9 @@ export const UserInfoCard: React.FC<UserInfoCardProps> = ({
// 调用更新用户信息接口,只传递修改的字段
const update_data = { [field as string]: value };
await updateUserInfo(update_data);
set_form_data((prev) => {
return { ...prev, ...update_data }
})
// 更新本地状态
// setFormData((prev) => ({ ...prev, [field as string]: value }));
// setUserInfo((prev) => ({ ...prev, [field as string]: value }));
@@ -323,13 +333,17 @@ export const UserInfoCard: React.FC<UserInfoCardProps> = ({
</Text>
<Text className="stat_label"></Text>
</View>
<View className="stat_item">
<View className="stat_item clickable"
onClick={() => onTab?.("hosted")}
>
<Text className="stat_number">
{user_info.stats?.hosted_games_count || 0}
</Text>
<Text className="stat_label"></Text>
</View>
<View className="stat_item">
<View className="stat_item clickable"
onClick={() => onTab?.("participated")}
>
<Text className="stat_number">
{user_info.stats?.participated_games_count || 0}
</Text>
@@ -384,12 +398,18 @@ export const UserInfoCard: React.FC<UserInfoCardProps> = ({
<Image
className="tag_icon"
src={require("../../static/userInfo/male.svg")}
onClick={() => {
handle_open_edit_modal("gender");
}}
/>
)}
{user_info.gender === "1" && (
<Image
className="tag_icon"
src={require("../../static/userInfo/female.svg")}
onClick={() => {
handle_open_edit_modal("gender");
}}
/>
)}
</View>
@@ -404,7 +424,11 @@ export const UserInfoCard: React.FC<UserInfoCardProps> = ({
</View>
) : null}
{user_info.ntrp_level !== "0" ? (
<View className="tag_item">
<View
className="tag_item"
onClick={() => {
handle_open_edit_modal("ntrp_level");
}}>
<Text className="tag_text">{`NTRP ${user_info.ntrp_level}`}</Text>
</View>
) : is_current_user ? (
@@ -418,7 +442,11 @@ export const UserInfoCard: React.FC<UserInfoCardProps> = ({
</View>
) : null}
{user_info.occupation ? (
<View className="tag_item">
<View
className="tag_item"
onClick={() => {
handle_open_edit_modal("occupation");
}}>
<Text className="tag_text">
{user_info.occupation.split(" ")[2]}
</Text>
@@ -434,7 +462,9 @@ export const UserInfoCard: React.FC<UserInfoCardProps> = ({
</View>
) : null}
{user_info.country || user_info.province || user_info.city ? (
<View className="tag_item">
<View
className="tag_item"
onClick={() => handle_open_edit_modal("location")}>
<Text className="tag_text">{`${user_info.province}${user_info.city}`}</Text>
</View>
) : is_current_user ? (

View File

@@ -30,4 +30,25 @@
font-weight: 500;
line-height: 24px;
}
.collapse-btn {
width: 100%;
font-family: PingFang SC;
font-weight: 400;
font-style: Regular;
font-size: 14px;
letter-spacing: 0.38px;
color: rgba(0, 0, 0, .3);
height: 40px;
display: flex;
justify-content: center;
align-items: center;
Image {
width: 16px;
height: 16px;
}
&:not(.fold) Image {
transform: rotate(180deg);
}
}
}

View File

@@ -1,4 +1,4 @@
import { View } from "@tarojs/components";
import { View, Text, Image } from "@tarojs/components";
import ListCard from "@/components/ListCard";
import ListLoadError from "@/components/ListLoadError";
import ListCardSkeleton from "@/components/ListCardSkeleton";
@@ -8,7 +8,7 @@ import { setStorage, getStorage } from "@/store/storage";
import { NTRPTestEntryCard } from "@/components";
import { EvaluateScene } from "@/store/evaluateStore";
import "./index.scss";
import { useRef, useEffect } from "react";
import { useRef, useEffect, useState } from "react";
const ListContainer = (props) => {
const {
@@ -23,9 +23,14 @@ const ListContainer = (props) => {
emptyText,
btnText,
btnImg,
style,
collapse = false,
defaultShowNum,
} = props;
const timerRef = useRef<NodeJS.Timeout | null>(null);
const [showNumber, setShowNumber] = useState(0)
const userInfo = useUserInfo();
useReachBottom(() => {
@@ -38,6 +43,14 @@ const ListContainer = (props) => {
// }, 500);
});
useEffect(() => {
setShowNumber(
() => {
return defaultShowNum === undefined ? data?.length : defaultShowNum
})
}, [data])
useEffect(() => {
return () => {
if (timerRef.current) {
@@ -97,6 +110,8 @@ const ListContainer = (props) => {
);
}
showNumber !== undefined && (list = list.slice(0, showNumber))
// 渲染数据
return (
<>
@@ -113,7 +128,7 @@ const ListContainer = (props) => {
};
return (
<View className="listContentWrapper">
<View className="listContentWrapper" style={style}>
{renderList(data)}
{/* 显示骨架屏 */}
{loading && renderSkeleton()}
@@ -122,7 +137,20 @@ const ListContainer = (props) => {
</View>
{renderList(recommendList)} */}
{/* 到底了 */}
{data?.length > 0 && <View className="bottomTextWrapper"></View>}
{collapse ?
data?.length > defaultShowNum ?
data?.length > showNumber ?
<View className="collapse-btn fold" onClick={() => { setShowNumber(data?.length) }}>
<Text></Text>
<Image src={require("@/static/userInfo/fold.svg")}></Image>
</View> :
<View className="collapse-btn" onClick={() => { setShowNumber(defaultShowNum) }}>
<Text></Text>
<Image src={require("@/static/userInfo/fold.svg")}></Image>
</View>
:
null
: data?.length > 0 && <View className="bottomTextWrapper"></View>}
</View>
);
};

View File

@@ -0,0 +1,4 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M12 4L8 8L4 4" stroke="black" stroke-opacity="0.2" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M12 8L8 12L4 8" stroke="black" stroke-opacity="0.2" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 368 B

View File

@@ -219,10 +219,10 @@ const DownloadBill: React.FC = () => {
transaction_sub_type,
date_range,
});
const { bill_example, fileName } = res.data;
const { fileUrl, fileName } = res.data;
// 调用下载文件接口
wx.downloadFile({
url: bill_example, // 文件路径
url: fileUrl, // 文件路径
success: function (res) {
// 只有200状态码表示下载成功
if (res.statusCode === 200) {

View File

@@ -170,9 +170,14 @@ const MyselfPage: React.FC = () => {
const handle_wallet = () => {
Taro.navigateTo({
url: "/user_pages/wallet/index",
// url: "/user_pages/other/index?userid=16"
});
};
const handleOnTab = (tab) => {
setActiveTab(tab)
}
return (
<View className="myself_page">
{/* 主要内容 */}
@@ -184,6 +189,7 @@ const MyselfPage: React.FC = () => {
is_current_user={is_current_user}
is_following={is_following}
on_follow={handle_follow}
onTab={handleOnTab}
/>
{/* 球局订单和收藏功能 */}
<View className="quick_actions_section">
@@ -219,9 +225,8 @@ const MyselfPage: React.FC = () => {
<Text className="tab_text"></Text>
</View>
<View
className={`tab_item ${
active_tab === "participated" ? "active" : ""
}`}
className={`tab_item ${active_tab === "participated" ? "active" : ""
}`}
onClick={() => setActiveTab("participated")}
>
<Text className="tab_text"></Text>
@@ -243,7 +248,10 @@ const MyselfPage: React.FC = () => {
btnImg="ICON_ADD"
reload={goPublish}
isShowNoData={game_records.length === 0}
loadMoreMatches={() => {}}
loadMoreMatches={() => { }}
collapse={true}
style={{ paddingBottom: 0, overflow: "hidden" }}
defaultShowNum={3}
/>
</ScrollView>
</View>
@@ -267,7 +275,10 @@ const MyselfPage: React.FC = () => {
error={null}
errorImg="ICON_LIST_EMPTY"
isShowNoData={ended_game_records.length === 0}
loadMoreMatches={() => {}}
loadMoreMatches={() => { }}
collapse={true}
style={{ paddingBottom: "90px", overflow: "hidden" }}
defaultShowNum={3}
/>
</ScrollView>
{/* </View> */}

View File

@@ -16,12 +16,13 @@ import { UserService, UserInfoType } from "@/services/userService";
import * as LoginService from "@/services/loginService";
import CustomNavbar from "@/components/CustomNavbar";
import { useGlobalState } from "@/store/global";
import { BackNavbar } from "@/components";
const OtherUserPage: React.FC = () => {
// 获取页面参数
const instance = Taro.getCurrentInstance();
const user_id = instance.router?.params?.userid;
if(!user_id) {
if (!user_id) {
Taro.showToast({
title: "用户不存在",
icon: "none",
@@ -87,9 +88,8 @@ const OtherUserPage: React.FC = () => {
nickname: userData.nickname || "",
avatar_url: userData.avatar_url || "",
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: {
following_count: userData.stats?.following_count || 0,
@@ -200,12 +200,15 @@ const OtherUserPage: React.FC = () => {
// 处理发送消息
const handle_send_message = () => {
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 || ""}`,
});
};
const handleOnTab = (tab) => {
setActiveTab(tab)
}
// 处理球局详情
// const handle_game_detail = (game_id: string) => {
// Taro.navigateTo({
@@ -215,19 +218,28 @@ const OtherUserPage: React.FC = () => {
return (
<View className="other_user_page">
<CustomNavbar>
{/* <CustomNavbar>
<View className="navbar_content">
<View className="navbar_back" onClick={() => Taro.navigateBack()}>
<View className="back_icon" />
</View>
<Text className="navbar_title"></Text>
<View className="navbar_action">
{/* 右侧占位,保持标题居中 */}
</View>
</View>
</CustomNavbar>
</CustomNavbar> */}
{/* 顶部导航栏 */}
<BackNavbar
title=""
showBackButton={true}
showAvatar={false}
backgroundColor="unset"
onBack={() => {
Taro.navigateBack();
}}
/>
{/* 主要内容 */}
<View className="main_content" style={{ paddingTop: `${totalHeight}px` }}>
<View className="main_content">
{/* 用户信息区域 */}
<View className="user_info_section">
<UserInfoCard
@@ -236,6 +248,7 @@ const OtherUserPage: React.FC = () => {
is_following={is_following}
on_follow={handle_follow}
on_message={handle_send_message}
onTab={handleOnTab}
/>
</View>
@@ -262,9 +275,13 @@ const OtherUserPage: React.FC = () => {
recommendList={[]}
loading={loading}
error={null}
isShowNoData={game_records.length === 0}
errorImg="ICON_LIST_EMPTY"
emptyText="暂无消息,去互动看看吧"
loadMoreMatches={() => {}}
emptyText="暂无球局信息"
loadMoreMatches={() => { }}
collapse={true}
style={{ paddingBottom: 0, overflow: "hidden" }}
defaultShowNum={3}
/>
</ScrollView>
{/* </View> */}
@@ -298,9 +315,13 @@ const OtherUserPage: React.FC = () => {
recommendList={[]}
loading={loading}
error={null}
isShowNoData={ended_game_records.length === 0}
errorImg="ICON_LIST_EMPTY"
emptyText="暂无消息,去互动看看吧"
loadMoreMatches={() => {}}
emptyText="暂无球局信息"
loadMoreMatches={() => { }}
collapse={true}
style={{ paddingBottom: "90px", overflow: "hidden" }}
defaultShowNum={3}
/>
</ScrollView>
{/* </View> */}

View File

@@ -92,9 +92,8 @@ const SetTransactionPassword: React.FC = () => {
title: "设置交易密码成功",
icon: "success",
});
Taro.redirectTo({
url: "/user_pages/wallet/index",
});
let delta = handleType === "set" ? 1 : 2;
Taro.navigateBack({ delta })
} catch (error) {
Taro.showToast({
title: "设置交易密码失败",