|
@@ -0,0 +1,549 @@
|
|
|
+<template>
|
|
|
+ <div class="app-container">
|
|
|
+ <div class="filter-container activity">
|
|
|
+ <div class="filter-control">
|
|
|
+ <span>活动时间:</span>
|
|
|
+ <el-date-picker
|
|
|
+ v-model="activityFormData.time"
|
|
|
+ format="yyyy-MM-dd HH:mm:ss"
|
|
|
+ value-format="yyyy-MM-dd HH:mm:ss"
|
|
|
+ type="datetimerange"
|
|
|
+ range-separator="至"
|
|
|
+ start-placeholder="开始日期"
|
|
|
+ end-placeholder="结束日期"
|
|
|
+ :disabled="activityFormData.status === 1"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ <div class="filter-control">
|
|
|
+ <span>活动状态:</span>
|
|
|
+ <el-switch
|
|
|
+ v-model="activityFormData.status"
|
|
|
+ el-switch
|
|
|
+ :active-value="1"
|
|
|
+ :inactive-value="0"
|
|
|
+ @change="onUpdateActivityStatus"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <el-divider />
|
|
|
+ <div class="filter-container">
|
|
|
+ <div class="filter-control">
|
|
|
+ <span>所属机构:</span>
|
|
|
+ <el-select v-model="listQuery.authId" placeholder="所属机构" clearable @change="getList">
|
|
|
+ <template v-for="(item, index) in clubList">
|
|
|
+ <el-option :key="index" :label="item.authParty" :value="item.authId" />
|
|
|
+ </template>
|
|
|
+ </el-select>
|
|
|
+ </div>
|
|
|
+ <div class="filter-control">
|
|
|
+ <span>登录账号:</span>
|
|
|
+ <el-input v-model="listQuery.userName" placeholder="登录账号" @keyup.enter.native="getList" />
|
|
|
+ </div>
|
|
|
+ <div class="filter-control">
|
|
|
+ <el-button type="primary" @click="getList">查询</el-button>
|
|
|
+ <el-button type="primary" :disabled="selectionList.length === 0" @click="onDownload('select')">下载</el-button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <!-- 列表 -->
|
|
|
+ <el-table
|
|
|
+ v-loading="listLoading"
|
|
|
+ :data="list"
|
|
|
+ border
|
|
|
+ fit
|
|
|
+ highlight-current-row
|
|
|
+ style="width: 100%"
|
|
|
+ header-row-class-name="tableHeader"
|
|
|
+ @selection-change="onSelectionChange"
|
|
|
+ >
|
|
|
+ <el-table-column type="selection" width="55" align="center" />
|
|
|
+ <el-table-column label="序号" :index="indexMethod" align="center" width="80" type="index" />
|
|
|
+ <el-table-column label="视频" align="center" width="100">
|
|
|
+ <template slot-scope="{ row }"><el-image class="cover" :src="row.cover" /></template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="登录账号" align="center" prop="userName" width="240" />
|
|
|
+ <el-table-column label="机构名称" align="center" prop="authParty" />
|
|
|
+ <el-table-column label="浏览量" align="center" prop="playCount" width="120" />
|
|
|
+ <el-table-column label="点赞数" align="center" prop="diggCount" width="120" />
|
|
|
+ <el-table-column label="排名" align="center" prop="rankNum" width="120" />
|
|
|
+ <el-table-column label="抖音上传状态" align="center" width="120">
|
|
|
+ <template slot-scope="{ row }">
|
|
|
+ <span v-if="row.status === 1" class="status success">已上传</span>
|
|
|
+ <span v-if="row.status === 0" class="status danger">未上传</span>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="上传时间" align="center" width="160">
|
|
|
+ <template slot-scope="{ row }">
|
|
|
+ <span>{{ row.releaseTime | formatDate }}</span>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="操作" align="center" width="440">
|
|
|
+ <template slot-scope="{ row }">
|
|
|
+ <permission-button
|
|
|
+ v-if="row.status !== 1"
|
|
|
+ size="mini"
|
|
|
+ type="primary"
|
|
|
+ @click="onSyancDouyin(row)"
|
|
|
+ >上传至抖音</permission-button>
|
|
|
+ <permission-button size="mini" type="primary" @click="onSaveCommand(row)">抖音口令</permission-button>
|
|
|
+ <permission-button size="mini" type="primary" @click="onPlayVideo(row)">播放视频</permission-button>
|
|
|
+ <permission-button size="mini" type="primary" @click="onDownload('single', row)">下载</permission-button>
|
|
|
+ <permission-button size="mini" type="primary" @click="onRemove(row)">删除</permission-button>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ </el-table>
|
|
|
+
|
|
|
+ <!-- 上传抖音 -->
|
|
|
+ <el-dialog
|
|
|
+ title="发布抖音"
|
|
|
+ :visible.sync="scanDialog"
|
|
|
+ width="300px"
|
|
|
+ center
|
|
|
+ :close-on-click-modal="false"
|
|
|
+ @close="onScanClose"
|
|
|
+ >
|
|
|
+ <el-image class="dy-code" :src="qrcodeUrl" />
|
|
|
+ <div class="tip">请使用抖音app扫码发布视频</div>
|
|
|
+ </el-dialog>
|
|
|
+
|
|
|
+ <!-- 抖音口令 -->
|
|
|
+ <el-dialog
|
|
|
+ title="抖音口令"
|
|
|
+ :visible.sync="commandDialog"
|
|
|
+ width="30%"
|
|
|
+ :show-close="false"
|
|
|
+ :close-on-click-modal="false"
|
|
|
+ @close="onCommandClose"
|
|
|
+ >
|
|
|
+ <el-form ref="commandForm" :model="commandFormData" :rules="commandRules">
|
|
|
+ <el-form-item prop="content">
|
|
|
+ <el-input v-model="commandFormData.content" type="textarea" :rows="5" placeholder="请输入抖音口令" />
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+ <div class="control">
|
|
|
+ <el-button @click="commandDialog = false">取消</el-button>
|
|
|
+ <el-button type="primary" @click="onCommandSubmit">提交</el-button>
|
|
|
+ </div>
|
|
|
+ </el-dialog>
|
|
|
+
|
|
|
+ <!-- 视频播放 -->
|
|
|
+ <el-dialog title="视频播放" :visible.sync="videoDialog" width="800px" center :close-on-click-modal="false">
|
|
|
+ <video class="video-play" :src="videoUrl" controls />
|
|
|
+ </el-dialog>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+import {
|
|
|
+ checkDouyinAccessToken,
|
|
|
+ fetchClubList,
|
|
|
+ fetchDouyinActivityStatus,
|
|
|
+ fetchDouyinVideoList,
|
|
|
+ getDouyinAccessToken,
|
|
|
+ onSendDouyinCommand,
|
|
|
+ removeVideo,
|
|
|
+ updateDouyinActivityStatus
|
|
|
+} from '@/api/activity'
|
|
|
+
|
|
|
+import Qrcode from 'qrcode'
|
|
|
+import { generateQueryUrl } from '@/utils'
|
|
|
+import { mapGetters } from 'vuex'
|
|
|
+import { getStorage, removeStorage } from '@/utils/storage'
|
|
|
+import { downloadWithUrl } from '@/utils/tools'
|
|
|
+
|
|
|
+export default {
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ // 视频播放
|
|
|
+ videoDialog: false,
|
|
|
+ videoUrl: '',
|
|
|
+ listQuery: {
|
|
|
+ status: '',
|
|
|
+ authId: '',
|
|
|
+ userName: '',
|
|
|
+ authParty: '',
|
|
|
+ pageNum: 1,
|
|
|
+ pageSize: 10
|
|
|
+ },
|
|
|
+ listLoading: false,
|
|
|
+ list: [],
|
|
|
+ // 活动表单数据
|
|
|
+ activityFormData: {
|
|
|
+ time: [],
|
|
|
+ status: 0
|
|
|
+ },
|
|
|
+ scanDialog: false,
|
|
|
+ commandDialog: false,
|
|
|
+ qrcodeUrl: '',
|
|
|
+ // 抖音口令表单数据
|
|
|
+ commandFormData: {
|
|
|
+ authId: '',
|
|
|
+ content: ''
|
|
|
+ },
|
|
|
+ commandRules: {
|
|
|
+ content: [{ required: true, message: '口令不能为空', trigger: ['blur'] }]
|
|
|
+ },
|
|
|
+ clubList: [],
|
|
|
+ selectionList: []
|
|
|
+ }
|
|
|
+ },
|
|
|
+ computed: {
|
|
|
+ ...mapGetters(['proxyInfo'])
|
|
|
+ },
|
|
|
+ created() {
|
|
|
+ this.getList()
|
|
|
+ this.getClubList()
|
|
|
+ this.fetchActivityStatus()
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ // 获取活动状态
|
|
|
+ async fetchActivityStatus() {
|
|
|
+ try {
|
|
|
+ const res = await fetchDouyinActivityStatus()
|
|
|
+ if (!res.data) return
|
|
|
+ const { startTime, endTime } = res.data
|
|
|
+ if (startTime && endTime) {
|
|
|
+ this.activityFormData.time = [startTime, endTime]
|
|
|
+ }
|
|
|
+ this.activityFormData.status = res.data.status
|
|
|
+ } catch (error) {
|
|
|
+ console.log(error)
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ // 验证活动时间
|
|
|
+ checkActivityTime(startTime, endTime) {
|
|
|
+ startTime = new Date(startTime).getTime()
|
|
|
+ endTime = new Date(endTime).getTime()
|
|
|
+ const nowTime = Date.now()
|
|
|
+ if (startTime < nowTime) {
|
|
|
+ return 1
|
|
|
+ }
|
|
|
+ if (endTime < startTime) {
|
|
|
+ return 2
|
|
|
+ }
|
|
|
+ if (endTime < nowTime) {
|
|
|
+ return 3
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ // 更新活动时间状态
|
|
|
+ onUpdateActivityStatus(value) {
|
|
|
+ let flag = -1
|
|
|
+
|
|
|
+ const dialog = {
|
|
|
+ 0: '请先设置活动时间后,再来开启活动按钮',
|
|
|
+ 1: '活动开始时间不能小于当前时间',
|
|
|
+ 2: '活动结束时间不能小于活动开始时间',
|
|
|
+ 3: '你设置的活动时间已失效,请重新设置有效活动时间后,再来开启活动按钮'
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!this.activityFormData.time) {
|
|
|
+ flag = 0
|
|
|
+ } else {
|
|
|
+ const [start, end] = this.activityFormData.time
|
|
|
+ flag = this.checkActivityTime(start, end)
|
|
|
+ }
|
|
|
+
|
|
|
+ if (flag > -1 && value === 1) {
|
|
|
+ this.$confirm(dialog[flag], '提示', {
|
|
|
+ confirmButtonText: '确定',
|
|
|
+ cancelButtonText: '取消',
|
|
|
+ type: 'warning',
|
|
|
+ closeOnClickModal: false,
|
|
|
+ showClose: false
|
|
|
+ })
|
|
|
+ .then(() => {
|
|
|
+ this.activityFormData.status = 0
|
|
|
+ })
|
|
|
+ .catch(() => {
|
|
|
+ this.activityFormData.status = 0
|
|
|
+ })
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ this.updateActivityStatus()
|
|
|
+ },
|
|
|
+
|
|
|
+ // 更新活动状态
|
|
|
+ async updateActivityStatus() {
|
|
|
+ try {
|
|
|
+ const {
|
|
|
+ status,
|
|
|
+ time: [startTime, endTime]
|
|
|
+ } = this.activityFormData
|
|
|
+ await updateDouyinActivityStatus({
|
|
|
+ startTime,
|
|
|
+ endTime,
|
|
|
+ status
|
|
|
+ })
|
|
|
+ this.$message.success(`活动已${status ? '开启' : '关闭'}`)
|
|
|
+ } catch (error) {
|
|
|
+ console.log(error)
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ // 获取视频列表
|
|
|
+ getList() {
|
|
|
+ this.list = []
|
|
|
+ this.listQuery.pageNum = 1
|
|
|
+ this.fetchDouyinVideoList()
|
|
|
+ },
|
|
|
+
|
|
|
+ // 获取视频列表
|
|
|
+ async fetchDouyinVideoList() {
|
|
|
+ try {
|
|
|
+ this.listLoading = true
|
|
|
+ const res = await fetchDouyinVideoList(this.listQuery)
|
|
|
+ this.list = res.data.list.map((item, index) => {
|
|
|
+ if (item.rankingStatus === 1) {
|
|
|
+ item.rankNum = index + 1
|
|
|
+ }
|
|
|
+ return item
|
|
|
+ })
|
|
|
+ this.listLoading = false
|
|
|
+ } catch (error) {
|
|
|
+ console.log(error)
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ // 表格数据选中
|
|
|
+ onSelectionChange(data) {
|
|
|
+ this.selectionList = data
|
|
|
+ },
|
|
|
+
|
|
|
+ // 表格索引
|
|
|
+ indexMethod(index) {
|
|
|
+ return index + this.listQuery.pageSize * (this.listQuery.pageNum - 1) + 1
|
|
|
+ },
|
|
|
+
|
|
|
+ // 获取已发布视频机构列表
|
|
|
+ async getClubList(list) {
|
|
|
+ try {
|
|
|
+ const res = await fetchClubList()
|
|
|
+ this.clubList = res.data
|
|
|
+ } catch (error) {
|
|
|
+ console.log(error)
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ // 上传抖音
|
|
|
+ async onSyancDouyin(row) {
|
|
|
+ // 代理模式下不允许操作
|
|
|
+ if (this.proxyInfo) {
|
|
|
+ return this.$confirm('请退出代操作,使用供应商账号登陆后操作!', {
|
|
|
+ confirmButtonText: '确定',
|
|
|
+ cancelButtonText: '取消'
|
|
|
+ })
|
|
|
+ .then(() => {})
|
|
|
+ .catch(() => {})
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ // 校验token
|
|
|
+ const { data: tokenFlag } = await checkDouyinAccessToken()
|
|
|
+ if (!tokenFlag) {
|
|
|
+ this.douyinLogin(row)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ const url = process.env.VUE_APP_LOCAL + `/#/douyin/schema?id=${row.id}`
|
|
|
+ await this.generateQrcode(url)
|
|
|
+ // 获取分享码
|
|
|
+ } catch (error) {
|
|
|
+ console.log(error)
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ // 登录抖音
|
|
|
+ async douyinLogin(row) {
|
|
|
+ const code = getStorage('zp_douyin_code')
|
|
|
+ if (!code) {
|
|
|
+ // 获取token
|
|
|
+ const url = generateQueryUrl('https://open.douyin.com/platform/oauth/connect', {
|
|
|
+ client_key: 'awwwvh9tsnvo54w1',
|
|
|
+ response_type: 'code',
|
|
|
+ scope: 'video.data,video.list,trial.whitelist,data.external.item,h5.share',
|
|
|
+ redirect_uri: process.env.VUE_APP_LOCAL + '#/douyin',
|
|
|
+ state: '/challenge/video'
|
|
|
+ })
|
|
|
+ window.open(url, '_blank')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ removeStorage('zp_douyin_code')
|
|
|
+ try {
|
|
|
+ await getDouyinAccessToken({ code })
|
|
|
+ this.onSyancDouyin(row)
|
|
|
+ } catch (error) {
|
|
|
+ console.log(error)
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ // 抖音视频对话框关闭
|
|
|
+ onScanClose() {
|
|
|
+ this.getList()
|
|
|
+ },
|
|
|
+
|
|
|
+ // 生成h5分享码
|
|
|
+ async generateQrcode(str) {
|
|
|
+ try {
|
|
|
+ const res = await Qrcode.toDataURL(str, {})
|
|
|
+ this.qrcodeUrl = res
|
|
|
+ this.scanDialog = true
|
|
|
+ } catch (error) {
|
|
|
+ console.log(error)
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ // 提交抖音口令
|
|
|
+ async onCommandSubmit() {
|
|
|
+ try {
|
|
|
+ await this.$refs.commandForm.validate()
|
|
|
+ await onSendDouyinCommand(this.commandFormData)
|
|
|
+ this.commandDialog = false
|
|
|
+ this.$message.success('抖音口令保存成功')
|
|
|
+ this.getList()
|
|
|
+ } catch (error) {
|
|
|
+ console.log(error)
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ // 保存抖音口令
|
|
|
+ async onSaveCommand(row) {
|
|
|
+ this.commandDialog = true
|
|
|
+ this.commandFormData.authId = row.authId
|
|
|
+ this.commandFormData.content = row.dyCommand
|
|
|
+ },
|
|
|
+
|
|
|
+ // 清楚表单信息
|
|
|
+ onCommandClose() {
|
|
|
+ this.commandFormData.authId = ''
|
|
|
+ this.$refs.commandForm.resetFields()
|
|
|
+ },
|
|
|
+
|
|
|
+ // 播放视频
|
|
|
+ onPlayVideo(row) {
|
|
|
+ this.videoDialog = true
|
|
|
+ this.videoUrl = row.ossUrl
|
|
|
+ },
|
|
|
+
|
|
|
+ // 下载视频
|
|
|
+ onDownload(type, row) {
|
|
|
+ if (type === 'single') {
|
|
|
+ this.downloadVideo([row.id + ','])
|
|
|
+ } else {
|
|
|
+ // this.downloadVideo[]
|
|
|
+ const ids = this.selectionList.map((item) => item.id)
|
|
|
+ this.downloadVideo(ids)
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ // 下载视频
|
|
|
+ async downloadVideo(fileIdList) {
|
|
|
+ try {
|
|
|
+ const filedIds = fileIdList.join(',')
|
|
|
+ const text = await this.$confirm(`确认下载所选视频?`, '提示', {
|
|
|
+ confirmButtonText: '确定',
|
|
|
+ cancelButtonText: '取消',
|
|
|
+ type: 'warning'
|
|
|
+ }).catch(() => {
|
|
|
+ this.exportClubList = []
|
|
|
+ this.$message.info('已取消操作')
|
|
|
+ })
|
|
|
+ if (text !== 'confirm') return
|
|
|
+ let notification = null
|
|
|
+ notification = this.$notify({
|
|
|
+ title: '提示',
|
|
|
+ message: `正在下载视频,请勿重复操作!`,
|
|
|
+ duration: 0
|
|
|
+ })
|
|
|
+ const downUrl = `${process.env.VUE_APP_BASE_API}/auth/downLoad/chose/zip?fileId=${filedIds}`
|
|
|
+ downloadWithUrl(downUrl, '抖音视频', {
|
|
|
+ headers: {
|
|
|
+ 'X-Token': this.$store.getters.token
|
|
|
+ }
|
|
|
+ })
|
|
|
+ .then((res) => {
|
|
|
+ this.getList()
|
|
|
+ })
|
|
|
+ .catch((err) => {
|
|
|
+ console.log(err)
|
|
|
+ this.$message.error(`下载抖音视频失败`)
|
|
|
+ })
|
|
|
+ .finally(() => {
|
|
|
+ notification.close()
|
|
|
+ })
|
|
|
+ } catch (error) {
|
|
|
+ console.log(error)
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ // 删除视频
|
|
|
+ async onRemove(row) {
|
|
|
+ try {
|
|
|
+ await this.$confirm('此操作将永久删除该视频, 是否继续?', '提示', {
|
|
|
+ confirmButtonText: '确定',
|
|
|
+ cancelButtonText: '取消',
|
|
|
+ type: 'warning'
|
|
|
+ })
|
|
|
+ this.removeVideo(row)
|
|
|
+ } catch (error) {
|
|
|
+ console.log(error)
|
|
|
+ this.$message.info('已取消操作')
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ // 删除视频
|
|
|
+ async removeVideo(row) {
|
|
|
+ try {
|
|
|
+ await removeVideo({ videoId: row.id })
|
|
|
+ this.$message.success('删除视频成功')
|
|
|
+ this.getList()
|
|
|
+ } catch (error) {
|
|
|
+ console.log(error)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</script>
|
|
|
+
|
|
|
+<style lang="scss" scoped>
|
|
|
+.activity {
|
|
|
+ .filter-control {
|
|
|
+ margin-bottom: 0;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.cover {
|
|
|
+ width: 80px;
|
|
|
+ display: block;
|
|
|
+}
|
|
|
+
|
|
|
+.el-divider {
|
|
|
+ margin: 12px 0;
|
|
|
+}
|
|
|
+
|
|
|
+.el-dialog {
|
|
|
+ .control {
|
|
|
+ text-align: right;
|
|
|
+ }
|
|
|
+
|
|
|
+ .video-play {
|
|
|
+ display: block;
|
|
|
+ width: 100%;
|
|
|
+ height: 480px;
|
|
|
+ background: #666;
|
|
|
+ }
|
|
|
+
|
|
|
+ .dy-code {
|
|
|
+ width: 160px;
|
|
|
+ height: 160px;
|
|
|
+ display: block;
|
|
|
+ margin: 0 auto;
|
|
|
+ }
|
|
|
+
|
|
|
+ .tip {
|
|
|
+ font-size: 14px;
|
|
|
+ text-align: center;
|
|
|
+ color: #666;
|
|
|
+ padding: 16px 0 8px;
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|