e6152cb932
- 小程序 content-detail:<RichText nodes=body> 渲染 HTML(图片/视频/排版),样式对齐 - 网站 Content.jsx 详情展开:dangerouslySetInnerHTML 渲染富文本 Co-Authored-By: Claude <noreply@anthropic.com>
71 lines
2.7 KiB
React
71 lines
2.7 KiB
React
import { View, Text, Image, Video, ScrollView, Button, RichText } from '@tarojs/components';
|
||
import Taro from '@tarojs/taro';
|
||
import { useState, useEffect } from 'react';
|
||
import { getContent } from '@/utils/content';
|
||
import './index.scss';
|
||
|
||
/** 资讯详情:封面/视频 + 正文 + 图集 + 外链 + 发布人。 */
|
||
export default function ContentDetail() {
|
||
const [item, setItem] = useState(null);
|
||
const [err, setErr] = useState('');
|
||
const [loaded, setLoaded] = useState(false);
|
||
|
||
useEffect(() => {
|
||
const inst = Taro.getCurrentInstance();
|
||
const id = (inst && inst.router && inst.router.params && inst.router.params.id) || '';
|
||
if (!id) { setErr('无效内容'); setLoaded(true); return; }
|
||
getContent(id).then(setItem).catch(() => setErr('加载失败')).finally(() => setLoaded(true));
|
||
}, []);
|
||
|
||
if (!loaded) return <View className="cd page-in"><Text className="cd-err">加载中…</Text></View>;
|
||
if (err || !item) return <View className="cd page-in"><Text className="cd-err">{err || '内容不存在'}</Text></View>;
|
||
|
||
const img = item.cover || (item.video ? item.video_cover : '');
|
||
const images = Array.isArray(item.images) ? item.images : [];
|
||
|
||
return (
|
||
<View className="cd page-in">
|
||
{/* 视频或封面 */}
|
||
{item.video
|
||
? <Video className="cd-video" src={item.video} poster={item.video_cover || item.cover || ''} controls />
|
||
: img
|
||
? <Image className="cd-cover" src={img} mode="widthFix" />
|
||
: null}
|
||
|
||
<Text className="cd-title">{item.title}</Text>
|
||
|
||
{/* 发布人行 */}
|
||
<View className="cd-meta-row">
|
||
{item.publisher_avatar
|
||
? <Image className="cd-ava" src={item.publisher_avatar} mode="aspectFill" />
|
||
: <View className="cd-ava" />}
|
||
<Text className="cd-author">{item.publisher_name || '云超服'}</Text>
|
||
<Text className="cd-dot">·</Text>
|
||
<Text className="cd-meta-at">{fmt(item.created_at)}</Text>
|
||
</View>
|
||
|
||
{item.summary ? <Text className="cd-summary">{item.summary}</Text> : null}
|
||
{item.body
|
||
? <RichText className="cd-body" nodes={item.body} />
|
||
: <Text className="cd-body">暂无正文</Text>}
|
||
|
||
{/* 图集 */}
|
||
{images.length > 0 && (
|
||
<ScrollView className="cd-gallery" scrollX>
|
||
{images.map((u, i) => <Image key={i} className="cd-gal-img" src={u} mode="aspectFill" />)}
|
||
</ScrollView>
|
||
)}
|
||
|
||
{item.link ? (
|
||
<Button className="btn btn-ghost cd-link" type="default" onClick={() => Taro.setClipboardData({ data: item.link })}>
|
||
原文链接(点击复制)
|
||
</Button>
|
||
) : null}
|
||
</View>
|
||
);
|
||
}
|
||
|
||
function fmt(s) {
|
||
return (s || '').replace('T', ' ').replace('Z', '').slice(0, 16);
|
||
}
|