560 lines
14 KiB
Vue
560 lines
14 KiB
Vue
<template>
|
||
<div class="webcast">
|
||
<a-form :label-col="labelCol" :wrapper-col="wrapperCol">
|
||
<div class="title">直播信息</div>
|
||
<a-form-item label="直播标题">
|
||
<a-input
|
||
size="small"
|
||
v-model:value="form.title"
|
||
placeholder="请输入您的直播标题"
|
||
/>
|
||
</a-form-item>
|
||
<a-form-item label="直播封面" class="item-cover">
|
||
<a-upload list-type="picture" :customRequest="uploadspic">
|
||
<div class="upload-image" v-if="!viewCover && form.img.length == 0">
|
||
<PlusOutlined
|
||
style="fontsize: 22px"
|
||
v-if="uploadpicprogress == 0"
|
||
/>
|
||
<a-progress
|
||
type="circle"
|
||
:percent="uploadpicprogress"
|
||
:width="80"
|
||
v-else
|
||
/>
|
||
</div>
|
||
<div class="upload-image" v-else>
|
||
<img style="width: 100%; height: 100%" :src="form.img" />
|
||
</div>
|
||
</a-upload>
|
||
</a-form-item>
|
||
<a-form-item label="视频介绍" class="video-introduction">
|
||
<a-upload list-type="picture" :customRequest="uploads">
|
||
<div class="upload-image" v-if="form.fileurl.length == 0">
|
||
<PlaySquareOutlined
|
||
style="fontsize: 22px"
|
||
v-if="uploadprogress == 0"
|
||
/>
|
||
<a-progress
|
||
type="circle"
|
||
:percent="uploadprogress"
|
||
:width="80"
|
||
v-else
|
||
/>
|
||
<video style="display: none" :src="videofile"></video>
|
||
</div>
|
||
<div
|
||
class="upload-image upload"
|
||
style="position: relative"
|
||
v-show="form.fileurl.length != 0"
|
||
>
|
||
<video
|
||
:src="form.fileurl"
|
||
:ref="
|
||
(el) => {
|
||
videos[0] = el;
|
||
}
|
||
"
|
||
class="upload"
|
||
></video>
|
||
<!-- <a-progress type="circle" :percent="100" :width="80" style="position:absolute;right:35%"/> -->
|
||
</div>
|
||
</a-upload>
|
||
<div class="demand">
|
||
<p class="one-line-hide">视频要求:</p>
|
||
<p class="one-line-hide">1.上传视频时间要求为30s之内</p>
|
||
<p class="one-line-hide">2.支持文件大小100M</p>
|
||
<p class="one-line-hide">
|
||
3.文件扩展名:fiv、mp4…文件扩展名:fiv、mp4…
|
||
</p>
|
||
</div>
|
||
</a-form-item>
|
||
<a-form-item label="开始时间">
|
||
<!-- <a-input
|
||
size="small"
|
||
v-model:value="form.startTime"
|
||
placeholder="请设置您的开始时间"
|
||
/> -->
|
||
<a-date-picker @change="startchange" placeholder="请设置您的开始时间" />
|
||
</a-form-item>
|
||
<a-form-item
|
||
label="直播时长"
|
||
class="duration"
|
||
v-bind="validateInfos.livetime"
|
||
>
|
||
<a-input
|
||
size="small"
|
||
v-model:value="form.livetime"
|
||
placeholder="请输入直播时间"
|
||
/>
|
||
<span class="unit">分钟</span>
|
||
</a-form-item>
|
||
<a-form-item label="直播人数" v-bind="validateInfos.livenumber">
|
||
<a-input
|
||
size="small"
|
||
v-model:value="form.livenumber"
|
||
placeholder="请输入直播人数"
|
||
/>
|
||
</a-form-item>
|
||
<a-form-item label="直播简介" class="brief">
|
||
<a-textarea
|
||
v-model:value="form.desc"
|
||
:autoSize="true"
|
||
class="brief-textarea"
|
||
:maxlength="200"
|
||
placeholder="请输入您的直播简介"
|
||
/>
|
||
<span class="words-number">{{ form.desc.length }}/200</span>
|
||
</a-form-item>
|
||
<a-form-item :wrapper-col="{ span: 4, offset: 0 }">
|
||
<a-button @click="onSubmit">发布直播</a-button>
|
||
</a-form-item>
|
||
</a-form>
|
||
<div class="modal-container">
|
||
<a-modal
|
||
centered
|
||
:footer="null"
|
||
:getContainer="modalNode"
|
||
dialogClass="modal-dialog"
|
||
v-model:visible="isEntitled"
|
||
@cancel="hideNoticeModal"
|
||
>
|
||
<template v-slot:closeIcon>
|
||
<img src="@/static/images/delete.png" class="close" />
|
||
</template>
|
||
<div class="notice-container report" v-if="0">
|
||
<div class="title">您尚未获得直播资格</div>
|
||
<div class="title sub-title">
|
||
您被 学生XXX<span class="red">举报,发生违规行为</span
|
||
>,如有疑问,点击反馈
|
||
</div>
|
||
<div class="confirm-btn">意见反馈</div>
|
||
</div>
|
||
<div class="notice-container" v-else>
|
||
<div class="title">您尚未获得直播资格</div>
|
||
<div class="title sub-title">
|
||
上一周/月您在平台视频点击量为
|
||
<span class="red">第24名</span>,要在前
|
||
<span class="bule">20名</span> 才能获得直播资格
|
||
</div>
|
||
<rank-list></rank-list>
|
||
</div>
|
||
</a-modal>
|
||
</div>
|
||
<nav-bottom></nav-bottom>
|
||
</div>
|
||
</template>
|
||
<script lang="ts">
|
||
import {
|
||
defineComponent,
|
||
onBeforeUpdate,
|
||
onMounted,
|
||
reactive,
|
||
Ref,
|
||
ref,
|
||
toRaw,
|
||
} from "vue";
|
||
import { PlaySquareOutlined, PlusOutlined } from "@ant-design/icons-vue";
|
||
import { useForm } from "@ant-design-vue/use";
|
||
import NavBottom from "@/components/NavBottom.vue";
|
||
import RankList from "./RankList.vue";
|
||
import { previewCover } from "@/utils/common";
|
||
import { FromSend, ImgInfo } from "@/types/index";
|
||
import { uploadflie } from "@/utils/vod";
|
||
import { liveadd } from "@/api";
|
||
|
||
export default defineComponent({
|
||
name: "ReleaseWebcast",
|
||
components: {
|
||
PlaySquareOutlined,
|
||
PlusOutlined,
|
||
NavBottom,
|
||
RankList,
|
||
},
|
||
setup() {
|
||
// 表单数据
|
||
const form = reactive({
|
||
title: "",
|
||
img: "",
|
||
fileid: "",
|
||
fileurl: "",
|
||
fileduration: 0,
|
||
dateline: "",
|
||
livetime: "",
|
||
livenumber: "",
|
||
desc: "",
|
||
});
|
||
|
||
const uploadprogress: Ref<number> = ref(0);
|
||
const uploadpicprogress: Ref<number> = ref(0);
|
||
const videofile = ref<File>();
|
||
const videos = ref<Array<any>>([]);
|
||
/**
|
||
* 验证直播时间
|
||
*/
|
||
async function validateaLivetime(
|
||
rule: unknown,
|
||
value: number
|
||
): Promise<string | void> {
|
||
console.log(value);
|
||
if (value < 30 || value > 120) {
|
||
return Promise.reject("*最短30min 最长120min");
|
||
} else {
|
||
return Promise.resolve();
|
||
}
|
||
}
|
||
/**
|
||
* 验证直播人数
|
||
*/
|
||
const validateLivenumber = async (
|
||
rule: unknown,
|
||
value: number
|
||
): Promise<string | void> => {
|
||
console.log(value);
|
||
if (value < 1 || value > 4) {
|
||
return Promise.reject("**最少1人,最多4人");
|
||
} else {
|
||
return Promise.resolve();
|
||
}
|
||
};
|
||
// 验证规则
|
||
const rules = reactive({
|
||
livetime: [
|
||
{
|
||
validator: validateaLivetime,
|
||
trigger: "change",
|
||
},
|
||
],
|
||
livenumber: [
|
||
{
|
||
validator: validateLivenumber,
|
||
trigger: "change",
|
||
},
|
||
],
|
||
});
|
||
|
||
// 是否显示封面预览 封面的路径
|
||
const viewCover: Ref<boolean> = ref(false);
|
||
const previewImage: Ref<string> = ref("");
|
||
|
||
/**
|
||
* 封面改变触发事件
|
||
*/
|
||
|
||
function coverChange(info: ImgInfo): void {
|
||
// console.log(info);
|
||
// 获取预览图片
|
||
previewCover(info.file).then((url) => (previewImage.value = url));
|
||
viewCover.value = true;
|
||
// form.cover = fileList;
|
||
}
|
||
|
||
const { resetFields, validate, validateInfos } = useForm(form, rules);
|
||
|
||
/**
|
||
* 表单提交
|
||
*/
|
||
|
||
const subdata = reactive({
|
||
title: "",
|
||
img: "",
|
||
fileid: "",
|
||
fileurl: "",
|
||
fileduration: "",
|
||
dateline: "",
|
||
livetime: "",
|
||
livenumber: "",
|
||
desc: "",
|
||
});
|
||
|
||
const onSubmit = (e: FromSend) => {
|
||
e.preventDefault();
|
||
validate()
|
||
.then(() => {
|
||
// console.log(toRaw(form),111);
|
||
let subdata = toRaw(form);
|
||
// subdata.fileid=picinfo.
|
||
console.log(subdata);
|
||
liveadd(subdata);
|
||
})
|
||
.catch((err: unknown) => {
|
||
console.log("error", err);
|
||
});
|
||
};
|
||
const isEntitled: Ref<boolean> = ref(true);
|
||
/**
|
||
* 隐藏无资格提示
|
||
*/
|
||
function hideNoticeModal(): void {
|
||
isEntitled.value = false;
|
||
}
|
||
|
||
/**
|
||
* 开始时间设置
|
||
*/
|
||
|
||
function startchange(e: string): void {
|
||
let month=new Date(e).getMonth()+1
|
||
console.log(new Date(e).getFullYear()+"-"+month+'-'+new Date(e).getDate())
|
||
form.dateline =
|
||
new Date(e).getFullYear() +
|
||
"-" +
|
||
month +
|
||
"-" +
|
||
new Date(e).getDate();
|
||
}
|
||
/**
|
||
* 上传文件
|
||
*/
|
||
const videoinfo = reactive({
|
||
fileId: "",
|
||
url: "",
|
||
});
|
||
const picinfo = reactive({
|
||
fileId: "",
|
||
url: "",
|
||
});
|
||
interface AntUpload {
|
||
action: string;
|
||
data: unknown;
|
||
file: File;
|
||
}
|
||
async function uploads(file: AntUpload) {
|
||
console.log(file);
|
||
videofile.value = file.file;
|
||
videos.value[0].addEventListener("durationchange", () => {
|
||
console.log(videos.value[0].duration);
|
||
form.fileduration = videos.value[0].duration;
|
||
});
|
||
let res = await uploadflie(file.file, (info: any) => {
|
||
console.log(info);
|
||
uploadprogress.value = info.percent.toFixed(2) * 100;
|
||
});
|
||
console.log(res);
|
||
|
||
form.fileid = res.fileId;
|
||
form.fileurl = res.video.url;
|
||
}
|
||
|
||
async function uploadspic(file: AntUpload) {
|
||
let res = await uploadflie(file.file, (info: any) => {
|
||
console.log(info);
|
||
uploadpicprogress.value = info.percent.toFixed(2) * 100;
|
||
});
|
||
console.log(res);
|
||
|
||
// picinfo.fileId=res.fileId
|
||
// picinfo.url=res.video.url
|
||
form.img = res.video.url;
|
||
}
|
||
|
||
return {
|
||
labelCol: { span: 4 },
|
||
wrapperCol: { span: 14 },
|
||
modalNode: () => document.getElementsByClassName("modal-container")[0],
|
||
validateInfos,
|
||
resetFields,
|
||
viewCover,
|
||
previewImage,
|
||
coverChange,
|
||
form,
|
||
onSubmit,
|
||
isEntitled,
|
||
hideNoticeModal,
|
||
uploads,
|
||
uploadprogress,
|
||
videoinfo,
|
||
uploadspic,
|
||
uploadpicprogress,
|
||
picinfo,
|
||
startchange,
|
||
videofile,
|
||
videos,
|
||
};
|
||
},
|
||
});
|
||
</script>
|
||
<style lang="scss" scoped>
|
||
.webcast {
|
||
width: 100%;
|
||
min-width: 700px;
|
||
background-color: #ffffff;
|
||
padding: 46px;
|
||
border-radius: 17px;
|
||
position: relative;
|
||
::v-deep(.ant-form) {
|
||
.title {
|
||
font-size: 12px;
|
||
font-weight: bold;
|
||
color: #111111;
|
||
margin-bottom: 28px;
|
||
}
|
||
.ant-row {
|
||
.ant-form-item-label {
|
||
width: 60px;
|
||
margin: 0 30px 0 17px;
|
||
> label {
|
||
font-size: 12px;
|
||
font-weight: 500;
|
||
color: #808080;
|
||
&::after {
|
||
content: "";
|
||
}
|
||
}
|
||
}
|
||
.upload {
|
||
width: 171px;
|
||
height: 96px;
|
||
}
|
||
.upload-image {
|
||
width: 171px;
|
||
height: 96px;
|
||
border: 1px solid #dcdfe0;
|
||
border-radius: 3px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
margin-right: 17px;
|
||
}
|
||
.ant-input {
|
||
width: 171px;
|
||
padding: 6px 11px;
|
||
border-radius: 3px;
|
||
border: 1px solid #dcdfe0;
|
||
font-size: 11px;
|
||
color: #3f3f3f;
|
||
&::-webkit-input-placeholder {
|
||
font-size: 12px;
|
||
color: #808080;
|
||
}
|
||
}
|
||
.ant-select {
|
||
font-size: 12px;
|
||
}
|
||
.ant-select-dropdown {
|
||
font-size: 12px;
|
||
}
|
||
.ant-form-explain {
|
||
font-size: 10px;
|
||
font-weight: 500;
|
||
color: #d22d2e;
|
||
}
|
||
.ant-upload-list {
|
||
display: none;
|
||
}
|
||
.ant-btn {
|
||
padding: 0;
|
||
width: 63px;
|
||
height: 23px;
|
||
background: #08ae98;
|
||
border-radius: 3px;
|
||
font-size: 10px;
|
||
font-weight: 500;
|
||
color: #ffffff;
|
||
}
|
||
}
|
||
.item-cover {
|
||
.preview-image {
|
||
width: 171px;
|
||
height: 96px;
|
||
}
|
||
}
|
||
.video-introduction {
|
||
.ant-form-item-control-wrapper {
|
||
.ant-form-item-children {
|
||
display: flex;
|
||
align-items: center;
|
||
.demand {
|
||
line-height: 17px;
|
||
font-size: 10px;
|
||
font-weight: 500;
|
||
color: #808080;
|
||
width: 134px;
|
||
> p {
|
||
margin: 0;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
.duration {
|
||
.unit {
|
||
margin-left: 18px;
|
||
font-size: 12px;
|
||
font-weight: 500;
|
||
color: #808080;
|
||
}
|
||
}
|
||
.brief {
|
||
position: relative;
|
||
.ant-input {
|
||
width: 359px;
|
||
}
|
||
.brief-textarea {
|
||
min-height: 85px;
|
||
padding-bottom: 30px;
|
||
}
|
||
.words-number {
|
||
position: absolute;
|
||
right: 11px;
|
||
bottom: -11px;
|
||
font-size: 11px;
|
||
font-weight: 500;
|
||
color: #7f7f7f;
|
||
user-select: none;
|
||
}
|
||
}
|
||
}
|
||
.modal-container {
|
||
::v-deep(.modal-dialog) {
|
||
.close {
|
||
width: 14px;
|
||
height: 14px;
|
||
}
|
||
.ant-modal-content {
|
||
box-sizing: border-box;
|
||
padding: 25px 30px;
|
||
width: 569px;
|
||
background: #ffffff;
|
||
box-shadow: 0px 4px 6px 0px rgba(102, 102, 102, 0.07);
|
||
border-radius: 28px;
|
||
.notice-container {
|
||
.title {
|
||
font-size: 11px;
|
||
font-weight: bold;
|
||
color: #111111;
|
||
margin-bottom: 16px;
|
||
}
|
||
.sub-title {
|
||
.red {
|
||
color: #d12c2d;
|
||
}
|
||
.bule {
|
||
color: #0dbba3;
|
||
}
|
||
}
|
||
.confirm-btn {
|
||
display: inline-block;
|
||
background: #07ad97;
|
||
border-radius: 2px;
|
||
font-size: 9px;
|
||
font-weight: 500;
|
||
color: #ffffff;
|
||
text-align: center;
|
||
cursor: pointer;
|
||
user-select: none;
|
||
height: 22px;
|
||
line-height: 22px;
|
||
padding: 0 17px;
|
||
}
|
||
}
|
||
.report {
|
||
.sub-title {
|
||
margin-bottom: 50px;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
</style> |