mirror of
https://github.com/wgh136/nysoure.git
synced 2025-09-27 20:27:23 +00:00
Encode usernames in API requests and navigation links to handle special characters.
This commit is contained in:
@@ -581,7 +581,7 @@ class Network {
|
|||||||
): Promise<PageResponse<Resource>> {
|
): Promise<PageResponse<Resource>> {
|
||||||
try {
|
try {
|
||||||
const response = await axios.get(
|
const response = await axios.get(
|
||||||
`${this.apiBaseUrl}/resource/user/${username}`,
|
`${this.apiBaseUrl}/resource/user/${encodeURIComponent(username)}`,
|
||||||
{
|
{
|
||||||
params: {
|
params: {
|
||||||
page,
|
page,
|
||||||
@@ -978,7 +978,7 @@ class Network {
|
|||||||
): Promise<PageResponse<CommentWithResource>> {
|
): Promise<PageResponse<CommentWithResource>> {
|
||||||
try {
|
try {
|
||||||
const response = await axios.get(
|
const response = await axios.get(
|
||||||
`${this.apiBaseUrl}/comments/user/${username}`,
|
`${this.apiBaseUrl}/comments/user/${encodeURIComponent(username)}`,
|
||||||
{
|
{
|
||||||
params: { page },
|
params: { page },
|
||||||
},
|
},
|
||||||
|
@@ -16,7 +16,7 @@ export default function ActivitiesPage() {
|
|||||||
const fetchNextPage = useCallback(async () => {
|
const fetchNextPage = useCallback(async () => {
|
||||||
if (isLoadingRef.current || pageRef.current >= maxPageRef.current) return;
|
if (isLoadingRef.current || pageRef.current >= maxPageRef.current) return;
|
||||||
isLoadingRef.current = true;
|
isLoadingRef.current = true;
|
||||||
const response = await network.getActivities(pageRef.current+1);
|
const response = await network.getActivities(pageRef.current + 1);
|
||||||
if (response.success) {
|
if (response.success) {
|
||||||
setActivities((prev) => [...prev, ...response.data!]);
|
setActivities((prev) => [...prev, ...response.data!]);
|
||||||
pageRef.current += 1;
|
pageRef.current += 1;
|
||||||
@@ -94,7 +94,9 @@ function ActivityCard({ activity }: { activity: Activity }) {
|
|||||||
} else if (activity.type === ActivityType.ResourceCommented) {
|
} else if (activity.type === ActivityType.ResourceCommented) {
|
||||||
content = (
|
content = (
|
||||||
<div className={"mt-2"}>
|
<div className={"mt-2"}>
|
||||||
<div className={"text-sm mx-1 whitespace-pre-wrap"}>{activity.comment?.content}</div>
|
<div className={"text-sm mx-1 whitespace-pre-wrap"}>
|
||||||
|
{activity.comment?.content}
|
||||||
|
</div>
|
||||||
<div className={"flex items-center mt-1"}>
|
<div className={"flex items-center mt-1"}>
|
||||||
<MdArrowRight />
|
<MdArrowRight />
|
||||||
<span className={"text-sm text-base-content/80"}>
|
<span className={"text-sm text-base-content/80"}>
|
||||||
|
@@ -161,7 +161,7 @@ export default function ResourcePage() {
|
|||||||
})}
|
})}
|
||||||
<button
|
<button
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
navigate(`/user/${resource.author.username}`);
|
navigate(`/user/${encodeURIComponent(resource.author.username)}`);
|
||||||
}}
|
}}
|
||||||
className="border-b-2 mx-4 py-1 cursor-pointer border-transparent hover:border-primary transition-colors duration-200 ease-in-out"
|
className="border-b-2 mx-4 py-1 cursor-pointer border-transparent hover:border-primary transition-colors duration-200 ease-in-out"
|
||||||
>
|
>
|
||||||
@@ -1276,7 +1276,9 @@ function CommentTile({ comment }: { comment: Comment }) {
|
|||||||
<div className={"flex flex-row items-center my-1 mx-1"}>
|
<div className={"flex flex-row items-center my-1 mx-1"}>
|
||||||
<div
|
<div
|
||||||
className="avatar cursor-pointer"
|
className="avatar cursor-pointer"
|
||||||
onClick={() => navigate(`/user/${comment.user.username}`)}
|
onClick={() =>
|
||||||
|
navigate(`/user/${encodeURIComponent(comment.user.username)}`)
|
||||||
|
}
|
||||||
>
|
>
|
||||||
<div className="w-8 rounded-full">
|
<div className="w-8 rounded-full">
|
||||||
<img src={network.getUserAvatar(comment.user)} alt={"avatar"} />
|
<img src={network.getUserAvatar(comment.user)} alt={"avatar"} />
|
||||||
@@ -1285,7 +1287,9 @@ function CommentTile({ comment }: { comment: Comment }) {
|
|||||||
<div className={"w-2"}></div>
|
<div className={"w-2"}></div>
|
||||||
<div
|
<div
|
||||||
className={"text-sm font-bold cursor-pointer"}
|
className={"text-sm font-bold cursor-pointer"}
|
||||||
onClick={() => navigate(`/user/${comment.user.username}`)}
|
onClick={() => {
|
||||||
|
navigate(`/user/${encodeURIComponent(comment.user.username)}`);
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
{comment.user.username}
|
{comment.user.username}
|
||||||
</div>
|
</div>
|
||||||
@@ -1388,11 +1392,7 @@ function DeleteFileDialog({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function EditCommentDialog({
|
function EditCommentDialog({ comment }: { comment: Comment }) {
|
||||||
comment,
|
|
||||||
}: {
|
|
||||||
comment: Comment;
|
|
||||||
}) {
|
|
||||||
const [isLoading, setLoading] = useState(false);
|
const [isLoading, setLoading] = useState(false);
|
||||||
const [content, setContent] = useState(comment.content);
|
const [content, setContent] = useState(comment.content);
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
@@ -1474,7 +1474,10 @@ function DeleteCommentDialog({ commentId }: { commentId: number }) {
|
|||||||
const dialog = document.getElementById(id) as HTMLDialogElement;
|
const dialog = document.getElementById(id) as HTMLDialogElement;
|
||||||
dialog.close();
|
dialog.close();
|
||||||
if (res.success) {
|
if (res.success) {
|
||||||
showToast({ message: t("Comment deleted successfully"), type: "success" });
|
showToast({
|
||||||
|
message: t("Comment deleted successfully"),
|
||||||
|
type: "success",
|
||||||
|
});
|
||||||
reload();
|
reload();
|
||||||
} else {
|
} else {
|
||||||
showToast({ message: res.message, type: "error" });
|
showToast({ message: res.message, type: "error" });
|
||||||
@@ -1498,7 +1501,9 @@ function DeleteCommentDialog({ commentId }: { commentId: number }) {
|
|||||||
<div className="modal-box">
|
<div className="modal-box">
|
||||||
<h3 className="font-bold text-lg">{t("Delete Comment")}</h3>
|
<h3 className="font-bold text-lg">{t("Delete Comment")}</h3>
|
||||||
<p className="py-4">
|
<p className="py-4">
|
||||||
{t("Are you sure you want to delete this comment? This action cannot be undone.")}
|
{t(
|
||||||
|
"Are you sure you want to delete this comment? This action cannot be undone.",
|
||||||
|
)}
|
||||||
</p>
|
</p>
|
||||||
<div className="modal-action">
|
<div className="modal-action">
|
||||||
<form method="dialog">
|
<form method="dialog">
|
||||||
|
@@ -11,7 +11,10 @@ import { MdOutlineArrowRight } from "react-icons/md";
|
|||||||
export default function UserPage() {
|
export default function UserPage() {
|
||||||
const [user, setUser] = useState<User | null>(null);
|
const [user, setUser] = useState<User | null>(null);
|
||||||
|
|
||||||
const { username } = useParams();
|
const { username: rawUsername } = useParams();
|
||||||
|
|
||||||
|
// 解码用户名,确保特殊字符被还原
|
||||||
|
const username = rawUsername ? decodeURIComponent(rawUsername) : "";
|
||||||
|
|
||||||
const [page, setPage] = useState(0);
|
const [page, setPage] = useState(0);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user