Merge pull request '发布直播 上传视频页面' (#16) from zhy into master

Reviewed-on: http://git.luyuan.tk/luyuan/beelink/pulls/16
This commit is contained in:
hansu 2020-09-27 17:07:35 +08:00
commit adf713964e
6 changed files with 458 additions and 84 deletions

View File

@ -8,6 +8,7 @@
"lint": "vue-cli-service lint"
},
"dependencies": {
"@ant-design-vue/use": "^0.0.1-alpha.6",
"ant-design-vue": "^2.0.0-beta.9",
"axios": "^0.20.0",
"core-js": "^3.6.5",

View File

@ -9,8 +9,19 @@ const routes: Array<RouteRecordRaw> = [
component: () => import("../layout/Mine.vue"),
children: [
{
path:"Archives",
path:"archives",
name: "Archives",
component: () => import("../views/mine/Archives.vue")
},
{
path:"webcast",
name: "Webcast",
component: () => import("../views/mine/ReleaseWebcast.vue")
},
{
path:"video",
name: "Video",
component: () => import("../views/mine/ReleaseVideo.vue")
}
]
},
@ -19,20 +30,6 @@ const routes: Array<RouteRecordRaw> = [
name: 'Home',
component: () => import(/* webpackChunkName: "about" */ '../components/NavTop.vue')
},
// {
// path: '/about',
// name: 'About',
// // route level code-splitting
// // this generates a separate chunk (about.[hash].js) for this route
// // which is lazy-loaded when the route is visited.
// component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
// }
{
path: '/archives',
name: 'Archives',
component: () => import('../views/mine/Archives.vue')
},
{
path: '/login',
name: 'Login',

View File

@ -345,7 +345,7 @@ export default defineComponent({
.ant-select {
font-size: 12px;
}
.select-down {
.ant-select-dropdown {
font-size: 12px;
}
}

View File

@ -0,0 +1,218 @@
<template>
<div class="upload-video">
<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="视频封面">
<a-upload
list-type="picture"
action="//jsonplaceholder.typicode.com/posts/"
>
<div class="upload-image">
<PlusOutlined style="fontSize: 22px;" />
</div>
</a-upload>
</a-form-item>
<a-form-item label="选择视频" class="video-introduction">
<div class="upload-container">
<a-upload
:beforeUpload="beforeUpload"
>
<div class="upload-image">
<PlaySquareOutlined style="fontSize: 22px;" />
</div>
</a-upload>
<div v-for="(item, index) in form.video" :key="index">{{ item.name }}</div>
</div>
<div class="demand">
<p class="one-line-hide">视频要求</p>
<p class="one-line-hide">1.文件扩展名fivmp4文件扩展名fivmp4</p>
</div>
</a-form-item>
<a-form-item label="视频简介" class="brief">
<a-textarea v-model:value="form.brief" :maxlength="200" placeholder="请输入您的视频简介" />
</a-form-item>
<a-form-item :wrapper-col="{ span: 4, offset: 0 }">
<a-button @click="onSubmit">上传视频</a-button>
</a-form-item>
</a-form>
<nav-bottom></nav-bottom>
</div>
</template>
<script lang="ts">
import { defineComponent, reactive } from 'vue';
import { PlaySquareOutlined, PlusOutlined } from '@ant-design/icons-vue';
import NavBottom from '@/components/NavBottom.vue';
export default defineComponent({
name: 'ReleaseWebcast',
components: {
PlaySquareOutlined,
PlusOutlined,
NavBottom,
},
setup() {
interface FileItem{
uid: string;
name: string;
}
const fileList: Array<FileItem> = [];
console.log(fileList);
//
const form = reactive({
title: '',
cover: '',
brief: '',
video: fileList,
});
/**
* 上传文件之前的钩子
* @param file 上传的文件
*/
const beforeUpload = (file: any): boolean => {
// console.log(file);
if(file.type != '') {
// handleRemove(file);
}
form.video = [...fileList, file];
return false;
}
/**
* 表单提交
*/
const onSubmit = (e: any) => {
e.preventDefault();
};
console.log(form.video);
return {
labelCol: { span: 4 },
wrapperCol: { span: 14 },
form,
fileList,
beforeUpload,
onSubmit,
}
}
})
</script>
<style lang="scss" scoped>
.upload-video {
width: 100%;
min-width: 700px;
background-color: #ffffff;
padding: 46px;
border-radius: 17px;
position: relative;
/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-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;
&::-webkit-input-placeholder{
font-size: 12px;
color: #808080;
}
}
.ant-select {
font-size: 12px;
}
.ant-select-dropdown {
font-size: 12px;
}
.ant-upload-list {
display: none;
color: #08AE98;
&:hover {
background-color: #ffffff;
}
.ant-upload-list-item {
opacity: 1;
.ant-upload-list-item-info {
background-color: #ffffff;
.anticon-paper-clip {
color: #08AE98;
}
}
}
}
.ant-btn {
padding: 0;
width: 63px;
height: 23px;
background: #08AE98;
border-radius: 3px;
font-size: 10px;
font-weight: 500;
color: #FFFFFF;
}
}
.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 {
.ant-input {
width: 359px;
}
}
}
}
</style>

View File

@ -1,92 +1,240 @@
<template>
<div class="webcast">
<a-form :model="form" :label-col="labelCol" :wrapper-col="wrapperCol">
<a-form-item label="Activity name">
<a-input v-model:value="form.name" />
<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="Activity zone">
<a-select v-model:value="form.region" placeholder="please select your zone">
<a-select-option value="shanghai">
Zone one
</a-select-option>
<a-select-option value="beijing">
Zone two
</a-select-option>
</a-select>
<a-form-item label="直播封面">
<a-upload
list-type="picture"
action="//jsonplaceholder.typicode.com/posts/"
>
<div class="upload-image">
<PlusOutlined style="fontSize: 22px;" />
</div>
</a-upload>
</a-form-item>
<a-form-item label="Activity time">
<a-date-picker
v-model:value="form.date1"
show-time
type="date"
placeholder="Pick a date"
style="width: 100%;"
/>
<a-form-item label="视频介绍" class="video-introduction">
<a-upload
list-type="picture"
action="//jsonplaceholder.typicode.com/posts/"
>
<div class="upload-image">
<PlaySquareOutlined style="fontSize: 22px;" />
</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.文件扩展名fivmp4文件扩展名fivmp4</p>
</div>
</a-form-item>
<a-form-item label="Instant delivery">
<a-switch v-model:checked="form.delivery" />
<a-form-item label="开始时间">
<a-input size="small" v-model:value="form.startTime" placeholder="请设置您的开始时间" />
</a-form-item>
<a-form-item label="Activity type">
<a-checkbox-group v-model:value="form.type">
<a-checkbox value="1" name="type">
Online
</a-checkbox>
<a-checkbox value="2" name="type">
Promotion
</a-checkbox>
<a-checkbox value="3" name="type">
Offline
</a-checkbox>
</a-checkbox-group>
<a-form-item label="直播时长" class="duration" v-bind="validateInfos.duration">
<a-input size="small" v-model:value="form.duration" placeholder="请输入直播时间" />
<span class="unit">分钟</span>
</a-form-item>
<a-form-item label="Resources">
<a-radio-group v-model:value="form.resource">
<a-radio value="1">
Sponsor
</a-radio>
<a-radio value="2">
Venue
</a-radio>
</a-radio-group>
<a-form-item label="直播人数" v-bind="validateInfos.number">
<a-input size="small" v-model:value="form.number" placeholder="请输入直播人数" />
</a-form-item>
<a-form-item label="Activity form">
<a-input v-model:value="form.desc" type="textarea" />
<a-form-item label="直播简介" class="brief">
<a-textarea v-model:value="form.brief" maxlength="200" placeholder="请输入您的直播简介" />
</a-form-item>
<a-form-item :wrapper-col="{ span: 14, offset: 4 }">
<a-button type="primary" @click="onSubmit">
Create
</a-button>
<a-button style="margin-left: 10px;">
Cancel
</a-button>
<a-form-item :wrapper-col="{ span: 4, offset: 0 }">
<a-button @click="onSubmit">发布直播</a-button>
</a-form-item>
</a-form>
<nav-bottom></nav-bottom>
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { defineComponent, reactive, toRaw } from 'vue';
import { PlaySquareOutlined, PlusOutlined } from '@ant-design/icons-vue';
import { useForm } from '@ant-design-vue/use';
import NavBottom from '@/components/NavBottom.vue';
export default defineComponent({
name: 'ReleaseWebcast',
components: {
PlaySquareOutlined,
PlusOutlined,
NavBottom,
},
setup() {
function onSubmit(): void {
}
//
const form = reactive({
title: '',
cover: '',
introduction: '',
startTime: '',
duration: '',
number: '',
brief: '',
});
/**
* 验证直播时间
*/
const validateDuration = async (rule: object, value: number): Promise<string | void> => {
if (value < 30 || value > 120) {
return Promise.reject('*最短30min 最长120min');
} else {
return Promise.resolve();
}
};
/**
* 验证直播人数
*/
const validateNumber = async (rule: object, value: number): Promise<string | void> => {
if (value < 1 || value > 4) {
return Promise.reject('**最少1人最多4人');
} else {
return Promise.resolve();
}
};
//
const rules = reactive({
duration: [
{
validator: validateDuration,
trigger: 'change',
},
],
number: [
{
validator: validateNumber,
trigger: 'change',
},
],
});
const { resetFields, validate, validateInfos } = useForm(form, rules);
/**
* 表单提交
*/
const onSubmit = (e: any) => {
e.preventDefault();
validate().then(() => {
console.log(toRaw(form));
}).catch((err: object) => {
console.log('error', err);
});
};
return {
labelCol: { span: 4 },
wrapperCol: { span: 14 },
form: {
name: '',
region: undefined,
date1: undefined,
delivery: false,
type: [],
resource: '',
desc: '',
},
onSubmit
validateInfos,
resetFields,
form,
onSubmit,
}
}
})
</script>
<style lang="scss" scoped>
.webcast {
width: 100%;
min-width: 700px;
background-color: #ffffff;
padding: 46px;
border-radius: 17px;
position: relative;
/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-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;
&::-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-btn {
padding: 0;
width: 63px;
height: 23px;
background: #08AE98;
border-radius: 3px;
font-size: 10px;
font-weight: 500;
color: #FFFFFF;
}
}
.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 {
.ant-input {
width: 359px;
}
}
}
}
</style>

View File

@ -2,6 +2,16 @@
# yarn lockfile v1
"@ant-design-vue/use@^0.0.1-alpha.6":
version "0.0.1-alpha.6"
resolved "https://registry.yarnpkg.com/@ant-design-vue/use/-/use-0.0.1-alpha.6.tgz#eafce73abcc7d2736dcbfff1e396c69b84b9e840"
integrity sha512-vyLeiVbi4KdCvkRhHFGyYhe2bZ6y0RJupw7+bdCGRrx4oHb/Rsm8MTqs8Nl1k0lX9qQIvNAoa6Rxf3FQH6nI7g==
dependencies:
"@vue/runtime-dom" "^3.0.0-rc.1"
async-validator "^3.4.0"
lodash-es "^4.17.15"
resize-observer-polyfill "^1.5.1"
"@ant-design/colors@^4.0.0":
version "4.0.5"
resolved "https://registry.npm.taobao.org/@ant-design/colors/download/@ant-design/colors-4.0.5.tgz?cache=0&sync_timestamp=1596611396536&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40ant-design%2Fcolors%2Fdownload%2F%40ant-design%2Fcolors-4.0.5.tgz#d7d100d7545cca8f624954604a6892fc48ba5aae"
@ -1533,7 +1543,7 @@
"@vue/reactivity" "3.0.0"
"@vue/shared" "3.0.0"
"@vue/runtime-dom@3.0.0":
"@vue/runtime-dom@3.0.0", "@vue/runtime-dom@^3.0.0-rc.1":
version "3.0.0"
resolved "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.0.0.tgz#e0d1f7c7e22e1318696014cc3501e06b288c2e11"
integrity sha512-f312n5w9gK6mVvkDSj6/Xnot1XjlKXzFBYybmoy6ahAVC8ExbQ+LOWti1IZM/adU8VMNdKaw7Q53Hxz3y5jX8g==
@ -2032,7 +2042,7 @@ async-limiter@~1.0.0:
resolved "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd"
integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==
async-validator@^3.3.0:
async-validator@^3.3.0, async-validator@^3.4.0:
version "3.4.0"
resolved "https://registry.npm.taobao.org/async-validator/download/async-validator-3.4.0.tgz?cache=0&sync_timestamp=1596625258256&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fasync-validator%2Fdownload%2Fasync-validator-3.4.0.tgz#871b3e594124bf4c4eb7bcd1a9e78b44f3b09cae"
integrity sha1-hxs+WUEkv0xOt7zRqeeLRPOwnK4=