diff --git a/src/app.config.ts b/src/app.config.ts
index 52281f8..5e46beb 100644
--- a/src/app.config.ts
+++ b/src/app.config.ts
@@ -9,6 +9,7 @@ export default defineAppConfig({
"game_pages/search/index", // 搜索页
"game_pages/searchResult/index", // 搜索结果页面
"game_pages/detail/index", // 球局详情页
+ "game_pages/sharePoster/index",
],
subPackages: [
diff --git a/src/components/Comments/index.tsx b/src/components/Comments/index.tsx
index 197e4b5..67c6c39 100644
--- a/src/components/Comments/index.tsx
+++ b/src/components/Comments/index.tsx
@@ -181,7 +181,7 @@ function CommentItem(props: {
blink_id,
} = props;
const currentUserInfo = useUserInfo();
- const isGamePublisher = publisher_id === comment.user.id;
+ const isGamePublisher = publisher_id === currentUserInfo.id;
const isCommentPublisher = currentUserInfo.id === comment.user.id;
return (
{getRelativeDay(comment.create_time)}
- 上海
+ {comment.user.province}
回复
- {isGamePublisher || isCommentPublisher}
-
- handleDelete({
- parent_id: comment.parent_id,
- id: comment.id,
- })
- }
- >
- 删除
-
+ {(isGamePublisher || isCommentPublisher) && (
+
+ handleDelete({
+ parent_id: comment.parent_id,
+ id: comment.id,
+ })
+ }
+ >
+ 删除
+
+ )}
{!isReplyComment(comment) &&
diff --git a/src/game_pages/detail/components/Carousel/index.module.scss b/src/game_pages/detail/components/Carousel/index.module.scss
new file mode 100644
index 0000000..72c52ec
--- /dev/null
+++ b/src/game_pages/detail/components/Carousel/index.module.scss
@@ -0,0 +1,34 @@
+.detail-swiper-container {
+ height: 270px;
+ width: 100%;
+ padding: 15px 15px 0;
+ box-sizing: border-box;
+ overflow-x: scroll;
+ &::-webkit-scrollbar {
+ display: none;
+ width: 0;
+ height: 0;
+ color: transparent; /* 透明色 */
+ }
+
+ .detail-swiper-scroll-container {
+ display: flex;
+ height: 250px;
+ width: auto;
+ align-items: center;
+ justify-content: flex-start;
+ flex-wrap: nowrap;
+ gap: 12px;
+
+ .detail-swiper-item {
+ flex: 0 0 auto;
+ height: 250px;
+ display: flex;
+ align-items: center;
+ &-image {
+ border-radius: 12px;
+ transition: transform 0.5s;
+ }
+ }
+ }
+}
diff --git a/src/game_pages/detail/components/Carousel/index.tsx b/src/game_pages/detail/components/Carousel/index.tsx
new file mode 100644
index 0000000..a56de35
--- /dev/null
+++ b/src/game_pages/detail/components/Carousel/index.tsx
@@ -0,0 +1,84 @@
+import Taro from "@tarojs/taro";
+import { useEffect, useState } from "react";
+import { View, Image } from "@tarojs/components";
+import styles from "./index.module.scss";
+
+type CarouselItemType = {
+ url: string;
+ width: number;
+ height: number;
+};
+export default function Carousel(props) {
+ const { detail } = props;
+ const [list, setList] = useState([]);
+ const [listWidth, setListWidth] = useState(0);
+ const { image_list } = detail;
+
+ async function getImagesMsg(imageList) {
+ const latest_list: CarouselItemType[] = [];
+ const sys_info = await Taro.getSystemInfo();
+ const max_width = sys_info.screenWidth - 30;
+ const max_height = 240;
+ const current_aspect_ratio = max_width / max_height;
+ let container_width = 0;
+ for (const imageUrl of imageList) {
+ const { width, height } = await Taro.getImageInfo({ src: imageUrl });
+ if (width && height) {
+ const aspect_ratio = width / height;
+ const latest_w_h = { width, height };
+ if (aspect_ratio < current_aspect_ratio) {
+ latest_w_h.width = max_height * aspect_ratio;
+ latest_w_h.height = max_height;
+ } else {
+ latest_w_h.width = max_width;
+ latest_w_h.height = max_width / aspect_ratio;
+ }
+ container_width += latest_w_h.width + 12;
+ latest_list.push({
+ url: imageUrl,
+ width: latest_w_h.width,
+ height: latest_w_h.height,
+ });
+ }
+ }
+ setList(latest_list);
+ setListWidth(container_width);
+ }
+
+ useEffect(() => {
+ getImagesMsg(image_list || []);
+ }, [image_list]);
+
+ function previewImage(current_url) {
+ Taro.previewImage({
+ current: current_url,
+ urls: list?.length > 0 ? list.map((c) => c.url) : [],
+ });
+ }
+
+ return (
+
+
+ {list.map((item, index) => {
+ return (
+ previewImage(item.url)}
+ >
+
+
+ );
+ })}
+
+
+ );
+}
diff --git a/src/game_pages/detail/components/GameInfo/index.module.scss b/src/game_pages/detail/components/GameInfo/index.module.scss
new file mode 100644
index 0000000..b71dd6c
--- /dev/null
+++ b/src/game_pages/detail/components/GameInfo/index.module.scss
@@ -0,0 +1,201 @@
+.detail-page-content-game-info {
+ &-date-weather {
+ padding: 20px 20px 0;
+ box-sizing: border-box;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ // gap: 12px;
+
+ &-calendar-date {
+ width: 60%;
+ display: flex;
+ align-items: center;
+ gap: 16px;
+
+ &-calendar {
+ display: flex;
+ width: 48px;
+ height: 48px;
+ box-sizing: border-box;
+ flex-direction: column;
+ align-items: center;
+ gap: 4px;
+ border-radius: 12px;
+ // border: 0.5px solid rgba(255, 255, 255, 0.08);
+ background: rgba(255, 255, 255, 0.25);
+ overflow: hidden;
+ color: #fff;
+ background: #536272;
+
+ .month {
+ width: 100%;
+ height: 18px;
+ font-size: 10px;
+ display: flex;
+ padding: 1px auto;
+ box-sizing: border-box;
+ justify-content: center;
+ align-items: center;
+ // border-bottom: 1px solid rgba(255, 255, 255, 0.08);
+ background: #7b828b;
+ }
+
+ .day {
+ display: flex;
+ width: 48px;
+ height: 30px;
+ // padding-bottom: 6px;
+ box-sizing: border-box;
+ flex-direction: column;
+ align-items: center;
+ // border: 0.5px solid rgba(255, 255, 255, 0.08);
+ // background: rgba(255, 255, 255, 0.25);
+ // background-color: #536272;
+ }
+ }
+
+ &-date {
+ display: flex;
+ flex-direction: column;
+ align-items: flex-start;
+ justify-content: space-evenly;
+ gap: 4px;
+ align-self: stretch;
+ color: #fff;
+
+ .date {
+ color: #fff;
+ font-feature-settings: "liga" off, "clig" off;
+ font-family: "PingFang SC";
+ font-size: 16px;
+ font-style: normal;
+ font-weight: 600;
+ line-height: 24px; /* 150% */
+ }
+
+ .venue-time {
+ color: rgba(255, 255, 255, 0.8);
+ font-feature-settings: "liga" off, "clig" off;
+ font-family: "PingFang SC";
+ font-size: 12px;
+ font-style: normal;
+ font-weight: 400;
+ line-height: 20px; /* 166.667% */
+ }
+ }
+ }
+
+ &-weather {
+ display: flex;
+ align-items: flex-end;
+ flex-direction: column;
+ gap: 4px;
+
+ &-icon {
+ width: 20px;
+ height: 20px;
+ color: rgba(255, 255, 255, 0.8);
+ }
+ &-text-temperature {
+ display: flex;
+ align-items: center;
+ gap: 12px;
+ color: rgba(255, 255, 255, 0.8);
+ font-feature-settings: "liga" off, "clig" off;
+ font-family: "PingFang SC";
+ font-size: 12px;
+ font-style: normal;
+ font-weight: 400;
+ line-height: 20px; /* 166.667% */
+ }
+ }
+ }
+
+ &-place {
+ .location-message {
+ padding: 20px 20px 0;
+ box-sizing: border-box;
+ display: flex;
+ align-items: center;
+ justify-content: flex-start;
+ gap: 12px;
+
+ &-icon {
+ width: 48px;
+ height: 48px;
+ border-radius: 12px;
+ padding: 14px;
+ box-sizing: border-box;
+ background: #4d5865;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ overflow: hidden;
+ // border: 0.5px solid rgba(255, 255, 255, 0.08);
+ // background: rgba(255, 255, 255, 0.25);
+
+ &-image {
+ width: 20px;
+ height: 20px;
+ }
+ }
+
+ &-text {
+ display: flex;
+ flex-direction: column;
+ align-items: flex-start;
+ justify-content: space-evenly;
+ gap: 4px;
+ align-self: stretch;
+
+ &-name-distance {
+ display: flex;
+ align-items: center;
+ gap: 4px;
+ color: #fff;
+ text-align: center;
+ font-feature-settings: "liga" off, "clig" off;
+ font-family: "PingFang SC";
+ font-size: 16px;
+ font-style: normal;
+ font-weight: 600;
+ line-height: 24px; /* 150% */
+
+ &-arrow {
+ width: 16px;
+ height: 16px;
+ }
+ }
+
+ &-address {
+ color: rgba(255, 255, 255, 0.8);
+ text-align: center;
+ font-feature-settings: "liga" off, "clig" off;
+ font-family: "PingFang SC";
+ font-size: 12px;
+ font-style: normal;
+ font-weight: 400;
+ line-height: 20px; /* 166.667% */
+ }
+ }
+ }
+
+ .location-map {
+ width: 100%;
+ padding: 20px 20px 0;
+ box-sizing: border-box;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ overflow: hidden;
+ border-radius: 12px;
+
+ &-map {
+ width: 100%;
+ height: 95px;
+ border-radius: 12px;
+ }
+ }
+ }
+}
diff --git a/src/game_pages/detail/components/GameInfo/index.tsx b/src/game_pages/detail/components/GameInfo/index.tsx
new file mode 100644
index 0000000..5aea090
--- /dev/null
+++ b/src/game_pages/detail/components/GameInfo/index.tsx
@@ -0,0 +1,188 @@
+import Taro from "@tarojs/taro";
+import dayjs from "dayjs";
+import "dayjs/locale/zh-cn";
+import { calculateDistance } from "@/utils";
+import { View, Image, Text, Map } from "@tarojs/components";
+import img from "@/config/images";
+import styles from "./index.module.scss";
+
+dayjs.locale("zh-cn");
+
+// 球局信息
+export default function GameInfo(props) {
+ const { detail, currentLocation } = props;
+ const {
+ latitude,
+ longitude,
+ location,
+ location_name,
+ start_time,
+ end_time,
+ weather,
+ } = detail || {};
+
+ const [{ iconDay, tempMax, tempMin }] = weather || [{}];
+
+ const openMap = () => {
+ Taro.openLocation({
+ latitude, // 纬度(必填)
+ longitude, // 经度(必填)
+ name: location_name, // 位置名(可选)
+ address: location, // 地址详情(可选)
+ scale: 15, // 地图缩放级别(1-28)
+ });
+ };
+
+ const [c_latitude, c_longitude] = currentLocation;
+ const distance =
+ latitude && longitude
+ ? calculateDistance(c_latitude, c_longitude, latitude, longitude) / 1000
+ : 0;
+
+ const startTime = dayjs(start_time);
+ const endTime = dayjs(end_time);
+ const game_length = endTime.diff(startTime, "minutes") / 60;
+
+ const startMonth = startTime.format("M");
+ const startDay = startTime.format("D");
+ const theDayOfWeek = startTime.format("dddd");
+ const startDate = `${startMonth}月${startDay}日 ${theDayOfWeek}`;
+ const gameRange = `${startTime.format("HH:mm")} - ${endTime.format("HH:mm")}`;
+
+ return (
+
+ {/* Date and Weather */}
+
+ {/* Calendar and Date time */}
+
+ {/* Calendar */}
+
+ {startMonth}月
+ {startDay}
+
+ {/* Date time */}
+
+ {startDate}
+
+ {gameRange} ({game_length}小时)
+
+
+
+ {/* Weather */}
+
+ {/* Weather icon */}
+
+ {/**/}
+
+
+ {/* Weather text and temperature */}
+
+ {tempMin && tempMax && (
+
+ {tempMin}℃ - {tempMax}℃
+
+ )}
+
+
+
+ {/* Place */}
+
+ {/* venue location message */}
+
+ {/* location icon */}
+
+
+
+ {/* location message */}
+
+ {/* venue name and distance */}
+ {distance ? (
+
+ {location_name || "-"}
+ ·
+ {distance.toFixed(1)}km
+
+
+ ) : (
+ ""
+ )}
+ {/* venue address */}
+
+ {location || "-"}
+
+
+
+ {/* venue map */}
+
+ {longitude && latitude && (
+
+
+
+ );
+}
diff --git a/src/game_pages/detail/components/GamePlayAndReq/index.module.scss b/src/game_pages/detail/components/GamePlayAndReq/index.module.scss
new file mode 100644
index 0000000..fe7c364
--- /dev/null
+++ b/src/game_pages/detail/components/GamePlayAndReq/index.module.scss
@@ -0,0 +1,54 @@
+.detail-page-content-gameplay-requirements {
+ padding: 24px 15px 0;
+ box-sizing: border-box;
+
+ .gameplay-requirements-title {
+ overflow: hidden;
+ color: #fff;
+ height: 24px;
+ padding-bottom: 6px;
+ font-feature-settings: "liga" off, "clig" off;
+ text-overflow: ellipsis;
+ font-family: "PingFang SC";
+ font-size: 16px;
+ font-style: normal;
+ font-weight: 600;
+ line-height: 24px; /* 150% */
+ border-bottom: 1px solid rgba(255, 255, 255, 0.1);
+ }
+
+ .gameplay-requirements {
+ padding: 12px 0 0;
+ display: flex;
+ flex-direction: column;
+ gap: 12px;
+
+ &-item {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ gap: 2px;
+ align-self: stretch;
+
+ &-title {
+ color: rgba(255, 255, 255, 0.8);
+ font-feature-settings: "liga" off, "clig" off;
+ font-family: "PingFang SC";
+ font-size: 14px;
+ font-style: normal;
+ font-weight: 400;
+ line-height: 24px; /* 171.429% */
+ }
+
+ &-desc {
+ color: #fff;
+ font-feature-settings: "liga" off, "clig" off;
+ font-family: "PingFang SC";
+ font-size: 15px;
+ font-style: normal;
+ font-weight: 600;
+ line-height: 24px; /* 160% */
+ }
+ }
+ }
+}
diff --git a/src/game_pages/detail/components/GamePlayAndReq/index.tsx b/src/game_pages/detail/components/GamePlayAndReq/index.tsx
new file mode 100644
index 0000000..ae81fe2
--- /dev/null
+++ b/src/game_pages/detail/components/GamePlayAndReq/index.tsx
@@ -0,0 +1,46 @@
+import { View, Text } from "@tarojs/components";
+import { genNTRPRequirementText } from "../../utils/helper";
+import styles from "./index.module.scss";
+
+// 玩法要求
+export default function GamePlayAndRequirement(props) {
+ const {
+ detail: { skill_level_min, skill_level_max, play_type, game_type },
+ } = props;
+
+ const requirements = [
+ {
+ title: "NTRP水平要求",
+ desc: genNTRPRequirementText(skill_level_min, skill_level_max),
+ },
+ {
+ title: "活动玩法",
+ desc: play_type || "-",
+ },
+ {
+ title: "人员构成",
+ desc: game_type || "-",
+ },
+ ];
+ return (
+
+ {/* title */}
+
+ 玩法要求
+
+ {/* requirements */}
+
+ {requirements.map((item, index) => (
+
+
+ {item.title}
+
+
+ {item.desc}
+
+
+ ))}
+
+
+ );
+}
diff --git a/src/game_pages/detail/components/GameTags/index.module.scss b/src/game_pages/detail/components/GameTags/index.module.scss
new file mode 100644
index 0000000..397759c
--- /dev/null
+++ b/src/game_pages/detail/components/GameTags/index.module.scss
@@ -0,0 +1,44 @@
+.detail-page-content-avatar-tags {
+ padding: 20px 20px 0;
+ box-sizing: border-box;
+ display: flex;
+ align-items: center;
+ gap: 6px;
+
+ &-avatar {
+ width: 28px;
+ height: 28px;
+ border-radius: 50%;
+ overflow: hidden;
+
+ &-image {
+ width: 28px;
+ height: 28px;
+ }
+ }
+
+ &-tags {
+ display: flex;
+ align-items: center;
+ flex-wrap: wrap;
+ gap: 6px;
+
+ &-tag {
+ display: flex;
+ height: 28px;
+ padding: 6px 12px;
+ box-sizing: border-box;
+ align-items: center;
+ gap: 4px;
+ border-radius: 999px;
+ border: 0.5px solid rgba(255, 255, 255, 0.08);
+ background: rgba(255, 255, 255, 0.25);
+ color: #fff;
+ font-size: 13px;
+ font-weight: 500;
+ line-height: 20px;
+ letter-spacing: -0.23px;
+ text-align: center;
+ }
+ }
+}
diff --git a/src/game_pages/detail/components/GameTags/index.tsx b/src/game_pages/detail/components/GameTags/index.tsx
new file mode 100644
index 0000000..ed04ab1
--- /dev/null
+++ b/src/game_pages/detail/components/GameTags/index.tsx
@@ -0,0 +1,49 @@
+import { View, Text, Image } from "@tarojs/components";
+import styles from "./index.module.scss";
+
+export default function GameTags(props) {
+ const { userInfo, handleViewUserInfo } = props;
+ const { avatar_url, id } = userInfo;
+ const tags = [
+ // {
+ // name: "🕙 急招",
+ // icon: "",
+ // },
+ // {
+ // name: "🔥 本周热门",
+ // icon: "",
+ // },
+ // {
+ // name: "🎉 新活动",
+ // icon: "",
+ // },
+ // {
+ // name: "官方组织",
+ // icon: "",
+ // },
+ ];
+ return (
+
+
+ {/* network image mock */}
+
+
+
+ {tags.map((tag, index) => (
+
+ {tag.icon && }
+ {tag.name}
+
+ ))}
+
+
+ );
+}
diff --git a/src/game_pages/detail/components/OrganizerInfo/index.module.scss b/src/game_pages/detail/components/OrganizerInfo/index.module.scss
new file mode 100644
index 0000000..bebb99d
--- /dev/null
+++ b/src/game_pages/detail/components/OrganizerInfo/index.module.scss
@@ -0,0 +1,239 @@
+.detail-page-content-organizer-recommend-games {
+ padding: 24px 15px 10px;
+
+ .organizer-title {
+ overflow: hidden;
+ padding-bottom: 6px;
+ height: 24px;
+ color: #fff;
+ font-feature-settings: "liga" off, "clig" off;
+ text-overflow: ellipsis;
+ font-family: "PingFang SC";
+ font-size: 16px;
+ font-style: normal;
+ font-weight: 600;
+ line-height: 24px; /* 150% */
+ border-bottom: 1px solid rgba(255, 255, 255, 0.1);
+ }
+
+ .organizer-avatar-name {
+ display: flex;
+ align-items: center;
+ padding: 16px 0 0;
+ align-items: center;
+ gap: 8px;
+ justify-content: flex-start;
+
+ &-avatar {
+ width: 40px;
+ height: 40px;
+ border-radius: 50%;
+ object-fit: cover;
+ }
+
+ &-message {
+ display: flex;
+ flex-direction: column;
+ gap: 4px;
+
+ &-name {
+ color: rgba(255, 255, 255, 0.85);
+ font-size: 13px;
+ font-style: normal;
+ font-weight: 500;
+ line-height: 24px; /* 184.615% */
+ }
+
+ &-stats {
+ display: flex;
+ align-items: center;
+ gap: 5px;
+ color: rgba(255, 255, 255, 0.6);
+ font-size: 12px;
+ font-style: normal;
+ font-weight: 400;
+ line-height: 16px; /* 133.333% */
+ letter-spacing: 0.06px;
+
+ &-separator {
+ width: 1px;
+ height: 10px;
+ color: rgba(255, 255, 255, 0.2);
+ }
+ }
+ }
+
+ .organizer-actions {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ margin-left: auto;
+
+ .organizer-actions-follow,
+ .organizer-actions-comment {
+ display: flex;
+ height: 32px;
+ box-sizing: border-box;
+ align-items: center;
+ gap: 4px;
+ border-radius: 999px;
+ // border: 0.5px solid rgba(255, 255, 255, 0.10);
+ background: rgba(255, 255, 255, 0.16);
+ box-shadow: 0 4px 48px 0 rgba(0, 0, 0, 0.08);
+
+ & > image {
+ width: 16px;
+ height: 16px;
+ }
+ }
+
+ .organizer-actions-follow {
+ padding: 8px 12px 8px;
+ &-text {
+ color: #fff;
+ font-size: 13px;
+ font-style: normal;
+ font-weight: 500;
+ line-height: 20px; /* 153.846% */
+ letter-spacing: -0.23px;
+ }
+ }
+
+ .organizer-actions-comment {
+ padding: 8px 10px;
+ }
+ }
+ }
+
+ .organizer-recommend-games {
+ padding-top: 20px;
+
+ .organizer-recommend-games-title {
+ overflow: hidden;
+ color: rgba(255, 255, 255, 0.65);
+ font-family: "PingFang SC";
+ font-size: 15px;
+ font-style: normal;
+ font-weight: 500;
+ line-height: 24px; /* 160% */
+ display: flex;
+ align-items: center;
+ gap: 2px;
+ align-self: stretch;
+
+ &-arrow {
+ width: 12px;
+ height: 12px;
+ }
+ }
+
+ .recommend-games-list {
+ padding: 10px 0;
+ display: flex;
+ gap: 8px;
+ flex-wrap: nowrap;
+
+ &-content {
+ display: flex;
+ gap: 8px;
+ flex-wrap: nowrap;
+
+ .recommend-games-list-item {
+ width: 246px;
+ height: 122px;
+ display: flex;
+ flex-direction: column;
+ gap: 6px;
+ flex: 0 0 auto;
+ border-radius: 20px;
+ border: 1px solid rgba(33, 178, 0, 0.2);
+ background: rgba(255, 255, 255, 0.16);
+ padding: 12px 0 12px 15px;
+ box-sizing: border-box;
+
+ &-title {
+ display: flex;
+ align-items: center;
+ height: 24px;
+ gap: 2px;
+ overflow: hidden;
+ color: rgba(255, 255, 255, 0.85);
+ text-overflow: ellipsis;
+ font-size: 16px;
+ font-style: normal;
+ font-weight: 600;
+ line-height: 24px; /* 150% */
+
+ &-arrow {
+ width: 12px;
+ height: 12px;
+ }
+ }
+
+ &-time-range {
+ overflow: hidden;
+ color: rgba(255, 255, 255, 0.45);
+ text-overflow: ellipsis;
+ font-size: 12px;
+ font-style: normal;
+ font-weight: 400;
+ line-height: 18px; /* 150% */
+ }
+
+ &-location-venue-distance {
+ display: flex;
+ align-items: center;
+ gap: 2px;
+ overflow: hidden;
+ color: rgba(255, 255, 255, 0.45);
+ font-feature-settings: "liga" off, "clig" off;
+ text-overflow: ellipsis;
+ font-family: "PingFang SC";
+ font-size: 12px;
+ font-style: normal;
+ font-weight: 400;
+ line-height: 18px; /* 150% */
+ }
+
+ &-addon {
+ display: flex;
+ align-items: center;
+ gap: 4px;
+
+ &-avatar {
+ width: 20px;
+ height: 20px;
+ border-radius: 50%;
+ object-fit: cover;
+ }
+
+ &-message {
+ display: flex;
+ gap: 4px;
+
+ &-applications,
+ &-level-requirements,
+ &-play-type {
+ color: rgba(255, 255, 255, 0.85);
+ font-size: 11px;
+ font-style: normal;
+ font-weight: 500;
+ line-height: 20px; /* 181.818% */
+ letter-spacing: -0.23px;
+ display: flex;
+ height: 20px;
+ padding: 6px 8px;
+ box-sizing: border-box;
+ align-items: center;
+ gap: 4px;
+ border-radius: 999px;
+ // border: 0.5px solid rgba(0, 0, 0, 0.16);
+ background: rgba(255, 255, 255, 0.12);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/src/game_pages/detail/components/OrganizerInfo/index.tsx b/src/game_pages/detail/components/OrganizerInfo/index.tsx
new file mode 100644
index 0000000..a3a772a
--- /dev/null
+++ b/src/game_pages/detail/components/OrganizerInfo/index.tsx
@@ -0,0 +1,276 @@
+import Taro from "@tarojs/taro";
+import dayjs from "dayjs";
+import { View, Text, Image, ScrollView } from "@tarojs/components";
+import { calculateDistance } from "@/utils";
+import { useUserInfo } from "@/store/userStore";
+import * as LoginService from "@/services/loginService";
+import img from "@/config/images";
+import { navto } from "../../utils/helper";
+import styles from "./index.module.scss";
+
+function genRecommendGames(games, location, avatar) {
+ return games.map((item) => {
+ const {
+ id,
+ title,
+ start_time,
+ end_time,
+ court_type,
+ location_name,
+ current_players,
+ max_players,
+ latitude,
+ longitude,
+ skill_level_max,
+ skill_level_min,
+ play_type,
+ } = item;
+ const [c_latitude, c_longitude] = location;
+ const distance =
+ calculateDistance(c_latitude, c_longitude, latitude, longitude) / 1000;
+ const startTime = dayjs(start_time);
+ const endTime = dayjs(end_time);
+ return {
+ id,
+ title,
+ time: startTime.format("YYYY-MM-DD HH:MM"),
+ timeLength: endTime.diff(startTime, "hour"),
+ venue: location_name,
+ venueType: court_type,
+ distance: `${distance.toFixed(2)}km`,
+ avatar,
+ applications: max_players,
+ checkedApplications: current_players,
+ levelRequirements:
+ skill_level_max !== skill_level_min
+ ? `${skill_level_min || "-"}至${skill_level_max || "-"}`
+ : skill_level_min === "1"
+ ? "无要求"
+ : `${skill_level_min}以上`,
+ playType: play_type,
+ };
+ });
+}
+
+export default function OrganizerInfo(props) {
+ const {
+ userInfo,
+ currentLocation: location,
+ onUpdateUserInfo = () => {},
+ handleViewUserInfo,
+ handleAddComment,
+ } = props;
+ const {
+ id,
+ nickname,
+ avatar_url,
+ is_following,
+ ntrp_level,
+ stats: { hosted_games_count } = {},
+ ongoing_games = [],
+ } = userInfo;
+
+ const myInfo = useUserInfo();
+ const { id: my_id } = myInfo as LoginService.UserInfoType;
+
+ const recommendGames = genRecommendGames(ongoing_games, location, avatar_url);
+
+ const toggleFollow = async (follow) => {
+ try {
+ if (follow) {
+ await LoginService.unFollowUser(id);
+ } else {
+ await LoginService.followUser(id);
+ }
+ onUpdateUserInfo();
+ Taro.showToast({
+ title: `${nickname} ${follow ? "已取消关注" : "已关注"}`,
+ icon: "success",
+ });
+ } catch (e) {
+ Taro.showToast({
+ title: `${nickname} ${follow ? "取消关注失败" : "关注失败"}`,
+ icon: "error",
+ });
+ }
+ };
+
+ function handleViewGame(gameId) {
+ navto(`/game_pages/detail/index?id=${gameId}&from=current`);
+ }
+
+ return (
+
+ {/* orgnizer title */}
+
+ 组织者
+
+ {/* organizer avatar and name */}
+
+
+
+
+ {nickname}
+
+
+ 已组织 {hosted_games_count} 次
+
+ NTRP {ntrp_level || "初学者"}
+
+
+
+ {my_id === id ? (
+ ""
+ ) : (
+
+ {is_following ? (
+
+ 取消关注
+
+ ) : (
+ <>
+
+
+ 关注
+
+ >
+ )}
+
+ )}
+ handleAddComment()}
+ >
+
+
+
+
+ {/* recommend games by organizer */}
+ {recommendGames.length > 0 && (
+
+
+ TA的更多活动
+
+
+
+
+ {recommendGames.map((game, index) => (
+
+ {/* game title */}
+
+ {game.title}
+
+
+ {/* game time and range */}
+
+ {game.time}
+ {game.timeLength}
+
+ {/* game location、vunue、distance */}
+
+ {game.venue}
+ ·
+ {game.venueType}
+ ·
+ {game.distance}
+
+ {/* organizer avatar、applications、level requirements、play type */}
+
+ {
+ e.stopPropagation();
+ handleViewUserInfo(id);
+ }}
+ />
+
+
+
+ 报名人数 {game.checkedApplications}/
+ {game.applications}
+
+
+
+ {game.levelRequirements}
+
+
+ {game.playType}
+
+
+
+
+ ))}
+
+
+
+ )}
+
+ );
+}
diff --git a/src/game_pages/detail/components/Participants/index.module.scss b/src/game_pages/detail/components/Participants/index.module.scss
new file mode 100644
index 0000000..de9448d
--- /dev/null
+++ b/src/game_pages/detail/components/Participants/index.module.scss
@@ -0,0 +1,132 @@
+.detail-page-content-participants {
+ padding: 24px 15px 0;
+ box-sizing: border-box;
+
+ .participants-title {
+ display: flex;
+ padding-bottom: 6px;
+ align-items: center;
+ overflow: hidden;
+ color: #fff;
+ font-feature-settings: "liga" off, "clig" off;
+ text-overflow: ellipsis;
+ font-family: "PingFang SC";
+ font-size: 16px;
+ font-style: normal;
+ font-weight: 600;
+ line-height: 24px; /* 150% */
+ border-bottom: 1px solid rgba(255, 255, 255, 0.1);
+ }
+
+ .participants-list {
+ padding: 10px 0 0;
+ height: 162px;
+ display: flex;
+ flex-direction: row;
+ gap: 8px;
+
+ &-application {
+ display: flex;
+ width: 108px;
+ height: 162px;
+ padding: 16px 12px 10px 12px;
+ box-sizing: border-box;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ gap: 8px;
+ align-self: stretch;
+ border-radius: 20px;
+ border: 1px dashed rgba(255, 255, 255, 0.2);
+ background: rgba(255, 255, 255, 0.16);
+ flex: 0 0 auto;
+
+ &-icon {
+ width: 28px;
+ height: 28px;
+ }
+
+ &-text {
+ color: rgba(255, 255, 255, 0.6);
+ font-feature-settings: "liga" off, "clig" off;
+ font-family: "PingFang SC";
+ font-size: 12px;
+ font-style: normal;
+ font-weight: 500;
+ line-height: 20px; /* 166.667% */
+ }
+ }
+
+ &-scroll {
+ flex: 0 0 auto;
+ width: calc(100% - 116px);
+
+ &-content {
+ display: flex;
+ flex-direction: row;
+ gap: 8px;
+ height: 162px;
+ flex-wrap: nowrap;
+
+ .participants-list-item {
+ display: flex;
+ width: 108px;
+ padding: 16px 4px 10px 4px;
+ box-sizing: border-box;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ gap: 4px;
+ border-radius: 20px;
+ border: 0.5px solid rgba(255, 255, 255, 0.2);
+ background: rgba(255, 255, 255, 0.16);
+ flex: 0 0 auto;
+
+ .participants-list-item-avatar {
+ width: 60px;
+ height: 60px;
+ border-radius: 50%;
+ overflow: hidden;
+ }
+
+ &-name {
+ width: 100%;
+ color: rgba(255, 255, 255, 0.85);
+ text-align: center;
+ font-feature-settings: "liga" off, "clig" off;
+ font-family: "PingFang SC";
+ font-size: 13px;
+ font-style: normal;
+ font-weight: 500;
+ line-height: 24px; /* 184.615% */
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ }
+
+ &-level {
+ color: rgba(255, 255, 255, 0.45);
+ text-align: center;
+ font-feature-settings: "liga" off, "clig" off;
+ font-family: "PingFang SC";
+ font-size: 12px;
+ font-style: normal;
+ font-weight: 400;
+ line-height: 20px; /* 166.667% */
+ }
+
+ &-role {
+ color: #fff;
+ text-align: center;
+ font-feature-settings: "liga" off, "clig" off;
+ font-family: "PingFang SC";
+ font-size: 12px;
+ font-style: normal;
+ font-weight: 500;
+ line-height: 20px; /* 166.667% */
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/src/game_pages/detail/components/Participants/index.tsx b/src/game_pages/detail/components/Participants/index.tsx
new file mode 100644
index 0000000..a761f77
--- /dev/null
+++ b/src/game_pages/detail/components/Participants/index.tsx
@@ -0,0 +1,106 @@
+import { View, Text, Image, ScrollView } from "@tarojs/components";
+import dayjs from "dayjs";
+import img from "@/config/images";
+import styles from "./index.module.scss";
+
+// 参与者
+export default function Participants(props) {
+ const { detail = {}, handleJoinGame, handleViewUserInfo } = props;
+ const participants = detail.participants || [];
+ const {
+ participant_count,
+ max_participants,
+ user_action_status = {},
+ start_time,
+ } = detail;
+ const { can_join, can_pay, can_substitute, is_substituting, waiting_start } =
+ user_action_status;
+ const showApplicationEntry =
+ [can_pay, can_substitute, is_substituting, waiting_start].every(
+ (item) => !item
+ ) &&
+ can_join &&
+ dayjs(start_time).isAfter(dayjs());
+ const leftCount = max_participants - participant_count;
+ return (
+
+
+ 参与者
+ ·
+ {leftCount > 0 ? `剩余空位 ${leftCount}` : "已满员"}
+
+ {participant_count > 0 || showApplicationEntry ? (
+
+ {/* application */}
+ {showApplicationEntry && (
+ {
+ handleJoinGame();
+ }}
+ >
+
+
+ 申请加入
+
+
+ )}
+ {/* participants list */}
+
+
+ {participants.map((participant) => {
+ const {
+ is_organizer,
+ user: {
+ avatar_url,
+ nickname,
+ level,
+ id: participant_user_id,
+ },
+ } = participant;
+ const role = is_organizer ? "组织者" : "参与者";
+ return (
+
+
+
+ {nickname || "未知"}
+
+
+ {level || "未知"}
+
+
+ {role}
+
+
+ );
+ })}
+
+
+
+ ) : (
+ ""
+ )}
+
+ );
+}
diff --git a/src/game_pages/detail/style.module.scss b/src/game_pages/detail/components/SharePopup/index.module.scss
similarity index 61%
rename from src/game_pages/detail/style.module.scss
rename to src/game_pages/detail/components/SharePopup/index.module.scss
index fce6dc2..6ac57ce 100644
--- a/src/game_pages/detail/style.module.scss
+++ b/src/game_pages/detail/components/SharePopup/index.module.scss
@@ -119,80 +119,3 @@
}
}
}
-
-.posterContainer {
- background: linear-gradient(180deg, #fff 0%, #fafafa 100%), #fff;
- padding: 20px;
-}
-
-.posterWrap {
- border-radius: 19.067px;
- border: 1px solid rgba(0, 0, 0, 0.06);
- background: linear-gradient(180deg, #bfffef 0%, #f2fffc 100%), #fff;
- box-shadow: 0 6.933px 55.467px 0 rgba(0, 0, 0, 0.1);
- overflow: hidden;
- box-sizing: border-box;
-}
-
-.sharePoster {
- margin-top: 40px;
- display: flex;
- align-items: center;
- justify-content: space-around;
-
- .shareItem {
- display: flex;
- flex-direction: column;
- align-items: center;
- justify-content: space-between;
- gap: 12px;
- color: rgba(0, 0, 0, 0.85);
- font-feature-settings: "liga" off, "clig" off;
- font-family: "PingFang SC";
- font-size: 14px;
- font-style: normal;
- font-weight: 600;
- line-height: normal;
-
- background-color: #fff;
- border: none;
- padding: 0;
- margin: 0;
- line-height: normal;
- font-size: inherit;
- color: inherit;
-
- &:after {
- border: none;
- background: transparent;
- }
-
- .icon {
- width: 64px;
- height: 64px;
- border-radius: 50%;
- background-color: #fff;
- display: flex;
- align-items: center;
- justify-content: center;
- border: 1px solid rgba(0, 0, 0, 0.06);
- box-shadow: 0 8px 64px 0 rgba(0, 0, 0, 0.1);
-
- &.wechatIcon {
- background-color: #07c160;
- }
- .download {
- width: 28px;
- height: 28px;
- }
- .wechat {
- width: 36px;
- height: 30px;
- }
- .timeline {
- width: 32px;
- height: 32px;
- }
- }
- }
-}
diff --git a/src/game_pages/detail/components/SharePopup/index.tsx b/src/game_pages/detail/components/SharePopup/index.tsx
new file mode 100644
index 0000000..ec607ed
--- /dev/null
+++ b/src/game_pages/detail/components/SharePopup/index.tsx
@@ -0,0 +1,165 @@
+import { forwardRef, useState, useEffect, useImperativeHandle } from "react";
+import { View, Button, Image, Text } from "@tarojs/components";
+import Taro, { useShareAppMessage } from "@tarojs/taro";
+import dayjs from "dayjs";
+import "dayjs/locale/zh-cn";
+import classnames from "classnames";
+import { generateShareImage } from "@/utils";
+import DetailService from "@/services/detailService";
+import { CommonPopup } from "@/components";
+import DownloadIcon from "@/static/detail/download_icon.svg";
+import WechatLogo from "@/static/detail/wechat_icon.svg";
+// import WechatTimeline from "@/static/detail/wechat_timeline.svg";
+import LinkIcon from "@/static/detail/link.svg";
+import CrossIcon from "@/static/detail/cross.svg";
+import { genNTRPRequirementText, navto } from "../../utils/helper";
+import { DayOfWeekMap } from "../../config";
+import styles from "./index.module.scss";
+
+dayjs.locale("zh-cn");
+
+// 分享弹窗
+export default forwardRef(({ id, from, detail, userInfo }, ref) => {
+ const [visible, setVisible] = useState(false);
+ const [publishFlag, setPublishFlag] = useState(false);
+ // const posterRef = useRef();
+ const { max_participants, participant_count } = detail || {};
+
+ useEffect(() => {
+ if (id) {
+ changeMessageType();
+ }
+ }, [id]);
+
+ async function changeMessageType() {
+ try {
+ const res = await DetailService.getActivityId({
+ business_id: id,
+ business_type: "game",
+ is_private: false,
+ });
+ if (res.code === 0) {
+ Taro.updateShareMenu({
+ withShareTicket: false, // 是否需要返回 shareTicket
+ isUpdatableMessage: true, // 是否是动态消息(需要服务端配置过模版)
+ activityId: res.data.activity_id, // 动态消息的活动 id
+ });
+ }
+ } catch (e) {
+ Taro.showToast({ title: e.message, icon: "none" });
+ }
+ }
+
+ useImperativeHandle(ref, () => ({
+ show: (publish_flag = false) => {
+ setPublishFlag(publish_flag);
+ setVisible(true);
+ },
+ }));
+
+ useShareAppMessage(async (res) => {
+ const {
+ play_type,
+ skill_level_max,
+ skill_level_min,
+ start_time,
+ end_time,
+ location_name,
+ venue_image_list,
+ } = detail || {};
+ const startTime = dayjs(start_time);
+ const endTime = dayjs(end_time);
+ const dayofWeek = DayOfWeekMap.get(startTime.day());
+ const gameLength = `${endTime.diff(startTime, "hour")}小时`;
+ const url = await generateShareImage({
+ userAvatar: userInfo.avatar_url,
+ userNickname: userInfo.nickname,
+ gameType: play_type,
+ skillLevel: `NTRP ${genNTRPRequirementText(
+ skill_level_min,
+ skill_level_max
+ )}`,
+ gameDate: `${startTime.format("M月D日")} (${dayofWeek})`,
+ gameTime: `${startTime.format("ah")}点 ${gameLength}`,
+ venueName: location_name,
+ venueImages: venue_image_list ? venue_image_list.map((c) => c.url) : [],
+ });
+ // console.log(res, "res");
+ return {
+ title: detail.title,
+ imageUrl: url || "https://img.yzcdn.cn/vant/cat.jpeg",
+ path: `/game_pages/detail/index?id=${id}&from=share`,
+ };
+ });
+
+ async function handlePost() {
+ navto(`/game_pages/sharePoster/index?id=${detail.id}`);
+ setVisible(false);
+ }
+
+ function onClose() {
+ setVisible(false);
+ setPublishFlag(false);
+ }
+
+ return (
+ <>
+
+
+
+ {publishFlag ? (
+ 球局发布成功 🎉
+ ) : (
+ 分享至
+ )}
+
+
+
+
+ {publishFlag && (
+
+
+ 还剩
+
+ {" "}
+ {max_participants - participant_count}{" "}
+
+ 人加入完成组局, 去邀请好友加入吧~
+
+
+ )}
+
+
+
+
+
+
+
+ {/* */}
+ >
+ );
+});
diff --git a/src/game_pages/detail/components/StickyBottom/index.module.scss b/src/game_pages/detail/components/StickyBottom/index.module.scss
new file mode 100644
index 0000000..5239968
--- /dev/null
+++ b/src/game_pages/detail/components/StickyBottom/index.module.scss
@@ -0,0 +1,124 @@
+.sticky-bottom-bar {
+ position: sticky;
+ bottom: 0;
+ padding: 10px 10px 32px;
+ box-sizing: border-box;
+ width: 100%;
+ height: 92px;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: 6px;
+
+ &-share-and-comment {
+ display: flex;
+ align-items: center;
+ height: 52px;
+ width: 120px;
+ box-sizing: border-box;
+ padding: 2px 20px;
+ justify-content: center;
+ gap: 16px;
+ border-radius: 16px;
+ border: 1px solid rgba(255, 255, 255, 0.06);
+ background: #fff;
+
+ .sticky-bottom-bar-share {
+ display: flex;
+ align-items: center;
+ flex-direction: column;
+ gap: 4px;
+
+ &-icon {
+ width: 16px;
+ height: 16px;
+ }
+
+ &-text {
+ color: rgba(0, 0, 0, 0.85);
+ font-size: 10px;
+ font-style: normal;
+ font-weight: 500;
+ line-height: 16px; /* 160% */
+ }
+ }
+
+ &-separator {
+ width: 1px;
+ height: 24px;
+ background: rgba(0, 0, 0, 0.1);
+ }
+
+ .sticky-bottom-bar-comment {
+ display: flex;
+ align-items: center;
+ flex-direction: column;
+ gap: 4px;
+
+ &-icon {
+ width: 16px;
+ height: 16px;
+ }
+
+ &-text {
+ color: rgba(0, 0, 0, 0.85);
+ font-size: 10px;
+ font-style: normal;
+ font-weight: 500;
+ line-height: 16px; /* 160% */
+ }
+ }
+ }
+
+ .detail-main-action {
+ display: flex;
+ align-items: center;
+ height: 52px;
+ width: auto;
+ // padding: 2px 6px;
+ box-sizing: border-box;
+ justify-content: center;
+ // gap: 12px;
+ flex: 1 0 0;
+ border-radius: 16px;
+ // border: 1px solid rgba(0, 0, 0, 0.06);
+ background: #fff;
+ overflow: hidden;
+
+ &.disabled {
+ background-color: #b4b4b4;
+ color: rgba(60, 60, 67, 0.6);
+ pointer-events: none;
+ }
+
+ .sticky-bottom-bar-join-game {
+ margin-left: auto;
+ // width: 151px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ flex: 1;
+
+ &-price {
+ font-family: "PoetsenOne";
+ font-size: 28px;
+ font-weight: 400;
+ line-height: 24px; /* 114.286% */
+ letter-spacing: -0.56px;
+ color: #000;
+ }
+ }
+
+ .game_manage {
+ width: 100px;
+ margin-left: auto;
+ height: 100%;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ background: #000;
+ color: #fff;
+ pointer-events: all;
+ }
+ }
+}
diff --git a/src/game_pages/detail/components/StickyBottom/index.tsx b/src/game_pages/detail/components/StickyBottom/index.tsx
new file mode 100644
index 0000000..53e986c
--- /dev/null
+++ b/src/game_pages/detail/components/StickyBottom/index.tsx
@@ -0,0 +1,253 @@
+import { useEffect, useRef, useState } from "react";
+import Taro from "@tarojs/taro";
+import classnames from "classnames";
+import dayjs from "dayjs";
+import { Text, View, Image } from "@tarojs/components";
+import OrderService from "@/services/orderService";
+import { EvaluateCallback, EvaluateScene } from "@/store/evaluateStore";
+import { MATCH_STATUS, IsSubstituteSupported } from "@/services/detailService";
+import { GameManagePopup, NTRPEvaluatePopup } from "@/components";
+import img from "@/config/images";
+import { toast, navto } from "../../utils/helper";
+import styles from "./index.module.scss";
+
+function isFull(counts) {
+ const {
+ max_players,
+ current_players,
+ max_substitute_players,
+ current_substitute_count,
+ is_substitute_supported,
+ } = counts;
+ if (max_players === current_players) {
+ return true;
+ } else if (is_substitute_supported === IsSubstituteSupported.SUPPORT) {
+ return max_substitute_players === current_substitute_count;
+ }
+
+ return false;
+}
+
+// 底部操作栏
+export default function StickyButton(props) {
+ const {
+ handleShare,
+ handleJoinGame,
+ detail,
+ onStatusChange,
+ handleAddComment,
+ getCommentCount,
+ } = props;
+ const [commentCount, setCommentCount] = useState(0);
+ const ntrpRef = useRef<{
+ show: (evaluateCallback: EvaluateCallback) => void;
+ }>({ show: () => {} });
+ const {
+ id,
+ price,
+ user_action_status,
+ match_status,
+ start_time,
+ end_time,
+ is_organizer,
+ } = detail || {};
+
+ const gameManageRef = useRef();
+
+ function handleSelfEvaluate() {
+ ntrpRef?.current?.show({
+ type: EvaluateScene.detail,
+ next: (flag) => {
+ if (flag) {
+ Taro.navigateTo({
+ url: `/order_pages/orderDetail/index?gameId=${id}`,
+ });
+ return;
+ }
+ Taro.redirectTo({ url: `/order_pages/orderDetail/index?gameId=${id}` });
+ },
+ onCancel: () => {
+ // Taro.redirectTo({ url: `/game_pages/detail/index?id=${id}` });
+ Taro.navigateBack();
+ },
+ });
+ }
+
+ useEffect(() => {
+ getCommentCount?.((count) => {
+ setCommentCount(count);
+ });
+ }, [getCommentCount]);
+
+ function generateTextAndAction(
+ user_action_status: null | { [key: string]: boolean }
+ ):
+ | undefined
+ | { text: string | React.FC; action?: () => void; available?: boolean } {
+ if (!user_action_status) {
+ return;
+ }
+ const displayPrice = is_organizer ? 0 : price;
+ // user_action_status.can_assess = true;
+ // user_action_status.can_join = false;
+ // console.log(user_action_status, "user_action");
+ const {
+ can_assess,
+ can_join,
+ can_substitute,
+ can_pay,
+ is_substituting,
+ waiting_start,
+ } = user_action_status || {};
+ if (MATCH_STATUS.CANCELED === match_status) {
+ return {
+ text: "活动已取消",
+ available: false,
+ // action: () => toast("活动已取消"),
+ };
+ } else if (dayjs(end_time).isBefore(dayjs())) {
+ return {
+ text: "活动已结束",
+ available: false,
+ // action: () => toast("活动已结束"),
+ };
+ } else if (dayjs(start_time).isBefore(dayjs())) {
+ return {
+ text: "活动已开始",
+ available: false,
+ // action: () => toast("活动已开始"),
+ };
+ } else if (isFull(detail)) {
+ return {
+ text: "活动已满员",
+ available: false,
+ // action: () => toast("活动已满员"),
+ };
+ }
+ if (waiting_start) {
+ return {
+ text: () => ¥{displayPrice} 已加入,
+ action: () => toast("已加入"),
+ };
+ } else if (is_substituting) {
+ return {
+ text: () => ¥{displayPrice} 已加入候补,
+ action: () => toast("已加入候补"),
+ };
+ } else if (can_pay) {
+ return {
+ text: () => ¥{price} 继续支付,
+ action: async () => {
+ const res = await OrderService.getUnpaidOrder(id);
+ if (res.code === 0) {
+ navto(
+ `/order_pages/orderDetail/index?id=${res.data.order_info.order_id}`
+ );
+ }
+ },
+ };
+ } else if (can_substitute) {
+ return {
+ text: () => ¥{displayPrice} 我要候补,
+ action: handleJoinGame,
+ };
+ } else if (can_join) {
+ return {
+ text: () => {
+ return ¥{displayPrice} 立即加入;
+ },
+ action: handleJoinGame,
+ };
+ } else if (can_assess) {
+ return {
+ text: () => ¥{displayPrice} 立即加入,
+ action: handleSelfEvaluate,
+ };
+ }
+ return {
+ text: "球局无法加入",
+ available: false,
+ };
+ }
+
+ if (!user_action_status) {
+ return "";
+ }
+
+ const {
+ text,
+ available = true,
+ action = () => {},
+ } = generateTextAndAction(user_action_status)!;
+
+ let ActionText: React.FC | string = text;
+
+ if (typeof ActionText === "string") {
+ ActionText = () => {
+ return {text as string};
+ };
+ }
+
+ return (
+ <>
+
+
+ handleShare()}
+ >
+
+ 分享
+
+
+ {
+ // Taro.showToast({ title: "To be continued", icon: "none" });
+ handleAddComment();
+ }}
+ >
+
+
+ {commentCount > 0 ? commentCount : "评论"}
+
+
+
+
+
+
+
+ {is_organizer && (
+ {
+ gameManageRef.current.show(detail, onStatusChange);
+ }}
+ >
+ 管理
+
+ )}
+
+
+
+
+ >
+ );
+}
diff --git a/src/game_pages/detail/components/SupplementalNotes/index.module.scss b/src/game_pages/detail/components/SupplementalNotes/index.module.scss
new file mode 100644
index 0000000..89efbf8
--- /dev/null
+++ b/src/game_pages/detail/components/SupplementalNotes/index.module.scss
@@ -0,0 +1,55 @@
+.detail-page-content-supplemental-notes {
+ padding: 24px 15px 0;
+
+ .supplemental-notes-title {
+ overflow: hidden;
+ padding-bottom: 7px;
+ height: 24px;
+ color: #fff;
+ font-feature-settings: "liga" off, "clig" off;
+ text-overflow: ellipsis;
+ font-family: "PingFang SC";
+ font-size: 16px;
+ font-style: normal;
+ font-weight: 600;
+ line-height: 24px; /* 150% */
+ border-bottom: 1px solid rgba(255, 255, 255, 0.1);
+ }
+
+ .supplemental-notes-content {
+ padding: 12px 0 0;
+ display: flex;
+ flex-direction: column;
+ gap: 6px;
+
+ &-tags {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ flex-wrap: wrap;
+
+ &-tag {
+ overflow: hidden;
+ color: #fff;
+ font-feature-settings: "liga" off, "clig" off;
+ text-overflow: ellipsis;
+ font-family: "PingFang SC";
+ font-size: 15px;
+ font-style: normal;
+ font-weight: 500;
+ line-height: 24px; /* 160% */
+ }
+ }
+
+ &-text {
+ overflow: hidden;
+ color: rgba(255, 255, 255, 0.65);
+ font-feature-settings: "liga" off, "clig" off;
+ font-family: "PingFang SC";
+ font-size: 15px;
+ font-style: normal;
+ font-weight: 400;
+ line-height: 24px; /* 160% */
+ }
+ }
+}
diff --git a/src/game_pages/detail/components/SupplementalNotes/index.tsx b/src/game_pages/detail/components/SupplementalNotes/index.tsx
new file mode 100644
index 0000000..08bcdf9
--- /dev/null
+++ b/src/game_pages/detail/components/SupplementalNotes/index.tsx
@@ -0,0 +1,33 @@
+import { Text, View } from "@tarojs/components";
+import styles from "./index.module.scss";
+import { insertDotInTags } from "../../utils/helper";
+
+export default function SupplementalNotes(props) {
+ const {
+ detail: { description, description_tag },
+ } = props;
+ return (
+
+
+ 补充说明
+
+
+ {/* supplemental notes tags */}
+
+ {insertDotInTags(description_tag || []).map((tag, index) => (
+
+ {tag}
+
+ ))}
+
+ {/* supplemental notes content */}
+
+ {description}
+
+
+
+ );
+}
diff --git a/src/game_pages/detail/components/VenueInfo/index.module.scss b/src/game_pages/detail/components/VenueInfo/index.module.scss
new file mode 100644
index 0000000..292fa6d
--- /dev/null
+++ b/src/game_pages/detail/components/VenueInfo/index.module.scss
@@ -0,0 +1,115 @@
+.detail-page-content-venue {
+ padding: 24px 15px 0;
+ box-sizing: border-box;
+
+ .venue-detail-title {
+ display: flex;
+ height: 31px;
+ align-items: center;
+ justify-content: flex-start;
+ gap: 8px;
+ padding-bottom: 6px;
+ color: #fff;
+ text-overflow: ellipsis;
+ font-family: "PingFang SC";
+ font-size: 16px;
+ font-style: normal;
+ font-weight: 600;
+ line-height: 24px;
+ border-bottom: 1px solid rgba(255, 255, 255, 0.1);
+
+ .venue-reserve-status {
+ display: inline-flex;
+ justify-content: flex-start;
+ align-items: center;
+ gap: 4px;
+ .venue-reserve-screenshot {
+ width: 16px;
+ height: 16px;
+ }
+ }
+ }
+
+ .venue-detail-content {
+ padding: 16px 0 0;
+ box-sizing: border-box;
+
+ &-tags {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ flex-wrap: wrap;
+
+ &-tag {
+ overflow: hidden;
+ color: #fff;
+ font-feature-settings: "liga" off, "clig" off;
+ text-overflow: ellipsis;
+ font-family: "PingFang SC";
+ font-size: 15px;
+ font-style: normal;
+ font-weight: 500;
+ line-height: 24px; /* 160% */
+ }
+ }
+
+ &-remarks {
+ overflow: hidden;
+ color: rgba(255, 255, 255, 0.65);
+ // font-feature-settings: 'liga' off, 'clig' off;
+ // text-overflow: ellipsis;
+ // white-space: nowrap;
+ font-family: "PingFang SC";
+ font-size: 15px;
+ font-style: normal;
+ font-weight: 400;
+ line-height: 24px; /* 160% */
+ }
+ }
+
+ .venue-screenshot-title {
+ display: flex;
+ padding: 18px 20px 10px 20px;
+ align-items: center;
+ align-self: stretch;
+ font-family: "PingFang SC";
+ font-size: 16px;
+ font-style: normal;
+ font-weight: 500;
+ line-height: 24px; /* 150% */
+ letter-spacing: -0.23px;
+ }
+
+ .venue-screenshot-scroll-view {
+ max-height: calc(100vh - 260px);
+ overflow-y: auto;
+ padding-bottom: 40px;
+
+ .venue-screenshot-image-list {
+ width: 100%;
+ padding: 0 16px;
+ box-sizing: border-box;
+ display: grid;
+ grid-template-columns: repeat(3, 1fr);
+ gap: 10px 10px;
+
+ .venue-screenshot-image-item {
+ aspect-ratio: 1/1;
+ border-radius: 9px;
+ border: 1px solid rgba(0, 0, 0, 0.12);
+ box-sizing: border-box;
+ background: rgba(0, 0, 0, 0.06);
+ margin: 0;
+ position: relative;
+
+ .venue-screenshot-image-item-image {
+ width: 100%;
+ height: 100%;
+ border-radius: 9px;
+ margin: 0;
+ object-fit: cover;
+ }
+ }
+ }
+ }
+}
diff --git a/src/game_pages/detail/components/VenueInfo/index.tsx b/src/game_pages/detail/components/VenueInfo/index.tsx
new file mode 100644
index 0000000..2cb8533
--- /dev/null
+++ b/src/game_pages/detail/components/VenueInfo/index.tsx
@@ -0,0 +1,105 @@
+import { useState } from "react";
+import { View, Text, Image, ScrollView } from "@tarojs/components";
+import Taro from "@tarojs/taro";
+import { CommonPopup } from "@/components";
+import img from "@/config/images";
+import styles from "./index.module.scss";
+import { insertDotInTags } from "../../utils/helper";
+
+// 场馆信息
+export default function VenueInfo(props) {
+ const { detail } = props;
+ const [visible, setVisible] = useState(false);
+ const {
+ venue_description,
+ venue_description_tag = [],
+ venue_image_list = [],
+ } = detail;
+
+ function showScreenShot() {
+ setVisible(true);
+ }
+ function onClose() {
+ setVisible(false);
+ }
+
+ function previewImage(current_url) {
+ Taro.previewImage({
+ current: current_url,
+ urls:
+ venue_image_list?.length > 0 ? venue_image_list.map((c) => c.url) : [],
+ });
+ }
+ return (
+
+ {/* venue detail title and venue ordered status */}
+
+ 场馆详情
+ {venue_image_list?.length > 0 ? (
+ <>
+ ·
+
+ 已订场
+
+
+ >
+ ) : (
+ ""
+ )}
+
+ {/* venue detail content */}
+
+ {/* venue detail tags */}
+
+ {insertDotInTags(venue_description_tag).map((tag, index) => (
+
+ {tag}
+
+ ))}
+
+ {/* venue remarks */}
+
+ {venue_description}
+
+
+
+ 预定截图
+
+
+ {venue_image_list?.length > 0 &&
+ venue_image_list.map((item) => {
+ return (
+
+
+
+ );
+ })}
+
+
+
+
+ );
+}
diff --git a/src/game_pages/detail/index.module.scss b/src/game_pages/detail/index.module.scss
new file mode 100644
index 0000000..757116c
--- /dev/null
+++ b/src/game_pages/detail/index.module.scss
@@ -0,0 +1,111 @@
+.detail-page {
+ width: 100%;
+ height: 100%;
+ // padding-bottom: env(safe-area-inset-bottom);
+
+ .custom-navbar {
+ height: 56px; /* 通常与原生导航栏高度一致 */
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ // background-color: #fff;
+ color: #000;
+ padding-top: 44px; /* 适配状态栏 */
+ position: sticky;
+ top: 0;
+ z-index: 100;
+ overflow: hidden;
+ background-color: rgba(0, 0, 0, 0.2);
+ }
+
+ .detail-navigator {
+ height: 30px;
+ width: 80px;
+ border-radius: 15px;
+ position: absolute;
+ left: 12px;
+ border: 1px solid #888;
+ box-sizing: border-box;
+ color: #fff;
+ display: flex;
+ align-items: center;
+ background: rgba(0, 0, 0, 0.1);
+
+ .detail-navigator-back {
+ border-right: 1px solid #444;
+ }
+
+ .detail-navigator-back,
+ .detail-navigator-icon {
+ height: 20px;
+ width: 50%;
+
+ display: flex;
+ justify-content: center;
+
+ & > .detail-navigator-back-icon {
+ width: 20px;
+ height: 20px;
+ color: #fff;
+ }
+
+ & > .detail-navigator-logo-icon {
+ width: 20px;
+ height: 20px;
+ color: #fff;
+ }
+ }
+ }
+
+ .detail-page-bg {
+ width: 100%;
+ height: 100%;
+ position: fixed;
+ left: 0;
+ top: 0;
+ background-size: cover;
+ // filter: blur(40px);
+ // transform: scale(1.5);
+ z-index: -2;
+ // width: calc(100% + 20px);
+ // height: calc(100% + 20px);
+ // margin: -10px;
+ width: 100vw;
+ height: 100vh;
+
+ &::after {
+ content: "";
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ z-index: -1;
+ background: linear-gradient(
+ 180deg,
+ rgba(0, 0, 0, 0.8) 0%,
+ rgba(0, 0, 0, 0.4) 100%
+ );
+ backdrop-filter: blur(100px);
+ }
+ }
+
+ .detail-page-content {
+ &-title {
+ padding: 20px 20px 0;
+ box-sizing: border-box;
+
+ &-text {
+ overflow: hidden;
+ color: #fff;
+ font-feature-settings: "liga" off, "clig" off;
+ text-overflow: ellipsis;
+ font-family: "PingFang SC";
+ font-size: 22px;
+ font-style: normal;
+ font-weight: 600;
+ line-height: 32px; /* 145.455% */
+ }
+ }
+ }
+}
diff --git a/src/game_pages/detail/index.scss b/src/game_pages/detail/index.scss
deleted file mode 100644
index 1fff31c..0000000
--- a/src/game_pages/detail/index.scss
+++ /dev/null
@@ -1,1138 +0,0 @@
-@use "~@/scss/images.scss" as img;
-
-.detail-page {
- width: 100%;
- height: 100%;
- // padding-bottom: env(safe-area-inset-bottom);
-
- .custom-navbar {
- height: 56px; /* 通常与原生导航栏高度一致 */
- display: flex;
- align-items: center;
- justify-content: center;
- // background-color: #fff;
- color: #000;
- padding-top: 44px; /* 适配状态栏 */
- position: sticky;
- top: 0;
- z-index: 100;
- overflow: hidden;
- background-color: rgba(0, 0, 0, 0.2);
- }
-
- .detail-navigator {
- height: 30px;
- width: 80px;
- border-radius: 15px;
- position: absolute;
- left: 12px;
- border: 1px solid #888;
- box-sizing: border-box;
- color: #fff;
- display: flex;
- align-items: center;
- background: rgba(0, 0, 0, 0.1);
-
- .detail-navigator-back {
- border-right: 1px solid #444;
- }
-
- .detail-navigator-back,
- .detail-navigator-icon {
- height: 20px;
- width: 50%;
-
- display: flex;
- justify-content: center;
-
- & > .detail-navigator-back-icon {
- width: 20px;
- height: 20px;
- color: #fff;
- }
-
- & > .detail-navigator-logo-icon {
- width: 20px;
- height: 20px;
- color: #fff;
- }
- }
- }
-
- .detail-page-bg {
- width: 100%;
- height: 100%;
- position: fixed;
- left: 0;
- top: 0;
- background-size: cover;
- // filter: blur(40px);
- // transform: scale(1.5);
- z-index: -2;
- // width: calc(100% + 20px);
- // height: calc(100% + 20px);
- // margin: -10px;
- width: 100vw;
- height: 100vh;
-
- &::after {
- content: "";
- position: absolute;
- top: 0;
- left: 0;
- width: 100%;
- height: 100%;
- z-index: -1;
- background: linear-gradient(
- 180deg,
- rgba(0, 0, 0, 0.8) 0%,
- rgba(0, 0, 0, 0.4) 100%
- );
- backdrop-filter: blur(100px);
- }
- }
-
- .detail-swiper-container {
- height: 270px;
- width: 100%;
- padding: 15px 15px 0;
- box-sizing: border-box;
- overflow-x: scroll;
- &::-webkit-scrollbar {
- display: none;
- width: 0;
- height: 0;
- color: transparent; /* 透明色 */
- }
-
- .detail-swiper-scroll-container {
- display: flex;
- height: 250px;
- width: auto;
- align-items: center;
- justify-content: flex-start;
- flex-wrap: nowrap;
- gap: 12px;
-
- .detail-swiper-item {
- flex: 0 0 auto;
- height: 250px;
- display: flex;
- align-items: center;
- &-image {
- border-radius: 12px;
- transition: transform 0.5s;
- }
- }
- }
- }
-
- .detail-swiper {
- height: 240px;
- margin-top: 15px;
- margin-left: 15px;
- }
-
- .detail-swiper-item {
- overflow: visible;
- height: 100%;
-
- .detail-swiper-item-image {
- width: 100%;
- height: 100%;
- border-radius: 12px;
- transition: transform 0.5s;
- }
- }
-
- .detail-page-content {
- &-avatar-tags {
- padding: 20px 20px 0;
- box-sizing: border-box;
- display: flex;
- align-items: center;
- gap: 6px;
-
- &-avatar {
- width: 28px;
- height: 28px;
- border-radius: 50%;
- overflow: hidden;
-
- &-image {
- width: 28px;
- height: 28px;
- }
- }
-
- &-tags {
- display: flex;
- align-items: center;
- flex-wrap: wrap;
- gap: 6px;
-
- &-tag {
- display: flex;
- height: 28px;
- padding: 6px 12px;
- box-sizing: border-box;
- align-items: center;
- gap: 4px;
- border-radius: 999px;
- border: 0.5px solid rgba(255, 255, 255, 0.08);
- background: rgba(255, 255, 255, 0.25);
- color: #fff;
- font-size: 13px;
- font-weight: 500;
- line-height: 20px;
- letter-spacing: -0.23px;
- text-align: center;
- }
- }
- }
-
- &-title {
- padding: 20px 20px 0;
- box-sizing: border-box;
-
- &-text {
- overflow: hidden;
- color: #fff;
- font-feature-settings: "liga" off, "clig" off;
- text-overflow: ellipsis;
- font-family: "PingFang SC";
- font-size: 22px;
- font-style: normal;
- font-weight: 600;
- line-height: 32px; /* 145.455% */
- }
- }
-
- &-game-info {
- &-date-weather {
- padding: 20px 20px 0;
- box-sizing: border-box;
- display: flex;
- align-items: center;
- justify-content: space-between;
- // gap: 12px;
-
- &-calendar-date {
- width: 60%;
- display: flex;
- align-items: center;
- gap: 16px;
-
- &-calendar {
- display: flex;
- width: 48px;
- height: 48px;
- box-sizing: border-box;
- flex-direction: column;
- align-items: center;
- gap: 4px;
- border-radius: 12px;
- // border: 0.5px solid rgba(255, 255, 255, 0.08);
- background: rgba(255, 255, 255, 0.25);
- overflow: hidden;
- color: #fff;
- background: #536272;
-
- .month {
- width: 100%;
- height: 18px;
- font-size: 10px;
- display: flex;
- padding: 1px auto;
- box-sizing: border-box;
- justify-content: center;
- align-items: center;
- // border-bottom: 1px solid rgba(255, 255, 255, 0.08);
- background: #7b828b;
- }
-
- .day {
- display: flex;
- width: 48px;
- height: 30px;
- // padding-bottom: 6px;
- box-sizing: border-box;
- flex-direction: column;
- align-items: center;
- // border: 0.5px solid rgba(255, 255, 255, 0.08);
- // background: rgba(255, 255, 255, 0.25);
- // background-color: #536272;
- }
- }
-
- &-date {
- display: flex;
- flex-direction: column;
- align-items: flex-start;
- justify-content: space-evenly;
- gap: 4px;
- align-self: stretch;
- color: #fff;
-
- .date {
- color: #fff;
- font-feature-settings: "liga" off, "clig" off;
- font-family: "PingFang SC";
- font-size: 16px;
- font-style: normal;
- font-weight: 600;
- line-height: 24px; /* 150% */
- }
-
- .venue-time {
- color: rgba(255, 255, 255, 0.8);
- font-feature-settings: "liga" off, "clig" off;
- font-family: "PingFang SC";
- font-size: 12px;
- font-style: normal;
- font-weight: 400;
- line-height: 20px; /* 166.667% */
- }
- }
- }
-
- &-weather {
- display: flex;
- align-items: flex-end;
- flex-direction: column;
- gap: 4px;
-
- &-icon {
- width: 20px;
- height: 20px;
- color: rgba(255, 255, 255, 0.8);
- }
- &-text-temperature {
- display: flex;
- align-items: center;
- gap: 12px;
- color: rgba(255, 255, 255, 0.8);
- font-feature-settings: "liga" off, "clig" off;
- font-family: "PingFang SC";
- font-size: 12px;
- font-style: normal;
- font-weight: 400;
- line-height: 20px; /* 166.667% */
- }
- }
- }
-
- &-place {
- .location-message {
- padding: 20px 20px 0;
- box-sizing: border-box;
- display: flex;
- align-items: center;
- justify-content: flex-start;
- gap: 12px;
-
- &-icon {
- width: 48px;
- height: 48px;
- border-radius: 12px;
- padding: 14px;
- box-sizing: border-box;
- background: #4d5865;
- display: flex;
- justify-content: center;
- align-items: center;
- overflow: hidden;
- // border: 0.5px solid rgba(255, 255, 255, 0.08);
- // background: rgba(255, 255, 255, 0.25);
-
- &-image {
- width: 20px;
- height: 20px;
- }
- }
-
- &-text {
- display: flex;
- flex-direction: column;
- align-items: flex-start;
- justify-content: space-evenly;
- gap: 4px;
- align-self: stretch;
-
- &-name-distance {
- display: flex;
- align-items: center;
- gap: 4px;
- color: #fff;
- text-align: center;
- font-feature-settings: "liga" off, "clig" off;
- font-family: "PingFang SC";
- font-size: 16px;
- font-style: normal;
- font-weight: 600;
- line-height: 24px; /* 150% */
-
- &-arrow {
- width: 16px;
- height: 16px;
- }
- }
-
- &-address {
- color: rgba(255, 255, 255, 0.8);
- text-align: center;
- font-feature-settings: "liga" off, "clig" off;
- font-family: "PingFang SC";
- font-size: 12px;
- font-style: normal;
- font-weight: 400;
- line-height: 20px; /* 166.667% */
- }
- }
- }
-
- .location-map {
- width: 100%;
- padding: 20px 20px 0;
- box-sizing: border-box;
- display: flex;
- align-items: center;
- justify-content: center;
- overflow: hidden;
- border-radius: 12px;
-
- &-map {
- width: 100%;
- height: 95px;
- border-radius: 12px;
- }
- }
- }
- }
-
- &-venue {
- padding: 24px 15px 0;
- box-sizing: border-box;
-
- .venue-detail-title {
- display: flex;
- height: 31px;
- align-items: center;
- justify-content: flex-start;
- gap: 8px;
- padding-bottom: 6px;
- color: #fff;
- text-overflow: ellipsis;
- font-family: "PingFang SC";
- font-size: 16px;
- font-style: normal;
- font-weight: 600;
- line-height: 24px;
- border-bottom: 1px solid rgba(255, 255, 255, 0.1);
-
- .venue-reserve-status {
- display: inline-flex;
- justify-content: flex-start;
- align-items: center;
- gap: 4px;
- .venue-reserve-screenshot {
- width: 16px;
- height: 16px;
- }
- }
- }
-
- .venue-detail-content {
- padding: 16px 0 0;
- box-sizing: border-box;
-
- &-tags {
- display: flex;
- align-items: center;
- gap: 8px;
- flex-wrap: wrap;
-
- &-tag {
- overflow: hidden;
- color: #fff;
- font-feature-settings: "liga" off, "clig" off;
- text-overflow: ellipsis;
- font-family: "PingFang SC";
- font-size: 15px;
- font-style: normal;
- font-weight: 500;
- line-height: 24px; /* 160% */
- }
- }
-
- &-remarks {
- overflow: hidden;
- color: rgba(255, 255, 255, 0.65);
- // font-feature-settings: 'liga' off, 'clig' off;
- // text-overflow: ellipsis;
- // white-space: nowrap;
- font-family: "PingFang SC";
- font-size: 15px;
- font-style: normal;
- font-weight: 400;
- line-height: 24px; /* 160% */
- }
- }
-
- .venue-screenshot-title {
- display: flex;
- padding: 18px 20px 10px 20px;
- align-items: center;
- align-self: stretch;
- font-family: "PingFang SC";
- font-size: 16px;
- font-style: normal;
- font-weight: 500;
- line-height: 24px; /* 150% */
- letter-spacing: -0.23px;
- }
-
- .venue-screenshot-scroll-view {
- max-height: calc(100vh - 260px);
- overflow-y: auto;
- padding-bottom: 40px;
-
- .venue-screenshot-image-list {
- width: 100%;
- padding: 0 16px;
- box-sizing: border-box;
- display: grid;
- grid-template-columns: repeat(3, 1fr);
- gap: 10px 10px;
-
- .venue-screenshot-image-item {
- aspect-ratio: 1/1;
- border-radius: 9px;
- border: 1px solid rgba(0, 0, 0, 0.12);
- box-sizing: border-box;
- background: rgba(0, 0, 0, 0.06);
- margin: 0;
- position: relative;
-
- .venue-screenshot-image-item-image {
- width: 100%;
- height: 100%;
- border-radius: 9px;
- margin: 0;
- object-fit: cover;
- }
- }
- }
- }
- }
-
- &-gameplay-requirements {
- padding: 24px 15px 0;
- box-sizing: border-box;
-
- .gameplay-requirements-title {
- overflow: hidden;
- color: #fff;
- height: 24px;
- padding-bottom: 6px;
- font-feature-settings: "liga" off, "clig" off;
- text-overflow: ellipsis;
- font-family: "PingFang SC";
- font-size: 16px;
- font-style: normal;
- font-weight: 600;
- line-height: 24px; /* 150% */
- border-bottom: 1px solid rgba(255, 255, 255, 0.1);
- }
-
- .gameplay-requirements {
- padding: 12px 0 0;
- display: flex;
- flex-direction: column;
- gap: 12px;
-
- &-item {
- display: flex;
- justify-content: space-between;
- align-items: center;
- gap: 2px;
- align-self: stretch;
-
- &-title {
- color: rgba(255, 255, 255, 0.8);
- font-feature-settings: "liga" off, "clig" off;
- font-family: "PingFang SC";
- font-size: 14px;
- font-style: normal;
- font-weight: 400;
- line-height: 24px; /* 171.429% */
- }
-
- &-desc {
- color: #fff;
- font-feature-settings: "liga" off, "clig" off;
- font-family: "PingFang SC";
- font-size: 15px;
- font-style: normal;
- font-weight: 600;
- line-height: 24px; /* 160% */
- }
- }
- }
- }
-
- &-participants {
- padding: 24px 15px 0;
- box-sizing: border-box;
-
- .participants-title {
- display: flex;
- padding-bottom: 6px;
- align-items: center;
- overflow: hidden;
- color: #fff;
- font-feature-settings: "liga" off, "clig" off;
- text-overflow: ellipsis;
- font-family: "PingFang SC";
- font-size: 16px;
- font-style: normal;
- font-weight: 600;
- line-height: 24px; /* 150% */
- border-bottom: 1px solid rgba(255, 255, 255, 0.1);
- }
-
- .participants-list {
- padding: 10px 0 0;
- height: 162px;
- display: flex;
- flex-direction: row;
- gap: 8px;
-
- &-application {
- display: flex;
- width: 108px;
- height: 162px;
- padding: 16px 12px 10px 12px;
- box-sizing: border-box;
- flex-direction: column;
- justify-content: center;
- align-items: center;
- gap: 8px;
- align-self: stretch;
- border-radius: 20px;
- border: 1px dashed rgba(255, 255, 255, 0.2);
- background: rgba(255, 255, 255, 0.16);
- flex: 0 0 auto;
-
- &-icon {
- width: 28px;
- height: 28px;
- }
-
- &-text {
- color: rgba(255, 255, 255, 0.6);
- font-feature-settings: "liga" off, "clig" off;
- font-family: "PingFang SC";
- font-size: 12px;
- font-style: normal;
- font-weight: 500;
- line-height: 20px; /* 166.667% */
- }
- }
-
- &-scroll {
- flex: 0 0 auto;
- width: calc(100% - 116px);
-
- &-content {
- display: flex;
- flex-direction: row;
- gap: 8px;
- height: 162px;
- flex-wrap: nowrap;
-
- .participants-list-item {
- display: flex;
- width: 108px;
- padding: 16px 4px 10px 4px;
- box-sizing: border-box;
- flex-direction: column;
- justify-content: center;
- align-items: center;
- gap: 4px;
- border-radius: 20px;
- border: 0.5px solid rgba(255, 255, 255, 0.2);
- background: rgba(255, 255, 255, 0.16);
- flex: 0 0 auto;
-
- .participants-list-item-avatar {
- width: 60px;
- height: 60px;
- border-radius: 50%;
- overflow: hidden;
- }
-
- &-name {
- width: 100%;
- color: rgba(255, 255, 255, 0.85);
- text-align: center;
- font-feature-settings: "liga" off, "clig" off;
- font-family: "PingFang SC";
- font-size: 13px;
- font-style: normal;
- font-weight: 500;
- line-height: 24px; /* 184.615% */
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
- }
-
- &-level {
- color: rgba(255, 255, 255, 0.45);
- text-align: center;
- font-feature-settings: "liga" off, "clig" off;
- font-family: "PingFang SC";
- font-size: 12px;
- font-style: normal;
- font-weight: 400;
- line-height: 20px; /* 166.667% */
- }
-
- &-role {
- color: #fff;
- text-align: center;
- font-feature-settings: "liga" off, "clig" off;
- font-family: "PingFang SC";
- font-size: 12px;
- font-style: normal;
- font-weight: 500;
- line-height: 20px; /* 166.667% */
- }
- }
- }
- }
- }
- }
-
- &-supplemental-notes {
- padding: 24px 15px 0;
-
- .supplemental-notes-title {
- overflow: hidden;
- padding-bottom: 7px;
- height: 24px;
- color: #fff;
- font-feature-settings: "liga" off, "clig" off;
- text-overflow: ellipsis;
- font-family: "PingFang SC";
- font-size: 16px;
- font-style: normal;
- font-weight: 600;
- line-height: 24px; /* 150% */
- border-bottom: 1px solid rgba(255, 255, 255, 0.1);
- }
-
- .supplemental-notes-content {
- padding: 12px 0 0;
- display: flex;
- flex-direction: column;
- gap: 6px;
-
- &-tags {
- display: flex;
- align-items: center;
- gap: 8px;
- flex-wrap: wrap;
-
- &-tag {
- overflow: hidden;
- color: #fff;
- font-feature-settings: "liga" off, "clig" off;
- text-overflow: ellipsis;
- font-family: "PingFang SC";
- font-size: 15px;
- font-style: normal;
- font-weight: 500;
- line-height: 24px; /* 160% */
- }
- }
-
- &-text {
- overflow: hidden;
- color: rgba(255, 255, 255, 0.65);
- font-feature-settings: "liga" off, "clig" off;
- font-family: "PingFang SC";
- font-size: 15px;
- font-style: normal;
- font-weight: 400;
- line-height: 24px; /* 160% */
- }
- }
- }
-
- &-organizer-recommend-games {
- padding: 24px 15px 10px;
-
- .organizer-title {
- overflow: hidden;
- padding-bottom: 6px;
- height: 24px;
- color: #fff;
- font-feature-settings: "liga" off, "clig" off;
- text-overflow: ellipsis;
- font-family: "PingFang SC";
- font-size: 16px;
- font-style: normal;
- font-weight: 600;
- line-height: 24px; /* 150% */
- border-bottom: 1px solid rgba(255, 255, 255, 0.1);
- }
-
- .organizer-avatar-name {
- display: flex;
- align-items: center;
- padding: 16px 0 0;
- align-items: center;
- gap: 8px;
- justify-content: flex-start;
-
- &-avatar {
- width: 40px;
- height: 40px;
- border-radius: 50%;
- object-fit: cover;
- }
-
- &-message {
- display: flex;
- flex-direction: column;
- gap: 4px;
-
- &-name {
- color: rgba(255, 255, 255, 0.85);
- font-size: 13px;
- font-style: normal;
- font-weight: 500;
- line-height: 24px; /* 184.615% */
- }
-
- &-stats {
- display: flex;
- align-items: center;
- gap: 5px;
- color: rgba(255, 255, 255, 0.6);
- font-size: 12px;
- font-style: normal;
- font-weight: 400;
- line-height: 16px; /* 133.333% */
- letter-spacing: 0.06px;
-
- &-separator {
- width: 1px;
- height: 10px;
- color: rgba(255, 255, 255, 0.2);
- }
- }
- }
-
- .organizer-actions {
- display: flex;
- align-items: center;
- gap: 8px;
- margin-left: auto;
-
- .organizer-actions-follow,
- .organizer-actions-comment {
- display: flex;
- height: 32px;
- box-sizing: border-box;
- align-items: center;
- gap: 4px;
- border-radius: 999px;
- // border: 0.5px solid rgba(255, 255, 255, 0.10);
- background: rgba(255, 255, 255, 0.16);
- box-shadow: 0 4px 48px 0 rgba(0, 0, 0, 0.08);
-
- & > image {
- width: 16px;
- height: 16px;
- }
- }
-
- .organizer-actions-follow {
- padding: 8px 12px 8px;
- &-text {
- color: #fff;
- font-size: 13px;
- font-style: normal;
- font-weight: 500;
- line-height: 20px; /* 153.846% */
- letter-spacing: -0.23px;
- }
- }
-
- .organizer-actions-comment {
- padding: 8px 10px;
- }
- }
- }
-
- .organizer-recommend-games {
- padding-top: 20px;
-
- .organizer-recommend-games-title {
- overflow: hidden;
- color: rgba(255, 255, 255, 0.65);
- font-family: "PingFang SC";
- font-size: 15px;
- font-style: normal;
- font-weight: 500;
- line-height: 24px; /* 160% */
- display: flex;
- align-items: center;
- gap: 2px;
- align-self: stretch;
-
- &-arrow {
- width: 12px;
- height: 12px;
- }
- }
-
- .recommend-games-list {
- padding: 10px 0;
- display: flex;
- gap: 8px;
- flex-wrap: nowrap;
-
- &-content {
- display: flex;
- gap: 8px;
- flex-wrap: nowrap;
-
- .recommend-games-list-item {
- width: 246px;
- height: 122px;
- display: flex;
- flex-direction: column;
- gap: 6px;
- flex: 0 0 auto;
- border-radius: 20px;
- border: 1px solid rgba(33, 178, 0, 0.2);
- background: rgba(255, 255, 255, 0.16);
- padding: 12px 0 12px 15px;
- box-sizing: border-box;
-
- &-title {
- display: flex;
- align-items: center;
- height: 24px;
- gap: 2px;
- overflow: hidden;
- color: rgba(255, 255, 255, 0.85);
- text-overflow: ellipsis;
- font-size: 16px;
- font-style: normal;
- font-weight: 600;
- line-height: 24px; /* 150% */
-
- &-arrow {
- width: 12px;
- height: 12px;
- }
- }
-
- &-time-range {
- overflow: hidden;
- color: rgba(255, 255, 255, 0.45);
- text-overflow: ellipsis;
- font-size: 12px;
- font-style: normal;
- font-weight: 400;
- line-height: 18px; /* 150% */
- }
-
- &-location-venue-distance {
- display: flex;
- align-items: center;
- gap: 2px;
- overflow: hidden;
- color: rgba(255, 255, 255, 0.45);
- font-feature-settings: "liga" off, "clig" off;
- text-overflow: ellipsis;
- font-family: "PingFang SC";
- font-size: 12px;
- font-style: normal;
- font-weight: 400;
- line-height: 18px; /* 150% */
- }
-
- &-addon {
- display: flex;
- align-items: center;
- gap: 4px;
-
- &-avatar {
- width: 20px;
- height: 20px;
- border-radius: 50%;
- object-fit: cover;
- }
-
- &-message {
- display: flex;
- gap: 4px;
-
- &-applications,
- &-level-requirements,
- &-play-type {
- color: rgba(255, 255, 255, 0.85);
- font-size: 11px;
- font-style: normal;
- font-weight: 500;
- line-height: 20px; /* 181.818% */
- letter-spacing: -0.23px;
- display: flex;
- height: 20px;
- padding: 6px 8px;
- box-sizing: border-box;
- align-items: center;
- gap: 4px;
- border-radius: 999px;
- // border: 0.5px solid rgba(0, 0, 0, 0.16);
- background: rgba(255, 255, 255, 0.12);
- }
- }
- }
- }
- }
- }
- }
- }
-
- .sticky-bottom-bar {
- position: sticky;
- bottom: 0;
- padding: 10px 10px 32px;
- box-sizing: border-box;
- width: 100%;
- height: 92px;
- display: flex;
- align-items: center;
- justify-content: space-between;
- gap: 6px;
-
- &-share-and-comment {
- display: flex;
- align-items: center;
- height: 52px;
- width: 120px;
- box-sizing: border-box;
- padding: 2px 20px;
- justify-content: center;
- gap: 16px;
- border-radius: 16px;
- border: 1px solid rgba(255, 255, 255, 0.06);
- background: #fff;
-
- .sticky-bottom-bar-share {
- display: flex;
- align-items: center;
- flex-direction: column;
- gap: 4px;
-
- &-icon {
- width: 16px;
- height: 16px;
- }
-
- &-text {
- color: rgba(0, 0, 0, 0.85);
- font-size: 10px;
- font-style: normal;
- font-weight: 500;
- line-height: 16px; /* 160% */
- }
- }
-
- &-separator {
- width: 1px;
- height: 24px;
- background: rgba(0, 0, 0, 0.1);
- }
-
- .sticky-bottom-bar-comment {
- display: flex;
- align-items: center;
- flex-direction: column;
- gap: 4px;
-
- &-icon {
- width: 16px;
- height: 16px;
- }
-
- &-text {
- color: rgba(0, 0, 0, 0.85);
- font-size: 10px;
- font-style: normal;
- font-weight: 500;
- line-height: 16px; /* 160% */
- }
- }
- }
-
- .detail-main-action {
- display: flex;
- align-items: center;
- height: 52px;
- width: auto;
- // padding: 2px 6px;
- box-sizing: border-box;
- justify-content: center;
- // gap: 12px;
- flex: 1 0 0;
- border-radius: 16px;
- // border: 1px solid rgba(0, 0, 0, 0.06);
- background: #fff;
- overflow: hidden;
-
- &.disabled {
- background-color: #b4b4b4;
- color: rgba(60, 60, 67, 0.6);
- pointer-events: none;
- }
-
- .sticky-bottom-bar-join-game {
- margin-left: auto;
- // width: 151px;
- display: flex;
- align-items: center;
- justify-content: center;
- flex: 1;
-
- &-price {
- font-family: "PoetsenOne";
- font-size: 28px;
- font-weight: 400;
- line-height: 24px; /* 114.286% */
- letter-spacing: -0.56px;
- color: #000;
- }
- }
-
- .game_manage {
- width: 100px;
- margin-left: auto;
- height: 100%;
- display: flex;
- align-items: center;
- justify-content: center;
- background: #000;
- color: #fff;
- pointer-events: all;
- }
- }
- }
- }
-}
diff --git a/src/game_pages/detail/index.tsx b/src/game_pages/detail/index.tsx
index 93b5930..2e06275 100644
--- a/src/game_pages/detail/index.tsx
+++ b/src/game_pages/detail/index.tsx
@@ -1,1409 +1,26 @@
-import React, {
- useState,
- useEffect,
- useRef,
- useImperativeHandle,
- forwardRef,
-} from "react";
-import { View, Text, Image, Map, ScrollView, Button } from "@tarojs/components";
-import Taro, {
- useRouter,
- useShareAppMessage,
- useShareTimeline,
- useDidShow,
- useLoad,
-} from "@tarojs/taro";
-import classnames from "classnames";
-import dayjs from "dayjs";
-import "dayjs/locale/zh-cn";
+import { useState, useEffect, useRef } from "react";
+import { View, Text, Image } from "@tarojs/components";
+import Taro, { useRouter, useDidShow } from "@tarojs/taro";
// 导入API服务
-import {
- CommonPopup,
- withAuth,
- NTRPEvaluatePopup,
- GameManagePopup,
- Comments,
-} from "@/components";
-import {
- generateShareImage,
- generatePosterImage,
- base64ToTempFilePath,
- delay,
-} from "@/utils";
-import DetailService, {
- MATCH_STATUS,
- IsSubstituteSupported,
-} from "@/services/detailService";
+import { withAuth, Comments } from "@/components";
+import DetailService from "@/services/detailService";
import * as LoginService from "@/services/loginService";
-import OrderService from "@/services/orderService";
-import { getCurrentLocation, calculateDistance } from "@/utils/locationUtils";
+import { getCurrentLocation } from "@/utils/locationUtils";
import { useUserInfo, useUserActions } from "@/store/userStore";
-import { EvaluateCallback, EvaluateScene } from "@/store/evaluateStore";
-import img from "@/config/images";
-import DownloadIcon from "@/static/detail/download_icon.svg";
-import WechatLogo from "@/static/detail/wechat_icon.svg";
-// import WechatTimeline from "@/static/detail/wechat_timeline.svg";
-import LinkIcon from "@/static/detail/link.svg";
-import CrossIcon from "@/static/detail/cross.svg";
-import { DayOfWeekMap } from "./config";
-import styles from "./style.module.scss";
-import "./index.scss";
-
-dayjs.locale("zh-cn");
-
-const useSceneRedirect = (defaultPage: string) => {
- useLoad((options) => {
- if (options.scene) {
- try {
- const decoded = decodeURIComponent(options.scene || "");
- const params: Record = {};
- decoded.split("&").forEach((pair) => {
- const [key, value] = pair.split("=");
- if (key) params[key] = value ? decodeURIComponent(value) : "";
- });
-
- // 拼接成 URL query
- const query = Object.entries(params)
- .map(([k, v]) => `${k}=${encodeURIComponent(v)}`)
- .join("&");
-
- Taro.redirectTo({
- url: query ? `/${defaultPage}?${query}` : `/${defaultPage}`,
- });
- } catch (err) {
- console.error("scene 解析失败:", err);
- }
- }
- });
-};
-
-// 将·作为连接符插入到标签文本之间
-function insertDotInTags(tags: string[]) {
- if (!tags) return [];
- return tags.join("-·-").split("-");
-}
-
-function GameTags(props) {
- const { userInfo, handleViewUserInfo } = props;
- const { avatar_url, id } = userInfo;
- const tags = [
- // {
- // name: "🕙 急招",
- // icon: "",
- // },
- // {
- // name: "🔥 本周热门",
- // icon: "",
- // },
- // {
- // name: "🎉 新活动",
- // icon: "",
- // },
- // {
- // name: "官方组织",
- // icon: "",
- // },
- ];
- return (
-
-
- {/* network image mock */}
-
-
-
- {tags.map((tag, index) => (
-
- {tag.icon && }
- {tag.name}
-
- ))}
-
-
- );
-}
-
-type CourselItemType = {
- url: string;
- width: number;
- height: number;
-};
-function Coursel(props) {
- const { detail } = props;
- const [list, setList] = useState([]);
- const [listWidth, setListWidth] = useState(0);
- const { image_list } = detail;
-
- async function getImagesMsg(imageList) {
- const latest_list: CourselItemType[] = [];
- const sys_info = await Taro.getSystemInfo();
- const max_width = sys_info.screenWidth - 30;
- const max_height = 240;
- const current_aspect_ratio = max_width / max_height;
- let container_width = 0;
- for (const imageUrl of imageList) {
- const { width, height } = await Taro.getImageInfo({ src: imageUrl });
- if (width && height) {
- const aspect_ratio = width / height;
- const latest_w_h = { width, height };
- if (aspect_ratio < current_aspect_ratio) {
- latest_w_h.width = max_height * aspect_ratio;
- latest_w_h.height = max_height;
- } else {
- latest_w_h.width = max_width;
- latest_w_h.height = max_width / aspect_ratio;
- }
- container_width += latest_w_h.width + 12;
- latest_list.push({
- url: imageUrl,
- width: latest_w_h.width,
- height: latest_w_h.height,
- });
- }
- }
- setList(latest_list);
- setListWidth(container_width);
- }
-
- useEffect(() => {
- getImagesMsg(image_list || []);
- }, [image_list]);
-
- function previewImage(current_url) {
- Taro.previewImage({
- current: current_url,
- urls: list?.length > 0 ? list.map((c) => c.url) : [],
- });
- }
-
- return (
-
-
- {list.map((item, index) => {
- return (
- previewImage(item.url)}
- >
-
-
- );
- })}
-
-
- );
-}
-
-// const PosterPopup = forwardRef((props, ref) => {
-// const [visible, setVisible] = useState(false);
-// const [posterData, setPosterData] = useState();
-// const posterRef = useRef();
-// useImperativeHandle(ref, () => ({
-// show: (detail, user) => {
-// setVisible(true);
-// const {
-// play_type,
-// skill_level_max,
-// skill_level_min,
-// image_list,
-// title,
-// start_time,
-// end_time,
-// location_name,
-// } = detail;
-// const { avatar_url, nickname } = user;
-// const startTime = dayjs(start_time);
-// const endTime = dayjs(end_time);
-// const dayofWeek = DayOfWeekMap.get(startTime.day());
-// const gameLength = `${endTime.diff(startTime, "hour")}小时`;
-// setPosterData({
-// playType: play_type,
-// ntrp: `NTRP ${genNTRPRequirementText(
-// skill_level_min,
-// skill_level_max
-// )}`,
-// mainCoursal:
-// image_list[0] ||
-// "https://bimwe.oss-cn-shanghai.aliyuncs.com/front/ball/images/0621b8cf-f7d6-43ad-b852-7dc39f29a782.png",
-// nickname,
-// avatarUrl: avatar_url,
-// title,
-// locationName: location_name,
-// date: `${startTime.format("M月D日")} (${dayofWeek})`,
-// time: `${startTime.format("ah")}点 ${gameLength}`,
-// });
-// },
-// }));
-
-// useShareAppMessage(async () => {
-// const tempFilePath = await posterRef.current.generateImage();
-// return {
-// // title: detail.title,
-// imageUrl: tempFilePath,
-// path: `/game_pages/detail/index?id=${props.id}&from=share`,
-// };
-// });
-
-// useShareTimeline(async () => {
-// const tempFilePath = await posterRef.current.generateImage();
-// return {
-// title: "分享",
-// imageUrl: tempFilePath,
-// path: `/game_pages/detail/index?id=${props.id}&from=share`,
-// };
-// });
-
-// function onClose() {
-// setVisible(false);
-// setPosterData(undefined);
-// Taro.updateShareMenu({
-// isUpdatableMessage: true, // 是否是动态消息(需要服务端配置过模版)
-// });
-// }
-
-// async function handleShare() {
-// const tempFilePath = await posterRef.current.generateImage();
-// Taro.showShareImageMenu({
-// path: tempFilePath,
-// });
-// }
-// return (
-// visible && (
-//
-//
-//
-// {posterData && }
-//
-//
-//
-//
-//
-//
-//
-//
-// )
-// );
-// });
-
-// 分享弹窗
-const SharePopup = forwardRef(({ id, from, detail, userInfo }, ref) => {
- const [visible, setVisible] = useState(false);
- const [publishFlag, setPublishFlag] = useState(false);
- // const posterRef = useRef();
- const { max_participants, participant_count } = detail || {};
-
- useEffect(() => {
- if (id) {
- changeMessageType();
- }
- }, [id]);
-
- async function changeMessageType() {
- try {
- const res = await DetailService.getActivityId({
- business_id: id,
- business_type: "game",
- is_private: false,
- });
- if (res.code === 0) {
- Taro.updateShareMenu({
- withShareTicket: false, // 是否需要返回 shareTicket
- isUpdatableMessage: true, // 是否是动态消息(需要服务端配置过模版)
- activityId: res.data.activity_id, // 动态消息的活动 id
- });
- }
- } catch (e) {
- Taro.showToast({ title: e.message, icon: "none" });
- }
- }
-
- useImperativeHandle(ref, () => ({
- show: (publish_flag = false) => {
- setPublishFlag(publish_flag);
- setVisible(true);
- },
- }));
-
- useShareAppMessage(async (res) => {
- const {
- play_type,
- skill_level_max,
- skill_level_min,
- start_time,
- end_time,
- location_name,
- venue_image_list,
- } = detail || {};
- const startTime = dayjs(start_time);
- const endTime = dayjs(end_time);
- const dayofWeek = DayOfWeekMap.get(startTime.day());
- const gameLength = `${endTime.diff(startTime, "hour")}小时`;
- const url = await generateShareImage({
- userAvatar: userInfo.avatar_url,
- userNickname: userInfo.nickname,
- gameType: play_type,
- skillLevel: `NTRP ${genNTRPRequirementText(
- skill_level_min,
- skill_level_max
- )}`,
- gameDate: `${startTime.format("M月D日")} (${dayofWeek})`,
- gameTime: `${startTime.format("ah")}点 ${gameLength}`,
- venueName: location_name,
- venueImages: venue_image_list ? venue_image_list.map((c) => c.url) : [],
- });
- // console.log(res, "res");
- return {
- title: detail.title,
- imageUrl: url || "https://img.yzcdn.cn/vant/cat.jpeg",
- path: `/game_pages/detail/index?id=${id}&from=share`,
- };
- });
-
- async function handlePost() {
- const {
- id,
- play_type,
- skill_level_max,
- skill_level_min,
- start_time,
- end_time,
- location_name,
- image_list,
- title,
- } = detail || {};
- const { avatar_url, nickname } = userInfo;
- const startTime = dayjs(start_time);
- const endTime = dayjs(end_time);
- const dayofWeek = DayOfWeekMap.get(startTime.day());
- const gameLength = `${endTime.diff(startTime, "hour")}小时`;
- Taro.showLoading({ title: "生成中..." });
- const qrCodeUrlRes = await DetailService.getQrCodeUrl({
- page: "game_pages/detail/index",
- scene: `id=${id}`,
- });
- const qrCodeUrl = await base64ToTempFilePath(
- qrCodeUrlRes.data.qr_code_base64
- );
- console.log(qrCodeUrl, "qrCodeUrl");
- await delay(100);
- const url = await generatePosterImage({
- playType: play_type,
- ntrp: `NTRP ${genNTRPRequirementText(skill_level_min, skill_level_max)}`,
- mainCoursal:
- image_list[0] ||
- "https://bimwe.oss-cn-shanghai.aliyuncs.com/front/ball/images/0621b8cf-f7d6-43ad-b852-7dc39f29a782.png",
- nickname,
- avatarUrl: avatar_url,
- title,
- locationName: location_name,
- date: `${startTime.format("M月D日")} (${dayofWeek})`,
- time: `${startTime.format("ah")}点 ${gameLength}`,
- qrCodeUrl,
- });
- Taro.hideLoading();
- setVisible(false);
- Taro.showShareImageMenu({
- path: url,
- });
- }
-
- function onClose() {
- setVisible(false);
- setPublishFlag(false);
- }
-
- return (
- <>
-
-
-
- {publishFlag ? (
- 球局发布成功 🎉
- ) : (
- 分享至
- )}
-
-
-
-
- {publishFlag && (
-
-
- 还剩
-
- {" "}
- {max_participants - participant_count}{" "}
-
- 人加入完成组局, 去邀请好友加入吧~
-
-
- )}
-
-
-
-
-
-
-
- {/* */}
- >
- );
-});
-
-function navto(url) {
- Taro.navigateTo({
- url: url,
- });
-}
-
-function toast(message) {
- Taro.showToast({ title: message, icon: "none" });
-}
-
-function isFull(counts) {
- const {
- max_players,
- current_players,
- max_substitute_players,
- current_substitute_count,
- is_substitute_supported,
- } = counts;
- if (max_players === current_players) {
- return true;
- } else if (is_substitute_supported === IsSubstituteSupported.SUPPORT) {
- return max_substitute_players === current_substitute_count;
- }
-
- return false;
-}
-
-// 底部操作栏
-function StickyButton(props) {
- const {
- handleShare,
- handleJoinGame,
- detail,
- onStatusChange,
- handleAddComment,
- getCommentCount,
- } = props;
- const [commentCount, setCommentCount] = useState(0);
- const ntrpRef = useRef<{
- show: (evaluateCallback: EvaluateCallback) => void;
- }>({ show: () => {} });
- const {
- id,
- price,
- user_action_status,
- match_status,
- start_time,
- end_time,
- is_organizer,
- } = detail || {};
-
- const gameManageRef = useRef();
-
- function handleSelfEvaluate() {
- ntrpRef?.current?.show({
- type: EvaluateScene.detail,
- next: (flag) => {
- if (flag) {
- Taro.navigateTo({
- url: `/order_pages/orderDetail/index?gameId=${id}`,
- });
- return;
- }
- Taro.redirectTo({ url: `/order_pages/orderDetail/index?gameId=${id}` });
- },
- onCancel: () => {
- // Taro.redirectTo({ url: `/game_pages/detail/index?id=${id}` });
- Taro.navigateBack();
- },
- });
- }
-
- useEffect(() => {
- getCommentCount?.((count) => {
- setCommentCount(count);
- });
- }, [getCommentCount]);
-
- function generateTextAndAction(
- user_action_status: null | { [key: string]: boolean }
- ):
- | undefined
- | { text: string | React.FC; action?: () => void; available?: boolean } {
- if (!user_action_status) {
- return;
- }
- const displayPrice = is_organizer ? 0 : price;
- // user_action_status.can_assess = true;
- // user_action_status.can_join = false;
- // console.log(user_action_status, "user_action");
- const {
- can_assess,
- can_join,
- can_substitute,
- can_pay,
- is_substituting,
- waiting_start,
- } = user_action_status || {};
- if (MATCH_STATUS.CANCELED === match_status) {
- return {
- text: "活动已取消",
- available: false,
- // action: () => toast("活动已取消"),
- };
- } else if (dayjs(end_time).isBefore(dayjs())) {
- return {
- text: "活动已结束",
- available: false,
- // action: () => toast("活动已结束"),
- };
- } else if (dayjs(start_time).isBefore(dayjs())) {
- return {
- text: "活动已开始",
- available: false,
- // action: () => toast("活动已开始"),
- };
- } else if (isFull(detail)) {
- return {
- text: "活动已满员",
- available: false,
- // action: () => toast("活动已满员"),
- };
- }
- if (waiting_start) {
- return {
- text: () => ¥{displayPrice} 已加入,
- action: () => toast("已加入"),
- };
- } else if (is_substituting) {
- return {
- text: () => ¥{displayPrice} 已加入候补,
- action: () => toast("已加入候补"),
- };
- } else if (can_pay) {
- return {
- text: () => ¥{price} 继续支付,
- action: async () => {
- const res = await OrderService.getUnpaidOrder(id);
- if (res.code === 0) {
- navto(
- `/order_pages/orderDetail/index?id=${res.data.order_info.order_id}`
- );
- }
- },
- };
- } else if (can_substitute) {
- return {
- text: () => ¥{displayPrice} 我要候补,
- action: handleJoinGame,
- };
- } else if (can_join) {
- return {
- text: () => {
- return ¥{displayPrice} 立即加入;
- },
- action: handleJoinGame,
- };
- } else if (can_assess) {
- return {
- text: () => ¥{displayPrice} 立即加入,
- action: handleSelfEvaluate,
- };
- }
- return {
- text: "球局无法加入",
- available: false,
- };
- }
-
- if (!user_action_status) {
- return "";
- }
-
- const {
- text,
- available = true,
- action = () => {},
- } = generateTextAndAction(user_action_status)!;
-
- let ActionText: React.FC | string = text;
-
- if (typeof ActionText === "string") {
- ActionText = () => {
- return {text as string};
- };
- }
-
- return (
- <>
-
-
- handleShare()}
- >
-
- 分享
-
-
- {
- // Taro.showToast({ title: "To be continued", icon: "none" });
- handleAddComment();
- }}
- >
-
-
- {commentCount > 0 ? commentCount : "评论"}
-
-
-
-
-
-
-
- {is_organizer && (
- {
- gameManageRef.current.show(detail, onStatusChange);
- }}
- >
- 管理
-
- )}
-
-
-
-
- >
- );
-}
-
-// 球局信息
-function GameInfo(props) {
- const { detail, currentLocation } = props;
- const {
- latitude,
- longitude,
- location,
- location_name,
- start_time,
- end_time,
- weather,
- } = detail || {};
-
- const [{ iconDay, tempMax, tempMin }] = weather || [{}];
-
- const openMap = () => {
- Taro.openLocation({
- latitude, // 纬度(必填)
- longitude, // 经度(必填)
- name: location_name, // 位置名(可选)
- address: location, // 地址详情(可选)
- scale: 15, // 地图缩放级别(1-28)
- });
- };
-
- const [c_latitude, c_longitude] = currentLocation;
- const distance =
- latitude && longitude
- ? calculateDistance(c_latitude, c_longitude, latitude, longitude) / 1000
- : 0;
-
- const startTime = dayjs(start_time);
- const endTime = dayjs(end_time);
- const game_length = endTime.diff(startTime, "minutes") / 60;
-
- const startMonth = startTime.format("M");
- const startDay = startTime.format("D");
- const theDayOfWeek = startTime.format("dddd");
- const startDate = `${startMonth}月${startDay}日 ${theDayOfWeek}`;
- const gameRange = `${startTime.format("HH:mm")} - ${endTime.format("HH:mm")}`;
-
- return (
-
- {/* Date and Weather */}
-
- {/* Calendar and Date time */}
-
- {/* Calendar */}
-
- {startMonth}月
- {startDay}
-
- {/* Date time */}
-
- {startDate}
-
- {gameRange} ({game_length}小时)
-
-
-
- {/* Weather */}
-
- {/* Weather icon */}
-
- {/**/}
-
-
- {/* Weather text and temperature */}
-
- {tempMin && tempMax && (
-
- {tempMin}℃ - {tempMax}℃
-
- )}
-
-
-
- {/* Place */}
-
- {/* venue location message */}
-
- {/* location icon */}
-
-
-
- {/* location message */}
-
- {/* venue name and distance */}
- {distance ? (
-
- {location_name || "-"}
- ·
- {distance.toFixed(1)}km
-
-
- ) : (
- ""
- )}
- {/* venue address */}
-
- {location || "-"}
-
-
-
- {/* venue map */}
-
- {longitude && latitude && (
-
-
-
- );
-}
-
-// 场馆信息
-function VenueInfo(props) {
- const { detail } = props;
- const [visible, setVisible] = useState(false);
- const {
- venue_description,
- venue_description_tag = [],
- venue_image_list = [],
- } = detail;
-
- function showScreenShot() {
- setVisible(true);
- }
- function onClose() {
- setVisible(false);
- }
-
- function previewImage(current_url) {
- Taro.previewImage({
- current: current_url,
- urls:
- venue_image_list?.length > 0 ? venue_image_list.map((c) => c.url) : [],
- });
- }
- return (
-
- {/* venue detail title and venue ordered status */}
-
- 场馆详情
- {venue_image_list?.length > 0 ? (
- <>
- ·
-
- 已订场
-
-
- >
- ) : (
- ""
- )}
-
- {/* venue detail content */}
-
- {/* venue detail tags */}
-
- {insertDotInTags(venue_description_tag).map((tag, index) => (
-
- {tag}
-
- ))}
-
- {/* venue remarks */}
-
- {venue_description}
-
-
-
- 预定截图
-
-
- {venue_image_list?.length > 0 &&
- venue_image_list.map((item) => {
- return (
-
-
-
- );
- })}
-
-
-
-
- );
-}
-
-function genNTRPRequirementText(min, max) {
- if (min && max && min !== max) {
- return `${min} - ${max} 之间`;
- } else if (max === "1") {
- return "无要求";
- } else if (max) {
- return `${max} 以上`;
- }
- return "-";
-}
-// 玩法要求
-function GamePlayAndRequirement(props) {
- const {
- detail: { skill_level_min, skill_level_max, play_type, game_type },
- } = props;
-
- const requirements = [
- {
- title: "NTRP水平要求",
- desc: genNTRPRequirementText(skill_level_min, skill_level_max),
- },
- {
- title: "活动玩法",
- desc: play_type || "-",
- },
- {
- title: "人员构成",
- desc: game_type || "-",
- },
- ];
- return (
-
- {/* title */}
-
- 玩法要求
-
- {/* requirements */}
-
- {requirements.map((item, index) => (
-
-
- {item.title}
-
- {item.desc}
-
- ))}
-
-
- );
-}
-
-// 参与者
-function Participants(props) {
- const { detail = {}, handleJoinGame, handleViewUserInfo } = props;
- const participants = detail.participants || [];
- const {
- participant_count,
- max_participants,
- user_action_status = {},
- start_time,
- } = detail;
- const { can_join, can_pay, can_substitute, is_substituting, waiting_start } =
- user_action_status;
- const showApplicationEntry =
- [can_pay, can_substitute, is_substituting, waiting_start].every(
- (item) => !item
- ) &&
- can_join &&
- dayjs(start_time).isAfter(dayjs());
- const leftCount = max_participants - participant_count;
- return (
-
-
- 参与者
- ·
- {leftCount > 0 ? `剩余空位 ${leftCount}` : "已满员"}
-
- {participant_count > 0 || showApplicationEntry ? (
-
- {/* application */}
- {showApplicationEntry && (
- {
- handleJoinGame();
- }}
- >
-
-
- 申请加入
-
-
- )}
- {/* participants list */}
-
-
- {participants.map((participant) => {
- const {
- is_organizer,
- user: {
- avatar_url,
- nickname,
- level,
- id: participant_user_id,
- },
- } = participant;
- const role = is_organizer ? "组织者" : "参与者";
- return (
-
-
-
- {nickname || "未知"}
-
-
- {level || "未知"}
-
- {role}
-
- );
- })}
-
-
-
- ) : (
- ""
- )}
-
- );
-}
-
-function SupplementalNotes(props) {
- const {
- detail: { description, description_tag },
- } = props;
- return (
-
-
- 补充说明
-
-
- {/* supplemental notes tags */}
-
- {insertDotInTags(description_tag || []).map((tag, index) => (
-
- {tag}
-
- ))}
-
- {/* supplemental notes content */}
-
- {description}
-
-
-
- );
-}
-
-function genRecommendGames(games, location, avatar) {
- return games.map((item) => {
- const {
- id,
- title,
- start_time,
- end_time,
- court_type,
- location_name,
- current_players,
- max_players,
- latitude,
- longitude,
- skill_level_max,
- skill_level_min,
- play_type,
- } = item;
- const [c_latitude, c_longitude] = location;
- const distance =
- calculateDistance(c_latitude, c_longitude, latitude, longitude) / 1000;
- const startTime = dayjs(start_time);
- const endTime = dayjs(end_time);
- return {
- id,
- title,
- time: startTime.format("YYYY-MM-DD HH:MM"),
- timeLength: endTime.diff(startTime, "hour"),
- venue: location_name,
- venueType: court_type,
- distance: `${distance.toFixed(2)}km`,
- avatar,
- applications: max_players,
- checkedApplications: current_players,
- levelRequirements:
- skill_level_max !== skill_level_min
- ? `${skill_level_min || "-"}至${skill_level_max || "-"}`
- : skill_level_min === "1"
- ? "无要求"
- : `${skill_level_min}以上`,
- playType: play_type,
- };
- });
-}
-
-function OrganizerInfo(props) {
- const {
- userInfo,
- currentLocation: location,
- onUpdateUserInfo = () => {},
- handleViewUserInfo,
- handleAddComment,
- } = props;
- const {
- id,
- nickname,
- avatar_url,
- is_following,
- ntrp_level,
- stats: { hosted_games_count } = {},
- ongoing_games = [],
- } = userInfo;
-
- const myInfo = useUserInfo();
- const { id: my_id } = myInfo as LoginService.UserInfoType;
-
- const recommendGames = genRecommendGames(ongoing_games, location, avatar_url);
-
- const toggleFollow = async (follow) => {
- try {
- if (follow) {
- await LoginService.unFollowUser(id);
- } else {
- await LoginService.followUser(id);
- }
- onUpdateUserInfo();
- Taro.showToast({
- title: `${nickname} ${follow ? "已取消关注" : "已关注"}`,
- icon: "success",
- });
- } catch (e) {
- Taro.showToast({
- title: `${nickname} ${follow ? "取消关注失败" : "关注失败"}`,
- icon: "error",
- });
- }
- };
-
- function handleViewGame(gameId) {
- navto(`/game_pages/detail/index?id=${gameId}&from=current`);
- }
-
- return (
-
- {/* orgnizer title */}
-
- 组织者
-
- {/* organizer avatar and name */}
-
-
-
- {nickname}
-
- 已组织 {hosted_games_count} 次
-
- NTRP {ntrp_level || "初学者"}
-
-
-
- {my_id === id ? (
- ""
- ) : (
-
- {is_following ? (
- 取消关注
- ) : (
- <>
-
- 关注
- >
- )}
-
- )}
- handleAddComment()}
- >
-
-
-
-
- {/* recommend games by organizer */}
- {recommendGames.length > 0 && (
-
-
- TA的更多活动
-
-
-
-
- {recommendGames.map((game, index) => (
-
- {/* game title */}
-
- {game.title}
-
-
- {/* game time and range */}
-
- {game.time}
- {game.timeLength}
-
- {/* game location、vunue、distance */}
-
- {game.venue}
- ·
- {game.venueType}
- ·
- {game.distance}
-
- {/* organizer avatar、applications、level requirements、play type */}
-
- {
- e.stopPropagation();
- handleViewUserInfo(id);
- }}
- />
-
-
-
- 报名人数 {game.checkedApplications}/
- {game.applications}
-
-
-
- {game.levelRequirements}
-
-
- {game.playType}
-
-
-
-
- ))}
-
-
-
- )}
-
- );
-}
+import GameTags from "./components/GameTags";
+import Carousel from "./components/Carousel";
+import StickyBottom from "./components/StickyBottom";
+import GameInfo from "./components/GameInfo";
+import VenueInfo from "./components/VenueInfo";
+import GamePlayAndRequirement from "./components/GamePlayAndReq";
+import Participants from "./components/Participants";
+import SupplementalNotes from "./components/SupplementalNotes";
+import OrganizerInfo from "./components/OrganizerInfo";
+import SharePopup from "./components/SharePopup";
+import { navto, toast, useSceneRedirect } from "./utils/helper";
+import ArrowLeft from "@/static/detail/icon-arrow-left.svg";
+import Logo from "@/static/detail/icon-logo-go.svg";
+import styles from "./index.module.scss";
function Index() {
const [detail, setDetail] = useState({});
@@ -1526,29 +143,32 @@ function Index() {
: {};
return (
-
+
{/* custom navbar */}
-
-
-
+
+
+
-
+
-
+
{/* swiper */}
-
+
{/* content */}
-
+
{/* avatar and tags */}
{/* title */}
-
- {detail.title}
+
+
+ {detail.title}
+
{/* Date and Place and weather */}
@@ -1591,7 +213,7 @@ function Index() {
publisher_id={Number(detail.publisher_id)}
/>
{/* sticky bottom action bar */}
- {
+ useLoad((options) => {
+ if (options.scene) {
+ try {
+ const decoded = decodeURIComponent(options.scene || "");
+ const params: Record = {};
+ decoded.split("&").forEach((pair) => {
+ const [key, value] = pair.split("=");
+ if (key) params[key] = value ? decodeURIComponent(value) : "";
+ });
+
+ // 拼接成 URL query
+ const query = Object.entries(params)
+ .map(([k, v]) => `${k}=${encodeURIComponent(v)}`)
+ .join("&");
+
+ Taro.redirectTo({
+ url: query ? `/${defaultPage}?${query}` : `/${defaultPage}`,
+ });
+ } catch (err) {
+ console.error("scene 解析失败:", err);
+ }
+ }
+ });
+};
+
+export function genNTRPRequirementText(min, max) {
+ if (min && max && min !== max) {
+ return `${min} - ${max} 之间`;
+ } else if (max === "1") {
+ return "无要求";
+ } else if (max) {
+ return `${max} 以上`;
+ }
+ return "-";
+}
\ No newline at end of file
diff --git a/src/game_pages/sharePoster/index.config.ts b/src/game_pages/sharePoster/index.config.ts
new file mode 100644
index 0000000..d57f38c
--- /dev/null
+++ b/src/game_pages/sharePoster/index.config.ts
@@ -0,0 +1,6 @@
+export default definePageConfig({
+ navigationBarTitleText: '生成分享图',
+ navigationStyle: 'custom',
+ enableShareAppMessage: true,
+ enableShareTimeline: true,
+})
diff --git a/src/game_pages/sharePoster/index.module.scss b/src/game_pages/sharePoster/index.module.scss
new file mode 100644
index 0000000..c334321
--- /dev/null
+++ b/src/game_pages/sharePoster/index.module.scss
@@ -0,0 +1,101 @@
+.navbar {
+ box-shadow: none;
+}
+
+.posterContainer {
+ width: 100vw;
+ height: 100vh;
+ background: linear-gradient(180deg, #fff 0%, #fafafa 100%), #fff;
+ padding: 100px 20px 40px;
+ box-sizing: border-box;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: space-between;
+ // gap: 20px;
+}
+
+.posterWrap {
+ width: 100%;
+ border-radius: 19.067px;
+ // border: 1px solid rgba(0, 0, 0, 0.06);
+ // background: linear-gradient(180deg, #bfffef 0%, #f2fffc 100%), #fff;
+ // box-shadow: 0 6.933px 55.467px 0 rgba(0, 0, 0, 0.1);
+ // overflow: hidden;
+ box-sizing: border-box;
+ .imageContainer {
+ width: 100%;
+ padding: 0 20px;
+ box-sizing: border-box;
+
+ .poster {
+ border-radius: 12px;
+ box-shadow: 0 6.933px 55.467px 0 rgba(0, 0, 0, 0.1);
+ width: 100%;
+ }
+ }
+}
+
+.sharePoster {
+ width: 100%;
+ margin-top: 40px;
+ display: flex;
+ align-items: center;
+ justify-content: space-around;
+
+ .shareItem {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: space-between;
+ gap: 12px;
+ color: rgba(0, 0, 0, 0.85);
+ font-feature-settings: "liga" off, "clig" off;
+ font-family: "PingFang SC";
+ font-size: 14px;
+ font-style: normal;
+ font-weight: 600;
+ line-height: normal;
+
+ background-color: #fff;
+ border: none;
+ padding: 0;
+ margin: 0;
+ line-height: normal;
+ font-size: inherit;
+ color: inherit;
+
+ &:after {
+ border: none;
+ background: transparent;
+ }
+
+ .icon {
+ width: 64px;
+ height: 64px;
+ border-radius: 50%;
+ background-color: #fff;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ border: 1px solid rgba(0, 0, 0, 0.06);
+ box-shadow: 0 8px 64px 0 rgba(0, 0, 0, 0.1);
+
+ &.wechatIcon {
+ background-color: #07c160;
+ }
+ .download {
+ width: 28px;
+ height: 28px;
+ }
+ .wechat {
+ width: 36px;
+ height: 30px;
+ }
+ .timeline {
+ width: 32px;
+ height: 32px;
+ }
+ }
+ }
+}
diff --git a/src/game_pages/sharePoster/index.tsx b/src/game_pages/sharePoster/index.tsx
new file mode 100644
index 0000000..579a039
--- /dev/null
+++ b/src/game_pages/sharePoster/index.tsx
@@ -0,0 +1,134 @@
+// import React from "react";
+import { useState, useEffect } from "react";
+import { View, Image, Text, Button } from "@tarojs/components";
+import Taro, { useRouter } from "@tarojs/taro";
+import classnames from "classnames";
+import dayjs from "dayjs";
+import { generatePosterImage, base64ToTempFilePath, delay } from "@/utils";
+import { withAuth } from "@/components";
+import GeneralNavbar from "@/components/GeneralNavbar";
+import DetailService from "@/services/detailService";
+import DownloadIcon from "@/static/detail/download_icon.svg";
+import WechatLogo from "@/static/detail/wechat_icon.svg";
+import WechatTimeline from "@/static/detail/wechat_timeline.svg";
+import { useUserActions } from "@/store/userStore";
+import { DayOfWeekMap } from "../detail/config";
+import { genNTRPRequirementText } from "@/game_pages/detail/utils/helper";
+import styles from "./index.module.scss";
+
+function SharePoster(props) {
+ const [url, setUrl] = useState("");
+ const { fetchUserInfo } = useUserActions();
+ const { id } = useRouter().params;
+
+ useEffect(() => {
+ fetchDetail();
+ }, []);
+
+ async function fetchDetail() {
+ const res = await DetailService.getDetail(Number(id));
+ handleGenPoster(res.data);
+ }
+ async function handleGenPoster(detail) {
+ const {
+ id,
+ play_type,
+ skill_level_max,
+ skill_level_min,
+ start_time,
+ end_time,
+ location_name,
+ image_list,
+ title,
+ } = detail || {};
+ const userInfo = await fetchUserInfo();
+ const { avatar_url, nickname } = userInfo;
+ const startTime = dayjs(start_time);
+ const endTime = dayjs(end_time);
+ const dayofWeek = DayOfWeekMap.get(startTime.day());
+ const gameLength = `${endTime.diff(startTime, "hour")}小时`;
+ Taro.showLoading({ title: "生成中..." });
+ const qrCodeUrlRes = await DetailService.getQrCodeUrl({
+ page: "game_pages/detail/index",
+ scene: `id=${id}`,
+ });
+ const qrCodeUrl = await base64ToTempFilePath(
+ qrCodeUrlRes.data.qr_code_base64
+ );
+ await delay(100);
+ const url = await generatePosterImage({
+ playType: play_type,
+ ntrp: `NTRP ${genNTRPRequirementText(skill_level_min, skill_level_max)}`,
+ mainCoursal:
+ image_list[0] ||
+ "https://bimwe.oss-cn-shanghai.aliyuncs.com/front/ball/images/0621b8cf-f7d6-43ad-b852-7dc39f29a782.png",
+ nickname,
+ avatarUrl: avatar_url,
+ title,
+ locationName: location_name,
+ date: `${startTime.format("M月D日")} (${dayofWeek})`,
+ time: `${startTime.format("ah")}点 ${gameLength}`,
+ qrCodeUrl,
+ });
+ Taro.hideLoading();
+ setUrl(url);
+ }
+ function handleShare() {
+ Taro.showShareImageMenu({
+ path: url,
+ });
+ }
+
+ return (
+ <>
+
+ {url && (
+
+
+
+
+
+
+
+
+
+
+
+
+ )}
+ >
+ );
+}
+
+export default withAuth(SharePoster);
diff --git a/src/order_pages/orderList/index.tsx b/src/order_pages/orderList/index.tsx
index 1f6017e..3a6a303 100644
--- a/src/order_pages/orderList/index.tsx
+++ b/src/order_pages/orderList/index.tsx
@@ -16,17 +16,13 @@ import { withAuth, RefundPopup } from "@/components";
import { payOrder, generateOrderActions } from "@/utils";
import emptyContent from "@/static/emptyStatus/publish-empty.png";
import CustomerIcon from "@/static/order/customer.svg";
+import { insertDotInTags } from "@/game_pages/detail/utils/helper";
import styles from "./index.module.scss";
dayjs.locale("zh-cn");
const PAGESIZE = 100;
-// 将·作为连接符插入到标签文本之间
-function insertDotInTags(tags: string[]) {
- return tags.join("-·-").split("-");
-}
-
const diffDayMap = new Map([
[0, "今天"],
[1, "明天"],
diff --git a/src/services/commentServices.ts b/src/services/commentServices.ts
index 1c89fde..474107a 100644
--- a/src/services/commentServices.ts
+++ b/src/services/commentServices.ts
@@ -10,6 +10,7 @@ export interface UserInfo {
id: number
nickname: string
avatar_url: string
+ province: string
}
export type BaseComment = {
diff --git a/src/store/userStore.ts b/src/store/userStore.ts
index 53a04e2..70c4ca6 100644
--- a/src/store/userStore.ts
+++ b/src/store/userStore.ts
@@ -7,7 +7,7 @@ import {
export interface UserState {
user: UserInfoType | {};
- fetchUserInfo: () => Promise;
+ fetchUserInfo: () => Promise;
updateUserInfo: (userInfo: Partial) => void;
}
@@ -16,9 +16,9 @@ export const useUser = create()((set) => ({
fetchUserInfo: async () => {
try {
const res = await fetchUserProfile();
- console.log(res);
set({ user: res.data });
- } catch {}
+ return res.data
+ } catch { }
},
updateUserInfo: async (userInfo: Partial) => {
const res = await updateUserProfile(userInfo);