feat: 期刊页面

main
fadeaway 6 months ago
parent 8b83e4ad7f
commit 0510cb0ba3

@ -22,7 +22,7 @@ module.exports = {
viewportUnit: 'vw',
fontViewportUnit: 'vw',
selectorBlackList: [],
minPixelValue: 1,
minPixelValue: 0,
mediaQuery: false,
replace: true,
exclude: undefined,

Binary file not shown.

After

Width:  |  Height:  |  Size: 935 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 891 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 656 B

@ -1,3 +1,6 @@
/**
* App
*/
'use client';
import Image from 'next/image';

@ -0,0 +1,96 @@
/**
*
*/
import Image from 'next/image';
import ArticalWrap from '@/components/ArticalWrap';
import SongItem from '@/components/SongItem';
import type { Metadata } from 'next';
export const metadata: Metadata = { title: '雀乐期刊' };
async function getJournalInfo(journalId: string) {
const res = await fetch(`http://39.103.180.196:9012/luoo-music/journal/${journalId}`);
return res.json();
}
async function getSongList(journalId: string) {
const res = await fetch(`http://39.103.180.196:9012/luoo-music/song/journalId/${journalId}`);
return res.json();
}
async function getInfo(journalId: string) {
return await Promise.all([getJournalInfo(journalId), getSongList(journalId)]);
}
export default async function Journal({ searchParams: { id } }: any) {
const [res0, res1] = await getInfo(id);
const journalInfo = res0?.data;
const songList = res1?.data;
return (
<main className="max-w-screen-sm min-h-screen mx-auto flex flex-col items-center font-normal text-[#000000f2] bg-white">
<div className="flex items-center w-full bg-[#000000f2] text-[#ffffffb2] text-[14px] py-[12px] px-[18px]">
<Image className="w-[28px] h-[28px]" width={28} height={28} src="/img/app_icon_white_bg.svg" alt="queyue" />
<span className="flex-1 pl-[12px]"></span>
<Image className="w-[24px] h-[24px]" width={24} height={24} src="/img/jourrnal_icon-5.svg" alt="right-arrow" />
</div>
{/* 期刊封面图 */}
<div className="relative w-[100vw] h-[264.84px]">
<Image className="object-cover" unoptimized fill src={journalInfo?.image} alt="journal-cover" />
</div>
<section className="relative w-full flex-1 bg-white mt-[-10px] rounded-tl-[12px] rounded-tr-[12px] z-1 py-[17px] px-[18px] mb-[79px]">
<Image
className="w-[60px] h-[60px] absolute top-[-30px] right-[16px]"
width={60}
height={60}
unoptimized
src="/img/icon_pause.png"
alt="icon_pause"
/>
<div className="flex items-center flex-wrap text-[#000000b2] mb-[5px]">
<div className="text-[14px] font-medium leading-[19.6px]">VOL·{journalInfo?.journalNo}</div>
<div className="ml-[11px] flex items-center flex-wrap text-[12px] leading-[12px]">
{journalInfo?.tags?.map((tag: string, index: number) => (
<div
className={`h-[18px] py-[3px] px-[10px] rounded-[15px] bg-[#0000000c] flex items-center ${index !== 0 && 'ml-[6px]'}`}
key={tag}
>
{tag}
</div>
))}
</div>
</div>
<h5 className="font-medium text-[20px] leading-[28px]">{journalInfo?.title}</h5>
<p className="flex item-center text-[#00000066] text-[12px] leading-[17px] mt-[3px]">
<span className="mr-[12px]">{journalInfo?.editor}</span>
<span>{journalInfo?.date}</span>
</p>
<ArticalWrap content={journalInfo?.content} />
<h5 className="mb-[12px] text-[#000000f2] text-[15px] h-[18px]">{songList?.length}</h5>
{songList?.map((song: ISong) => <SongItem key={song.id} data={song} />)}
</section>
<section className="w-full flex items-center border-t-[1px] border-[#00000019] pt-[14px] pb-[35px] px-[18px]">
<div className="w-[294px] h-[38px] rounded-full bg-[#0000000c] px-[24px] flex items-center text-[15px] text-[#000000b2]">
</div>
<div className="relative ml-[14px]">
<Image
className="w-[24px] h-[24px]"
width={24}
height={24}
unoptimized
src="/img/icon_comment.png"
alt="icon_comment"
/>
<div className="absolute top-0 left-[100%] text-[8px] text-[#00000066]">{journalInfo?.totalCommentReply}</div>
</div>
</section>
</main>
);
}

@ -1,5 +1,3 @@
import { RegularFont } from '@/utils/font';
import type { Metadata, Viewport } from 'next';
import './globals.css';
@ -20,7 +18,7 @@ export const viewport: Viewport = {
export default function RootLayout({ children }: Readonly<{ children: React.ReactNode }>) {
return (
<html lang="zn-ch" className={RegularFont.className}>
<html lang="zh-cn">
<body>{children}</body>
</html>
);

@ -6,6 +6,7 @@ import Image from 'next/image';
import Link from 'next/link';
import AppLogo from '@/components/AppLogo';
import WXShareBtn from '@/components/WXComponent/WXShareBtn';
import { download } from '@/utils/download';
@ -15,10 +16,6 @@ export default function Home() {
const firstScreenRef = useRef<HTMLDivElement>(null);
const { inWX } = useUA();
const handleShare = () => {
alert('正在开发中,敬请期待');
};
const handleDownload = () => {
download();
};
@ -28,112 +25,103 @@ export default function Home() {
};
return (
<main className="max-w-screen-sm min-h-screen mx-auto flex flex-col items-center text-white font-normal">
{/* 首屏 */}
<div
ref={firstScreenRef}
className="relative w-full min-h-screen flex flex-col items-center bg-[url(/img/index_background.svg)] bg-center bg-cover"
>
{/* title */}
{!inWX && <h1 className="text-center text-[17px] h-[44px] leading-[44px]"></h1>}
{/* App logo */}
<AppLogo className="absolute top-[22%]" />
<div className="w-full flex flex-col items-center absolute bottom-0">
<button
className="w-[283px] h-[48px] flex items-center justify-center bg-[#000000f2] font-medium text-[17px] rounded-full mb-[16px]"
onClick={handleShare}
>
<>
<main className="max-w-screen-sm min-h-screen mx-auto flex flex-col items-center text-white font-normal">
{/* 首屏 */}
<div
ref={firstScreenRef}
className="relative w-full min-h-screen flex flex-col items-center bg-[url(/img/index_background.svg)] bg-center bg-cover"
>
{/* title */}
{!inWX && <h1 className="text-center text-[17px] h-[44px] leading-[44px]"></h1>}
{/* App logo */}
<AppLogo className="absolute top-[22%]" />
<div className="w-full flex flex-col items-center absolute bottom-0">
{/* 分享 */}
<WXShareBtn />
{/* 下载 */}
<button
className="w-[283px] h-[48px] flex items-center justify-center bg-[#B44343] font-medium text-[17px] rounded-full mb-[16px]"
onClick={handleDownload}
>
APP
</button>
<button className="w-[283px] h-[48px] flex justify-center" onClick={handleSlideDown}>
<Image
className="w-[36px] h-[36px] animate-bounce"
width={36}
height={36}
src="/img/index_Dropdown.svg"
alt="download"
/>
</button>
</div>
</div>
{/* 第二屏 */}
<div className="relative w-full min-h-screen flex flex-col items-center bg-black">
<div className="w-[75.5%]">
<Image
className="w-[24px] h-[24px] mr-[6px]"
width={24}
height={24}
src="/img/index_weChatIcon.svg"
alt="wx-share"
className="w-[165.24px] h-[46.44px] mt-[51.58px]"
width={165.24}
height={46.44}
src="/img/handwritten_white.svg"
alt="we are back"
/>
<span></span>
</button>
<button
className="w-[283px] h-[48px] flex items-center justify-center bg-[#B44343] font-medium text-[17px] rounded-full mb-[16px]"
onClick={handleDownload}
>
APP
</button>
<button className="w-[283px] h-[48px] flex justify-center" onClick={handleSlideDown}>
<p className="text-[#ffffffb2] text-[14px] leading-[26px] mt-[19.98px]">
<br />
<br />
<br />
<br />
<br />
<br />
<br />
便
<br />
&nbsp;
</p>
<Image
className="w-[36px] h-[36px] animate-bounce"
width={36}
height={36}
src="/img/index_Dropdown.svg"
alt="download"
className="w-[299px] h-[451.61px] mt-[26px] ml-auto mr-auto"
width={299}
height={451.61}
src="/img/index_mockup.svg"
alt="app preview"
/>
</button>
</div>
</div>
{/* 第二屏 */}
<div className="relative w-full min-h-screen flex flex-col items-center bg-black">
<div className="w-[75.5%]">
<Image
className="w-[165.24px] h-[46.44px] mt-[51.58px]"
width={165.24}
height={46.44}
src="/img/handwritten_white.svg"
alt="we are back"
/>
<p className="text-[#ffffffb2] text-[14px] leading-[26px] mt-[19.98px]">
<br />
<br />
<br />
<br />
<br />
<br />
<br />
便
<br />
&nbsp;
</p>
<Image
className="w-[299px] h-[451.61px] mt-[26px] ml-auto mr-auto"
width={299}
height={451.61}
src="/img/index_mockup.svg"
alt="app preview"
/>
<h5 className="text-[#ffffffb2] text-center text-[15px] leading-[21px] mt-[100px] mb-[4px]"></h5>
<p className="text-center text-[20px] font-medium leading-[33.6px]">rock@indie.cn</p>
<h5 className="text-[#ffffffb2] text-center text-[15px] leading-[21px] mt-[47px] mb-[4px]">Weibo</h5>
<p className="text-center text-[20px] font-medium leading-[33.6px] flex items-center justify-center">
<Link
className="relative"
href="https://weibo.com/1886232237?refer_flag=1001030103_"
target="_blank"
rel="noopener noreferrer"
>
<Image
className="w-[24px] h-[24px] absolute top-[50%] right-[-24px] translate-y-[-50%]"
width={24}
height={24}
src="/img/icon.svg"
alt="arrow-right"
/>
</Link>
</p>
{/* <h5 className="text-[#ffffffb2] text-center text-[15px] leading-[21px] mt-[47px] mb-[4px]"></h5>
<h5 className="text-[#ffffffb2] text-center text-[15px] leading-[21px] mt-[100px] mb-[4px]"></h5>
<p className="text-center text-[20px] font-medium leading-[33.6px]">rock@indie.cn</p>
<h5 className="text-[#ffffffb2] text-center text-[15px] leading-[21px] mt-[47px] mb-[4px]">Weibo</h5>
<p className="text-center text-[20px] font-medium leading-[33.6px] flex items-center justify-center">
<Link
className="relative"
href="https://weibo.com/1886232237?refer_flag=1001030103_"
target="_blank"
rel="noopener noreferrer"
>
<Image
className="w-[24px] h-[24px] absolute top-[50%] right-[-24px] translate-y-[-50%]"
width={24}
height={24}
src="/img/icon.svg"
alt="arrow-right"
/>
</Link>
</p>
{/* <h5 className="text-[#ffffffb2] text-center text-[15px] leading-[21px] mt-[47px] mb-[4px]"></h5>
<p className="text-center text-[20px] font-medium leading-[33.6px] flex items-center justify-center">
<span className="relative">
@ -147,29 +135,30 @@ export default function Home() {
</span>
</p> */}
<Link
className="block w-[fit-content] mt-[68px] ml-auto mr-auto"
href="http://weixin.qq.com/r/thLfx-3EHaBirbmk90ek"
target="_blank"
rel="noopener noreferrer"
>
<Image
className="w-[97.5px] h-[97.5px] mb-[10.5px] rounded-sm"
width={97.5}
height={97.5}
src="/img/index_QRCode.svg"
alt="arrow-right"
/>
<h5 className="text-[#ffffffb2] text-center text-[12px] leading-[18.8px]"></h5>
</Link>
<p className="text-[#ffffff33] text-center text-[9px] leading-[12.6px] mt-[53px] mb-[52px]">
ICP2024190175-1
<br />
Shenzhen QueYue Culture Technology Co., Ltd.
</p>
<Link
className="block w-[fit-content] mt-[68px] ml-auto mr-auto"
href="http://weixin.qq.com/r/thLfx-3EHaBirbmk90ek"
target="_blank"
rel="noopener noreferrer"
>
<Image
className="w-[97.5px] h-[97.5px] mb-[10.5px] rounded-sm"
width={97.5}
height={97.5}
src="/img/index_QRCode.svg"
alt="arrow-right"
/>
<h5 className="text-[#ffffffb2] text-center text-[12px] leading-[18.8px]"></h5>
</Link>
<p className="text-[#ffffff33] text-center text-[9px] leading-[12.6px] mt-[53px] mb-[52px]">
ICP2024190175-1
<br />
Shenzhen QueYue Culture Technology Co., Ltd.
</p>
</div>
</div>
</div>
</main>
</main>
</>
);
}

@ -0,0 +1,48 @@
'use client';
import { useState } from 'react';
import Image from 'next/image';
const Icon = ({ name }: { name: string }) => (
<Image
className="w-[24px] h-[24px] ml-[1px]"
width={24}
height={24}
unoptimized
src={`/img/${name}.png`}
alt={name}
/>
);
export default function ArticalWrap(props: { content?: any }) {
const { content } = props;
const [isFold, setIsFold] = useState(true);
const handleToggle = () => {
setIsFold(!isFold);
};
return (
<div className="relative text-[#000000b2] text-[15px] mt-[15px] mb-[36px]">
<article
className={`leading-[25px] overflow-hidden ${isFold && 'h-[96px]'}`}
dangerouslySetInnerHTML={{ __html: content }}
/>
{isFold && (
<div className="absolute w-full h-[96px] top-0 left-0 bg-gradient-to-b from-[#ffffff00] to-[#fffffff2]" />
)}
<div className="relative flex items-center text-[15px] pt-[17px]" onClick={handleToggle}>
{isFold ? (
<>
<Icon name="icon_arrow_down" />
</>
) : (
<>
<Icon name="icon_arrow_up" />
</>
)}
</div>
</div>
);
}

@ -0,0 +1,20 @@
'use client';
import Image from 'next/image';
export default function SongItem(props: { data: ISong }) {
const { pic, title, artist } = props?.data || {};
const handleClick = () => {
// TODO:
};
return (
<div className="flex items-center py-[12px]" onClick={handleClick}>
<Image className="w-[48px] h-[48px]" width={48} height={48} unoptimized src={pic} alt="歌曲封面" />
<div className="flex flex-1 flex-col pl-[15px] pr-[15px] overflow-hidden">
<div className="font-medium text-[15px] leading-[21px] mb-[2px] text-[#000000f2] truncate">{title}</div>
<div className="text-[12px] leading-[16.8px] text-[#000000b2] truncate">{artist}</div>
</div>
<Image className="w-[24px] h-[24px]" width={24} height={24} unoptimized src="/img/icon_song_dot.png" alt="dot" />
</div>
);
}

@ -0,0 +1,66 @@
'use client';
import { useEffect } from 'react';
import Image from 'next/image';
// import { APPID } from '@/const';
import useUA from '@/hooks/useUA';
export default function WXShareBtn() {
const { inWX } = useUA();
const handleShare = () => {
alert('敬请期待');
};
useEffect(() => {
if (!inWX) return;
const { searchParams } = new URL(window.location.href);
const code = searchParams.get('code');
if (code) {
// 已授权
// wx.config({
// debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来若要查看传入的参数可以在pc端打开参数信息会通过log打出仅在pc端时才会打印。
// appId: '', // 必填,公众号的唯一标识
// timestamp: 0, // 必填,生成签名的时间戳
// nonceStr: '', // 必填,生成签名的随机串
// signature: '', // 必填,签名
// jsApiList: [wx.updateAppMessageShareData], // 必填需要使用的JS接口列表
// });
// wx.ready(function () {
// //需在用户可能点击分享按钮前就先调用
// wx.updateAppMessageShareData({
// title: '', // 分享标题
// desc: '', // 分享描述
// link: '', // 分享链接该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
// imgUrl: '', // 分享图标
// success: function () {
// // 设置成功
// },
// });
// });
} else {
// 未授权
// window.location.replace(
// `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${APPID}&redirect_uri=${encodeURIComponent(window.location.href)}&response_type=code&scope=snsapi_base&state=code#wechat_redirect`,
// );
}
}, [inWX]);
return (
<button
className="w-[283px] h-[48px] flex items-center justify-center bg-[#000000f2] font-medium text-[17px] rounded-full mb-[16px]"
onClick={handleShare}
>
<Image
className="w-[24px] h-[24px] mr-[6px]"
width={24}
height={24}
src="/img/index_weChatIcon.svg"
alt="wx-share"
/>
<span></span>
</button>
);
}

@ -0,0 +1 @@
export const APPID = 'wxae6fb76efa147314';

@ -1 +1,12 @@
declare module 'lib-flexible';
interface ISong {
id: string;
title: string;
artist: string;
album: string;
src: string;
pic: string;
lrc: string;
journalNo: string;
songNo: number;
haveCollect: boolean;
}

Loading…
Cancel
Save