beelink/src/views/mine/ReleaseWebcast.vue

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(lan.$t('zhibobiaotiweikong'));
return;
} else if (subdata.img == "") {
message.error(lan.$t('zhibofengmianweikong'));
return;
} else if (subdata.fileurl == "") {
message.error(lan.$t('shipinjieshaoweikong'));
return;
} else if (subdata.dateline == "") {
message.error(lan.$t('kaishishijianweikong'));
return;
} else if (subdata.livetime == "") {
message.error(lan.$t('zhiboshichangweikong'));
return;
} else if (subdata.livenumber == "") {
message.error(lan.$t('zhiborenshuweikong'));
return;
} else if (subdata.desc == "") {
message.error(lan.$t('zhibojianjieweikong'));
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(lan.$t('wuzhibozigeale'));
}
}
})
.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(lan.$t('shipinjieshaoccuowu'));
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(lan.$t('fengmiangeshi'));
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>