beelink/src/views/mine/ReleaseWebcast.vue
2020-10-30 15:08:34 +08:00

711 lines
24 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="webcast">
<a-form :label-col="labelCol" :wrapper-col="wrapperCol">
<div class="title">{{ lan.$t("zhiboxinxi") }}</div>
<a-form-item :label="lan.$t('zhibobiaoti')">
<a-input
size="small"
v-model:value="form.title"
:placeholder="lan.$t('shuruzhibobiaoti')"
/>
</a-form-item>
<a-form-item :label="lan.$t('zhibofengmian')" class="item-cover">
<a-upload
list-type="picture"
:customRequest="uploadspic"
:before-upload="beforeUploadpic"
>
<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="lan.$t('shipinjieshao')"
class="video-introduction"
>
<a-upload
list-type="picture"
:customRequest="uploads"
:before-upload="beforeUpload"
>
<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">
{{ lan.$t("shipinyaoqiu") }}
</p>
<p class="one-line-hide">1.{{ lan.$t("shipinyaoqiu1") }}</p>
<p class="one-line-hide">2.{{ lan.$t("shipinyaoqiu2") }}</p>
<p class="one-line-hide">3.{{ lan.$t("shipinyaoqiu3") }}</p>
</div>
<!-- <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.文件扩展名fivmp4文件扩展名fivmp4
</p>
</div> -->
</a-form-item>
<a-form-item :label="lan.$t('kaishishijian')">
<!-- <a-input
size="small"
v-model:value="form.startTime"
placeholder="请设置您的开始时间"
/> -->
<a-date-picker
show-time
:value="form.dateline"
@change="startchange"
:placeholder="lan.$t('shezhikaishishijian')"
/>
</a-form-item>
<a-form-item
:label="lan.$t('zhiboshichang')"
class="duration"
v-bind="validateInfos.livetime"
>
<a-input
size="small"
v-model:value="form.livetime"
:placeholder="lan.$t('shuruzhiboshijian')"
type="number"
/>
<span class="unit">{{ lan.$t("fenzhong") }}</span>
<div style="color: red;font-size: 0.12rem;line-height: 1.3;">*最短30min, 最长120min</div>
</a-form-item>
<a-form-item
:label="lan.$t('zhiborenshu')"
v-bind="validateInfos.livenumber"
>
<a-input
size="small"
v-model:value="form.livenumber"
:placeholder="lan.$t('shuruzhiborenshu')"
type="number"
/>
<div style="color: red;font-size: 0.12rem;line-height: 1.3;">*最少1人, 最多4人</div>
</a-form-item>
<a-form-item :label="lan.$t('zhibojianjie')" class="brief">
<a-textarea
v-model:value="form.desc"
:autoSize="true"
class="brief-textarea"
:maxlength="200"
:placeholder="lan.$t('shuruzhibojianjie')"
/>
<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">{{ lan.$t("fabuzhibo") }}</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="lives.status == 1">
<div class="title">{{ lan.$t("wuzhibozige") }}</div>
<div class="title sub-title">
{{ lives.data.msg }}
</div>
<div class="confirm-btn" @click="fankui">
{{ lan.$t("yijianfankui") }}
</div>
</div>
<div class="notice-container" v-else>
<div class="title">{{ lan.$t("wuzhibozige") }}</div>
<div class="title sub-title">
<!-- 上一周/月您在平台视频点击量为
<span class="red">第24名</span>要在前
<span class="bule">20</span> 才能获得直播资格 -->
{{ lives.msg }}
</div>
<rank-list :list="lives.data"></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 { getlivest, liveadd, liveinfo, setlive } from "@/api";
import { useRoute } from "vue-router";
import dayjs from "dayjs";
import { message } from "ant-design-vue";
import router from "@/router";
import { useI18n } from "@/utils/i18n";
export default defineComponent({
name: "ReleaseWebcast",
components: {
PlaySquareOutlined,
PlusOutlined,
NavBottom,
RankList,
},
setup() {
const lan: any = useI18n();
// 表单数据
const form = ref({
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>>([]);
const lives = ref<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;
}
function fankui() {
router.push({ path: "/mine/aboutus", query: { selected: 3 } });
}
const { resetFields, validate, validateInfos } = useForm(form, rules);
/**
* 表单提交
*/
// const subdata = ref({
// title: "",
// img: "",
// fileid: "",
// fileurl: "",
// fileduration: "",
// dateline: "",
// livetime: "",
// livenumber: "",
// desc: "",
// });
/**
* todo 需要后台返回年份
*/
const id = useRoute().query.id;
if (id != null && typeof id == "string") {
liveinfo(parseInt(id)).then((res) => {
form.value = res;
});
}
const onSubmit = (e: FromSend) => {
e.preventDefault();
validate()
.then(() => {
console.log(toRaw(form), 111);
const subdata: any = toRaw(form.value);
if (subdata.title == "") {
message.error("直播标题不能为空");
return;
} else if (subdata.img == "") {
message.error("直播封面不能为空");
return;
} else if (subdata.fileurl == "") {
message.error("视频介绍不能为空");
return;
} else if (subdata.dateline == "") {
message.error("开始时间不能为空");
return;
} else if (subdata.livetime == "") {
message.error("直播时长不能为空");
return;
} else if (subdata.livenumber == "") {
message.error("直播人数不能为空");
return;
} else if (subdata.desc == "") {
message.error("直播简介不能为空");
return;
} else {
if(subdata.livetime < 30 || subdata.livetime > 120){
message.error("直播时长最短30min, 最长120min");
return ;
}
if(subdata.livenumber > 4 || subdata.livenumber < 1){
message.error("直播人数最少1人, 最多4人");
return ;
}
if (!lives.value.status) {
// subdata.fileid=picinfo.
if (id != undefined && id) {
/**
* todo 提交会报错 编辑直播
*/
subdata.id = id;
setlive(subdata)
} else {
console.log(subdata);
console.log(lives.value);
liveadd(subdata);
}
} else {
message.error("您尚未获得直播资格");
}
}
})
.catch((err: unknown) => {
console.log("error", err);
});
};
const isEntitled: Ref<boolean> = ref(false);
/**
* 隐藏无资格提示
*/
function hideNoticeModal(): void {
isEntitled.value = false;
}
/**
* 开始时间设置
*/
function startchange(e: string): void {
// const month = new Date(e).getMonth()+1
// console.log(new Date(e).getFullYear()+"-"+month+'-'+new Date(e).getDate())
// console.log(e.toString())
const time = dayjs(new Date(e));
const timestr =
time.year() +
"-" +
(time.month() + 1) +
"-" +
time.date() +
" " +
time.hour() +
":" +
time.minute() +
":" +
time.second();
console.log(timestr);
form.value.dateline = timestr;
}
/**
* 上传文件
*/
const videoinfo = reactive({
fileId: "",
url: "",
});
const picinfo = reactive({
fileId: "",
url: "",
});
interface AntUpload {
action: string;
data: unknown;
file: File;
}
const ifallowupload = ref<boolean>(false);
function beforeUpload(info?: any) {
console.log(info);
if (info.type.split("/")[0] != "video") {
ifallowupload.value = false;
message.error("视频介绍的文件格式错误");
return;
} else {
ifallowupload.value = true;
}
}
async function uploads(file: AntUpload) {
if (ifallowupload.value) {
console.log(file);
videofile.value = file.file;
videos.value[0].addEventListener("durationchange", () => {
console.log(videos.value[0].duration);
form.value.fileduration = videos.value[0].duration;
});
const res = await uploadflie(file.file, (info: any) => {
console.log(info);
uploadprogress.value = info.percent.toFixed(2) * 100;
});
console.log(res);
form.value.fileid = res.fileId;
form.value.fileurl = res.video.url;
}
}
const ifallowpic = ref<boolean>(false);
async function uploadspic(file: AntUpload) {
if (ifallowpic.value) {
const 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.value.img = res.video.url;
}
}
getlivest().then((res) => {
if (res) {
isEntitled.value = true;
lives.value = res;
}
});
function beforeUploadpic(info?: any) {
console.log(info);
if (info.type.split("/")[0] != "image") {
message.error("封面必须是图片文件");
ifallowpic.value = false;
return;
} else {
ifallowpic.value = true;
}
}
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,
lives,
beforeUploadpic,
ifallowpic,
beforeUpload,
ifallowupload,
fankui,
lan,
};
},
});
</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>