feat: 生成海报
This commit is contained in:
9
src/game_pages/detail/config.ts
Normal file
9
src/game_pages/detail/config.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
export const DayOfWeekMap = new Map([
|
||||
[0, "周日"],
|
||||
[1, "周一"],
|
||||
[2, "周二"],
|
||||
[3, "周三"],
|
||||
[4, "周四"],
|
||||
[5, "周五"],
|
||||
[6, "周六"],
|
||||
]);
|
||||
@@ -2,4 +2,5 @@ export default definePageConfig({
|
||||
navigationBarTitleText: '球局详情',
|
||||
navigationStyle: 'custom',
|
||||
enableShareAppMessage: true,
|
||||
enableShareTimeline: true,
|
||||
})
|
||||
|
||||
@@ -6,7 +6,6 @@ import React, {
|
||||
forwardRef,
|
||||
} from "react";
|
||||
import { View, Text, Image, Map, ScrollView, Button } from "@tarojs/components";
|
||||
// import { Avatar } from "@nutui/nutui-react-taro";
|
||||
import Taro, {
|
||||
useRouter,
|
||||
useShareAppMessage,
|
||||
@@ -25,6 +24,7 @@ import {
|
||||
Comments,
|
||||
Poster,
|
||||
} from "@/components";
|
||||
import { generateShareImage, generatePosterImage } from "@/utils";
|
||||
import DetailService, {
|
||||
MATCH_STATUS,
|
||||
IsSubstituteSupported,
|
||||
@@ -35,6 +35,12 @@ import { getCurrentLocation, calculateDistance } 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";
|
||||
|
||||
@@ -173,100 +179,281 @@ function Coursel(props) {
|
||||
);
|
||||
}
|
||||
|
||||
// 分享弹窗
|
||||
const SharePopup = forwardRef(
|
||||
({ id, from }: { id: string; from: string }, ref) => {
|
||||
const [visible, setVisible] = useState(true);
|
||||
|
||||
useImperativeHandle(ref, () => ({
|
||||
show: () => {
|
||||
setVisible(true);
|
||||
},
|
||||
}));
|
||||
|
||||
useShareAppMessage((res) => {
|
||||
console.log(res, "res");
|
||||
return {
|
||||
title: "分享",
|
||||
imageUrl: "https://img.yzcdn.cn/vant/cat.jpeg",
|
||||
path: `/game_pages/detail/index?id=${id}&from=share`,
|
||||
};
|
||||
});
|
||||
|
||||
// function handleShareToWechatMoments() {
|
||||
// useShareTimeline(() => {
|
||||
// return {
|
||||
// title: '分享',
|
||||
// path: `/game_pages/detail/index?id=${id}&from=share`,
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
|
||||
function handleSaveToLocal() {
|
||||
Taro.showToast({ title: "not yet", icon: "error" });
|
||||
return;
|
||||
Taro.saveImageToPhotosAlbum({
|
||||
filePath: "",
|
||||
success: () => {
|
||||
Taro.showToast({ title: "保存成功", icon: "success" });
|
||||
},
|
||||
fail: () => {
|
||||
Taro.showToast({ title: "保存失败", icon: "none" });
|
||||
},
|
||||
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}`,
|
||||
});
|
||||
}
|
||||
},
|
||||
}));
|
||||
|
||||
return (
|
||||
<>
|
||||
{/* <CommonPopup
|
||||
title="分享至"
|
||||
visible={visible}
|
||||
onClose={() => {
|
||||
setVisible(false);
|
||||
}}
|
||||
hideFooter
|
||||
style={{ minHeight: "100px" }}
|
||||
>
|
||||
<View className={styles.shareContainer}>
|
||||
<View catchMove className={styles.title}>
|
||||
分享至
|
||||
</View>
|
||||
<View className={styles.shareItems}>
|
||||
<Button
|
||||
className={classnames(styles.button, styles.share)}
|
||||
openType="share"
|
||||
>
|
||||
微信好友
|
||||
</Button>
|
||||
<Button
|
||||
className={classnames(styles.button, styles.save)}
|
||||
onClick={handleSaveToLocal}
|
||||
>
|
||||
生成分享图
|
||||
</Button>
|
||||
</View>
|
||||
</View>
|
||||
</CommonPopup> */}
|
||||
<CommonPopup
|
||||
title="分享至"
|
||||
visible={visible}
|
||||
onClose={() => {
|
||||
setVisible(false);
|
||||
}}
|
||||
showHeader={false}
|
||||
position="center"
|
||||
hideFooter
|
||||
enableDragToClose={false}
|
||||
style={{ minHeight: "100px" }}
|
||||
>
|
||||
<View className={styles.posterWrap}>
|
||||
<Poster />
|
||||
</View>
|
||||
</CommonPopup>
|
||||
</>
|
||||
);
|
||||
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 && (
|
||||
<CommonPopup
|
||||
title="分享至"
|
||||
visible={visible}
|
||||
onClose={onClose}
|
||||
showHeader={false}
|
||||
position="center"
|
||||
hideFooter
|
||||
enableDragToClose={false}
|
||||
style={{ minHeight: "100px" }}
|
||||
zIndex={2001}
|
||||
>
|
||||
<View className={styles.posterContainer}>
|
||||
<View className={styles.posterWrap}>
|
||||
{posterData && <Poster ref={posterRef} data={posterData} />}
|
||||
</View>
|
||||
<View className={styles.sharePoster}>
|
||||
<Button className={styles.shareItem} plain={true}>
|
||||
<View className={styles.icon}>
|
||||
<Image className={styles.download} src={DownloadIcon} />
|
||||
</View>
|
||||
<Text>保存至手机</Text>
|
||||
</Button>
|
||||
<Button
|
||||
className={styles.shareItem}
|
||||
plain={true}
|
||||
onClick={handleShare}
|
||||
>
|
||||
<View className={classnames(styles.icon, styles.wechatIcon)}>
|
||||
<Image className={styles.wechat} src={WechatLogo} />
|
||||
</View>
|
||||
<Text>微信好友</Text>
|
||||
</Button>
|
||||
<Button className={styles.shareItem} plain={true} openType="share">
|
||||
<View className={styles.icon}>
|
||||
<Image className={styles.timeline} src={WechatTimeline} />
|
||||
</View>
|
||||
<Text>朋友圈</Text>
|
||||
</Button>
|
||||
</View>
|
||||
</View>
|
||||
</CommonPopup>
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
// 分享弹窗
|
||||
const SharePopup = forwardRef(({ id, from, detail, userInfo }, ref) => {
|
||||
const [visible, setVisible] = useState(false);
|
||||
const posterRef = useRef();
|
||||
|
||||
useEffect(() => {
|
||||
changeMessageType();
|
||||
}, []);
|
||||
|
||||
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: () => {
|
||||
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 {
|
||||
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 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}`,
|
||||
});
|
||||
Taro.hideLoading();
|
||||
setVisible(false);
|
||||
Taro.showShareImageMenu({
|
||||
path: url,
|
||||
});
|
||||
}
|
||||
|
||||
function onClose() {
|
||||
setVisible(false);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<CommonPopup
|
||||
title="分享至"
|
||||
visible={visible}
|
||||
onClose={onClose}
|
||||
showHeader={false}
|
||||
hideFooter
|
||||
enableDragToClose={false}
|
||||
style={{ minHeight: "100px" }}
|
||||
zIndex={1000}
|
||||
>
|
||||
<View className={styles.shareContainer}>
|
||||
<View catchMove className={styles.title}>
|
||||
<Text>分享至</Text>
|
||||
<View className={styles.closeIconWrap} onClick={onClose}>
|
||||
<Image className={styles.closeIcon} src={CrossIcon} />
|
||||
</View>
|
||||
</View>
|
||||
<View className={styles.shareItems}>
|
||||
<Button className={styles.button} openType="share">
|
||||
<View className={classnames(styles.icon, styles.wechatIcon)}>
|
||||
<Image className={styles.wechat} src={WechatLogo} />
|
||||
</View>
|
||||
<Text>微信好友</Text>
|
||||
</Button>
|
||||
<Button className={styles.button} onClick={handlePost}>
|
||||
<View className={styles.icon}>
|
||||
<Image className={styles.download} src={DownloadIcon} />
|
||||
</View>
|
||||
<Text>生成分享图</Text>
|
||||
</Button>
|
||||
<Button className={styles.button}>
|
||||
<View className={styles.icon}>
|
||||
<Image className={styles.linkIcon} src={LinkIcon} />
|
||||
</View>
|
||||
<Text>复制链接</Text>
|
||||
</Button>
|
||||
</View>
|
||||
</View>
|
||||
</CommonPopup>
|
||||
{/* <PosterPopup ref={posterRef} id={detail.id} /> */}
|
||||
</>
|
||||
);
|
||||
});
|
||||
|
||||
function navto(url) {
|
||||
Taro.navigateTo({
|
||||
@@ -1346,6 +1533,8 @@ function Index() {
|
||||
ref={sharePopupRef}
|
||||
id={id as string}
|
||||
from={from as string}
|
||||
detail={detail}
|
||||
userInfo={userInfo}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
@@ -2,26 +2,173 @@
|
||||
.title {
|
||||
padding: 20px;
|
||||
color: #000;
|
||||
text-align: center;
|
||||
// text-align: center;
|
||||
font-family: "PingFang SC";
|
||||
font-size: 18px;
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
line-height: 28px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
.closeIconWrap {
|
||||
display: flex;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
flex-shrink: 0;
|
||||
border-radius: 999px;
|
||||
border: 1px solid rgba(0, 0, 0, 0.06);
|
||||
background: #fff;
|
||||
box-shadow: 0 4px 36px 0 rgba(0, 0, 0, 0.06);
|
||||
|
||||
.closeIcon {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.shareItems {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
justify-content: space-around;
|
||||
padding-bottom: 60px;
|
||||
|
||||
.button {
|
||||
width: 140px;
|
||||
height: 40px;
|
||||
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;
|
||||
}
|
||||
.linkIcon {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.posterWrap {
|
||||
.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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user