From baa60bbfcb27599f29eff3b709b63e03776e56fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E6=88=90?= Date: Sat, 14 Feb 2026 13:56:54 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=86=85=E5=AE=B9=E8=BF=87?= =?UTF-8?q?=E6=BB=A4=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Comments/index.tsx | 64 ++++--- src/components/UserInfo/index.tsx | 10 +- src/publish_pages/publishBall/index.tsx | 217 ++++++++++++------------ src/store/userStore.ts | 5 + src/user_pages/edit/index.tsx | 9 +- src/utils/helper.ts | 13 ++ 6 files changed, 171 insertions(+), 147 deletions(-) diff --git a/src/components/Comments/index.tsx b/src/components/Comments/index.tsx index 21fb5b2..b907347 100644 --- a/src/components/Comments/index.tsx +++ b/src/components/Comments/index.tsx @@ -11,7 +11,7 @@ import dayjs from "dayjs"; import classnames from "classnames"; import CommentServices from "@/services/commentServices"; import messageService from "@/services/messageService"; -import { delay } from "@/utils"; +import { delay, getBackendErrorMsg } from "@/utils"; import type { BaseComment, Comment, @@ -459,36 +459,48 @@ export default forwardRef(function Comments( } async function createComment(val: string) { - const res = await CommentServices.createComment({ game_id, content: val }); - if (res.code === 0) { - setComments((prev) => { - commentCountUpdateRef.current?.(prev.length + 1); - return [{ ...res.data, replies: [] }, ...prev]; - }); - toast("发布成功"); + try { + const res = await CommentServices.createComment({ game_id, content: val }); + if (res.code === 0) { + setComments((prev) => { + commentCountUpdateRef.current?.(prev.length + 1); + return [{ ...res.data, replies: [] }, ...prev]; + }); + toast("发布成功"); + } else { + toast(getBackendErrorMsg(res, "评论失败")); + } + } catch (error) { + toast(getBackendErrorMsg(error, "评论失败")); } } async function replyComment({ parent_id, reply_to_user_id, content }) { - const res = await CommentServices.replyComment({ - parent_id, - reply_to_user_id, - content, - }); - if (res.code === 0) { - setComments((prev) => { - return prev.map((item) => { - if (item.id === parent_id) { - return { - ...item, - replies: [res.data, ...item.replies], - reply_count: item.reply_count + 1, - }; - } - return item; - }); + try { + const res = await CommentServices.replyComment({ + parent_id, + reply_to_user_id, + content, }); - toast("回复成功"); + if (res.code === 0) { + setComments((prev) => { + return prev.map((item) => { + if (item.id === parent_id) { + return { + ...item, + replies: [res.data, ...item.replies], + reply_count: item.reply_count + 1, + }; + } + return item; + }); + }); + toast("回复成功"); + } else { + toast(getBackendErrorMsg(res, "回复失败")); + } + } catch (error) { + toast(getBackendErrorMsg(error, "回复失败")); } } diff --git a/src/components/UserInfo/index.tsx b/src/components/UserInfo/index.tsx index e23774d..aa0a2ec 100644 --- a/src/components/UserInfo/index.tsx +++ b/src/components/UserInfo/index.tsx @@ -18,7 +18,7 @@ import { useProfessions, useNtrpLevels, } from "@/store/pickerOptionsStore"; -import { formatNtrpDisplay } from "@/utils/helper"; +import { formatNtrpDisplay, getBackendErrorMsg } from "@/utils/helper"; import { useGlobalState } from "@/store/global"; // 用户信息接口 @@ -252,8 +252,8 @@ const UserInfoCardComponent: React.FC = ({ } catch (error) { console.warn("保存失败:", error); Taro.showToast({ - title: "保存失败", - icon: "error", + title: getBackendErrorMsg(error, "保存失败"), + icon: "none", }); } }; @@ -295,8 +295,8 @@ const UserInfoCardComponent: React.FC = ({ } catch (error) { console.warn("保存失败:", error); Taro.showToast({ - title: "保存失败", - icon: "error", + title: getBackendErrorMsg(error, "保存失败"), + icon: "none", }); } }; diff --git a/src/publish_pages/publishBall/index.tsx b/src/publish_pages/publishBall/index.tsx index 8076856..51cb87b 100644 --- a/src/publish_pages/publishBall/index.tsx +++ b/src/publish_pages/publishBall/index.tsx @@ -13,7 +13,7 @@ import { } from "../../config/formSchema/publishBallFormSchema"; import { PublishBallFormData } from "../../../types/publishBall"; import PublishService from "@/services/publishService"; -import { getNextHourTime, getEndTime, delay } from "@/utils"; +import { getNextHourTime, getEndTime, delay, getBackendErrorMsg } from "@/utils"; import { useGlobalState } from "@/store/global"; import GeneralNavbar from "@/components/GeneralNavbar"; import images from "@/config/images"; @@ -364,104 +364,27 @@ const PublishBall: React.FC = () => { }; // 提交表单 const handleSubmit = async () => { - // 基础验证 const params = getParams(); const { republish } = params || {}; if (activityType === "individual") { const isValid = validateFormData(formData[0]); - if (!isValid || publishLoading) { - return; - } + if (!isValid || publishLoading) return; setPublishLoading(true); - const { - activityInfo, - descriptionInfo, - is_substitute_supported, - timeRange, - players, - skill_level, - image_list, - wechat, - id, - ...rest - } = formData[0]; - const { min, max, organizer_joined } = players; - const options = { - ...rest, - ...activityInfo, - ...descriptionInfo, - ...timeRange, - max_players: max, - min_players: min, - organizer_joined: organizer_joined === true ? 1 : 0, - skill_level_min: skill_level[0], - skill_level_max: skill_level[1], - image_list: image_list.map((item) => item.url), - is_wechat_contact: wechat.is_wechat_contact ? 1 : 0, - wechat_contact: wechat.wechat_contact || wechat.default_wechat_contact, - is_substitute_supported: is_substitute_supported ? "1" : "0", - ...(republish === "0" ? { id } : {}), - }; - const res = - republish === "0" - ? await PublishService.gamesUpdate(options) - : await PublishService.createPersonal(options); - const successText = republish === "0" ? "更新成功" : "发布成功"; - if (res.code === 0 && res.data) { - Taro.showToast({ - title: successText, - icon: "success", - }); - delay(1000); - // 如果是个人球局,则跳转到详情页,并自动分享 - // 如果是畅打,则跳转第一个球局详情页,并自动分享 @刘杰 - const id = (res as any).data?.id; - // 如果是编辑,就返回,否则就是新发布 - if (republish === "0") { - Taro.navigateBack(); - } else { - // 使用 redirectTo 替换当前页面,避免返回时回到发布页面 - Taro.redirectTo({ - // @ts-expect-error: id - url: `/game_pages/detail/index?id=${ - id || 1 - }&from=publish&autoShare=1`, - }); - } - } else { - Taro.showToast({ - title: res.message, - icon: "none", - }); - setPublishLoading(false); - } - } - if (activityType === "group") { - const isValid = formData.every((item) => validateFormData(item)); - if (!isValid || publishLoading) { - return; - } - setPublishLoading(true); - if (checkAdjacentDataSame(formData)) { - Taro.showToast({ - title: "信息不可与前序场完全一致", - icon: "none", - }); - return; - } - const options = formData.map((item) => { + try { const { activityInfo, descriptionInfo, + is_substitute_supported, timeRange, players, skill_level, - is_substitute_supported, + image_list, + wechat, id, ...rest - } = item; + } = formData[0]; const { min, max, organizer_joined } = players; - return { + const options = { ...rest, ...activityInfo, ...descriptionInfo, @@ -471,38 +394,108 @@ const PublishBall: React.FC = () => { organizer_joined: organizer_joined === true ? 1 : 0, skill_level_min: skill_level[0], skill_level_max: skill_level[1], + image_list: image_list.map((item) => item.url), + is_wechat_contact: wechat.is_wechat_contact ? 1 : 0, + wechat_contact: wechat.wechat_contact || wechat.default_wechat_contact, is_substitute_supported: is_substitute_supported ? "1" : "0", - image_list: item.image_list.map((img) => img.url), ...(republish === "0" ? { id } : {}), }; - }); - const successText = republish === "0" ? "更新成功" : "发布成功"; - const res = - republish === "0" - ? await PublishService.gamesUpdate(options[0]) - : await PublishService.create_play_pmoothlys({ rows: options }); - if (res.code === 0 && res.data) { - Taro.showToast({ - title: successText, - icon: "success", - }); - delay(1000); - // 如果是个人球局,则跳转到详情页,并自动分享 - // 如果是畅打,则跳转第一个球局详情页,并自动分享 @刘杰 - const id = + const res = republish === "0" - ? (res as any).data?.id - : (res as any).data?.[0]?.id; - // 使用 redirectTo 替换当前页面,避免返回时回到发布页面 - Taro.redirectTo({ - // @ts-expect-error: id - url: `/game_pages/detail/index?id=${ - id || 1 - }&from=publish&autoShare=1`, - }); - } else { + ? await PublishService.gamesUpdate(options) + : await PublishService.createPersonal(options); + const successText = republish === "0" ? "更新成功" : "发布成功"; + if (res.code === 0 && res.data) { + Taro.showToast({ title: successText, icon: "success" }); + delay(1000); + const id = (res as any).data?.id; + if (republish === "0") { + Taro.navigateBack(); + } else { + Taro.redirectTo({ + url: `/game_pages/detail/index?id=${id || 1}&from=publish&autoShare=1`, + }); + } + } else { + Taro.showToast({ + title: getBackendErrorMsg(res, "发布失败"), + icon: "none", + }); + setPublishLoading(false); + } + } catch (error) { Taro.showToast({ - title: res.message, + title: getBackendErrorMsg(error, "发布失败"), + icon: "none", + }); + setPublishLoading(false); + } + return; + } + if (activityType === "group") { + const isValid = formData.every((item) => validateFormData(item)); + if (!isValid || publishLoading) return; + if (checkAdjacentDataSame(formData)) { + Taro.showToast({ + title: "信息不可与前序场完全一致", + icon: "none", + }); + return; + } + setPublishLoading(true); + try { + const options = formData.map((item) => { + const { + activityInfo, + descriptionInfo, + timeRange, + players, + skill_level, + is_substitute_supported, + id, + ...rest + } = item; + const { min, max, organizer_joined } = players; + return { + ...rest, + ...activityInfo, + ...descriptionInfo, + ...timeRange, + max_players: max, + min_players: min, + organizer_joined: organizer_joined === true ? 1 : 0, + skill_level_min: skill_level[0], + skill_level_max: skill_level[1], + is_substitute_supported: is_substitute_supported ? "1" : "0", + image_list: item.image_list.map((img) => img.url), + ...(republish === "0" ? { id } : {}), + }; + }); + const successText = republish === "0" ? "更新成功" : "发布成功"; + const res = + republish === "0" + ? await PublishService.gamesUpdate(options[0]) + : await PublishService.create_play_pmoothlys({ rows: options }); + if (res.code === 0 && res.data) { + Taro.showToast({ title: successText, icon: "success" }); + delay(1000); + const id = + republish === "0" + ? (res as any).data?.id + : (res as any).data?.[0]?.id; + Taro.redirectTo({ + url: `/game_pages/detail/index?id=${id || 1}&from=publish&autoShare=1`, + }); + } else { + Taro.showToast({ + title: getBackendErrorMsg(res, "发布失败"), + icon: "none", + }); + setPublishLoading(false); + } + } catch (error) { + Taro.showToast({ + title: getBackendErrorMsg(error, "发布失败"), icon: "none", }); setPublishLoading(false); diff --git a/src/store/userStore.ts b/src/store/userStore.ts index bc32b85..fcebfa9 100644 --- a/src/store/userStore.ts +++ b/src/store/userStore.ts @@ -12,6 +12,7 @@ import evaluateService, { LastTimeTestResult, } from "@/services/evaluateService"; import { useListStore } from "./listStore"; +import { getBackendErrorMsg } from "@/utils/helper"; export interface UserState { user: UserInfoType | {}; @@ -123,6 +124,10 @@ export const useUser = create()((set) => ({ // 如果需要确保数据一致性,可以在特定场景下手动调用 fetchUserInfo } catch (error) { console.warn("更新用户信息失败:", error); + Taro.showToast({ + title: getBackendErrorMsg(error, "保存失败"), + icon: "none", + }); throw error; } }, diff --git a/src/user_pages/edit/index.tsx b/src/user_pages/edit/index.tsx index 0461f7e..1348765 100644 --- a/src/user_pages/edit/index.tsx +++ b/src/user_pages/edit/index.tsx @@ -22,6 +22,7 @@ import { } from "@/store/pickerOptionsStore"; import { handleCustomerService } from "@/services/userService"; import evaluateService from "@/services/evaluateService"; +import { getBackendErrorMsg } from "@/utils/helper"; const EditProfilePage: React.FC = () => { const { updateUserInfo, updateNickname } = useUserActions(); @@ -248,8 +249,8 @@ const EditProfilePage: React.FC = () => { } catch (error) { console.warn("保存失败:", error); Taro.showToast({ - title: "保存失败", - icon: "error", + title: getBackendErrorMsg(error, "保存失败"), + icon: "none", }); } }; @@ -309,8 +310,8 @@ const EditProfilePage: React.FC = () => { } catch (error) { console.warn("保存失败:", error); Taro.showToast({ - title: "保存失败", - icon: "error", + title: getBackendErrorMsg(error, "保存失败"), + icon: "none", }); } }; diff --git a/src/utils/helper.ts b/src/utils/helper.ts index 1e85644..16380bc 100644 --- a/src/utils/helper.ts +++ b/src/utils/helper.ts @@ -94,6 +94,19 @@ export function toast(message) { Taro.showToast({ title: message, icon: "none" }); } +/** 从接口/请求错误中取出后端返回的文案,用于保存失败等场景的 toast */ +export function getBackendErrorMsg(error: any, fallback = "操作失败"): string { + if (error == null) return fallback; + const msg = + error?.message || + (typeof error?.error === "string" ? error.error : error?.error?.message) || + error?.data?.message || + error?.data?.msg || + ""; + const s = String(msg).trim(); + return s || fallback; +} + // 将·作为连接符插入到标签文本之间 export function insertDotInTags(tags: string[]) { if (!tags) return [];