<script setup> /** * 发布视频 */ import { reactive, getCurrentInstance, ref, computed, } from 'vue'; import { onLoad, } from '@dcloudio/uni-app' import { useStore } from 'vuex' // 工具库 import util from '@/common/js/util'; // api import api from '@/api/index.js' const { proxy } = getCurrentInstance() const store = useStore() class Form { videoId = '' // 视频地址 videoUrl = '' // 缩略图 coverUrl = '' // 标题 title = '' // 正文 description = '' // 话题 tags = '' // 视频大小 videoSize = '' // 视频时长 videoDuration = '' // 视频状态 0草稿 1待审核 2审核失败 3已发布 4已下架 status = '' } // 发布视频 const form = reactive(new Form()) // 话题列表 let label = reactive({ pageNum: 1, pageSize: 10, list: [], }) // 话题关键字 const labelKeyword = ref('') // 已选择的话题列表 const labelSelect = reactive([]) // 用户列表 const userList = reactive({ data: [], pageNum: 1, pageSize: 20, total: 0, }) // 已选择的用户列表 const userSelect = reactive([]) // 用户关键字 const userKeyword = ref('') // 产品列表 const product = reactive({ pageNum: 1, pageSize: 10, list: [], }) // 用户信息 const userinfo = computed(() => store.state.userinfo) // onLoad((option) => { // 视频id if (option.videoId) { form.videoId = option.videoId // 获取标签 获取详情 Promise.all([getVideoDetail(), getLabel()]).then(rs => { // 详情 const detail = rs[0] // 标签 const labels = rs[1] // at用户 const users = rs[2] console.log('release getDetail', detail) // 视频id form.id = detail.id // 视频大小 form.videoSize = detail.videoSize // 宽 form.breadth = detail.breadth // 高 form.height = detail.height // 时长 form.videoDuration = detail.videoDuration // 缩略图 form.coverUrl = detail.coverUrl // 视频地址 form.videoUrl = detail.videoUrl // 标题 form.title = detail.title // 正文 form.description = detail.description // //视频状态 0草稿 1待审核 2审核失败 3已发布 4已下架 form.status = detail.status // 第几秒展示 if (detail.popupTime) form.popupTime = detail.popupTime // 关联视频的商品id if (detail.productId) { form.productId = detail.productId // 商品名称 form.productName = detail.productName // 商品价格 form.productPrice = detail.productPrice // 商品图片 form.productImage = detail.productImage // 商品佣金 form.commission = detail.commission } // 回显话题列表 if (detail.tagsList) labelSelect.push(...detail.tagsList) // 匹配用户id // detail.subscriber = detail.subscriber.split(',') // detail.subscriberId.split(',').forEach((item, index) => { // userSelect.push({ // userId: item, // userNickname: detail.subscriber[index] // }) // }) }) } else { // 获取标签 getLabel() } // 获取我发布的产品 getProductList() }) // 获取视频详情 function getVideoDetail() { return new Promise((resolve, reject) => { api.video.getVideoById({ data: { id: form.videoId, } }).then(rs => { if (rs.code == 200) { resolve(rs.data) return } util.alert({ content: rs.msg, showCancel: false, }) }) }) } // 上传图片 function uploadImg() { util.upload_image({ value: form.coverUrl, type: 1, success: rs => { form.coverUrl = rs.value } }) } // 上传视频 function uploadVideo() { util.upload_video({ success: rs => { // 视频大小 form.videoSize = rs.size // 宽 form.breadth = rs.width // 高 form.height = rs.height // 时长 form.videoDuration = rs.duration // 路径 form.videoUrl = rs.value } }) } // 刷新列表 function refreshLabel() { label.pageNum = 1 label.total = 0 getLabel() } // 获取更多标签分类 function getMoreLabel() { if (label.total <= label.list.length) return label.pageNum++ getLabel() } // 获取标签分类 function getLabel() { return new Promise((resolve, reject) => { api.video.getLabel({ data: { pageNum: label.pageNum, pageSize: label.pageSize, tagName: labelKeyword.value, } }).then(rs => { if (rs.code == 200) { const result = rs.rows // if (label.pageNum == 1) label.list.length = 0 // 标签列表输出 label.list.push(...result) // 总数 label.total = rs.total // resolve(label.list) // 结果 if (!result[0] && labelKeyword.value) { util.alert({ content: `当前没有${labelKeyword.value}的话题,是否添加?`, }).then(rs => { if (rs.confirm) addLabel() }) } return } util.alert({ content: rs.msg, showCancel: false, }) }) }) } // 添加标签 function addLabel() { api.video.setLabel({ query: { tagName: labelKeyword.value, status: '1', } }).then(rs => { if (rs.code == 200) { label.list.length = 0 // 标签列表输出 label.list.push(rs.data) label.total = 1 return } util.alert({ content: rs.msg, showCancel: false }) }) } /** * 选择话题列表 * @param {Object} ev * @param {Number} index 需要操作的下标 */ function handleSelectLabel(ev, index) { // 是否包含 const findIndex = labelSelect.findIndex(item => item.tagId == ev.tagId) // if (findIndex < 0) { if (labelSelect.length >= 5) util.alert('最多上传5个') else labelSelect.push(ev) } } /** * 点击标签删除 * @param {Object} item */ function handleLabelSelectDel(item, index) { labelSelect.splice(index, 1) } // 获取更多朋友列表 function getMoreUserList() { if (userList.data.length >= userList.total) return userList.pageNum++ getUserList() } // 获取朋友列表 function getUserList() { return new Promise((resolve, reject) => { api.video.searchFriendByName({ path: [userKeyword.value], query: { pageNum: userList.pageNum, pageSize: userList.pageSize, } }).then(rs => { if (rs.code == 200) { if (userList.pageNum) userList.data.length = 0 // 追加朋友列表 userList.data.push(...rs.rows) // 视频列表 userList.total = rs.total resolve(userList.data) return } util.alert({ content: rs.msg, showCancel: false, }) }) }) } /** * 选择用户列表 * @param {Object} ev * @param {Number} index 需要操作的下标 */ function handleSelectUser(ev, index) { // 是否包含 const findIndex = userSelect.findIndex(item => item.id == ev.id) if (findIndex < 0) userSelect.push(ev) } /** * 点击用户删除 * @param {Object} item */ function handleUserSelectDel(item, index) { userSelect.splice(index, 1) } // 发布视频 function handleSubmit(status) { const data = { ...form } //视频状态 0草稿 1待审核 2审核失败 3已发布 4已下架 data.status = status ? status : 0 console.log('data', data) // 验证必填项 if (!data.videoUrl) { util.alert('视频不能为空') return } if (!data.coverUrl) { util.alert('封面不能为空') return } if (!data.title) { util.alert('标题不能为空') return } // 如果不是草稿箱 if (data.status == 1) { if (!data.description) { util.alert('正文不能为空') return } if (!labelSelect[0]) { util.alert('标签不能为空') return } } // 如果有选择的标签 if (labelSelect[0]) { data.tags = labelSelect.map(item => item.tagId).join(',') } // if (userSelect[0]) { // data.subscriberId = userSelect.map(item => item.userId).join(',') // data.subscriber = userSelect.map(item => item.userNickname).join(',') // } // 发布 api.video.saveVideo({ data, }).then(rs => { if (rs.code == 200) { util.alert({ content: data.status == 1 ? '视频发布成功,请等待后台审核' : '保存草稿成功', showCancel: false, confirmText: '我知道了', }).then(rs => { uni.navigateBack() }) return } util.alert({ content: rs.msg, showCancel: false, }) }) } // 获取更多商品 function getMoreProductList() { if (product.list.length >= product.total) return product.pageNum++ getProductList() } // 获取已发布的商品列表 function getProductList() { api.shop.getProductionListByUserId({ data: { pageNum: product.pageNum, pageSize: product.pageSize, } }).then(rs => { if (rs.code == 200) { if (product.pageNum == 1) product.list.length = 0 product.list.push(...rs.rows) product.total = rs.total return } util.alert({ content: rs.msg, showCancel: false, }) }) } /** * 选择商品 * @param {Object} item */ function handleProduct(item) { if (form.productId == item.id) return form.productId = item.id form.productName = item.name form.productPrice = item.price form.productImage = item.sliderImage.split(',')[0] form.commission = item.commission proxy.$refs.productRef.close() } // 移除商品 function handleRemoveProduct() { if (!form.productId) return util.alert({ content: '是否清空所选商品信息', }).then(rs => { if (!rs.confirm) return form.productId = '' form.productName = '' form.productPrice = '' form.productImage = '' form.commission = '' form.popupTime = '' }) } </script> <template> <view class="appbw"> <view class="form mtb30 mlr30 c666 f32"> <view class="line mtb20"> <view class="key">上传封面</view> <view class="value mt20 imgList"> <view class="imgs wh200 br10" v-if="form.coverUrl"> <image :src="form.coverUrl" class="br10" mode="aspectFill" /> </view> <view class="imgs wh200 upload fmid bfff br10" @click="uploadImg"> <uni-icons type="plusempty" color="#E8E8E8" size="50rpx" /> </view> </view> </view> <view class="line mtb20"> <view class="key">上传视频</view> <view class="value mt20 imgList"> <view class="imgs wh200 br10" v-if="form.videoUrl"> <video :src="form.videoUrl" class="br10" /> </view> <view class="imgs wh200 upload fmid bfff br10" @click="uploadVideo"> <uni-icons type="plusempty" color="#E8E8E8" size="50rpx" /> </view> </view> </view> <view class="main mtb20 plr20 br20"> <view class="title ptb20"> <input type="text" class="f32" placeholder="填写标题会有更多曝光率哦~" placeholder-class="placeholderStyle" v-model="form.title" /> </view> <view class="content ptb10"> <textarea class="textarea f32" v-model="form.description" placeholder="添加正文" /> </view> </view> <!-- 标签 --> <view class="labels items mt20 df fww c333 f28" v-if="labelSelect[0]"> <view class="item fmid mr20 mb20 plr20 bar" v-for="(item,index) in labelSelect" :key="index"> <view class="mr10">#{{item.tagName}}</view> <uni-icons type="closeempty" size="28rpx" @click="handleLabelSelectDel(item,index)" /> </view> </view> <!-- 用户 --> <view class="labels items mt20 df fww c333 f28" v-if="userSelect[0]"> <view class="item fmid mr20 mb20 plr20 bar" v-for="(item,index) in userSelect" :key="index"> <view class="mr10">@{{item.userNickname}}</view> <uni-icons type="closeempty" size="28rpx" @click="handleLabelSelectDel(item,index)" /> </view> </view> <!-- 菜单 --> <view class="menu df fww f28"> <view class="item mr20 ptb5 plr20 bar" @click="$refs.labelRef.open()">#话题</view> <view class="item mr20 ptb5 plr20 bar" @click="$refs.userRef.open()">@用户</view> <view class="item mr20 ptb5 plr20 bar" v-if="0">@地点</view> </view> <!-- 地点 --> <view class="mtb20" v-if="0"> <view class="key rows"> <uni-icons type="location"></uni-icons> <view class="f1">添加地点</view> </view> <view class="value mt20"> <scroll-view scroll-x="true" class="scroll wsn"> <view class="locate items df f24"> <view class="item mr20 ptb5 plr20 bar" v-for="(item,index) in 5" :key="index">北京天安门</view> </view> </scroll-view> </view> </view> <template v-if="userinfo.isShop == 1"> <view class="product mtb20" @click="$refs.productRef.open()"> <view class="header rows" @click.stop> <view class="key">添加商品链接</view> <view class="remove"> <uni-icons type="trash" color="#999" size="34rpx" @click="handleRemoveProduct" /> </view> </view> <view class="main mtb20 ptb20 tac br20" v-if="!form.productId">点击选择</view> <view class="main df oh mtb20 plr30 br20" v-else> <view class="df oh mtb20"> <view class="col oh df fdc jcsb f1 mr20"> <view class="name">{{form.productName}}</view> <view class="price thd mt10 cFF9B27 f28"> <text class="price thd mr20">价格{{form.productPrice}}</text> <text class="commission thd">佣金{{form.commission}}</text> </view> </view> <view class="wh200 fs0 c999 bfff br10"> <image class="br10" :src="form.productImage" mode="aspectFill" /> </view> </view> </view> </view> <view class="second df jcr mtb20"> <view>需要在第</view> <input type="text" v-model="form.popupTime" class="input" /> <view>秒展示</view> </view> </template> <view class="fill" style="height: 150rpx;"></view> <view class="footer rows plr30 bfff shadow"> <view class="btn bar lg disabled w180" @click="handleSubmit(0)">存草稿</view> <view class="btn bar lg colourful f1 ml30" @click="handleSubmit(1)">发布作品</view> </view> </view> <!-- 话题列表 --> <uni-popup ref="labelRef" type="bottom"> <view class="selectionBox ptb20 plr20 bfff c999 f28"> <view class="title c333 f34 tac">话题列表</view> <!-- 可选的列表 --> <view class="mt20"> <scroll-view scroll-y="true" class="scroll" @scrolltolower="getMoreLabel"> <view class="selection"> <view class="option df aic" v-for="(item,index) in label.list" :key="index" @click="handleSelectLabel(item,index)" :class="{ active: labelSelect.map(node => node.tagId).includes(item.tagId) }"> <text class="thd f1">#{{item.tagName}}</text> </view> </view> </scroll-view> </view> <!-- 结果 --> <view class="reult items mt20 df fww c333 f28" v-if="labelSelect[0]"> <view class="item fmid mr20 mb20 plr20 bar" v-for="(item,index) in labelSelect" :key="index"> <view class="mr10">#{{item.tagName}}</view> <uni-icons type="closeempty" size="28rpx" @click="handleLabelSelectDel(item,index)" /> </view> </view> <!-- --> <view class="editBox rows mt20 ptb10 plr20 br20"> <view class="c333 f28">#</view> <input class="f1" type="text" v-model="labelKeyword" placeholder="输入你想选择的话题" /> <view class="" @click="refreshLabel">搜索</view> </view> </view> </uni-popup> <!-- at用户列表 --> <uni-popup ref="userRef" type="bottom"> <view class="selectionBox ptb20 plr20 bfff c999 f28"> <view class="title c333 f34 tac">@用户列表</view> <!-- 可选的列表 --> <view class="mt20"> <scroll-view scroll-y="true" class="scroll" @scrolltolower="getMoreUserList"> <view class="selection"> <view class="option df aic" v-for="(item,index) in userList.data" :key="index" @click="handleSelectUser(item,index)" :class="{ active: userSelect.map(node => node.userId).includes(item.userId) }"> <text class="thd f1">@{{item.userNickname}}</text> </view> </view> </scroll-view> </view> <!-- 结果 --> <view class="reult items mt20 df fww c333 f28" v-if="userSelect[0]"> <view class="item fmid mr20 mb20 plr20 bar" v-for="(item,index) in userSelect" :key="index"> <view class="mr10">@{{item.userNickname}}</view> <uni-icons type="closeempty" size="28rpx" @click="handleUserSelectDel(item,index)" /> </view> </view> <!-- --> <view class="editBox rows mt20 ptb10 plr20 br20"> <view class="c333 f28">@</view> <input class="f1" type="text" v-model="userKeyword" placeholder="输入你想选择的用户" /> <view class="" @click="getUserList">搜索</view> </view> </view> </uni-popup> <!-- 发布的产品列表 --> <uni-popup ref="productRef" type="bottom"> <view class="productAlt popBot bfff"> <view class="header ptb30 tac">我的商品展示</view> <view class="listBox"> <scroll-view class="scroll" scroll-y="true" @scrolltolower="getMoreProductList"> <view class="item df aic mlr20 ptb20" v-for="(item,index) in product.list" :key="index" @click="handleProduct(item)"> <view class="wh120"> <image class="br10" :src="item.sliderImage.split(',')[0]" mode="aspectFill" /> </view> <view class="f1 t2hd ml20 c666 f30"> <text class="t2hd">{{item.name}}</text> </view> </view> </scroll-view> </view> </view> </uni-popup> </view> </template> <style lang="scss"> image, video { width: 100%; height: 100%; } // .upload { background-color: #F4F4F4; } // 背景 .main { background-color: #F4F4F4; // 内容 .content { border-top: 2rpx solid #E5E5E5; .textarea { width: 100%; height: 300rpx; } } } // 菜单 .menu { .item { background-color: #F4F4F4; } } // 选项集合 .items { .item { background-color: #F4F4F4; } } // 菜单选择列表 .selectionBox { .scroll { height: 420rpx; .option { box-sizing: border-box; height: 60rpx; border-bottom: 1rpx solid #E5E5E5; // 被选择的 &.active { background-color: #E5E5E5; } } } // .editBox { background-color: #F4F4F4; } } // 产品 .productAlt { .scroll { height: 800rpx; .item+.item { border-top: 2rpx solid #eee; } } } // 商家视频展示的秒数 .second { .input { width: 80rpx; text-align: center; flex: none; border-bottom: 2rpx solid #111; } } </style>