update: 更新历史视频库
This commit is contained in:
parent
0699fa1145
commit
94d300d0be
@ -24,6 +24,7 @@ type Props = {
|
||||
onChange?: (state: State) => void;
|
||||
onProgress?: (current:number,duration:number) => void;
|
||||
muted?: boolean;
|
||||
autoPlay?: boolean;
|
||||
}
|
||||
export type PlayerInstance = {
|
||||
play: (url: string, currentTime: number) => void;
|
||||
@ -79,7 +80,7 @@ export const Player = React.forwardRef<PlayerInstance, Props>((props, ref) => {
|
||||
controls: props.showControls,
|
||||
// muted:props.muted,
|
||||
poster: props.poster,
|
||||
autoplay: true,
|
||||
autoplay: typeof(props.autoPlay) != 'undefined' ? props.autoPlay : true,
|
||||
licenseUrl: 'https://license.vod2.myqcloud.com/license/v2/1328581896_1/v_cube.license'
|
||||
}
|
||||
)
|
||||
|
@ -1,49 +1,59 @@
|
||||
import {Button, Form, Input, Select, Space} from "antd";
|
||||
import {useSetState} from "ahooks";
|
||||
import {PlayCircleOutlined} from "@ant-design/icons";
|
||||
import {PlayCircleOutlined, SearchOutlined} from "@ant-design/icons";
|
||||
import {SearchListTimes} from "@/pages/news/components/news-source.ts";
|
||||
import React from "react";
|
||||
import TimeSelect from "@/components/form/time-select.tsx";
|
||||
|
||||
type Props = {
|
||||
onSearch?: (params: VideoSearchParams) => void;
|
||||
onBtnStartClick?: () => Promise<void>;
|
||||
loading?:boolean;
|
||||
loading?: boolean;
|
||||
}
|
||||
export default function SearchForm({onSearch, onBtnStartClick,loading}: Props) {
|
||||
|
||||
export default function SearchForm({onSearch, onBtnStartClick, loading}: Props) {
|
||||
const [state, setState] = useSetState<{
|
||||
pushing?: boolean;
|
||||
}>({})
|
||||
const onFinish = (values) => {
|
||||
time_flag: number;
|
||||
title?: string;
|
||||
}>({
|
||||
time_flag:0
|
||||
})
|
||||
|
||||
const onFinish = (params: Partial<VideoSearchParams>) => {
|
||||
onSearch?.({
|
||||
...values,
|
||||
pagination: {page: 1, limit: 10}
|
||||
time_flag: params.time_flag,
|
||||
title: params.title,
|
||||
pagination: {page: 1, limit: 12}
|
||||
})
|
||||
//console.log(values)
|
||||
}
|
||||
|
||||
return (<div className={'search-panel'}>
|
||||
const handleTimeFilter = (time_flag: number) => {
|
||||
setState({time_flag})
|
||||
onFinish({
|
||||
title:state.title,time_flag
|
||||
})
|
||||
}
|
||||
|
||||
return (<div className={'search-panel pt-6 pb-2'}>
|
||||
<div className="flex justify-between items-center">
|
||||
<div className="search-form">
|
||||
<Form<VideoSearchParams> className={""} layout="inline" onFinish={onFinish} initialValues={{title:'',time_flag:0}}>
|
||||
<Form.Item name="title">
|
||||
<Input className="w-[200px]" allowClear placeholder={'请输入搜索信息'}/>
|
||||
</Form.Item>
|
||||
<Form.Item label={'更新时间'} name="time_flag" className="w-[250px]">
|
||||
<Select
|
||||
options={SearchListTimes}
|
||||
optionRender={(option) => (
|
||||
<div className="flex items-center">
|
||||
<span role="icon" className={`radio-icon`}></span>
|
||||
<span role="listitem" aria-label={String(option.label)}>{option.label}</span>
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item>
|
||||
<Space size={10}>
|
||||
<Button loading={loading} type={'primary'} htmlType={'submit'}>搜索</Button>
|
||||
</Space>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
<div className="flex items-center gap-4">
|
||||
<Input
|
||||
className="w-[270px] rounded-3xl"
|
||||
prefix={<SearchOutlined/>}
|
||||
onChange={e=>setState({title: e.target.value})}
|
||||
onPressEnter={()=>onFinish(state)}
|
||||
onBlur={()=>onFinish(state)}
|
||||
allowClear
|
||||
placeholder={'请输入视频标题关键字进行信息'}
|
||||
/>
|
||||
<TimeSelect
|
||||
className="w-[120px] ml-1"
|
||||
value={state.time_flag}
|
||||
onChange={handleTimeFilter}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<Space size={10}>
|
||||
<Button
|
||||
|
@ -8,6 +8,7 @@ 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";
|
||||
import {formatTime, timeFromNow} from "@/util/strings.ts";
|
||||
|
||||
type Props = {
|
||||
video?: VideoInfo;
|
||||
@ -51,32 +52,21 @@ export default function VideoDetail({video, onClose}: Props) {
|
||||
}, [video])
|
||||
|
||||
return (<>
|
||||
<Modal open={!!video} title="新闻视频详情" width={1000} footer={null} onCancel={onClose}>
|
||||
<Modal open={!!video} title={null} width={1500} footer={null} onCancel={onClose}>
|
||||
<div className="header text-2xl" style={{marginTop:-10}}>{video?.title || "新闻视频详情"}</div>
|
||||
<div className="flex gap-2 my-5">
|
||||
<div className="news-video w-[350px]">
|
||||
<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 className="video-container bg-gray-100 rounded overflow-hidden h-[560px]">
|
||||
<Player autoPlay={false} url={video?.oss_video_url} poster={video?.cover} showControls={true}
|
||||
className="w-[360px] h-[560px] bg-white"/>
|
||||
</div>
|
||||
<div className="video-info text-right text-sm text-gray-600 mt-3">
|
||||
<span>创建时间: 5小时前</span>
|
||||
<span>创建时间: {timeFromNow(video?.ctime)}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="detail flex-1 ml-5">
|
||||
<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="aricle-body mt-3">
|
||||
<div className="title">
|
||||
<span className="text text-base">正文</span>
|
||||
</div>
|
||||
<div className="box mt-1">
|
||||
<ArticleGroup groups={groups}/>
|
||||
</div>
|
||||
<ArticleGroup groups={groups}/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,11 +1,8 @@
|
||||
import {Checkbox, Image, Tag} from "antd";
|
||||
import {Checkbox, Tag} from "antd";
|
||||
import {IconDelete} from "@/components/icons";
|
||||
import {useState} from "react";
|
||||
|
||||
|
||||
import ImageCover from './cover.png'
|
||||
import {formatDuration, timeFromNow} from "@/util/strings.ts";
|
||||
import dayjs from "dayjs";
|
||||
|
||||
type VideoItemProps = {
|
||||
videoInfo: VideoInfo;
|
||||
@ -25,7 +22,7 @@ export default function VideoItem(props: VideoItemProps) {
|
||||
}
|
||||
}
|
||||
|
||||
return <div className={'video-item bg-gray-100 hover:drop-shadow-md rounded overflow-hidden relative group'}>
|
||||
return <div className={'video-item bg-white rounded overflow-hidden relative group'}>
|
||||
<div className={`controls absolute top-1 right-1 z-[2] p-1 rounded items-center gap-2 bg-white/80 ${state.checked?'flex':'hidden'} group-hover:flex`}>
|
||||
<span onClick={props.onRemove} className={'cursor-pointer text-blue-500 text-2xl cursor-pointer'}><IconDelete /></span>
|
||||
{!props.onLive && <Checkbox onChange={e=>handleCheckedChange(e.target.checked)} />}
|
||||
@ -34,7 +31,7 @@ export default function VideoItem(props: VideoItemProps) {
|
||||
<img className={'w-full cursor-pointer h-[180px] object-cover'} src={props.videoInfo.cover}/>
|
||||
</div>
|
||||
<div className="text-sm py-2 px-3">
|
||||
<div className="title my-1 cursor-pointer" onClick={props.onClick}>{props.videoInfo.title}</div>
|
||||
<div className="title my-1 cursor-pointer line-clamp-1" onClick={props.onClick}>{props.videoInfo.title}</div>
|
||||
<div className="info flex justify-between gap-2 text-sm">
|
||||
<div className="video-time-info text-gray-500">
|
||||
<span>时长: {formatDuration(Math.ceil(props.videoInfo.duration / 1000))}</span>
|
||||
|
@ -6,6 +6,7 @@ import VideoItem from "@/pages/library/components/video-item.tsx";
|
||||
import SearchForm from "@/pages/library/components/search-form.tsx";
|
||||
import VideoDetail from "@/pages/library/components/video-detail.tsx";
|
||||
import {search} from "@/service/api/video.ts";
|
||||
import InfiniteScroller from "@/components/scoller/infinite-scroller.tsx";
|
||||
|
||||
export default function LibraryIndex() {
|
||||
const [modal, contextHolder] = Modal.useModal();
|
||||
@ -14,7 +15,7 @@ export default function LibraryIndex() {
|
||||
time_flag: 0,
|
||||
pagination: {
|
||||
page: 1,
|
||||
limit: 10
|
||||
limit: 12
|
||||
}
|
||||
})
|
||||
const {data,loading} = useRequest(() => search(params), {
|
||||
@ -42,7 +43,7 @@ export default function LibraryIndex() {
|
||||
const [detailVideo, setDetailVideo] = useState<VideoInfo>()
|
||||
|
||||
return (<>
|
||||
<div className={'container py-20'}>
|
||||
<div className={'container pb-5'}>
|
||||
{contextHolder}
|
||||
<div className="search-form-container mb-5">
|
||||
<SearchForm
|
||||
@ -51,22 +52,24 @@ export default function LibraryIndex() {
|
||||
loading={loading}
|
||||
/>
|
||||
</div>
|
||||
<div className="bg-white rounded p-5">
|
||||
<div className={'video-list-container grid gap-5 grid-cols-4'}>
|
||||
{data?.list?.map((it, idx) => (
|
||||
<VideoItem
|
||||
onLive={idx == 2} key={it.id}
|
||||
videoInfo={it}
|
||||
onRemove={() => handleRemove(it)}
|
||||
onClick={() => setDetailVideo(it)}
|
||||
onCheckedChange={(checked) => {
|
||||
setCheckedIdArray(idArray => {
|
||||
return checked ? idArray.concat(it.id) : idArray.filter(id => id != it.id);
|
||||
})
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
<div className="">
|
||||
<InfiniteScroller loading={loading} pagination={data?.pagination} onCallback={()=>{}}>
|
||||
<div className={'video-list-container grid gap-5 grid-cols-4'}>
|
||||
{data?.list?.map((it, idx) => (
|
||||
<VideoItem
|
||||
onLive={idx == 2} key={it.id}
|
||||
videoInfo={it}
|
||||
onRemove={() => handleRemove(it)}
|
||||
onClick={() => setDetailVideo(it)}
|
||||
onCheckedChange={(checked) => {
|
||||
setCheckedIdArray(idArray => {
|
||||
return checked ? idArray.concat(it.id) : idArray.filter(id => id != it.id);
|
||||
})
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</InfiniteScroller>
|
||||
<div className="video-page-container flex justify-center mt-5">
|
||||
{data?.pagination && data?.pagination.total > 0 ? <div className="flex justify-center mt-10">
|
||||
<Pagination
|
||||
|
@ -3,13 +3,15 @@ import {Suspense,} from "react";
|
||||
import {ConfigProvider,App} from "antd";
|
||||
import zhCN from 'antd/locale/zh_CN';
|
||||
// for date-picker i18n
|
||||
import dayjs from "dayjs";
|
||||
import 'dayjs/locale/zh-cn';
|
||||
|
||||
import ErrorBoundary from "./error.tsx";
|
||||
import Loader from "@/components/loader.tsx";
|
||||
import routes from "@/routes/routes.tsx";
|
||||
|
||||
|
||||
dayjs.locale('zh-cn');
|
||||
|
||||
const router = createBrowserRouter([
|
||||
...routes,
|
||||
{path: '*', element: <ErrorBoundary/>}
|
||||
|
Loading…
x
Reference in New Issue
Block a user