feat: 历史视频详情查看

This commit is contained in:
LittleBoy 2024-12-17 20:52:24 +08:00
parent a2770765d8
commit 661b6f38da
7 changed files with 72 additions and 16 deletions

View File

@ -19,6 +19,7 @@ type StateUpdate = Partial<State> | ((prev: State) => Partial<State>)
type Props = {
url?: string; cover?: string; showControls?: boolean; className?: string;
poster?: string;
onChange?: (state: State) => void;
muted?: boolean;
}
@ -47,6 +48,13 @@ export const Player = React.forwardRef<PlayerInstance, Props>((props, ref) => {
return _state
})
}
useEffect(()=>{
if(props.url && tcPlayer){
tcPlayer.src(props.url)
}
},[props.url, tcPlayer])
useEffect(() => {
const playerVideo = document.createElement('video');
const playerId = `player-container-${Date.now().toString(16)}`;
@ -61,6 +69,7 @@ export const Player = React.forwardRef<PlayerInstance, Props>((props, ref) => {
//sources: [{src: props.url}],
controls: props.showControls,
// muted:props.muted,
poster: props.poster,
autoplay: true,
licenseUrl: 'https://license.vod2.myqcloud.com/license/v2/1328581896_1/v_cube.license'
}

View File

@ -1,42 +1,88 @@
import {Button, Modal} from "antd";
import {Button, Input, Modal} from "antd";
import {saveAs} from "file-saver";
import {useEffect, useState} from "react";
import {useSetState} from "ahooks";
import {Player} from "@/components/video/player.tsx";
import ArticleGroup from "@/components/article/group";
import * as article from "@/service/api/article.ts";
import {push2room} from "@/service/api/video.ts";
import {showErrorToast, showToast} from "@/components/message.ts";
type Props = {
video?: VideoInfo;
onClose?: () => void
}
export default function VideoDetail({video, onClose}: Props) {
const startStream = () => {
const [groups, setGroups] = useState<BlockContent[][]>([]);
const [state, setState] = useSetState({
exporting: false,
pushing: false,
})
// 将视频推送到数字人直播间
const pushToRoom = () => {
if (video) {
if (state.pushing) return
setState({pushing: true})
push2room([video.id]).then(() => {
showToast('一键推流成功,已推流至数字人直播间,请查看!', 'success')
}).catch(showErrorToast).finally(() => {
setState({pushing: false})
})
}
}
// 下载视频
const downloadVideo = () => {
if (video?.oss_video_url) {
const filename = video.oss_video_url.split('/').pop() || `${video.id}.flv`
saveAs(video.oss_video_url, filename)
}
}
useEffect(() => {
if (video) {
if (video.id > 0) {
article.getById(video.id).then(res => {
setGroups(res.content_group)
})
}
}
}, [video])
return (<>
<Modal open={!!video} title="新闻视频详情" width={1000} footer={null} onCancel={onClose}>
<div className="flex gap-2 my-5">
<div className="news-video w-[350px]">
<div className="video-container bg-gray-100 rounded overflow-hidden h-[400px]">
<Player url={'https://file.wx.wm-app.xyz/os/media/ymca.mp4'} simple showControls />
<div className="video-container bg-gray-100 rounded overflow-hidden h-[640px]">
<Player url={video?.oss_video_url} poster={video?.cover} showControls={true}
className="w-[360px] h-[640px] bg-white"/>
</div>
<div className="video-info text-right text-sm text-gray-600 mt-3">
<span>创建时间: 5小时前</span>
</div>
</div>
<div className="detail flex-1 ml-5">
<div className="title">
<span>标题: xxxxxxxx</span>
<div className="text-lg"></div>
<div className="article-title mt-5 items-center flex">
<span className="text text-base"></span>
<span className="ml-4 flex-1">
<Input value={video?.title}/>
</span>
</div>
<div className="content-container max-h-[500px] overflow-auto pr-1 mt-4">
<ArticleGroup groups={[]}/>
<div className="aricle-body mt-3">
<div className="title">
<span className="text text-base"></span>
</div>
<div className="box mt-1">
<ArticleGroup groups={groups}/>
</div>
</div>
</div>
</div>
<div className="footer flex justify-between">
<div className="action flex gap-2">
<Button type="primary" onClick={startStream}></Button>
<Button loading={state.pushing} type="primary" onClick={pushToRoom}></Button>
<Button onClick={downloadVideo}></Button>
</div>
<div className="close">

View File

@ -86,6 +86,6 @@ export default function LibraryIndex() {
</div>
</div>
</div>
<VideoDetail video={detailVideo} onClose={() => setDetailVideo(undefined)}/>
{detailVideo && <VideoDetail video={detailVideo} onClose={() => setDetailVideo(undefined)}/>}
</>)
}

View File

@ -4,12 +4,13 @@ import {showErrorToast, showToast} from "@/components/message.ts";
import {push2video} from "@/service/api/article.ts";
export default function ButtonPush2Video(props: { ids: Id[] }) {
export default function ButtonPush2Video(props: { ids: Id[];onSuccess?:()=>void; }) {
const [loading, setLoading] = useState(false)
const handlePush = () => {
setLoading(true)
push2video(props.ids).then(() => {
showToast('一键推流成功,已成功推入数字人视频生成,请前往数字人视频生成页面查看!', 'success')
props.onSuccess?.()
}).catch(showErrorToast).finally(() => {
setLoading(false)
})

View File

@ -89,7 +89,7 @@ export default function NewEdit() {
pagination: {page, limit: 10}
}))}
/>
<ButtonPush2Video ids={selectedRowKeys}/>
<ButtonPush2Video ids={selectedRowKeys} onSuccess={refresh}/>
</div>}
</div>
<ArticleEditModal

View File

@ -111,7 +111,7 @@ export default function NewsIndex() {
<div className="info text-gray-300 flex items-center justify-between gap-3 text-sm">
<div>: <span>{item.media_name}</span></div>
{/*<Divider type="vertical" />*/}
<div>: <span>{item.publish_time}</span></div>
<div>: <span>{formatTime(item.publish_time)}</span></div>
</div>
</div>
</div>

View File

@ -45,9 +45,9 @@ export default function VideoIndex() {
// 播放视频
const playVideo = (video: VideoInfo, playingIndex: number) => {
if (video.status !== 1) { // video.oss_video_url &&
if (video.oss_video_url && video.status !== 1) {
setState({playingIndex})
player.current?.play(video.oss_video_url||'https://staticplus.gachafun.com/ai-collect/composite_video/2024-12-14/1185251497659736064.flv', 0)
player.current?.play(video.oss_video_url, 0)
}
}
// 处理全选