|
|
@@ -6,6 +6,11 @@
|
|
|
<el-option v-for="v in vestOptions" :key="v.id" :label="v.nickName + '(' + v.id + ')'" :value="v.id"/>
|
|
|
</el-select>
|
|
|
</el-form-item>
|
|
|
+ <el-form-item label="内容分类" prop="category">
|
|
|
+ <el-select v-model="queryParams.category" clearable placeholder="全部" size="small" style="width:140px">
|
|
|
+ <el-option v-for="d in categoryOptions" :key="d.dictValue" :label="d.dictLabel" :value="d.dictLabel"/>
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
<el-form-item label="关键字" prop="keyword">
|
|
|
<el-input v-model="queryParams.keyword" placeholder="标题/ID/文件名" clearable size="small" @keyup.enter.native="handleQuery"/>
|
|
|
</el-form-item>
|
|
|
@@ -25,10 +30,17 @@
|
|
|
<el-col :span="1.5">
|
|
|
<el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd" v-hasPermi="['life:video:add']">新增</el-button>
|
|
|
</el-col>
|
|
|
+ <el-col :span="1.5">
|
|
|
+ <el-button type="success" plain icon="el-icon-document-copy" size="mini" @click="handleBatchAdd" v-hasPermi="['life:video:add']">批量添加</el-button>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="1.5">
|
|
|
+ <el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple" @click="handleBatchDelete" v-hasPermi="['life:video:remove']">批量删除</el-button>
|
|
|
+ </el-col>
|
|
|
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
|
|
</el-row>
|
|
|
|
|
|
- <el-table border v-loading="loading" :data="videoList">
|
|
|
+ <el-table border v-loading="loading" :data="videoList" @selection-change="handleSelectionChange">
|
|
|
+ <el-table-column type="selection" width="55" align="center"/>
|
|
|
<el-table-column label="视频ID" align="center" prop="videoId" width="90"/>
|
|
|
<el-table-column label="封面" align="center" width="80">
|
|
|
<template slot-scope="scope">
|
|
|
@@ -36,9 +48,15 @@
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
<el-table-column label="标题" align="center" prop="title" show-overflow-tooltip/>
|
|
|
+ <el-table-column label="内容分类" align="center" prop="category" width="100"/>
|
|
|
<el-table-column label="文件名" align="center" prop="fileName" show-overflow-tooltip/>
|
|
|
<el-table-column label="马甲ID" align="center" prop="vestId" width="80"/>
|
|
|
<el-table-column label="时长(秒)" align="center" prop="duration" width="90"/>
|
|
|
+ <el-table-column label="上传时间" align="center" prop="createTime" width="160">
|
|
|
+ <template slot-scope="scope">
|
|
|
+ <span>{{ parseTime(scope.row.createTime) }}</span>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
<el-table-column label="上架" align="center" width="80">
|
|
|
<template slot-scope="scope">
|
|
|
<el-tag v-if="scope.row.isShow === 1" type="success">是</el-tag>
|
|
|
@@ -69,13 +87,18 @@
|
|
|
|
|
|
<pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList"/>
|
|
|
|
|
|
- <el-dialog :title="title" :visible.sync="open" width="720px" append-to-body>
|
|
|
+ <el-dialog :title="title" :visible.sync="open" width="780px" append-to-body :before-close="handleDialogClose">
|
|
|
<el-form ref="form" :model="form" :rules="rules" label-width="110px">
|
|
|
<el-form-item label="马甲号" prop="vestId">
|
|
|
<el-select v-model="form.vestId" filterable placeholder="请选择马甲号" style="width:100%">
|
|
|
<el-option v-for="v in vestOptions" :key="v.id" :label="v.nickName + '(' + v.id + ')'" :value="v.id"/>
|
|
|
</el-select>
|
|
|
</el-form-item>
|
|
|
+ <el-form-item label="内容分类" prop="category">
|
|
|
+ <el-select v-model="form.category" placeholder="请选择内容分类" style="width:100%">
|
|
|
+ <el-option v-for="d in categoryOptions" :key="d.dictValue" :label="d.dictLabel" :value="d.dictLabel"/>
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
<el-form-item label="视频标题" prop="title">
|
|
|
<el-input v-model="form.title" maxlength="20" show-word-limit placeholder="不超过20字"/>
|
|
|
</el-form-item>
|
|
|
@@ -83,13 +106,37 @@
|
|
|
<el-input v-model="form.fileName" placeholder="上传文件名或标识"/>
|
|
|
</el-form-item>
|
|
|
<el-form-item label="封面" prop="coverUrl">
|
|
|
- <image-upload v-model="form.coverUrl" :limit="1"/>
|
|
|
+ <image-upload v-model="form.coverUrl" :limit="1" :file-size="2" aspect-ratio="16:9"/>
|
|
|
+ <div style="color:#909399;font-size:12px;line-height:1.4;margin-top:4px">比例 16:9,大小不超过 2MB</div>
|
|
|
</el-form-item>
|
|
|
- <el-form-item label="视频地址" prop="videoUrl">
|
|
|
- <el-input v-model="form.videoUrl" placeholder="mp4 地址(素材库上传后粘贴)"/>
|
|
|
+ <video-upload
|
|
|
+ :type="3"
|
|
|
+ :show-control="true"
|
|
|
+ :videoUrl.sync="form.videoUrl"
|
|
|
+ :fileName.sync="form.fileName"
|
|
|
+ @video-ready="onVideoReady"
|
|
|
+ @change="onVideoReady"
|
|
|
+ @video-duration="onVideoDuration"
|
|
|
+ ref="videoUpload"
|
|
|
+ />
|
|
|
+ <el-form-item v-if="form.videoUrl" label="上传时间">
|
|
|
+ <el-input :value="uploadTimeDisplay" disabled style="width:220px"/>
|
|
|
</el-form-item>
|
|
|
<el-form-item label="时长(秒)" prop="duration">
|
|
|
<el-input-number v-model="form.duration" :min="0" :controls="false"/>
|
|
|
+ <span style="margin-left:8px;color:#909399;font-size:12px">上传/选取后自动读取,可手动修改</span>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="播放量" prop="views">
|
|
|
+ <el-input-number v-model="form.views" :min="0" :controls="false" style="width:160px"/>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="点赞数" prop="likes">
|
|
|
+ <el-input-number v-model="form.likes" :min="0" :controls="false" style="width:160px"/>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="收藏数" prop="favoriteNum">
|
|
|
+ <el-input-number v-model="form.favoriteNum" :min="0" :controls="false" style="width:160px"/>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="分享数" prop="shareNum">
|
|
|
+ <el-input-number v-model="form.shareNum" :min="0" :controls="false" style="width:160px"/>
|
|
|
</el-form-item>
|
|
|
<el-form-item label="是否上架" prop="isShow">
|
|
|
<el-radio-group v-model="form.isShow">
|
|
|
@@ -103,8 +150,15 @@
|
|
|
<el-radio :label="0">否</el-radio>
|
|
|
</el-radio-group>
|
|
|
</el-form-item>
|
|
|
- <el-form-item label="关联商品">
|
|
|
- <el-button type="primary" size="mini" @click="openProductDialog">选择商品</el-button>
|
|
|
+ <el-form-item label="是否关联商品" prop="isProduct">
|
|
|
+ <el-radio-group v-model="form.isProduct" @change="onIsProductChange">
|
|
|
+ <el-radio :label="1">是</el-radio>
|
|
|
+ <el-radio :label="0">否</el-radio>
|
|
|
+ </el-radio-group>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item v-show="form.isProduct === 1" label="关联商品">
|
|
|
+ <el-button type="primary" size="mini" :disabled="selectedProducts.length >= 1" @click="openProductDialog">选择商品</el-button>
|
|
|
+ <span style="margin-left:8px;color:#909399;font-size:12px">最多关联 1 个商品</span>
|
|
|
<el-table :data="selectedProducts" border size="mini" style="margin-top:8px">
|
|
|
<el-table-column label="商品ID" prop="productId" width="90"/>
|
|
|
<el-table-column label="名称" prop="productName" show-overflow-tooltip/>
|
|
|
@@ -124,6 +178,75 @@
|
|
|
</div>
|
|
|
</el-dialog>
|
|
|
|
|
|
+ <el-dialog title="批量添加视频" :visible.sync="batchOpen" width="860px" append-to-body top="5vh">
|
|
|
+ <el-form label-width="90px" size="small">
|
|
|
+ <el-form-item label="马甲号" required>
|
|
|
+ <el-select v-model="batchVestId" filterable placeholder="请选择马甲号" style="width:320px">
|
|
|
+ <el-option v-for="v in vestOptions" :key="v.id" :label="v.nickName + '(' + v.id + ')'" :value="v.id"/>
|
|
|
+ </el-select>
|
|
|
+ <el-button type="primary" size="mini" style="margin-left:12px" @click="addBatchRow">添加一条</el-button>
|
|
|
+ <span style="margin-left:8px;color:#909399;font-size:12px">每条支持本地上传或素材库选取</span>
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+ <div class="batch-list" style="max-height:62vh;overflow:auto;padding-right:4px">
|
|
|
+ <div
|
|
|
+ v-for="(row, index) in batchRows"
|
|
|
+ :key="row._key"
|
|
|
+ style="border:1px solid #EBEEF5;border-radius:4px;padding:12px 12px 4px;margin-bottom:12px;background:#FAFAFA"
|
|
|
+ >
|
|
|
+ <div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:8px">
|
|
|
+ <span style="font-weight:600">第 {{ index + 1 }} 条</span>
|
|
|
+ <el-button type="text" size="mini" style="color:#F56C6C" @click="removeBatchRow(index)">删除</el-button>
|
|
|
+ </div>
|
|
|
+ <el-form label-width="90px" size="small">
|
|
|
+ <el-form-item label="标题" required>
|
|
|
+ <el-input v-model="row.title" maxlength="20" show-word-limit placeholder="不超过20字"/>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="内容分类" required>
|
|
|
+ <el-select v-model="row.category" placeholder="请选择" style="width:220px">
|
|
|
+ <el-option v-for="d in categoryOptions" :key="d.dictValue" :label="d.dictLabel" :value="d.dictLabel"/>
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="封面" required>
|
|
|
+ <image-upload v-model="row.coverUrl" :limit="1" :file-size="2" aspect-ratio="16:9"/>
|
|
|
+ <div style="color:#909399;font-size:12px">比例 16:9,大小不超过 2MB</div>
|
|
|
+ </el-form-item>
|
|
|
+ <video-upload
|
|
|
+ :type="3"
|
|
|
+ :show-control="true"
|
|
|
+ :videoUrl.sync="row.videoUrl"
|
|
|
+ :fileName.sync="row.fileName"
|
|
|
+ @video-ready="onBatchVideoReady(index)"
|
|
|
+ @change="onBatchVideoReady(index)"
|
|
|
+ @video-duration="d => onBatchVideoDuration(index, d)"
|
|
|
+ />
|
|
|
+ <el-form-item v-if="row.videoUrl" label="上传时间">
|
|
|
+ <el-input :value="row.uploadTimeDisplay" disabled style="width:220px"/>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="时长(秒)">
|
|
|
+ <el-input-number v-model="row.duration" :min="0" :controls="false"/>
|
|
|
+ <span style="margin-left:8px;color:#909399;font-size:12px">自动读取,可改</span>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="播放量">
|
|
|
+ <el-input-number v-model="row.views" :min="0" :controls="false" style="width:120px"/>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="赞/藏/享">
|
|
|
+ <el-input-number v-model="row.likes" :min="0" :controls="false" style="width:90px"/>
|
|
|
+ <el-input-number v-model="row.favoriteNum" :min="0" :controls="false" style="width:90px;margin:0 8px"/>
|
|
|
+ <el-input-number v-model="row.shareNum" :min="0" :controls="false" style="width:90px"/>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="是否上架">
|
|
|
+ <el-switch v-model="row.isShow" :active-value="1" :inactive-value="0"/>
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div slot="footer" class="dialog-footer">
|
|
|
+ <el-button type="primary" :loading="batchSubmitting" @click="submitBatch">确 定</el-button>
|
|
|
+ <el-button @click="batchOpen = false">取 消</el-button>
|
|
|
+ </div>
|
|
|
+ </el-dialog>
|
|
|
+
|
|
|
<el-dialog title="选择商品" :visible.sync="productOpen" width="780px" append-to-body>
|
|
|
<el-form :inline="true" size="small">
|
|
|
<el-form-item label="商品名称">
|
|
|
@@ -145,8 +268,13 @@
|
|
|
<el-table-column label="库存" prop="stock" width="80"/>
|
|
|
<el-table-column label="操作" width="100">
|
|
|
<template slot-scope="scope">
|
|
|
- <el-button type="text" size="mini" :disabled="isSelected(scope.row.productId)" @click="pickProduct(scope.row)">
|
|
|
- {{ isSelected(scope.row.productId) ? '已选' : '选择' }}
|
|
|
+ <el-button
|
|
|
+ type="text"
|
|
|
+ size="mini"
|
|
|
+ :disabled="isSelected(scope.row.productId) || (selectedProducts.length >= 1 && !isSelected(scope.row.productId))"
|
|
|
+ @click="pickProduct(scope.row)"
|
|
|
+ >
|
|
|
+ {{ isSelected(scope.row.productId) ? '已选' : (selectedProducts.length >= 1 ? '已满' : '选择') }}
|
|
|
</el-button>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
@@ -158,33 +286,42 @@
|
|
|
|
|
|
<script>
|
|
|
import { listLifeVest } from '@/api/life/vest'
|
|
|
-import { listLifeVideo, getLifeVideo, addLifeVideo, updateLifeVideo, delLifeVideo, shelfLifeVideo, searchLifeVideoProduct } from '@/api/life/video'
|
|
|
+import { listLifeVideo, getLifeVideo, addLifeVideo, updateLifeVideo, delLifeVideo, shelfLifeVideo, searchLifeVideoProduct, batchAddLifeVideo } from '@/api/life/video'
|
|
|
+import VideoUpload from '@/components/VideoUpload/index.vue'
|
|
|
|
|
|
export default {
|
|
|
name: 'LifeVideo',
|
|
|
+ components: { VideoUpload },
|
|
|
data() {
|
|
|
return {
|
|
|
loading: true,
|
|
|
showSearch: true,
|
|
|
total: 0,
|
|
|
videoList: [],
|
|
|
+ ids: [],
|
|
|
+ multiple: true,
|
|
|
vestOptions: [],
|
|
|
+ categoryOptions: [],
|
|
|
title: '',
|
|
|
open: false,
|
|
|
+ uploadTimeDisplay: '',
|
|
|
queryParams: {
|
|
|
pageNum: 1,
|
|
|
pageSize: 10,
|
|
|
vestId: null,
|
|
|
+ category: null,
|
|
|
keyword: null,
|
|
|
isShow: null
|
|
|
},
|
|
|
form: {},
|
|
|
rules: {
|
|
|
vestId: [{ required: true, message: '请选择马甲号', trigger: 'change' }],
|
|
|
+ category: [{ required: true, message: '请选择内容分类', trigger: 'change' }],
|
|
|
title: [{ required: true, message: '标题不能为空', trigger: 'blur' }],
|
|
|
coverUrl: [{ required: true, message: '封面不能为空', trigger: 'change' }],
|
|
|
- videoUrl: [{ required: true, message: '视频地址不能为空', trigger: 'blur' }],
|
|
|
- isShow: [{ required: true, message: '请选择是否上架', trigger: 'change' }]
|
|
|
+ videoUrl: [{ required: true, message: '请上传或选择视频', trigger: 'change' }],
|
|
|
+ isShow: [{ required: true, message: '请选择是否上架', trigger: 'change' }],
|
|
|
+ isProduct: [{ required: true, message: '请选择是否关联商品', trigger: 'change' }]
|
|
|
},
|
|
|
selectedProducts: [],
|
|
|
productOpen: false,
|
|
|
@@ -195,22 +332,37 @@ export default {
|
|
|
pageNum: 1,
|
|
|
pageSize: 10,
|
|
|
productName: null
|
|
|
- }
|
|
|
+ },
|
|
|
+ batchOpen: false,
|
|
|
+ batchVestId: null,
|
|
|
+ batchRows: [],
|
|
|
+ batchSubmitting: false
|
|
|
}
|
|
|
},
|
|
|
created() {
|
|
|
if (this.$route.query.vestId) {
|
|
|
this.queryParams.vestId = Number(this.$route.query.vestId)
|
|
|
}
|
|
|
+ this.loadCategories()
|
|
|
this.loadVests()
|
|
|
this.getList()
|
|
|
},
|
|
|
methods: {
|
|
|
+ loadCategories() {
|
|
|
+ this.getDicts('life_video_category').then(res => {
|
|
|
+ this.categoryOptions = res.data || []
|
|
|
+ })
|
|
|
+ },
|
|
|
loadVests() {
|
|
|
- listLifeVest({ pageNum: 1, pageSize: 500 }).then(res => {
|
|
|
+ // 仅启用中的马甲出现在下拉
|
|
|
+ listLifeVest({ pageNum: 1, pageSize: 500, status: 1 }).then(res => {
|
|
|
this.vestOptions = res.rows || []
|
|
|
})
|
|
|
},
|
|
|
+ defaultCategory() {
|
|
|
+ const def = this.categoryOptions.find(d => d.isDefault === 'Y') || this.categoryOptions[0]
|
|
|
+ return def ? def.dictLabel : '默认分类'
|
|
|
+ },
|
|
|
getList() {
|
|
|
this.loading = true
|
|
|
listLifeVideo(this.queryParams).then(res => {
|
|
|
@@ -220,24 +372,90 @@ export default {
|
|
|
})
|
|
|
},
|
|
|
cancel() {
|
|
|
- this.open = false
|
|
|
- this.reset()
|
|
|
+ this.handleDialogClose(() => {
|
|
|
+ this.open = false
|
|
|
+ })
|
|
|
+ },
|
|
|
+ /** 已填写内容时取消需二次确认 */
|
|
|
+ isFormDirty() {
|
|
|
+ const f = this.form || {}
|
|
|
+ return !!(f.title || f.coverUrl || f.videoUrl || f.fileName
|
|
|
+ || (f.likes && f.likes > 0) || (f.favoriteNum && f.favoriteNum > 0) || (f.shareNum && f.shareNum > 0)
|
|
|
+ || (this.selectedProducts && this.selectedProducts.length))
|
|
|
+ },
|
|
|
+ handleDialogClose(done) {
|
|
|
+ const finish = () => {
|
|
|
+ this.reset()
|
|
|
+ if (typeof done === 'function') {
|
|
|
+ done()
|
|
|
+ } else {
|
|
|
+ this.open = false
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (!this.isFormDirty()) {
|
|
|
+ finish()
|
|
|
+ return
|
|
|
+ }
|
|
|
+ this.$confirm('已填写内容,确认放弃并关闭?', '提示', { type: 'warning' }).then(() => {
|
|
|
+ finish()
|
|
|
+ }).catch(() => {})
|
|
|
+ },
|
|
|
+ formatNow() {
|
|
|
+ const d = new Date()
|
|
|
+ const pad = n => (n < 10 ? '0' + n : '' + n)
|
|
|
+ return d.getFullYear() + '-' + pad(d.getMonth() + 1) + '-' + pad(d.getDate())
|
|
|
+ + ' ' + pad(d.getHours()) + ':' + pad(d.getMinutes()) + ':' + pad(d.getSeconds())
|
|
|
+ },
|
|
|
+ /** 本地上传完成 / 素材库选完后展示上传时间 */
|
|
|
+ onVideoReady() {
|
|
|
+ if (!this.form.videoUrl) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if (this.form.videoId) {
|
|
|
+ this.uploadTimeDisplay = this.parseTime(this.form.createTime) || this.formatNow()
|
|
|
+ } else {
|
|
|
+ this.uploadTimeDisplay = this.formatNow()
|
|
|
+ }
|
|
|
+ if (this.form.duration == null) {
|
|
|
+ this.form.duration = 0
|
|
|
+ }
|
|
|
+ this.$nextTick(() => {
|
|
|
+ this.$refs.form && this.$refs.form.validateField('videoUrl')
|
|
|
+ })
|
|
|
+ },
|
|
|
+ onVideoDuration(duration) {
|
|
|
+ const d = Number(duration)
|
|
|
+ if (!isNaN(d) && d >= 0) {
|
|
|
+ this.form.duration = Math.round(d)
|
|
|
+ }
|
|
|
},
|
|
|
reset() {
|
|
|
this.form = {
|
|
|
videoId: null,
|
|
|
vestId: this.queryParams.vestId || null,
|
|
|
+ category: this.defaultCategory(),
|
|
|
title: null,
|
|
|
fileName: null,
|
|
|
coverUrl: null,
|
|
|
videoUrl: null,
|
|
|
duration: 0,
|
|
|
+ views: 0,
|
|
|
+ likes: 0,
|
|
|
+ favoriteNum: 0,
|
|
|
+ shareNum: 0,
|
|
|
isShow: 1,
|
|
|
isHot: 0,
|
|
|
+ isProduct: 0,
|
|
|
productIds: []
|
|
|
}
|
|
|
+ this.uploadTimeDisplay = ''
|
|
|
this.selectedProducts = []
|
|
|
this.resetForm('form')
|
|
|
+ this.$nextTick(() => {
|
|
|
+ if (this.$refs.videoUpload && this.$refs.videoUpload.resetUpload) {
|
|
|
+ this.$refs.videoUpload.resetUpload()
|
|
|
+ }
|
|
|
+ })
|
|
|
},
|
|
|
handleQuery() {
|
|
|
this.queryParams.pageNum = 1
|
|
|
@@ -246,6 +464,7 @@ export default {
|
|
|
resetQuery() {
|
|
|
this.resetForm('queryForm')
|
|
|
this.queryParams.vestId = null
|
|
|
+ this.queryParams.category = null
|
|
|
this.handleQuery()
|
|
|
},
|
|
|
handleAdd() {
|
|
|
@@ -253,14 +472,115 @@ export default {
|
|
|
this.open = true
|
|
|
this.title = '新增生活号视频'
|
|
|
},
|
|
|
+ handleBatchAdd() {
|
|
|
+ this.batchVestId = this.queryParams.vestId || null
|
|
|
+ this.batchRows = [this.newBatchRow()]
|
|
|
+ this.batchOpen = true
|
|
|
+ },
|
|
|
+ newBatchRow() {
|
|
|
+ return {
|
|
|
+ _key: 'b_' + Date.now() + '_' + Math.random().toString(36).slice(2, 8),
|
|
|
+ title: '',
|
|
|
+ category: this.defaultCategory(),
|
|
|
+ coverUrl: null,
|
|
|
+ videoUrl: null,
|
|
|
+ fileName: null,
|
|
|
+ uploadTimeDisplay: '',
|
|
|
+ duration: 0,
|
|
|
+ views: 0,
|
|
|
+ likes: 0,
|
|
|
+ favoriteNum: 0,
|
|
|
+ shareNum: 0,
|
|
|
+ isShow: 1,
|
|
|
+ isHot: 0
|
|
|
+ }
|
|
|
+ },
|
|
|
+ addBatchRow() {
|
|
|
+ if (this.batchRows.length >= 50) {
|
|
|
+ this.$message.warning('单次最多批量新增50条')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ this.batchRows.push(this.newBatchRow())
|
|
|
+ },
|
|
|
+ removeBatchRow(index) {
|
|
|
+ this.batchRows.splice(index, 1)
|
|
|
+ },
|
|
|
+ onBatchVideoReady(index) {
|
|
|
+ const row = this.batchRows[index]
|
|
|
+ if (!row || !row.videoUrl) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ row.uploadTimeDisplay = this.formatNow()
|
|
|
+ if (row.duration == null) {
|
|
|
+ row.duration = 0
|
|
|
+ }
|
|
|
+ },
|
|
|
+ onBatchVideoDuration(index, duration) {
|
|
|
+ const row = this.batchRows[index]
|
|
|
+ if (!row) return
|
|
|
+ const d = Number(duration)
|
|
|
+ if (!isNaN(d) && d >= 0) {
|
|
|
+ row.duration = Math.round(d)
|
|
|
+ }
|
|
|
+ },
|
|
|
+ submitBatch() {
|
|
|
+ if (!this.batchVestId) {
|
|
|
+ this.$message.warning('请选择马甲号')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if (!this.batchRows.length) {
|
|
|
+ this.$message.warning('请至少添加一条视频')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ for (let i = 0; i < this.batchRows.length; i++) {
|
|
|
+ const row = this.batchRows[i]
|
|
|
+ if (!row.title || !row.coverUrl || !row.videoUrl || !row.category) {
|
|
|
+ this.$message.warning(`第 ${i + 1} 条:标题、封面、视频、分类均为必填(视频请本地上传或素材库选取)`)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ }
|
|
|
+ const payload = this.batchRows.map(row => ({
|
|
|
+ vestId: this.batchVestId,
|
|
|
+ title: row.title,
|
|
|
+ category: row.category,
|
|
|
+ coverUrl: row.coverUrl,
|
|
|
+ videoUrl: row.videoUrl,
|
|
|
+ fileName: row.fileName,
|
|
|
+ duration: row.duration || 0,
|
|
|
+ views: row.views || 0,
|
|
|
+ likes: row.likes || 0,
|
|
|
+ favoriteNum: row.favoriteNum || 0,
|
|
|
+ shareNum: row.shareNum || 0,
|
|
|
+ isShow: row.isShow,
|
|
|
+ isHot: row.isHot || 0,
|
|
|
+ productIds: []
|
|
|
+ }))
|
|
|
+ this.batchSubmitting = true
|
|
|
+ batchAddLifeVideo(payload).then(() => {
|
|
|
+ this.msgSuccess('批量添加成功')
|
|
|
+ this.batchOpen = false
|
|
|
+ this.getList()
|
|
|
+ }).finally(() => {
|
|
|
+ this.batchSubmitting = false
|
|
|
+ })
|
|
|
+ },
|
|
|
handleUpdate(row) {
|
|
|
this.reset()
|
|
|
getLifeVideo(row.videoId).then(res => {
|
|
|
this.form = Object.assign({}, res.data)
|
|
|
+ if (!this.form.category) {
|
|
|
+ this.form.category = this.defaultCategory()
|
|
|
+ }
|
|
|
+ this.form.likes = this.form.likes || 0
|
|
|
+ this.form.favoriteNum = this.form.favoriteNum || 0
|
|
|
+ this.form.shareNum = this.form.shareNum || 0
|
|
|
+ this.form.views = this.form.views || 0
|
|
|
+ this.form.duration = this.form.duration == null ? 0 : this.form.duration
|
|
|
+ this.uploadTimeDisplay = this.parseTime(this.form.createTime) || ''
|
|
|
const ids = res.data.productIds || []
|
|
|
this.form.productIds = ids
|
|
|
+ this.form.isProduct = ids.length > 0 ? 1 : 0
|
|
|
this.selectedProducts = ids.map(id => ({ productId: id, productName: '商品#' + id, price: '-', stock: '-' }))
|
|
|
- // 回填商品详情
|
|
|
if (ids.length) {
|
|
|
searchLifeVideoProduct({ pageNum: 1, pageSize: 100 }).then(p => {
|
|
|
const map = {}
|
|
|
@@ -275,7 +595,17 @@ export default {
|
|
|
submitForm() {
|
|
|
this.$refs['form'].validate(valid => {
|
|
|
if (!valid) return
|
|
|
- this.form.productIds = this.selectedProducts.map(p => p.productId)
|
|
|
+ if (this.form.isProduct === 1 && this.selectedProducts.length === 0) {
|
|
|
+ this.$message.warning('请选择关联商品')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if (this.selectedProducts.length > 1) {
|
|
|
+ this.$message.warning('最多关联一个商品')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ this.form.productIds = this.form.isProduct === 1
|
|
|
+ ? this.selectedProducts.map(p => p.productId)
|
|
|
+ : []
|
|
|
const req = this.form.videoId != null ? updateLifeVideo(this.form) : addLifeVideo(this.form)
|
|
|
req.then(() => {
|
|
|
this.msgSuccess('操作成功')
|
|
|
@@ -291,6 +621,10 @@ export default {
|
|
|
this.getList()
|
|
|
})
|
|
|
},
|
|
|
+ handleSelectionChange(selection) {
|
|
|
+ this.ids = selection.map(item => item.videoId)
|
|
|
+ this.multiple = !selection.length
|
|
|
+ },
|
|
|
handleDelete(row) {
|
|
|
this.$confirm('删除后不可恢复,确认删除该视频?', '警告', { type: 'warning' }).then(() => {
|
|
|
return delLifeVideo(row.videoId)
|
|
|
@@ -299,6 +633,18 @@ export default {
|
|
|
this.msgSuccess('删除成功')
|
|
|
}).catch(() => {})
|
|
|
},
|
|
|
+ handleBatchDelete() {
|
|
|
+ if (!this.ids.length) {
|
|
|
+ this.$message.warning('请选择要删除的视频')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ this.$confirm('删除后不可恢复,确认批量删除选中的 ' + this.ids.length + ' 条视频?', '警告', { type: 'warning' }).then(() => {
|
|
|
+ return delLifeVideo(this.ids.join(','))
|
|
|
+ }).then(() => {
|
|
|
+ this.getList()
|
|
|
+ this.msgSuccess('删除成功')
|
|
|
+ }).catch(() => {})
|
|
|
+ },
|
|
|
openProductDialog() {
|
|
|
this.productOpen = true
|
|
|
this.searchProduct()
|
|
|
@@ -315,9 +661,16 @@ export default {
|
|
|
return this.selectedProducts.some(p => p.productId === productId)
|
|
|
},
|
|
|
pickProduct(row) {
|
|
|
- if (!this.isSelected(row.productId)) {
|
|
|
- this.selectedProducts.push(row)
|
|
|
+ if (this.isSelected(row.productId)) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if (this.selectedProducts.length >= 1) {
|
|
|
+ this.$message.warning('最多关联一个商品,请先删除已选商品')
|
|
|
+ return
|
|
|
}
|
|
|
+ this.selectedProducts.push(row)
|
|
|
+ this.form.isProduct = 1
|
|
|
+ this.productOpen = false
|
|
|
},
|
|
|
removeProduct(index) {
|
|
|
this.selectedProducts.splice(index, 1)
|