parent
8b83e4ad7f
commit
0510cb0ba3
After Width: | Height: | Size: 935 B |
After Width: | Height: | Size: 891 B |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 3.4 KiB |
After Width: | Height: | Size: 656 B |
@ -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>
|
||||||
|
);
|
||||||
|
}
|
@ -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 @@
|
|||||||
|
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…
Reference in new issue