资源视频编辑组件、视频预览组件

This commit is contained in:
禺狨 2023-06-13 10:42:48 +08:00
parent 7cb408a1cb
commit 87d1fc8e01
10 changed files with 291 additions and 0 deletions

View File

@ -8,9 +8,15 @@
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"
/>
<title>管理后台</title>
<script src="/js/DPlayer.min.js"></script>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
<script
crossorigin="anonymous"
integrity="sha512-oHrfR/z2wkuRuaHrdZ9NhoT/o/1kteub+QvmQgVzOKK7NTvIKQMvnY9+/RR0+eW311o4lAE/YzzLXXmP2XUvig=="
src="https://lib.baomitu.com/hls.js/1.1.4/hls.min.js"
></script>
</body>
</html>

1
public/js/DPlayer.min.js vendored Normal file

File diff suppressed because one or more lines are too long

1
public/js/xg/hls.min.js vendored Normal file

File diff suppressed because one or more lines are too long

21
public/js/xg/index.js Normal file

File diff suppressed because one or more lines are too long

View File

@ -62,6 +62,10 @@ export function destroyResourceMulti(ids: number[]) {
});
}
export function videoDetail(id: number) {
return client.get(`/backend/v1/resource/${id}`, {});
}
export function videoUpdate(id: number, params: any) {
return client.put(`/backend/v1/resource/${id}`, params);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 736 B

View File

@ -0,0 +1,138 @@
import React, { useState, useEffect } from "react";
import { Modal, Form, Input, message, TreeSelect } from "antd";
import { resource, resourceCategory } from "../../../../../api/index";
interface PropInterface {
id: number;
open: boolean;
onCancel: () => void;
}
export const VideosUpdateDialog: React.FC<PropInterface> = ({
id,
open,
onCancel,
}) => {
const [form] = Form.useForm();
const [loading, setLoading] = useState<boolean>(true);
const [categories, setCategories] = useState<any>([]);
useEffect(() => {
if (id === 0) {
return;
}
if (open) {
getCategory();
getDetail();
}
}, [id, open]);
const getCategory = () => {
resourceCategory.resourceCategoryList().then((res: any) => {
const categories = res.data.categories;
if (JSON.stringify(categories) !== "{}") {
const new_arr: any = checkArr(categories, 0, null);
setCategories(new_arr);
}
});
};
const getDetail = () => {
resource.videoDetail(id).then((res: any) => {
let data = res.data.resources;
form.setFieldsValue({
name: data.name,
category_id: res.data.category_ids,
});
});
};
const checkArr = (departments: any[], id: number, counts: any) => {
const arr = [];
for (let i = 0; i < departments[id].length; i++) {
if (!departments[departments[id][i].id]) {
arr.push({
title: departments[id][i].name,
value: departments[id][i].id,
});
} else {
const new_arr: any = checkArr(
departments,
departments[id][i].id,
counts
);
arr.push({
title: departments[id][i].name,
value: departments[id][i].id,
children: new_arr,
});
}
}
return arr;
};
const onFinish = (values: any) => {
resource.videoUpdate(id, values).then((res: any) => {
message.success("保存成功!");
onCancel();
});
};
const onFinishFailed = (errorInfo: any) => {
console.log("Failed:", errorInfo);
};
return (
<>
<Modal
title="编辑视频"
centered
forceRender
open={open}
width={416}
onOk={() => form.submit()}
onCancel={() => onCancel()}
maskClosable={false}
>
<div className="float-left mt-24">
<Form
form={form}
name="videos-update"
labelCol={{ span: 8 }}
wrapperCol={{ span: 16 }}
initialValues={{ remember: true }}
onFinish={onFinish}
onFinishFailed={onFinishFailed}
autoComplete="off"
>
<Form.Item
label="视频分类"
name="category_id"
rules={[{ required: true, message: "请选择视频分类!" }]}
>
<TreeSelect
showCheckedStrategy={TreeSelect.SHOW_ALL}
allowClear
style={{ width: 200 }}
treeData={categories}
placeholder="视频分类"
treeDefaultExpandAll
/>
</Form.Item>
<Form.Item
label="视频名称"
name="name"
rules={[{ required: true, message: "请输入视频名称!" }]}
>
<Input
allowClear
style={{ width: 200 }}
placeholder="请输入视频名称"
/>
</Form.Item>
</Form>
</div>
</Modal>
</>
);
};

View File

@ -0,0 +1,40 @@
.play-mask {
width: 100%;
height: 100%;
top: 0;
bottom: 0;
left: 0;
right: 0;
position: fixed;
display: flex;
align-items: center;
justify-content: center;
z-index: 200;
.play-dialog {
width: 800px;
height: 450px;
border-radius: 8px;
overflow: hidden;
position: relative;
.close-button {
width: 30px;
height: 30px;
position: absolute;
top: 24px;
right: 24px;
cursor: pointer;
z-index: 1000;
&:hover {
opacity: 0.8;
}
img {
width: 30px;
height: 30px;
}
}
.play-box {
width: 800px;
height: 450px;
}
}
}

View File

@ -0,0 +1,64 @@
import React, { useState, useEffect } from "react";
import styles from "./index.module.less";
import closeIcon from "../../../../../assets/images/commen/close.png";
interface PropInterface {
id: number;
url: string;
open: boolean;
onCancel: () => void;
}
declare const window: any;
export const VideoPlayDialog: React.FC<PropInterface> = ({
id,
url,
open,
onCancel,
}) => {
const [loading, setLoading] = useState<boolean>(true);
useEffect(() => {
if (open && url) {
initDPlayer(url);
}
}, [id, open, url]);
const initDPlayer = (playUrl: string) => {
window.player = new window.DPlayer({
container: document.getElementById("meedu-player-container"),
autoplay: false,
video: {
url: playUrl,
},
});
window.player.on("ended", () => {
window.player && window.player.destroy();
});
};
return (
<>
{open && (
<div className={styles["play-mask"]}>
<div className={styles["play-dialog"]}>
<div
className={styles["close-button"]}
onClick={() => {
window.player && window.player.destroy();
onCancel();
}}
>
<img src={closeIcon} />
</div>
<div
className={styles["play-box"]}
id="meedu-player-container"
></div>
</div>
</div>
)}
</>
);
};

View File

@ -9,6 +9,8 @@ import type { ColumnsType } from "antd/es/table";
import { dateFormat } from "../../../utils/index";
import { TreeCategory, DurationText, PerButton } from "../../../compenents";
import { UploadVideoButton } from "../../../compenents/upload-video-button";
import { VideoPlayDialog } from "./compenents/video-play-dialog";
import { VideosUpdateDialog } from "./compenents/update-dialog";
const { confirm } = Modal;
@ -39,6 +41,7 @@ const ResourceVideosPage = () => {
const [playVisible, setPlayeVisible] = useState<boolean>(false);
const [multiConfig, setMultiConfig] = useState<boolean>(false);
const [updateId, setUpdateId] = useState(0);
const [playUrl, setPlayUrl] = useState<string>("");
useEffect(() => {
setCateId(Number(result.get("cid")));
@ -131,6 +134,8 @@ const ResourceVideosPage = () => {
size="small"
className="b-n-link c-red"
onClick={() => {
setUpdateId(record.id);
setPlayUrl(record.url);
setPlayeVisible(true);
}}
>
@ -332,6 +337,17 @@ const ResourceVideosPage = () => {
)}
</div>
</div>
<VideoPlayDialog
id={Number(updateId)}
open={playVisible}
url={playUrl}
onCancel={() => setPlayeVisible(false)}
></VideoPlayDialog>
<VideosUpdateDialog
id={Number(updateId)}
open={updateVisible}
onCancel={() => setUpdateVisible(false)}
></VideosUpdateDialog>
</div>
</>
);