"use client"; import React, { useState, useEffect } from "react"; import html2canvas from "html2canvas"; import baseRequest from "@/utils/baseRequest"; import { Toast } from "antd-mobile"; import { generateSignature } from "@/utils/crypto"; export default function Share({ params }) { //获取页面数据、生成二维码 const [data, setData] = useState({}); const [qrcodeUrl, setQrcodeUrl] = useState(""); const [shareWebUrl, setShareWebUrl] = useState("https://tiefen.fun"); const [isFetching, setIsFetching] = useState(true); function generateRandomString(length = 10) { const characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; let result = ""; for (let i = 0; i < length; i++) { result += characters.charAt( Math.floor(Math.random() * characters.length) ); } return result; } useEffect(() => { function getRandomUrl(urls) { return urls[Math.floor(Math.random() * urls.length)]; } const getData = async () => { try { const base = baseRequest(); const signature = generateSignature({ user_id: parseInt(params.user_id, 10), ...base, }); const detailResponse = await fetch( `/api/streamer/list_ext_by_user_id?signature=${signature}`, { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ user_id: parseInt(params.user_id, 10), ...base, }), } ); const detailData = await detailResponse.json(); if (detailData.ret === -1) { Toast.show({ content: detailData.msg, }); return; } setData(detailData.data.streamer_ext); const urlsResponse = await fetch(`/api/config/cold_config`, { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ ...base }), }); const urlsData = await urlsResponse.json(); if (urlsData.ret === -1) { Toast.show({ content: urlsData.msg, }); return; } const randomUrl = getRandomUrl(urlsData.data.share_redirect_urls); setShareWebUrl(randomUrl); const randomStr = generateRandomString(); var QRCode = require("qrcode"); QRCode.toDataURL( `${randomUrl}/zone/${params.user_id}/${randomStr}`, function (err, url) { setQrcodeUrl(url); } ); setIsFetching(false); } catch (error) { console.error(error); } }; getData(); }, []); //分享海报组件 const Poster = () => { return ( <div className="flex flex-col"> <div id="print" className="flex flex-col overflow-hidden bg-[#07050A]"> <div className="flex w-full justify-center items-center aspect-square overflow-hidden"> <img className="w-full" src={data?.cover?.images[0].urls[0]} alt="" /> </div> <div className="flex flex-row items-center w-full p-2 bg-[#07050A]"> <div className="flex flex-col justify-around items-start shrink min-w-0"> <div className="flex flex-row items-center w-full"> <div className="flex items-center justify-center shrink-0 rounded-full overflow-hidden aspect-square w-12 border border-white"> <img className="w-full" src={data?.avatar?.images[0].urls[0]} alt="" /> </div> <div className="flex flex-col ml-2 shrink min-w-0"> <p className="font-medium text-base text-white truncate"> {data?.name} </p> <div className="flex justify-start flex-1"> <div className="flex flex-row items-center py-0.5 px-2 bg-[#FFFFFF1A] rounded-full"> <p className="text-xs text-white font-medium">ID</p> <p className="text-white text-xs font-medium ml-0.5"> {data?.user_id} </p> </div> </div> </div> </div> <div className="flex flex-col px-2 py-1 mt-2 bg-[#FF61B030] rounded-full justify-center"> <p className="text-xs text-[#FF669E] rounded-full text-center"> 邀您加入我的 <span className="text-xs text-[#FF669E] font-semibold"> 「铁粉空间」 </span> </p> </div> <div className="py-1 text-xs flex flex-wrap items-center "> <div className="flex items-center flex-nowrap"> <img className="object-cover scale-110 w-3 mr-1" src={ process.env.NEXT_PUBLIC_CDN_URL + "/public/images/icon_without_bg.png" } /> <span className="whitespace-nowrap">铁粉空间</span> </div> <span className="text-[#ffffff80] whitespace-nowrap"> |官网:tiefen.fun </span> </div> </div> <div className="h-20 aspect-square ml-auto overflow-hidden rounded shrink-0"> <img className="object-cover scale-110 w-full" src={qrcodeUrl} /> </div> </div> </div> <button onClick={saveImage} className="btn btn-md bg-gradient-to-r from-[#FF668B] to-[#FF66F0] rounded-full text-white text-base font-medium w-full mt-4" > 保存图片 </button> <button onClick={copyUrl} className="btn btn-md bg-gradient-to-r from-[#FF668B] to-[#FF66F0] rounded-full text-white text-base font-medium w-full mt-4" > 复制链接 </button> </div> ); }; //保存图片 const saveImage = async () => { const element = document.getElementById("print"); const canvas = await html2canvas(element, { useCORS: true, }); const data = canvas.toDataURL("image/jpg"); window.ReactNativeWebView.postMessage( JSON.stringify({ type: "SAVE_IMAGE", data: data, }) ); }; //复制链接 const copyUrl = () => { const randomStr = generateRandomString(); window.ReactNativeWebView.postMessage( JSON.stringify({ type: "COPY_URL", data: `${shareWebUrl}/zone/${params.user_id}/${randomStr}`, }) ); }; if (isFetching) { return ( <section className="flex flex-1 justify-center container"> <span className="absolute top-1/2 loading loading-spinner loading-lg"></span> </section> ); } return ( <section className="flex flex-1 flex-col items-center justify-center container"> <div className="w-4/5"> <Poster /> </div> </section> ); }