Initial commit
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Executable
+46
@@ -0,0 +1,46 @@
|
||||
<template>
|
||||
<div id="app">
|
||||
<router-view />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getSyscfg } from '@/api/system/systemConfig'
|
||||
import { getToken } from '@/utils/auth' // get token from cookie
|
||||
export default {
|
||||
name: 'App',
|
||||
async created() {
|
||||
const hasToken = getToken()
|
||||
if (hasToken) {
|
||||
await this.getData()
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// TODO:请求系统配置列表数据
|
||||
getData() {
|
||||
if (getToken()) {
|
||||
getSyscfg({}).then((res) => {
|
||||
if (res.code === 200) {
|
||||
this.form = res.data
|
||||
this.$store.dispatch('system/setConfig', res.data)
|
||||
} else {
|
||||
this.$message.error('请求系统配置失败')
|
||||
}
|
||||
}).catch(err => {
|
||||
console.log(err, 'ss')
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.el-tooltip__popper {
|
||||
max-width: 600px;
|
||||
}
|
||||
|
||||
.el-table {
|
||||
font-size: 12px !important;
|
||||
color: rgb(56, 51, 51) !important;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* @Author: 江涛
|
||||
* @Mail: jt213219216@gmail.com
|
||||
* @Date: 2021-02-22 10:36:38
|
||||
* @LastEditTime: 2021-03-15 11:11:22
|
||||
* @LastEditors: 江涛
|
||||
* @FilePath: /web-admin-MDDSP/src/api/account/accountList.js
|
||||
*/
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 帐号列表
|
||||
export function accList(params) {
|
||||
return request({
|
||||
url: '/api/web/acc/list',
|
||||
method: 'GET',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
// 账号删除
|
||||
export function accDel(data) {
|
||||
return request({
|
||||
url: '/api/web/acc/del',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 账号添加
|
||||
export function accAdd(data) {
|
||||
return request({
|
||||
url: '/api/web/acc/add',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
// 更新账号
|
||||
export function accUp(data) {
|
||||
return request({
|
||||
url: '/api/web/acc/up',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 获取可用角色列表
|
||||
export function roleDrop(data) {
|
||||
return request({
|
||||
url: '/api/web/role/drop',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 更改账号状态
|
||||
export function accSavestatus(data) {
|
||||
return request({
|
||||
url: '/api/web/acc/savestatus',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* @Author: 江涛
|
||||
* @Mail: jt213219216@gmail.com
|
||||
* @Date: 2021-02-22 10:36:38
|
||||
* @LastEditTime: 2021-03-12 19:49:15
|
||||
* @LastEditors: 江涛
|
||||
* @FilePath: /web-admin-MDDSP/src/api/account/roleList.js
|
||||
*/
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 新增角色
|
||||
export function roleAdd(data) {
|
||||
return request({
|
||||
url: '/api/web/role/add',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 角色删除
|
||||
export function roleDel(data) {
|
||||
return request({
|
||||
url: '/api/web/role/del',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 获取角色列表
|
||||
export function getRoleList(params) {
|
||||
return request({
|
||||
url: '/api/web/role/list',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
// 新增角色
|
||||
export function roleUp(data) {
|
||||
return request({
|
||||
url: '/api/web/role/up',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 请求角色权限
|
||||
export function getAuth(params) {
|
||||
return request({
|
||||
url: '/api/web/role/getauth',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
// 更新权限
|
||||
export function upAuth(data) {
|
||||
return request({
|
||||
url: '/api/web/role/upauth',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 角色使能
|
||||
export function roleEnable(data) {
|
||||
return request({
|
||||
url: '/api/web/role/enable',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 获取信息
|
||||
// export function roleGetinfo(data) {
|
||||
// return request({
|
||||
// url: '/web/role/getinfo',
|
||||
// method: 'post',
|
||||
// data
|
||||
// })
|
||||
// }
|
||||
@@ -0,0 +1,81 @@
|
||||
|
||||
/*
|
||||
* @Author: 江涛
|
||||
* @Mail: jt213219216@gmail.com
|
||||
* @Date: 2021-02-22 10:36:38
|
||||
* @LastEditTime: 2022-08-15 19:48:00
|
||||
* @LastEditors: Please set LastEditors
|
||||
* @FilePath: /sq_web_admin/src/api/account/upList.js
|
||||
*/
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 新增角色
|
||||
export function upAdd(data) {
|
||||
return request({
|
||||
url: '/api/web/upmaster/add',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 角色删除
|
||||
export function upDel(data) {
|
||||
return request({
|
||||
url: '/api/web/uploader/del',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 获取角色列表
|
||||
export function getUpList(data) {
|
||||
return request({
|
||||
url: '/api/web/uploader/list',
|
||||
method: 'post',
|
||||
filterParam: true,
|
||||
data
|
||||
})
|
||||
}
|
||||
// 更新权限
|
||||
export function upAuth(data) {
|
||||
return request({
|
||||
url: '/api/web/uploader/update',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
// 新增角色
|
||||
// export function roleUp(data) {
|
||||
// return request({
|
||||
// url: '/api/web/role/up',
|
||||
// method: 'post',
|
||||
// data
|
||||
// })
|
||||
// }
|
||||
|
||||
// 请求角色权限
|
||||
// export function getAuth(params) {
|
||||
// return request({
|
||||
// url: '/api/web/role/getauth',
|
||||
// method: 'get',
|
||||
// params
|
||||
// })
|
||||
// }
|
||||
|
||||
// 角色使能
|
||||
// export function roleEnable(data) {
|
||||
// return request({
|
||||
// url: '/api/web/role/enable',
|
||||
// method: 'post',
|
||||
// data
|
||||
// })
|
||||
// }
|
||||
|
||||
// 获取信息
|
||||
// export function roleGetinfo(data) {
|
||||
// return request({
|
||||
// url: '/web/role/getinfo',
|
||||
// method: 'post',
|
||||
// data
|
||||
// })
|
||||
// }
|
||||
@@ -0,0 +1,38 @@
|
||||
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 请求位置列表
|
||||
export function appInfoList(data) {
|
||||
return request({
|
||||
url: '/media/web/appinfo/info/list',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 位置更新更新
|
||||
export function appInfoUpdate(data) {
|
||||
return request({
|
||||
url: '/media/web/appinfo/info/update',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 新增位置
|
||||
export function appInfoAdd(data) {
|
||||
return request({
|
||||
url: '/media/web/appinfo/info/add',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 删除位置
|
||||
export function appInfoDel(data) {
|
||||
return request({
|
||||
url: '/media/web/appinfo/info/del',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
export function dockingAppCategoryList(data) {
|
||||
return request({
|
||||
url: '/media/web/appcategory/list',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function dockingAppCategoryAdd(data) {
|
||||
return request({
|
||||
url: '/media/web/appcategory/add',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function dockingAppCategoryUpdate(data) {
|
||||
return request({
|
||||
url: '/media/web/appcategory/update',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function dockingAppCategoryDel(data) {
|
||||
return request({
|
||||
url: '/media/web/appcategory/del',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
export function dockingAppList(data) {
|
||||
return request({
|
||||
url: '/media/web/appinfo/list',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function dockingAppAdd(data) {
|
||||
return request({
|
||||
url: '/media/web/appinfo/add',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function dockingAppUpdate(data) {
|
||||
return request({
|
||||
url: '/media/web/appinfo/update',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function dockingAppDel(data) {
|
||||
return request({
|
||||
url: '/media/web/appinfo/del',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
export function upLoadFile(data, source) {
|
||||
return request({
|
||||
url: '/api/web/file/uploadImg',
|
||||
method: 'post',
|
||||
headers: { 'Content-Type': 'multipart/form-data' },
|
||||
data,
|
||||
timeout: 0,
|
||||
cancelToken: source.token
|
||||
})
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* @Author: 王涛
|
||||
* @Mail: no
|
||||
* @Date: 2021-01-05 10:36:27
|
||||
* @LastEditors: 王涛
|
||||
* @LastEditTime: 2021-01-07 22:20:44
|
||||
*/
|
||||
import request from '@/utils/request'
|
||||
// 上传图片
|
||||
export function mediaUploadImg(data) {
|
||||
return request({
|
||||
url: '/api/web/file/uploadImg',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
|
||||
import request from '@/utils/request'
|
||||
|
||||
// // 请求首页今日数据
|
||||
export function getToday() {
|
||||
return request({ url: '/web/report/today', method: 'get' })
|
||||
}
|
||||
|
||||
// // 请求全部数据
|
||||
// export function getTotal() {
|
||||
// return request({
|
||||
// url: '/web/report/total',
|
||||
// method: 'get'
|
||||
// })
|
||||
// }
|
||||
// /**
|
||||
// *
|
||||
// * @param {*} params
|
||||
// */
|
||||
// export function getVisit(params) {
|
||||
// return request({
|
||||
// url: '/web/report/visit/list',
|
||||
// method: 'get',
|
||||
// params
|
||||
// })
|
||||
// }
|
||||
|
||||
// /**
|
||||
// * 水印列表导出
|
||||
// * @param {*} params
|
||||
// */
|
||||
Executable
+28
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* @Author: 王涛
|
||||
* @Mail: no
|
||||
* @Date: 2020-10-06 01:01:28
|
||||
* @LastEditors: 江涛
|
||||
* @LastEditTime: 2021-03-12 19:41:26
|
||||
*/
|
||||
import request from '@/utils/request'
|
||||
|
||||
export function login(data) {
|
||||
return request({
|
||||
url: '/api/web/login/acc',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// /**
|
||||
// * 确认绑定二维码 code为333时 调用
|
||||
// * @param {*} data
|
||||
// */
|
||||
export function validateQR(data) {
|
||||
return request({
|
||||
url: '/api/web/login/bind',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 获取视频列表
|
||||
export function lsjVideoList(data) {
|
||||
return request({
|
||||
url: '/api/web/laosiji/movie/search',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 获取视频列表
|
||||
export function lsjVideoDel(data) {
|
||||
return request({
|
||||
url: '/api/web/laosiji/movie/search',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function lsjVideoDetail(data) {
|
||||
return request({
|
||||
url: '/api/web/laosiji/movie/detail',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function lsjVideoAdd(data) {
|
||||
return request({
|
||||
url: '/api/web/laosiji/movie/add',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 影片列表
|
||||
export function mediaSearch(data) {
|
||||
return request({
|
||||
url: '/api/web/mediafile/search',
|
||||
method: 'post',
|
||||
filterParam: true,
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 视频列表
|
||||
export function mediaSearchV1(data) {
|
||||
return request({
|
||||
url: '/media/web/mediafile/search',
|
||||
method: 'post',
|
||||
filterParam: true,
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 视频列表V2
|
||||
export function mediaSearchV2(data) {
|
||||
return request({
|
||||
url: '/media/web/mediafile/searchV2',
|
||||
method: 'post',
|
||||
filterParam: true,
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 删除影片
|
||||
export function mediaDel(data) {
|
||||
return request({
|
||||
url: '/api/web/mediafile/del',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 同步
|
||||
export function mediaUpdate(data) {
|
||||
return request({
|
||||
url: '/media/web/mediafile/sync',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 编辑影片
|
||||
export function mediaEdit(data) {
|
||||
return request({
|
||||
url: '/api/web/mediafile/update',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 更新预览时长
|
||||
export function updatePreTime(data) {
|
||||
return request({
|
||||
url: '/api/web/mediafile/update/prefile',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 删除视频
|
||||
export function sourceDel(data) {
|
||||
return request({
|
||||
url: '/media/web/source/del',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 资源列表
|
||||
export function sourceList(data) {
|
||||
return request({
|
||||
url: '/media/web/source/list',
|
||||
method: 'post',
|
||||
filterParam: true,
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 修改视频
|
||||
export function sourceUpdate(data) {
|
||||
return request({
|
||||
url: '/media/web/source/update',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
// 新增视频
|
||||
export function sourceAdd(data) {
|
||||
return request({
|
||||
url: '/media/web/source/add',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
// 视频上传
|
||||
export function videoBody(data) {
|
||||
return request({
|
||||
url: '/media/web/proxy/videoBody',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
// 视频上传成功
|
||||
export function videoOk(data) {
|
||||
return request({
|
||||
url: '/media/web/proxy/videoOk',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 删除视频
|
||||
export function taskDel(data) {
|
||||
return request({
|
||||
url: '/media/web/task/del',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 资源列表
|
||||
export function taskList(data) {
|
||||
return request({
|
||||
url: '/media/web/task/list',
|
||||
method: 'post',
|
||||
filterParam: true,
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 新增视频
|
||||
export function taskAdd(data) {
|
||||
return request({
|
||||
url: '/media/web/task/add',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
// 重新生成添加水印
|
||||
export function updateWaterMark(data) {
|
||||
return request({
|
||||
url: '/media/web/task/update/watermark',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
export function audioAdd(data) { // 音频新增
|
||||
return request({
|
||||
url: '/api/web/audio/add',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
export function audioDel(data) { // 音频新增
|
||||
return request({
|
||||
url: '/api/web/audio/del',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
export function audioList(data) { // 音频新增
|
||||
return request({
|
||||
url: '/api/web/audio/list',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
export function audioUpdate(data) { // 音频新增
|
||||
return request({
|
||||
url: '/api/web/audio/update',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* @Author:
|
||||
* @Mail:
|
||||
* @Date: 2022-03-11 17:20:20
|
||||
* @LastEditTime: 2022-06-06 17:45:03
|
||||
* @LastEditors: Please set LastEditors
|
||||
* @FilePath: /kkjm-web-admin/src/api/novels/novels.js
|
||||
*/
|
||||
import request from '@/utils/request'
|
||||
|
||||
export function novelsUpdate(data) {
|
||||
return request({
|
||||
url: '/api/web/novel/update',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function novelsAdd(data) {
|
||||
return request({
|
||||
url: '/api/web/novel/add',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function novelsDel(data) {
|
||||
return request({
|
||||
url: '/api/web/novel/del',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function novelsList(data) {
|
||||
return request({
|
||||
url: '/api/web/novel/list',
|
||||
method: 'post',
|
||||
filterParam: true,
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function novelsAddTopics(data) {
|
||||
return request({
|
||||
url: '/api/web/novel/addTopics',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function novelsNewOne(data) {
|
||||
return request({
|
||||
url: '/api/web/novel/newOne',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 添加评论
|
||||
export function novelsAddComment(data) {
|
||||
return request({
|
||||
url: '/api/web/novel/addComment',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 批量添加标签
|
||||
export function novelsAddTags(data) {
|
||||
return request({
|
||||
url: '/api/web/novel/addTags',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 获取最新章节和章节数不同的小说
|
||||
export function novelsGetNaN(data) {
|
||||
return request({
|
||||
url: '/api/web/novel/getNaN',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 更新所有主题小说数量
|
||||
export function novelsUpCTC(data) {
|
||||
return request({
|
||||
url: '/api/web/novel/upCTC',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 更新所有小说免费章节
|
||||
export function novelsUpNone(data) {
|
||||
return request({
|
||||
url: '/api/web/novel/upNone',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 更新小说状态
|
||||
export function novelsUpdNovelStatus(data) {
|
||||
return request({
|
||||
url: '/api/web/novel/updNovelStatus',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 更新小说状态
|
||||
export function novelsAddTxtNovel(data) {
|
||||
return request({
|
||||
url: '/api/web/novel/addTxtNovel',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
export function comicsCvUpdate(data) { // MDVlogCV更新
|
||||
return request({
|
||||
url: '/api/web/comicscv/update',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function comicsCvAdd(data) { // 画CV添加
|
||||
return request({
|
||||
url: '/api/web/comicscv/add',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function comicsCvDel(data) { // MDVlogCV删除
|
||||
return request({
|
||||
url: '/api/web/comicscv/del',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function comicsCvList(data) { // MDVlogCV列表
|
||||
return request({
|
||||
url: '/api/web/comicscv/list',
|
||||
method: 'post',
|
||||
filterParam: true,
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* @Author:
|
||||
* @Mail:
|
||||
* @Date: 2022-03-12 13:55:34
|
||||
* @LastEditTime: 2022-06-06 17:44:56
|
||||
* @LastEditors: Please set LastEditors
|
||||
* @FilePath: /kkjm-web-admin/src/api/novelsManagement/novelsChapter.js
|
||||
*/
|
||||
import request from '@/utils/request'
|
||||
|
||||
export function novelsChapterUpdate(data) {
|
||||
return request({
|
||||
url: '/api/web/novelChapter/update',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
export function novelsChapterAdd(data) {
|
||||
return request({
|
||||
url: '/api/web/novelChapter/add',
|
||||
method: 'post',
|
||||
data,
|
||||
timeout: 0
|
||||
})
|
||||
}
|
||||
export function novelsChapterDel(data) {
|
||||
return request({
|
||||
url: '/api/web/novelChapter/del',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
export function novelsChapterList(data) {
|
||||
return request({
|
||||
url: '/api/web/novelChapter/list',
|
||||
method: 'post',
|
||||
filterParam: true,
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 更新章节的小说id
|
||||
export function novelsChapterUpNovelId(data) {
|
||||
return request({
|
||||
url: '/api/web/novelChapter/upNovelId',
|
||||
method: 'post',
|
||||
filterParam: true,
|
||||
data
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* @Author:
|
||||
* @Mail:
|
||||
* @Date: 2022-03-12 14:41:19
|
||||
* @LastEditTime: 2022-06-06 17:45:21
|
||||
* @LastEditors: Please set LastEditors
|
||||
* @FilePath: /novels-admin/src/api/novelsManagement/novelsTag.js
|
||||
*/
|
||||
import request from '@/utils/request'
|
||||
|
||||
export function novelsTagUpdate(data) {
|
||||
return request({
|
||||
url: '/api/web/novelTag/update',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function novelsTagAdd(data) {
|
||||
return request({
|
||||
url: '/api/web/novelTag/add',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function novelsTagDel(data) {
|
||||
return request({
|
||||
url: '/api/web/novelTag/del',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function novelsTagList(data) {
|
||||
return request({
|
||||
url: '/api/web/novelTag/list',
|
||||
method: 'post',
|
||||
filterParam: true,
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function novelsTagList100(data) {
|
||||
return request({
|
||||
url: '/api/web/novelTag/tag100list',
|
||||
method: 'post',
|
||||
filterParam: true,
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* @Author:
|
||||
* @Mail:
|
||||
* @Date: 2022-03-11 20:53:58
|
||||
* @LastEditTime: 2024-04-09 20:01:48
|
||||
* @LastEditors: Administrator admin@example.com
|
||||
* @FilePath: /txsm_webAdmin/src/api/novelsManagement/novelsTopic.js
|
||||
*/
|
||||
import request from '@/utils/request'
|
||||
export function novelsTopicList(data) {
|
||||
return request({
|
||||
url: '/api/web/novelTopic/list',
|
||||
method: 'post',
|
||||
filterParam: true,
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function novelsLabelsList(data) {
|
||||
return request({
|
||||
url: '/api/web/novelTag/tag100list',
|
||||
method: 'post',
|
||||
filterParam: true,
|
||||
data
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
export function comicsmediaUpdate(data) { // MDVlog视频更新
|
||||
return request({
|
||||
url: '/api/web/comicsmedia/update',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function comicsmediaAdd(data) { // MDVlog视频添加
|
||||
return request({
|
||||
url: '/api/web/comicsmedia/add',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function comicsmediaDel(data) { // MDVlog视频删除
|
||||
return request({
|
||||
url: '/api/web/comicsmedia/del',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function comicsmediaList(data) { // MDVlog视频列表
|
||||
return request({
|
||||
url: '/api/web/comicsmedia/list',
|
||||
method: 'post',
|
||||
filterParam: true,
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
export function playletCategoryList(params) {
|
||||
return request({
|
||||
url: '/api/web/playlet/category/list',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
export function playletCategoryAdd(data) {
|
||||
return request({
|
||||
url: '/api/web/playlet/category/add',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function playletCategoryUpdate(data) {
|
||||
return request({
|
||||
url: '/api/web/playlet/category/update',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function playletCategoryDel(data) {
|
||||
return request({
|
||||
url: '/api/web/playlet/category/del',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
export function playletJiahuaList(params) {
|
||||
return request({
|
||||
url: '/api/web/resource/jh/list',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
export function playletJiahuaChapters(params) {
|
||||
return request({
|
||||
url: '/api/web/resource/jh/chapters',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
export function playletJiahuaImport(data) {
|
||||
return request({
|
||||
url: '/api/web/resource/jh/import',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,153 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
export function playletList(params) {
|
||||
return request({
|
||||
url: '/api/web/playlet/list',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
export function playletAdd(data) {
|
||||
return request({
|
||||
url: '/api/web/playlet/add',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function playletUpdate(data) {
|
||||
return request({
|
||||
url: '/api/web/playlet/update',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function playletStatusSet(data) {
|
||||
return request({
|
||||
url: '/api/web/playlet/status/set',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function playletRecommendSet(data) {
|
||||
return request({
|
||||
url: '/api/web/playlet/recommend/set',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function playletFeaturedSet(data) {
|
||||
return request({
|
||||
url: '/api/web/playlet/featured/set',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function playletOperateTypeSet(data) {
|
||||
return request({
|
||||
url: '/api/web/playlet/operate-type/set',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function playletThemeSet(data) {
|
||||
return request({
|
||||
url: '/api/web/playlet/theme/set',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function playletCategorySet(data) {
|
||||
return request({
|
||||
url: '/api/web/playlet/category/set',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function playletTagSet(data) {
|
||||
return request({
|
||||
url: '/api/web/playlet/tag/set',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function playletWatermarkReset(data) {
|
||||
return request({
|
||||
url: '/api/web/playlet/watermark/reset',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function playletVirtualLikeSet(data) {
|
||||
return request({
|
||||
url: '/api/web/playlet/like/virtual/set',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function playletBannerSet(data) {
|
||||
return request({
|
||||
url: '/api/web/playlet/banner/set',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function playletChapterList(params) {
|
||||
return request({
|
||||
url: '/api/web/playlet/chapter/list',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
export function playletChapterAdd(data) {
|
||||
return request({
|
||||
url: '/api/web/playlet/chapter/add',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function playletChapterUpdate(data) {
|
||||
return request({
|
||||
url: '/api/web/playlet/chapter/update',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function playletChapterPayTypeSet(data) {
|
||||
return request({
|
||||
url: '/api/web/playlet/chapter/pay-type/set',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function playletChapterDel(data) {
|
||||
return request({
|
||||
url: '/api/web/playlet/chapter/del',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function playletChapterSync(data) {
|
||||
return request({
|
||||
url: '/api/web/playlet/chapter/sync',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
export function playletResourceList(params) {
|
||||
return request({
|
||||
url: '/api/web/resource/list',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
export function playletResourceChapters(params) {
|
||||
return request({
|
||||
url: '/api/web/resource/chapters',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
export function playletResourceImport(data) {
|
||||
return request({
|
||||
url: '/api/web/resource/import',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
export function playletTagList(params) {
|
||||
return request({
|
||||
url: '/api/web/playlet/tag/list',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
export function playletTagAdd(data) {
|
||||
return request({
|
||||
url: '/api/web/playlet/tag/add',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function playletTagUpdate(data) {
|
||||
return request({
|
||||
url: '/api/web/playlet/tag/update',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function playletTagDel(data) {
|
||||
return request({
|
||||
url: '/api/web/playlet/tag/del',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
export function playletThemeList(params) {
|
||||
return request({
|
||||
url: '/api/web/playlet/theme/list',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
export function playletThemeAdd(data) {
|
||||
return request({
|
||||
url: '/api/web/playlet/theme/add',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function playletThemeUpdate(data) {
|
||||
return request({
|
||||
url: '/api/web/playlet/theme/update',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function playletThemeDel(data) {
|
||||
return request({
|
||||
url: '/api/web/playlet/theme/del',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
export function rechargePackageList(data) {
|
||||
return request({
|
||||
url: '/api/web/recharge/package/list',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function rechargeVipPackageList(data) {
|
||||
return request({
|
||||
url: '/api/web/recharge/package/vip/list',
|
||||
method: 'post',
|
||||
data: data || {}
|
||||
})
|
||||
}
|
||||
|
||||
export function rechargePackageAdd(data) {
|
||||
return request({
|
||||
url: '/api/web/recharge/package/add',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function rechargePackageUpdate(data) {
|
||||
return request({
|
||||
url: '/api/web/recharge/package/update',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function rechargePackageDel(data) {
|
||||
return request({
|
||||
url: '/api/web/recharge/package/del',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function rechargePackageStatusSet(data) {
|
||||
return request({
|
||||
url: '/api/web/recharge/package/status/set',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
export function announcementList(data) {
|
||||
return request({
|
||||
url: '/api/web/announcement/list',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function announcementAdd(data) {
|
||||
return request({
|
||||
url: '/api/web/announcement/add',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function announcementUpdate(data) {
|
||||
return request({
|
||||
url: '/api/web/announcement/update',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function announcementDel(data) {
|
||||
return request({
|
||||
url: '/api/web/announcement/del',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
export function contactusList(params) {
|
||||
return request({
|
||||
url: '/api/web/contactus/list',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
export function contactusHandle(data) {
|
||||
return request({
|
||||
url: '/api/web/contactus/handle',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
export function ipBlackAdd(data) { // 音频新增
|
||||
return request({
|
||||
url: '/api/web/ipblack/add',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
export function ipBlackDel(data) { // 音频新增
|
||||
return request({
|
||||
url: '/api/web/ipblack/del',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
export function ipBlackList(data) { // 音频新增
|
||||
return request({
|
||||
url: '/api/web/ipblack/list',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* @Author: 王涛
|
||||
* @Mail: no
|
||||
* @Date: 2020-10-04 14:54:35
|
||||
* @LastEditors: 江涛
|
||||
* @LastEditTime: 2021-03-12 20:17:59
|
||||
*/
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 操作日志
|
||||
export function accOps(data) {
|
||||
return request({
|
||||
url: '/api/web/acc/ops',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
// 媒资库操作日志
|
||||
export function mzkAccOps(data) {
|
||||
return request({
|
||||
url: '/media/web/acc/ops',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* @Author: 王涛
|
||||
* @Mail: no
|
||||
* @Date: 2020-10-06 01:01:28
|
||||
* @LastEditors: 江涛
|
||||
* @LastEditTime: 2021-03-23 22:03:06
|
||||
*/
|
||||
|
||||
import request from '@/utils/request'
|
||||
// 获取系统配置
|
||||
export function getSyscfg(data) {
|
||||
return request({
|
||||
url: '/api/web/syscfg/get',
|
||||
method: 'get',
|
||||
params: data
|
||||
})
|
||||
}
|
||||
|
||||
// 修改系统配置
|
||||
export function updateSyscfg(data) {
|
||||
return request({
|
||||
url: '/api/web/syscfg/update',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
export function coinTransList(data) {
|
||||
return request({
|
||||
url: '/api/web/coin/trans',
|
||||
method: 'post',
|
||||
filterParam: true,
|
||||
data
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
export function vipOrderList(data) {
|
||||
return request({
|
||||
url: '/api/web/card/order/list',
|
||||
method: 'post',
|
||||
filterParam: true,
|
||||
data
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 详情导航列表
|
||||
export function detailNavList(data) {
|
||||
return request({
|
||||
url: '/api/web/detailnav/list',
|
||||
method: 'post',
|
||||
filterParam: true,
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 新增详情导航
|
||||
export function detailNavAdd(data) {
|
||||
return request({
|
||||
url: '/api/web/detailnav/add',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 编辑详情导航
|
||||
export function detailNavUpdate(data) {
|
||||
return request({
|
||||
url: '/api/web/detailnav/update',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 删除详情导航
|
||||
export function detailNavDel(data) {
|
||||
return request({
|
||||
url: '/api/web/detailnav/del',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
export function homeBannerList(params) {
|
||||
return request({
|
||||
url: '/api/web/home/banner/list',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
export function homeBannerAdd(data) {
|
||||
return request({
|
||||
url: '/api/web/home/banner/add',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function homeBannerUpdate(data) {
|
||||
return request({
|
||||
url: '/api/web/home/banner/update',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function homeBannerDel(data) {
|
||||
return request({
|
||||
url: '/api/web/home/banner/del',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 热门导航配置-列表
|
||||
export function hotNavList(data) {
|
||||
return request({
|
||||
url: '/api/web/hotnav/list',
|
||||
method: 'post',
|
||||
filterParam: true,
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 热门导航配置-增加
|
||||
export function hotNavAdd(data) {
|
||||
return request({
|
||||
url: '/api/web/hotnav/add',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 热门导航配置-更新
|
||||
export function hotNavUpdate(data) {
|
||||
return request({
|
||||
url: '/api/web/hotnav/update',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 热门导航配置-删除
|
||||
export function hotNavDel(data) {
|
||||
return request({
|
||||
url: '/api/web/hotnav/del',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 删除视频
|
||||
export function translationDel(data) {
|
||||
return request({
|
||||
url: '/api/web/translation/del',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 视频列表
|
||||
export function translationSearch(data) {
|
||||
return request({
|
||||
url: '/api/web/translation/list',
|
||||
method: 'post',
|
||||
filterParam: true,
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 修改视频
|
||||
export function translationUpdate(data) {
|
||||
return request({
|
||||
url: '/api/web/translation/update',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 一键同步
|
||||
export function translationAdd(data) {
|
||||
return request({
|
||||
url: '/api/web/translation/add',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 删除视频
|
||||
export function translationcategoryDel(data) {
|
||||
return request({
|
||||
url: '/api/web/translationcategory/del',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 视频列表
|
||||
export function translationcategorySearch(data) {
|
||||
return request({
|
||||
url: '/api/web/translationcategory/list',
|
||||
method: 'post',
|
||||
filterParam: true,
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 修改视频
|
||||
export function translationcategoryUpdate(data) {
|
||||
return request({
|
||||
url: '/api/web/translationcategory/update',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 一键同步
|
||||
export function translationcategoryAdd(data) {
|
||||
return request({
|
||||
url: '/api/web/translationcategory/add',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
export function feedbackList(params) {
|
||||
return request({
|
||||
url: '/api/web/feedback/list',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
export function feedbackHandle(data) {
|
||||
return request({
|
||||
url: '/api/web/feedback/handle',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
export function getUserList(data) {
|
||||
return request({
|
||||
url: '/api/web/user/list',
|
||||
method: 'post',
|
||||
filterParam: true,
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function userUpdate(data) {
|
||||
return request({
|
||||
url: '/api/web/user/update',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function userVipUpdate(data) {
|
||||
return request({
|
||||
url: '/api/web/user/vip/update',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function userGiftCoin(data) {
|
||||
return request({
|
||||
url: '/api/web/user/giftcoin',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 封禁用户(评论管理等页面使用)
|
||||
export function userBan(data) {
|
||||
return request({
|
||||
url: '/api/web/user/ban',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 解封用户(兼容其他页面调用)
|
||||
export function userUnBan(data) {
|
||||
return userUpdate({
|
||||
id: data.userId,
|
||||
param: { status: 0 }
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* @Author:
|
||||
* @Mail:
|
||||
* @Date: 2023-07-14 12:00:29
|
||||
* @LastEditTime: 2023-07-14 16:08:07
|
||||
* @LastEditors: Please set LastEditors
|
||||
* @FilePath: /web-admin/src/api/userAnalysis/index.js
|
||||
*/
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 用户日活
|
||||
export function analyzeDau(data) {
|
||||
return request({
|
||||
url: '/api/web/analyze/dau',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 首充区间
|
||||
export function analyzeInterval(data) {
|
||||
return request({
|
||||
url: '/api/web/analyze/interval',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 二次消费
|
||||
export function analyzePurchase(data) {
|
||||
return request({
|
||||
url: '/api/web/analyze/purchase',
|
||||
method: 'post',
|
||||
filterParam: true,
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* @Author: 王涛
|
||||
* @Mail: no
|
||||
* @Date: 2020-10-05 14:44:43
|
||||
* @LastEditors: 江涛
|
||||
* @LastEditTime: 2021-03-24 11:39:15
|
||||
*/
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 请求视频enkey解密密钥
|
||||
export function videoFeviewList(params, urll) {
|
||||
return request({
|
||||
url: '/api/web/enkey',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
export function videoOk(data) {
|
||||
return request({
|
||||
url: '/media/web/upload/videoOk',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 随机选择指定条数
|
||||
export function commentLibSelect(data) {
|
||||
return request({
|
||||
url: '/api/web/post/comment/batch/add',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* @Author:
|
||||
* @Mail:
|
||||
* @Date: 2022-02-22 14:30:36
|
||||
* @LastEditTime: 2022-06-06 18:02:56
|
||||
* @LastEditors: Please set LastEditors
|
||||
* @FilePath: /comics-admin/src/api/videoManagement/commentManage.js
|
||||
*/
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 请求评论列表
|
||||
export function commentList(data) {
|
||||
return request({
|
||||
url: '/api/web/post/comment/list',
|
||||
method: 'post',
|
||||
filterParam: true,
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 删除评论
|
||||
export function commentDelete(data) {
|
||||
return request({
|
||||
url: '/api/web/post/comment/del',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 评论回复
|
||||
export function commentReply(data) {
|
||||
return request({
|
||||
url: '/api/web/post/comment/replay',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
// 删除所有评论
|
||||
export function commentDeluser(data) {
|
||||
return request({
|
||||
url: '/api/web/post/comment/user/del',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 评论审核
|
||||
export function commentReview(data) {
|
||||
return request({
|
||||
url: '/api/web/post/comment/review',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 评论批量审核
|
||||
export function commentReviewBatch(data) {
|
||||
return request({
|
||||
url: '/api/web/post/comment/reviewBatch',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 评论编辑/评论置顶
|
||||
export function commentUpdate(data) {
|
||||
return request({
|
||||
url: '/api/web/post/comment/update',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
export function dockingVideoTopicList(data) {
|
||||
return request({
|
||||
url: '/api/web/videotopic/list',
|
||||
method: 'post',
|
||||
filterParam: true,
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function dockingVideoTopicAdd(data) {
|
||||
return request({
|
||||
url: '/api/web/videotopic/add',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function dockingVideoTopicUpdate(data) {
|
||||
return request({
|
||||
url: '/api/web/videotopic/update',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function dockingVideoTopicDel(data) {
|
||||
return request({
|
||||
url: '/api/web/videotopic/del',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function dockingVideoTopicUpdateSlug(data) {
|
||||
return request({
|
||||
url: '/api/web/videotopic/updateslug',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* @Author:
|
||||
* @Mail:
|
||||
* @Date: 2022-03-14 15:25:07
|
||||
* @LastEditTime: 2022-06-06 18:03:01
|
||||
* @LastEditors:
|
||||
* @FilePath: /comics-admin/src/api/videoManagement/filterWord.js
|
||||
*/
|
||||
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 获取非法词列表
|
||||
export function getFilterList(data) {
|
||||
return request({
|
||||
url: 'api/web/filterword/list',
|
||||
method: 'post',
|
||||
filterParam: true,
|
||||
data
|
||||
})
|
||||
}
|
||||
// 删除非法词
|
||||
export function filterWordDel(data) {
|
||||
return request({
|
||||
url: '/api/web/filterword/del',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 新增非法词
|
||||
export function filterWordAdd(data) {
|
||||
return request({
|
||||
url: '/api/web/filterword/add',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 标签分类列表
|
||||
export function videoLabelList(data) {
|
||||
return request({
|
||||
url: '/api/web/videotagcategory/list',
|
||||
method: 'post',
|
||||
filterParam: true,
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 新增标签分类
|
||||
export function videoLabelAdd(data) {
|
||||
return request({
|
||||
url: '/api/web/videotagcategory/add',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
// 修改标签分类
|
||||
export function videoLabelUpdate(data) {
|
||||
return request({
|
||||
url: '/api/web/videotagcategory/update',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 删除标签分类
|
||||
export function videoLabelDel(data) {
|
||||
return request({
|
||||
url: '/api/web/videotagcategory/del',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* @Author:
|
||||
* @Mail:
|
||||
* @Date: 2022-07-21 19:49:58
|
||||
* @LastEditTime: 2023-02-22 10:33:20
|
||||
* @LastEditors: Please set LastEditors
|
||||
* @FilePath: /xd_web_admin/src/api/videoManagement/mdsqsyncMedia.js
|
||||
*/
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 快手视频列表
|
||||
export function mdsqsyncMediaSearch(data) {
|
||||
return request({
|
||||
url: '/api/web/mdsync/media/search',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 请求快手标签
|
||||
export function mdsqsyncMediatagSearch(data) {
|
||||
return request({
|
||||
url: '/api/web/mdsync/mediatag/list',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 请求快手分类
|
||||
export function mdsqsyncMediacategorySearch(data) {
|
||||
return request({
|
||||
url: '/api/web/mdsync/mediacategory/list',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 请求快手专题
|
||||
export function mdsqsyncTopicSearch(data) {
|
||||
return request({
|
||||
url: '/api/web/mdsync/topic/search',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 批量同步快手资源
|
||||
export function mdsqsyncSyncmedias(data) {
|
||||
return request({
|
||||
url: '/api/web/mdsync/syncmedias',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* @Author:
|
||||
* @Mail:
|
||||
* @Date: 2022-07-07 15:16:43
|
||||
* @LastEditTime: 2022-07-07 15:17:51
|
||||
* @LastEditors: Please set LastEditors
|
||||
* @FilePath: /web_admin/src/api/videoManagement/recommend.js
|
||||
*/
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 视频推荐列表
|
||||
export function recommendSeach(data) {
|
||||
return request({
|
||||
url: '/api/web/media/recommend/search',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 删除推荐视频
|
||||
export function recommendDel(data) {
|
||||
return request({
|
||||
url: '/api/web/media/recommend/del',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* @Author:
|
||||
* @Mail:
|
||||
* @Date: 2022-03-14 15:25:07
|
||||
* @LastEditTime: 2022-06-06 18:03:15
|
||||
* @LastEditors: Please set LastEditors
|
||||
* @FilePath: /comics-admin/src/api/videoManagement/recommendTopic.js
|
||||
*/
|
||||
|
||||
import request from '@/utils/request'
|
||||
|
||||
export function topicAdd(data) {
|
||||
return request({
|
||||
url: '/api/web/recommend/topic/add',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function topicDel(data) {
|
||||
return request({
|
||||
url: '/api/web/recommend/topic/del',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
export function topicList(data) {
|
||||
return request({
|
||||
url: '/api/web/recommend/topic/list',
|
||||
method: 'post',
|
||||
filterParam: true,
|
||||
data
|
||||
})
|
||||
}
|
||||
export function topicUpdate(data) {
|
||||
return request({
|
||||
url: '/api/web/recommend/topic/update',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* @Author:
|
||||
* @Mail:
|
||||
* @Date: 2022-07-21 19:49:58
|
||||
* @LastEditTime: 2023-02-22 10:33:20
|
||||
* @LastEditors: Please set LastEditors
|
||||
* @FilePath: /xd_web_admin/src/api/videoManagement/mdsqsyncMedia.js
|
||||
*/
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 快手视频列表
|
||||
export function kkjmsqsyncMediaSearch(data) {
|
||||
return request({
|
||||
url: '/api/web/kkjmsync/media/search',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 请求快手标签
|
||||
export function kkjmsqsyncMediatagSearch(data) {
|
||||
return request({
|
||||
url: '/api/web/kkjmsync/mediatag/list',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 请求快手分类
|
||||
export function kkjmsqsyncMediacategorySearch(data) {
|
||||
return request({
|
||||
url: '/api/web/kkjmsync/mediacategory/list',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 请求快手专题
|
||||
export function kkjmsqsyncTopicSearch(data) {
|
||||
return request({
|
||||
url: '/api/web/kkjmsync/topic/search',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 批量同步快手资源
|
||||
export function kkjmsqsyncSyncmedias(data) {
|
||||
return request({
|
||||
url: '/api/web/kkjmsync/syncmedias',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 删除视频
|
||||
export function videocategoryDel(data) {
|
||||
return request({
|
||||
url: '/api/web/videocategory/del',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 视频列表
|
||||
export function videocategorySearch(data) {
|
||||
return request({
|
||||
url: '/api/web/videocategory/list',
|
||||
method: 'post',
|
||||
filterParam: true,
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 修改视频
|
||||
export function videocategoryUpdate(data) {
|
||||
return request({
|
||||
url: '/api/web/videocategory/update',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 一键同步
|
||||
export function videocategoryAdd(data) {
|
||||
return request({
|
||||
url: '/api/web/videocategory/add',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
|
||||
import request from '@/utils/request'
|
||||
|
||||
export function videoinfoAdd(data) {
|
||||
return request({
|
||||
url: '/api/web/videoinfo/sync',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 删除视频
|
||||
export function videoinfoDel(data) {
|
||||
return request({
|
||||
url: '/api/web/videoinfo/del',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 视频列表
|
||||
export function videoinfoSearch(data) {
|
||||
return request({
|
||||
url: '/api/web/videoinfo/list',
|
||||
method: 'post',
|
||||
filterParam: true,
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 修改视频
|
||||
export function videoinfoUpdate(data) {
|
||||
return request({
|
||||
url: '/api/web/videoinfo/update',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 视频转H265
|
||||
export function videoinfoTranscode(data) {
|
||||
return request({
|
||||
url: '/api/web/videoinfo/transcode',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 修改视频
|
||||
export function videoBindPreview(data) {
|
||||
return request({
|
||||
url: '/api/web/videoinfo/bindpre',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* @Author:
|
||||
* @Mail:
|
||||
* @Date: 2022-01-21 16:55:02
|
||||
* @LastEditTime: 2022-08-09 21:30:33
|
||||
* @LastEditors: Please set LastEditors
|
||||
* @FilePath: /sq_web_admin/src/api/videoManagement/videoRank.js
|
||||
*/
|
||||
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 查询视频排行榜
|
||||
export function mediarankList(data) {
|
||||
return request({
|
||||
url: '/api/web/mediarank/list',
|
||||
method: 'post',
|
||||
filterParam: true,
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 删除视频排行榜
|
||||
export function mediarankDel(data) {
|
||||
return request({
|
||||
url: '/api/web/mediarank/del',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 添加一个视频排行榜
|
||||
export function mediarankAdd(data) {
|
||||
return request({
|
||||
url: '/api/web/mediarank/add',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
// 更新一个视频排行榜
|
||||
export function mediarankupdate(data) {
|
||||
return request({
|
||||
url: '/api/web/mediarank/update',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 删除视频
|
||||
export function videotopicDel(data) {
|
||||
return request({
|
||||
url: '/api/web/videotopic/del',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 视频列表
|
||||
export function videotopicSearch(data) {
|
||||
return request({
|
||||
url: '/api/web/videotopic/list',
|
||||
method: 'post',
|
||||
filterParam: true,
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 修改视频
|
||||
export function videotopicUpdate(data) {
|
||||
return request({
|
||||
url: '/api/web/videotopic/update',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 一键同步
|
||||
export function videotopicAdd(data) {
|
||||
return request({
|
||||
url: '/api/web/videotopic/add',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 修改合集内视频列表
|
||||
export function videocollectionOption(data) {
|
||||
return request({
|
||||
url: '/api/web/videocollection/media/option',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 获取合集视频列表
|
||||
export function videocollectionMediaList(data) {
|
||||
return request({
|
||||
url: '/api/web/videocollection/media/list',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
// 修改合集里的视频排序
|
||||
export function videocollectionMediaRank(data) {
|
||||
return request({
|
||||
url: '/api/web/videocollection/media/rank',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
// 新增合集
|
||||
export function addVideocollectionMedia(data) {
|
||||
return request({
|
||||
url: '/api/web/videoinfo/addcoll',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 删除视频作者
|
||||
export function videocreaterDel(data) {
|
||||
return request({
|
||||
url: '/api/web/videocreater/del',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 视频作者列表
|
||||
export function videocreaterSearch(data) {
|
||||
return request({
|
||||
url: '/api/web/videocreater/list',
|
||||
method: 'post',
|
||||
filterParam: true,
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 修改视频作者
|
||||
export function videocreaterUpdate(data) {
|
||||
return request({
|
||||
url: '/api/web/videocreater/update',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 一键同步
|
||||
export function videocreaterAdd(data) {
|
||||
return request({
|
||||
url: '/api/web/videocreater/add',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 视频标签列表
|
||||
export function videotagList(data) {
|
||||
return request({
|
||||
url: '/api/web/videotag/list',
|
||||
method: 'post',
|
||||
filterParam: true,
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 删除视频标签
|
||||
export function videotagDel(data) {
|
||||
return request({
|
||||
url: '/api/web/videotag/del',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 新增视频标签
|
||||
export function videotagAdd(data) {
|
||||
return request({
|
||||
url: '/api/web/videotag/add',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
// 更新视频标签
|
||||
export function videotagUpdate(data) {
|
||||
return request({
|
||||
url: '/api/web/videotag/update',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* @Author:
|
||||
* @Mail:
|
||||
* @Date: 2022-07-21 19:49:58
|
||||
* @LastEditTime: 2022-07-21 21:26:34
|
||||
* @LastEditors: Please set LastEditors
|
||||
* @FilePath: /xd_web_admin/src/api/videoManagement/zhsyncMedia.js
|
||||
*/
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 快手视频列表
|
||||
export function zhsyncMediaSearch(data) {
|
||||
return request({
|
||||
url: '/api/web/zhsync/media/search',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 请求快手标签
|
||||
export function zhsyncMediatagSearch(data) {
|
||||
return request({
|
||||
url: '/api/web/zhsync/mediatag/list',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 请求快手分类
|
||||
export function zhsyncMediacategorySearch(data) {
|
||||
return request({
|
||||
url: '/api/web/zhsync/mediacategory/list',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 请求快手专题
|
||||
export function zhsyncTopicSearch(data) {
|
||||
return request({
|
||||
url: '/api/web/zhsync/topic/search',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 批量同步快手资源
|
||||
export function zhsyncSyncmedias(data) {
|
||||
return request({
|
||||
url: '/api/web/zhsync/syncmedias',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 请求富文本列表
|
||||
export function richtextcontentList(data) {
|
||||
return request({
|
||||
url: '/api/web/richtextcontent/list',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 富文本更新更新
|
||||
export function richtextcontentUpdate(data) {
|
||||
return request({
|
||||
url: '/api/web/richtextcontent/update',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 新增富文本
|
||||
export function richtextcontentAdd(data) {
|
||||
return request({
|
||||
url: '/api/web/richtextcontent/add',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 删除富文本
|
||||
export function richtextcontentDel(data) {
|
||||
return request({
|
||||
url: '/api/web/richtextcontent/del',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
Executable
BIN
Binary file not shown.
|
After Width: | Height: | Size: 160 KiB |
Executable
BIN
Binary file not shown.
|
After Width: | Height: | Size: 96 KiB |
Executable
BIN
Binary file not shown.
|
After Width: | Height: | Size: 4.7 KiB |
File diff suppressed because one or more lines are too long
Binary file not shown.
|
After Width: | Height: | Size: 1.8 MiB |
Binary file not shown.
|
After Width: | Height: | Size: 328 B |
Executable
+94
@@ -0,0 +1,94 @@
|
||||
<!--
|
||||
* @Author: 王涛
|
||||
* @Mail: no
|
||||
* @Date: 2020-05-16 10:46:46
|
||||
* @LastEditors: 王涛
|
||||
* @LastEditTime: 2021-01-27 10:44:03
|
||||
-->
|
||||
<template>
|
||||
<el-breadcrumb class="app-breadcrumb" separator="/">
|
||||
<transition-group name="breadcrumb">
|
||||
<el-breadcrumb-item v-for="(item,index) in levelList" :key="item.path">
|
||||
<span
|
||||
v-if="item.redirect==='noRedirect'||index==levelList.length-1"
|
||||
class="no-redirect">{{ item.meta.title }}</span>
|
||||
<a v-else @click.prevent="handleLink(item)">{{ item.meta.title }}</a>
|
||||
</el-breadcrumb-item>
|
||||
</transition-group>
|
||||
</el-breadcrumb>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import pathToRegexp from 'path-to-regexp'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
levelList: null
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
$route(route) {
|
||||
// if you go to the redirect page, do not update the breadcrumbs
|
||||
if (route.path.startsWith('/redirect/')) {
|
||||
return
|
||||
}
|
||||
this.getBreadcrumb()
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getBreadcrumb()
|
||||
},
|
||||
methods: {
|
||||
getBreadcrumb() {
|
||||
// only show routes with meta.title
|
||||
const matched = this.$route.matched.filter(item => item.meta && item.meta.title)
|
||||
// const first = matched[0]
|
||||
|
||||
// if (!this.isDashboard(first)) {
|
||||
// matched = [{ path: '/promptPage', meta: { title: '首页' }}].concat(matched)
|
||||
// }
|
||||
|
||||
this.levelList = matched.filter(item => item.meta && item.meta.title && item.meta.breadcrumb !== false)
|
||||
},
|
||||
isDashboard(route) {
|
||||
const name = route && route.name
|
||||
if (!name) {
|
||||
return false
|
||||
}
|
||||
return name.trim().toLocaleLowerCase() === 'Home'.toLocaleLowerCase()
|
||||
},
|
||||
pathCompile(path) {
|
||||
// To solve this problem https://github.com/PanJiaChen/vue-element-admin/issues/561
|
||||
const { params } = this.$route
|
||||
var toPath = pathToRegexp.compile(path)
|
||||
return toPath(params)
|
||||
},
|
||||
handleLink(item) {
|
||||
const { redirect, path } = item
|
||||
if (redirect) {
|
||||
this.$router.push(redirect)
|
||||
return
|
||||
}
|
||||
this.$router.push(this.pathCompile(path))
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '@/styles/variables.scss';
|
||||
.app-breadcrumb.el-breadcrumb {
|
||||
display: inline-block;
|
||||
font-size: 12px;
|
||||
line-height: 50px;
|
||||
margin-left: 8px;
|
||||
|
||||
.no-redirect {
|
||||
color: $themeColor;
|
||||
cursor: text;
|
||||
font-weight: bold;
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Executable
+53
@@ -0,0 +1,53 @@
|
||||
<!--
|
||||
* @Author:
|
||||
* @Mail:
|
||||
* @Date: 2021-11-16 17:10:43
|
||||
* @LastEditTime: 2022-04-07 20:17:07
|
||||
* @LastEditors: Please set LastEditors
|
||||
* @FilePath: /comics-admin/src/components/Hamburger/index.vue
|
||||
-->
|
||||
<template>
|
||||
<div style="padding: 0 15px" @click="toggleClick">
|
||||
<svg :class="{'is-active':isActive}" class="hamburger" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" width="64" height="64">
|
||||
<path d="M408 442h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm-8 204c0 4.4 3.6 8 8 8h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56zm504-486H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0 632H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zM142.4 642.1L298.7 519a8.84 8.84 0 0 0 0-13.9L142.4 381.9c-5.8-4.6-14.4-.5-14.4 6.9v246.3a8.9 8.9 0 0 0 14.4 7z" />
|
||||
</svg>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import variables from '@/styles/variables.scss'
|
||||
export default {
|
||||
name: 'Hamburger',
|
||||
props: {
|
||||
isActive: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
variables() {
|
||||
return variables
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
toggleClick() {
|
||||
this.$emit('toggleClick')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.hamburger {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background-color: #fff;
|
||||
|
||||
}
|
||||
|
||||
.hamburger.is-active {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
</style>
|
||||
Executable
+180
@@ -0,0 +1,180 @@
|
||||
<template>
|
||||
<div :class="{'show':show}" class="header-search">
|
||||
<svg-icon class-name="search-icon" icon-class="search" @click.stop="click" />
|
||||
<el-select ref="headerSearchSelect" v-model="search" :remote-method="querySearch" filterable default-first-option remote placeholder="Search" class="header-search-select" @change="change">
|
||||
<el-option v-for="item in options" :key="item.path" :value="item" :label="item.title.join(' > ')" />
|
||||
</el-select>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// fuse is a lightweight fuzzy-search module
|
||||
// make search results more in line with expectations
|
||||
import Fuse from 'fuse.js'
|
||||
import path from 'path'
|
||||
|
||||
export default {
|
||||
name: 'HeaderSearch',
|
||||
data() {
|
||||
return {
|
||||
search: '',
|
||||
options: [],
|
||||
searchPool: [],
|
||||
show: false,
|
||||
fuse: undefined
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
routes() {
|
||||
return this.$store.getters.permission_routes
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
routes() {
|
||||
this.searchPool = this.generateRoutes(this.routes)
|
||||
},
|
||||
searchPool(list) {
|
||||
this.initFuse(list)
|
||||
},
|
||||
show(value) {
|
||||
if (value) {
|
||||
document.body.addEventListener('click', this.close)
|
||||
} else {
|
||||
document.body.removeEventListener('click', this.close)
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.searchPool = this.generateRoutes(this.routes)
|
||||
},
|
||||
methods: {
|
||||
click() {
|
||||
this.show = !this.show
|
||||
if (this.show) {
|
||||
this.$refs.headerSearchSelect && this.$refs.headerSearchSelect.focus()
|
||||
}
|
||||
},
|
||||
close() {
|
||||
this.$refs.headerSearchSelect && this.$refs.headerSearchSelect.blur()
|
||||
this.options = []
|
||||
this.show = false
|
||||
},
|
||||
change(val) {
|
||||
this.$router.push(val.path)
|
||||
this.search = ''
|
||||
this.options = []
|
||||
this.$nextTick(() => {
|
||||
this.show = false
|
||||
})
|
||||
},
|
||||
initFuse(list) {
|
||||
this.fuse = new Fuse(list, {
|
||||
shouldSort: true, // 是否按分数对结果列表排序
|
||||
threshold: 0.4, // 匹配算法阀值,阀值为0时需完全匹配,1为完全不匹配
|
||||
location: 0, // 确定文本中预期找到的模式的大致位置
|
||||
distance: 100,
|
||||
maxPatternLength: 32, // 模式的最大长度
|
||||
minMatchCharLength: 1, // 模式的最小字符长度
|
||||
keys: [
|
||||
{
|
||||
// 搜索标题与路径
|
||||
name: 'title',
|
||||
weight: 0.7
|
||||
},
|
||||
{
|
||||
name: 'path',
|
||||
weight: 0.3
|
||||
}
|
||||
]
|
||||
})
|
||||
},
|
||||
// Filter out the routes that can be displayed in the sidebar
|
||||
// And generate the internationalized title
|
||||
generateRoutes(routes, basePath = '/', prefixTitle = []) {
|
||||
let res = []
|
||||
|
||||
for (const router of routes) {
|
||||
// skip hidden router
|
||||
if (router.hidden) {
|
||||
continue
|
||||
}
|
||||
|
||||
const data = {
|
||||
path: path.resolve(basePath, router.path),
|
||||
title: [...prefixTitle]
|
||||
}
|
||||
|
||||
if (router.meta && router.meta.title) {
|
||||
data.title = [...data.title, router.meta.title]
|
||||
|
||||
if (router.redirect !== 'noRedirect') {
|
||||
// only push the routes with title
|
||||
// special case: need to exclude parent router without redirect
|
||||
res.push(data)
|
||||
}
|
||||
}
|
||||
|
||||
// recursive child routes
|
||||
if (router.children) {
|
||||
const tempRoutes = this.generateRoutes(
|
||||
router.children,
|
||||
data.path,
|
||||
data.title
|
||||
)
|
||||
if (tempRoutes.length >= 1) {
|
||||
res = [...res, ...tempRoutes]
|
||||
}
|
||||
}
|
||||
}
|
||||
return res
|
||||
},
|
||||
querySearch(query) {
|
||||
if (query !== '') {
|
||||
this.options = this.fuse.search(query)
|
||||
} else {
|
||||
this.options = []
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.header-search {
|
||||
font-size: 0 !important;
|
||||
|
||||
.search-icon {
|
||||
cursor: pointer;
|
||||
font-size: 18px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.header-search-select {
|
||||
font-size: 18px;
|
||||
transition: width 0.2s;
|
||||
width: 0;
|
||||
overflow: hidden;
|
||||
background: transparent;
|
||||
border-radius: 0;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
|
||||
::v-deep .el-input__inner {
|
||||
border-radius: 0;
|
||||
border: 0;
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
box-shadow: none !important;
|
||||
border-bottom: 1px solid #d9d9d9;
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
|
||||
&.show {
|
||||
.header-search-select {
|
||||
width: 210px;
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,373 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
:visible.sync="Visible"
|
||||
@close="close"
|
||||
center
|
||||
class="ac-dialog"
|
||||
width="390px">
|
||||
<div class="itemData-main">
|
||||
<header class="header">
|
||||
<div class="title">{{ itemData.title }}</div>
|
||||
<div class="info">
|
||||
<a>{{ itemData.creatorName }} •</a>
|
||||
{{ itemData.addedTime | BeiJingTime }}
|
||||
<span v-for="(item, index) in itemData.categoryIds" :key="item">{{ item |
|
||||
changeCategoryName(videoCategoryList)
|
||||
}} <span v-if="index !== itemData.categoryIds.length - 1">•</span> </span>
|
||||
</div>
|
||||
</header>
|
||||
<div class="postContent">
|
||||
<div class="postBox" v-for="(item, index) in itemData.nodes" :key="index">
|
||||
<p class="postTitle">{{ item.title }}</p>
|
||||
<ShowImg v-for="(img, imgINdex) in item.images" :key="imgINdex" :urls="img" />
|
||||
<span class="postText">{{ item.text }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<DPlayer
|
||||
ref="player"
|
||||
class="dplayerBox"
|
||||
v-if="itemData.video && itemData.video.url"
|
||||
:video="{
|
||||
url: '/api/web/m3u8/' + filterM3u8(itemData.video.url),
|
||||
type: 'hls',
|
||||
pic: '',
|
||||
}"
|
||||
hotkey></DPlayer>
|
||||
<div class="keywords">
|
||||
关键词:
|
||||
<span v-for="(keyName,keyIndex) in itemData.keyworld" :key="keyIndex">#{{keyName}} </span>
|
||||
</div>
|
||||
<div class="tagBox">
|
||||
<p class="tagList" v-for="(tag,tagIndex) in itemData.tags" :key="tagIndex">
|
||||
<span class="tagItem">{{tag | changeCategoryName(videoTagList)}}</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</template>
|
||||
<script>
|
||||
import ShowImg from '@/components/ShowImg/index.vue'
|
||||
import DPlayer from '@/components/VueDplayerHls/index.vue'
|
||||
|
||||
export default {
|
||||
props: ['itemData', 'videoCategoryList', 'videoTagList'],
|
||||
components: {
|
||||
ShowImg,
|
||||
DPlayer
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
Visible: true
|
||||
}
|
||||
},
|
||||
async mounted() {
|
||||
|
||||
},
|
||||
filters: {
|
||||
changeCategoryName(v, list) {
|
||||
let arr = []
|
||||
if (v) {
|
||||
arr = list.filter(item => {
|
||||
return item.id === v
|
||||
})
|
||||
if (arr[0]) {
|
||||
return arr[0].name
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
||||
},
|
||||
methods: {
|
||||
filterM3u8(v) {
|
||||
return /\.m3u8/g.test(v) ? v : v + '.m3u8'
|
||||
},
|
||||
// 关闭编辑
|
||||
close() {
|
||||
this.$emit('close', false)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang='scss' scoped>
|
||||
.ac-dialog{
|
||||
overflow: hidden;
|
||||
::v-deep{
|
||||
.el-dialog{
|
||||
margin-top: 10px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
.itemData-main {
|
||||
/* rem适配基础设置 */
|
||||
font-size: 16px;
|
||||
/* 基准字体大小 */
|
||||
background: #000;
|
||||
color: #fff;
|
||||
height: 844px;
|
||||
overflow-y: scroll;
|
||||
padding: 10px;
|
||||
|
||||
a,
|
||||
a:link,
|
||||
a:visited,
|
||||
a:hover,
|
||||
a:active {
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.topBox {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 8px 16px;
|
||||
background: #212121;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
z-index: 99;
|
||||
/* display: none; */
|
||||
}
|
||||
|
||||
.navBtn {
|
||||
width: 51px;
|
||||
height: 24px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 10px;
|
||||
color: #E0E0E0;
|
||||
border-radius: 6px;
|
||||
background: rgba(255, 255, 255, 0.10);
|
||||
}
|
||||
|
||||
.navBtn .moreIcon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin-right: 3px;
|
||||
}
|
||||
|
||||
.logo {
|
||||
width: 94px;
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
.searchIcon {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
margin-left: 27px;
|
||||
}
|
||||
|
||||
.header {
|
||||
width: 100%;
|
||||
/* height: 159px; */
|
||||
background: #212121;
|
||||
padding: 12px 16px;
|
||||
box-sizing: border-box;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.header .title {
|
||||
text-align: center;
|
||||
color: #BDBDBD;
|
||||
font-size: 26px;
|
||||
line-height: 32px;
|
||||
margin-bottom: 14px;
|
||||
}
|
||||
|
||||
.header .info {
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
color: rgba(255, 255, 255, 0.70);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 3;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.header .info a {
|
||||
text-decoration-line: underline;
|
||||
}
|
||||
|
||||
.main .lineBox {
|
||||
padding: 0 16px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.main .lineBox .line {
|
||||
width: 100%;
|
||||
height: 1px;
|
||||
background: rgba(255, 255, 255, 0.10);
|
||||
margin: 18px 0;
|
||||
}
|
||||
|
||||
.postContent {
|
||||
margin: 36px 0 0;
|
||||
}
|
||||
|
||||
.postBox {
|
||||
color: #FAFAFA;
|
||||
/* margin-bottom: 18px; */
|
||||
}
|
||||
|
||||
.postTitle {
|
||||
font-size: 24px;
|
||||
font-weight: 600;
|
||||
line-height: 32px;
|
||||
margin-bottom: 28px;
|
||||
padding: 0 16px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.postText {
|
||||
color: #FAFAFA;
|
||||
margin: 0 16px 36px;
|
||||
font-size: 16px;
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
.postimage {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
margin-bottom: 18px;
|
||||
/* margin-bottom: 47px; */
|
||||
}
|
||||
|
||||
.postDesc {
|
||||
font-size: 16px;
|
||||
color: #FAFAFA;
|
||||
line-height: 22px;
|
||||
padding: 0 16px;
|
||||
box-sizing: border-box;
|
||||
margin-bottom: 19px;
|
||||
}
|
||||
|
||||
.postDesc span {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.postLine {
|
||||
margin: 0 16px;
|
||||
border-bottom: 1px dashed rgba(255, 255, 255, 0.50);
|
||||
}
|
||||
|
||||
.tagBox {
|
||||
margin-bottom: 12px;
|
||||
padding: 0 16px;
|
||||
}
|
||||
|
||||
.tagBox .tagList {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
gap: 7px;
|
||||
margin-bottom: 18px;
|
||||
}
|
||||
|
||||
.tagBox .tagList .tagItem {
|
||||
padding: 8px 16px;
|
||||
box-sizing: border-box;
|
||||
border-radius: 62px;
|
||||
background: rgba(255, 255, 255, 0.05);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 12px;
|
||||
color: #BDBDBD;
|
||||
}
|
||||
|
||||
.lastDay {
|
||||
text-align: right;
|
||||
color: #BDBDBD;
|
||||
line-height: 20px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.copyBox {
|
||||
color: #FFF;
|
||||
text-align: center;
|
||||
text-shadow: 0 0 20px #FF8400, 0 0 20px #FF8400;
|
||||
font-family: "PingFang SC";
|
||||
font-size: 20px;
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
line-height: 28px;
|
||||
/* 140% */
|
||||
padding: 18px;
|
||||
box-sizing: border-box;
|
||||
margin-bottom: 18px;
|
||||
}
|
||||
|
||||
.copySuccess {
|
||||
color: #FFF;
|
||||
text-align: center;
|
||||
text-shadow: 0 0 20px #FF00B2, 0 0 20px #FF00B2;
|
||||
font-family: "PingFang SC";
|
||||
font-size: 20px;
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
line-height: 28px;
|
||||
/* 140% */
|
||||
padding: 18px;
|
||||
box-sizing: border-box;
|
||||
margin-bottom: 18px;
|
||||
}
|
||||
|
||||
.dplayerBox {
|
||||
margin-bottom: 18px;
|
||||
max-height: 300px;
|
||||
}
|
||||
|
||||
.gridAdvBox {
|
||||
margin: 0 16px 18px;
|
||||
}
|
||||
|
||||
.gridAdvBox .gridAdvTitle {
|
||||
padding: 0 16px;
|
||||
box-sizing: border-box;
|
||||
height: 49px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-top: 1px solid rgba(255, 255, 255, 0.10);
|
||||
background: rgba(255, 255, 255, 0.05);
|
||||
font-size: 18px;
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
line-height: 24px;
|
||||
}
|
||||
|
||||
.keywords {
|
||||
box-sizing: border-box;
|
||||
font-size: 16px;
|
||||
line-height: 22px;
|
||||
color: #BDBDBD;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 768px) {
|
||||
|
||||
/* body {
|
||||
margin-top: 140px;
|
||||
} */
|
||||
body main {
|
||||
max-width: 720px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.header {
|
||||
max-width: 720px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.topBox {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,264 @@
|
||||
<!--
|
||||
* @Author:
|
||||
* @Mail:
|
||||
* @Date: 2021-11-13 14:46:20
|
||||
* @LastEditTime: 2023-01-02 19:27:36
|
||||
* @LastEditors: Please set LastEditors
|
||||
* @FilePath: /web_admin/src/components/QuillEditor/index.vue
|
||||
-->
|
||||
<template>
|
||||
<div>
|
||||
<quill-editor
|
||||
v-model="content"
|
||||
ref="myQuillEditor"
|
||||
:options="editorOption"
|
||||
@ready="onEditorReady($event)"></quill-editor>
|
||||
<!-- el-uploader不好手动触发上传功能 -->
|
||||
<uploader
|
||||
:style="{ display: 'none' }"
|
||||
:options="{ ...options, target: '/api/web/file/uploadImg' }"
|
||||
class="uploader-example"
|
||||
@file-success="imageSuccess">
|
||||
<uploader-drop>
|
||||
<uploader-btn ref="editorUploadImg" :attrs="attrsImg"></uploader-btn>
|
||||
</uploader-drop>
|
||||
</uploader>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { handleVerAutoImg } from '@/utils/index.js'
|
||||
import 'quill/dist/quill.core.css'
|
||||
import 'quill/dist/quill.snow.css'
|
||||
import 'quill/dist/quill.bubble.css'
|
||||
import Quill from 'quill'
|
||||
const Link = Quill.import('formats/link')
|
||||
Link.PROTOCOL_WHITELIST = ['http', 'https', 'mailto', 'tel', 'yinseinner', 'blob']
|
||||
import { quillEditor } from 'vue-quill-editor'
|
||||
import { ImageDrop } from 'quill-image-drop-module'
|
||||
import ImageResize from 'quill-image-resize-module'
|
||||
Quill.register('modules/imageDrop', ImageDrop)
|
||||
Quill.register('modules/imageResize', ImageResize)
|
||||
|
||||
// Quill 默认 Image.sanitize 只允许 http/https/data,解密后的 blob: 会被清成 //:0
|
||||
const ImageFormat = Quill.import('formats/image')
|
||||
const originalImageSanitize = ImageFormat.sanitize
|
||||
ImageFormat.sanitize = function(url) {
|
||||
if (url && typeof url === 'string' && url.indexOf('blob:') === 0) {
|
||||
return url
|
||||
}
|
||||
return originalImageSanitize.call(this, url)
|
||||
}
|
||||
Quill.register(ImageFormat, true)
|
||||
|
||||
// 自定义字体类型
|
||||
var fonts = ['SimSun', 'SimHei', 'Microsoft-YaHei', 'KaiTi', 'FangSong', 'Arial', 'Times-New-Roman', 'sans-serif']
|
||||
var Font = Quill.import('formats/font')
|
||||
Font.whitelist = fonts // 将字体加入到白名单
|
||||
Quill.register(Font, true)
|
||||
|
||||
export default {
|
||||
name: 'Editor',
|
||||
components: {
|
||||
quillEditor
|
||||
},
|
||||
props: {
|
||||
textNode: {
|
||||
default: ''
|
||||
}
|
||||
|
||||
},
|
||||
computed: {
|
||||
currentDomain() {
|
||||
return this.domain || this.$store.getters.getSystemConfig.imgWebCdn || ''
|
||||
},
|
||||
options() {
|
||||
return {
|
||||
chunkSize: 1024 * 1024 * 30, // 切片大小
|
||||
method: 'application/json',
|
||||
testChunks: false,
|
||||
allowDuplicateUploads: false, // 是否可以重复选择
|
||||
query: {},
|
||||
singleFile: false, // 是否只能选择单项
|
||||
headers: {
|
||||
Authorization: this.$store.getters.token
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
const _that = this
|
||||
return {
|
||||
content: '',
|
||||
imgPath: [],
|
||||
domain: this.$store.getters.getSystemConfig.imgWebCdn, // 不能暴露源站地址
|
||||
attrsImg: {
|
||||
accept: ['image/*']
|
||||
},
|
||||
trackId: undefined,
|
||||
editorOption: {
|
||||
placeholder: '请输入帖子内容',
|
||||
modules: {
|
||||
toolbar: {
|
||||
container: [
|
||||
['bold', 'italic', 'underline', 'strike'], // toggled buttons
|
||||
['blockquote', 'code-block'],
|
||||
|
||||
[{ header: 1 }, { header: 2 }], // custom button values
|
||||
[{ list: 'ordered' }, { list: 'bullet' }],
|
||||
[{ script: 'sub' }, { script: 'super' }], // superscript/subscript
|
||||
[{ indent: '-1' }, { indent: '+1' }], // outdent/indent
|
||||
[{ direction: 'rtl' }], // text direction
|
||||
|
||||
[{ size: ['small', false, 'large', 'huge'] }], // custom dropdown
|
||||
[{ header: [1, 2, 3, 4, 5, 6, false] }],
|
||||
|
||||
[{ color: [] }, { background: [] }], // dropdown with defaults from theme
|
||||
[{ font: [] }],
|
||||
[{ align: [] }],
|
||||
['link', 'image'],
|
||||
['clean']
|
||||
],
|
||||
handlers: {
|
||||
// 自定义上传图片
|
||||
image: value => {
|
||||
_that.$refs.editorUploadImg.$el.childNodes[0].click()
|
||||
}
|
||||
}
|
||||
},
|
||||
// //配置富文本框图片大小调整功能
|
||||
imageDrop: true,
|
||||
imageResize: {
|
||||
displayStyles: {
|
||||
backgroundColor: 'black',
|
||||
border: 'none',
|
||||
color: 'white'
|
||||
},
|
||||
modules: ['Resize', 'DisplaySize', 'Toolbar']
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// 暂存图片base64
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
// 与 ShowImg.buildImageUrl 保持一致
|
||||
buildImageUrl(path) {
|
||||
if (!path) return ''
|
||||
if (/^(blob:|https?:\/\/|data:)/.test(path)) return path
|
||||
const base = this.currentDomain || ''
|
||||
if (!base) return path
|
||||
const normalizedBase = base.endsWith('/') ? base.slice(0, -1) : base
|
||||
const normalizedPath = path.startsWith('/') ? path : `/${path}`
|
||||
return `${normalizedBase}${normalizedPath}`
|
||||
},
|
||||
/**
|
||||
* 回显:先粘贴原始 HTML,再按 ShowImg 方式逐张解密并写回 DOM
|
||||
*/
|
||||
async pasteAndDecryptImages(html) {
|
||||
const sourceHtml = html || ''
|
||||
if (!this.$refs.myQuillEditor || !this.$refs.myQuillEditor.quill) return
|
||||
const myeditor = this.$refs.myQuillEditor.quill
|
||||
myeditor.setContents([])
|
||||
if (sourceHtml) {
|
||||
myeditor.clipboard.dangerouslyPasteHTML(0, sourceHtml)
|
||||
}
|
||||
|
||||
const imgNodes = Array.from(myeditor.container.querySelectorAll('img'))
|
||||
for (const node of imgNodes) {
|
||||
// 已有 data-custom 说明业务侧已解密过,src 已是 blob
|
||||
const existingCustom = node.getAttribute('data-custom')
|
||||
if (existingCustom) continue
|
||||
|
||||
const originalSrc = node.getAttribute('src')
|
||||
if (!originalSrc || /^(blob:|data:)/.test(originalSrc)) continue
|
||||
|
||||
try {
|
||||
const blobUrl = await handleVerAutoImg(this.buildImageUrl(originalSrc))
|
||||
if (blobUrl) {
|
||||
node.setAttribute('data-custom', originalSrc)
|
||||
node.setAttribute('src', blobUrl)
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('富文本图片解密失败:', originalSrc, e)
|
||||
}
|
||||
}
|
||||
this.content = myeditor.root.innerHTML
|
||||
},
|
||||
getdata() {
|
||||
const myeditor = this.$refs.myQuillEditor.quill
|
||||
|
||||
// 找到所有包含 data-custom 属性的 img 标签
|
||||
const imgNodes = myeditor.container.querySelectorAll('img[data-custom]')
|
||||
imgNodes.forEach((node) => {
|
||||
const dataCustomValue = node.getAttribute('data-custom') // 获取 data-custom 的值
|
||||
// 交换 src 和 data-custom 的值
|
||||
node.setAttribute('src', dataCustomValue)
|
||||
node.removeAttribute('data-custom') // 删除 data-custom 属性
|
||||
})
|
||||
|
||||
// 检查内容是否为空
|
||||
if (this.content === '<p><br></p>' || this.content.trim() === '') {
|
||||
this.content = '' // 将内容设置为空字符串
|
||||
} else {
|
||||
// 直接更新 this.content 中的内容
|
||||
this.content = myeditor.root.innerHTML // 获取编辑器内容
|
||||
}
|
||||
return this.content
|
||||
},
|
||||
onEditorReady() {
|
||||
if (!this.textNode) return
|
||||
this.pasteAndDecryptImages(this.textNode)
|
||||
},
|
||||
extractImageSources(htmlString) {
|
||||
const imgSrcRegex = /<img[^>]+src="([^">]+)"/g
|
||||
const srcArray = []
|
||||
let match
|
||||
|
||||
while ((match = imgSrcRegex.exec(htmlString)) !== null) {
|
||||
srcArray.push(match[1])
|
||||
}
|
||||
return srcArray
|
||||
},
|
||||
imageSuccess(rootFile, file, message) {
|
||||
const { code, data } = JSON.parse(message)
|
||||
if (code === 200) {
|
||||
const reader = new FileReader()
|
||||
|
||||
reader.onload = (e) => {
|
||||
const base64Data = e.target.result // 获取转换后的 Data URL
|
||||
|
||||
const myeditor = this.$refs.myQuillEditor.quill
|
||||
const index = myeditor.getSelection().index
|
||||
|
||||
// 插入图片
|
||||
myeditor.insertEmbed(index, 'image', base64Data)
|
||||
|
||||
// 使用 setTimeout 确保 DOM 更新
|
||||
setTimeout(() => {
|
||||
// 查找插入的 img 元素
|
||||
const imgNode = myeditor.container.querySelector(`img[src="${base64Data}"]`)
|
||||
if (imgNode) {
|
||||
imgNode.setAttribute('data-custom', data.path) // 设置自定义属性
|
||||
} else {
|
||||
console.log('Image not found in the DOM') // 调试信息
|
||||
}
|
||||
}, 0)
|
||||
// 设置光标位置
|
||||
myeditor.setSelection(index + 1)
|
||||
}
|
||||
|
||||
// 读取 Blob 数据
|
||||
reader.readAsDataURL(file.file)
|
||||
}
|
||||
},
|
||||
|
||||
clearInput() {
|
||||
this.value = ''
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
Executable
+145
@@ -0,0 +1,145 @@
|
||||
<template>
|
||||
<div ref="rightPanel" :class="{show:show}" class="rightPanel-container">
|
||||
<div class="rightPanel-background" />
|
||||
<div class="rightPanel">
|
||||
<div class="handle-button" :style="{'top':buttonTop+'px','background-color':theme}" @click="show=!show">
|
||||
<i :class="show?'el-icon-close':'el-icon-setting'" />
|
||||
</div>
|
||||
<div class="rightPanel-items">
|
||||
<slot />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { addClass, removeClass } from '@/utils'
|
||||
|
||||
export default {
|
||||
name: 'RightPanel',
|
||||
props: {
|
||||
clickNotClose: {
|
||||
default: false,
|
||||
type: Boolean
|
||||
},
|
||||
buttonTop: {
|
||||
default: 250,
|
||||
type: Number
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
show: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
theme() {
|
||||
return this.$store.state.settings.theme
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
show(value) {
|
||||
if (value && !this.clickNotClose) {
|
||||
this.addEventClick()
|
||||
}
|
||||
if (value) {
|
||||
addClass(document.body, 'showRightPanel')
|
||||
} else {
|
||||
removeClass(document.body, 'showRightPanel')
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.insertToBody()
|
||||
},
|
||||
beforeDestroy() {
|
||||
const elx = this.$refs.rightPanel
|
||||
elx.remove()
|
||||
},
|
||||
methods: {
|
||||
addEventClick() {
|
||||
window.addEventListener('click', this.closeSidebar)
|
||||
},
|
||||
closeSidebar(evt) {
|
||||
const parent = evt.target.closest('.rightPanel')
|
||||
if (!parent) {
|
||||
this.show = false
|
||||
window.removeEventListener('click', this.closeSidebar)
|
||||
}
|
||||
},
|
||||
insertToBody() {
|
||||
const elx = this.$refs.rightPanel
|
||||
const body = document.querySelector('body')
|
||||
body.insertBefore(elx, body.firstChild)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.showRightPanel {
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
width: calc(100% - 15px);
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.rightPanel-background {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
opacity: 0;
|
||||
transition: opacity .3s cubic-bezier(.7, .3, .1, 1);
|
||||
background: rgba(0, 0, 0, .2);
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
.rightPanel {
|
||||
width: 100%;
|
||||
max-width: 260px;
|
||||
height: 100vh;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 0;
|
||||
box-shadow: 0px 0px 15px 0px rgba(0, 0, 0, .05);
|
||||
transition: all .25s cubic-bezier(.7, .3, .1, 1);
|
||||
transform: translate(100%);
|
||||
background: #fff;
|
||||
z-index: 40000;
|
||||
}
|
||||
|
||||
.show {
|
||||
transition: all .3s cubic-bezier(.7, .3, .1, 1);
|
||||
|
||||
.rightPanel-background {
|
||||
z-index: 20000;
|
||||
opacity: 1;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.rightPanel {
|
||||
transform: translate(0);
|
||||
}
|
||||
}
|
||||
|
||||
.handle-button {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
position: absolute;
|
||||
left: -48px;
|
||||
text-align: center;
|
||||
font-size: 24px;
|
||||
border-radius: 6px 0 0 6px !important;
|
||||
z-index: 0;
|
||||
pointer-events: auto;
|
||||
cursor: pointer;
|
||||
color: #fff;
|
||||
line-height: 48px;
|
||||
i {
|
||||
font-size: 24px;
|
||||
line-height: 48px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Executable
+60
@@ -0,0 +1,60 @@
|
||||
<template>
|
||||
<div>
|
||||
<svg-icon :icon-class="isFullscreen?'exit-fullscreen':'fullscreen'" @click="click" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import screenfull from 'screenfull'
|
||||
|
||||
export default {
|
||||
name: 'Screenfull',
|
||||
data() {
|
||||
return {
|
||||
isFullscreen: false
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.init()
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.destroy()
|
||||
},
|
||||
methods: {
|
||||
click() {
|
||||
if (!screenfull.enabled) {
|
||||
this.$message({
|
||||
message: 'you browser can not work',
|
||||
type: 'warning'
|
||||
})
|
||||
return false
|
||||
}
|
||||
screenfull.toggle()
|
||||
},
|
||||
change() {
|
||||
this.isFullscreen = screenfull.isFullscreen
|
||||
},
|
||||
init() {
|
||||
if (screenfull.enabled) {
|
||||
screenfull.on('change', this.change)
|
||||
}
|
||||
},
|
||||
destroy() {
|
||||
if (screenfull.enabled) {
|
||||
screenfull.off('change', this.change)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.screenfull-svg {
|
||||
display: inline-block;
|
||||
cursor: pointer;
|
||||
fill: #5a5e66;;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
vertical-align: 10px;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,230 @@
|
||||
<template>
|
||||
<div class="select-sort">
|
||||
<el-button size="mini" @click="openManage">标签管理</el-button>
|
||||
<div class="flex-wrap">
|
||||
<el-tag class="flex-wrap-item" size="mini" type="success" v-for="item in value" :key="item">
|
||||
{{ item | changeTagName(VcrightList) }}
|
||||
</el-tag>
|
||||
</div>
|
||||
<el-dialog z-index="99999999" :title="title" :visible.sync="visible" class="ac-dialog" center top="50px" width="700px" :modal="false" @close="cancel">
|
||||
<el-row>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="标签搜索" prop="searchText" class="search-button">
|
||||
<el-input v-model="searchText" style="width: 180px;" clearable placeholder="请输入标签关键字"></el-input>
|
||||
<el-button style="margin-left: 10px;" type="primary" @click="filterLeftData">搜索选择</el-button>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row type="flex" align="stretch">
|
||||
<el-col :span="10">
|
||||
<h3>未选中</h3>
|
||||
<draggable class="list-group" :list="leftData" group="people">
|
||||
<div class="list-group-item" v-for="(element, index) in leftData" @click="toggleSelection(element, 'left')" :key="index">
|
||||
<el-tag size="mini">{{ element.title }}</el-tag>
|
||||
</div>
|
||||
</draggable>
|
||||
</el-col>
|
||||
<el-col :span="4">
|
||||
<div class="transfer-wrapper">
|
||||
<div class="el-transfer__buttons">
|
||||
<i class="el-icon-arrow-right"></i>
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="10">
|
||||
<h3>已选中</h3>
|
||||
<draggable class="list-group" :list="rightData" group="people">
|
||||
<div class="list-group-item" v-for="(element, index) in rightData" @click="toggleSelection(element, 'right')" :key="index">
|
||||
<el-tag size="mini" type="success">{{ element.title }}</el-tag>
|
||||
</div>
|
||||
</draggable>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<div class="dialog-footer">
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
<el-button @click="confirm" type="primary">确 定</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import draggable from 'vuedraggable'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
draggable
|
||||
},
|
||||
filters: {
|
||||
changeTagName(value, list) {
|
||||
const found = list.find(item => item.id === value)
|
||||
return found ? found.title : ''
|
||||
}
|
||||
},
|
||||
props: {
|
||||
value: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
VcrightList: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: '权益管理'
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
visible: false,
|
||||
rightData: [],
|
||||
leftData: [],
|
||||
searchText: ''
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
value: {
|
||||
handler: 'initializeData',
|
||||
immediate: true
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
filterLeftData() {
|
||||
const leftArr = [...this.leftData]
|
||||
const rightArr = [...this.rightData]
|
||||
const selectedLabels = this.searchText.split(/\s+/) // 按空格分割
|
||||
const selected = leftArr.filter(item => selectedLabels.includes(item.title))
|
||||
const remaining = leftArr.filter(item => !selectedLabels.includes(item.title))
|
||||
this.leftData = remaining
|
||||
this.rightData = [...new Map([...rightArr, ...selected].map(item => [item.id, item])).values()]
|
||||
// if (this.searchText) {
|
||||
// // 当输入有文本时,过滤左侧数据
|
||||
// this.leftData = this.VcrightList.filter(item => item.title.toLowerCase().includes(this.searchText.toLowerCase()));
|
||||
// } else {
|
||||
// // 当没有文本时,恢复所有未选中的标签
|
||||
// this.leftData = this.VcrightList.filter(item => !this.rightData.some(selected => selected.id === item.id));
|
||||
// }
|
||||
},
|
||||
toggleSelection(item, direction) {
|
||||
if (direction === 'right') {
|
||||
this.rightData = this.rightData.filter(i => i !== item)
|
||||
this.leftData.push(item)
|
||||
} else {
|
||||
this.leftData = this.leftData.filter(i => i !== item)
|
||||
this.rightData.push(item)
|
||||
}
|
||||
},
|
||||
initializeData() {
|
||||
console.log(this.value, '-=-=')
|
||||
if (this.value && this.value.length > 0) {
|
||||
this.rightData = this.value.map(item => ({
|
||||
id: item,
|
||||
title: this.VcrightList.find(el => el.id === item) ? this.VcrightList.find(el => el.id === item).title : ''
|
||||
}))
|
||||
} else {
|
||||
this.rightData = []
|
||||
}
|
||||
if (this.VcrightList && this.VcrightList.length > 0) {
|
||||
this.leftData = this.VcrightList.filter(item => !this.value.includes(item.id))
|
||||
} else {
|
||||
this.leftData = []
|
||||
}
|
||||
},
|
||||
openManage() {
|
||||
this.visible = true
|
||||
},
|
||||
cancel() {
|
||||
this.visible = false
|
||||
},
|
||||
confirm() {
|
||||
this.$emit('changeInput', this.rightData.map(item => item.id))
|
||||
this.visible = false
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.select-sort {
|
||||
// 容器样式
|
||||
margin: 10px 20px;
|
||||
|
||||
.flex-wrap {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 5px;
|
||||
}
|
||||
|
||||
.transfer-wrapper {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
&__flex-wrap {
|
||||
margin-top: 6px;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
||||
&-item {
|
||||
margin-right: 4px;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
}
|
||||
|
||||
&__list-group {
|
||||
padding: 4px;
|
||||
height: calc(100% - 40px);
|
||||
border: 1px solid #ebeef5;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-around;
|
||||
|
||||
&-item {
|
||||
// 其他 list-group item 的样式
|
||||
}
|
||||
}
|
||||
|
||||
&__transfer-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
font-size: 40px;
|
||||
|
||||
.el-transfer__buttons {
|
||||
// 按钮样式
|
||||
}
|
||||
}
|
||||
|
||||
&__search-button {
|
||||
display: flex;
|
||||
width: 500px;
|
||||
|
||||
::v-deep {
|
||||
.el-form-item__content {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.list-group {
|
||||
max-height: 400px;
|
||||
overflow-y: auto;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 5px;
|
||||
}
|
||||
// 响应式风格
|
||||
@media (max-width: 768px) {
|
||||
.select-sort {
|
||||
&__search-button {
|
||||
width: 100%; // 在小屏幕上占满宽度
|
||||
}
|
||||
|
||||
&__flex-wrap {
|
||||
flex-direction: column; // 在小屏幕下垂直排列
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,91 @@
|
||||
<!--
|
||||
* @Author: 王涛
|
||||
* @Mail: no
|
||||
* @Date: 2020-10-05 11:37:08
|
||||
* @LastEditors: 王涛
|
||||
* @LastEditTime: 2020-11-24 17:04:24
|
||||
-->
|
||||
<template>
|
||||
<el-dialog class="img_dialog" append-to-body :title="title" align="center" :visible.sync="dialogVisible" width="40%" :before-close="handleClose" :close-on-click-modal="false" :modal-append-to-body='false'>
|
||||
<el-carousel v-if="isArry" indicator-position="outside">
|
||||
<el-carousel-item v-for="item in mediaUrl" :key="item">
|
||||
<div class="media-box" id="img-box" > <img :src="item" /></div>
|
||||
</el-carousel-item>
|
||||
</el-carousel>
|
||||
<div v-else class="media-box" id="img-box" > <img :src="mediaUrl" /></div>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
baseConfig: {},
|
||||
dialogVisible: false,
|
||||
domain: this.$store.getters.getSystemConfig.imgWebCdn, // 存放图片的域名
|
||||
mediaUrl: '',
|
||||
title: '查看图片',
|
||||
isArry: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
token() {
|
||||
return this.$store.state.token
|
||||
}
|
||||
|
||||
},
|
||||
mounted() {
|
||||
},
|
||||
methods: {
|
||||
|
||||
handleClose() {
|
||||
if (this.player) {
|
||||
this.player.dispose()
|
||||
}
|
||||
this.dialogVisible = false
|
||||
this.mediaUrl = ''
|
||||
},
|
||||
open(url, type, data) {
|
||||
if (typeof url === 'string') {
|
||||
this.isArry = false
|
||||
} else {
|
||||
this.isArry = true
|
||||
}
|
||||
this.dialogVisible = true
|
||||
this.title = '封面图查看'
|
||||
this.mediaUrl = url
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
.img_dialog{
|
||||
::v-deep{
|
||||
.el-dialog__body{
|
||||
height: auto;
|
||||
.el-carousel__item{
|
||||
overflow: auto !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.media-box {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
overflow: hidden;
|
||||
img {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
#my-video {
|
||||
width: 100% !important;
|
||||
height: 100% !important;
|
||||
border: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -0,0 +1,181 @@
|
||||
<!--
|
||||
* @Author: 王涛
|
||||
* @Mail: no
|
||||
* @Date: 2020-10-05 11:36:16
|
||||
* @LastEditors: 江涛
|
||||
* @LastEditTime: 2021-03-03 17:50:26
|
||||
-->
|
||||
|
||||
<template>
|
||||
<div class="img-wrap">
|
||||
<div v-if='showChangeBtn' class="changeLeft" @click="changeLeft">
|
||||
<i class="el-icon-arrow-left"></i>
|
||||
</div>
|
||||
<div class="showImg">
|
||||
<div v-if="showNoImg">暂无</div>
|
||||
<el-image v-else-if="src" :src="src" :preview-src-list="previewSrcList" fit="contain">
|
||||
<div slot="placeholder" class="image-slot" :style="{ width: width, height: height, lineHeight: height }">
|
||||
<i class="el-icon-loading"></i>加载中
|
||||
</div>
|
||||
</el-image>
|
||||
</div>
|
||||
<div v-if='showChangeBtn' class="changeRight" @click="changeRight">
|
||||
<i class="el-icon-arrow-right"></i>
|
||||
</div>
|
||||
<!--封面图、视频弹窗组件-->
|
||||
<Dialog ref="dialog"></Dialog>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import Dialog from './components/dialog'
|
||||
import { handleVerAutoImg } from '@/utils/index.js'
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
showNoImg: false,
|
||||
src: '',
|
||||
showChangeBtn: false,
|
||||
imgsUrl: []
|
||||
}
|
||||
},
|
||||
components: {
|
||||
Dialog
|
||||
},
|
||||
props: ['width', 'height', 'urls', 'domain'],
|
||||
watch: {
|
||||
urls: {
|
||||
handler(o, n) {
|
||||
this.getBlobUri()
|
||||
},
|
||||
immediate: true
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
currentDomain() {
|
||||
return this.domain || this.$store.getters.getSystemConfig.imgWebCdn || ''
|
||||
},
|
||||
previewSrcList() {
|
||||
return this.imgsUrl && this.imgsUrl.length ? this.imgsUrl : [this.src]
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
buildImageUrl(path) {
|
||||
if (!path) return ''
|
||||
if (/^(blob:|https?:\/\/|data:)/.test(path)) return path
|
||||
const base = this.currentDomain || ''
|
||||
if (!base) return path
|
||||
const normalizedBase = base.endsWith('/') ? base.slice(0, -1) : base
|
||||
const normalizedPath = path.startsWith('/') ? path : `/${path}`
|
||||
return `${normalizedBase}${normalizedPath}`
|
||||
},
|
||||
|
||||
changeLeft() {
|
||||
const index = this.imgsUrl.indexOf(this.src)
|
||||
if (index === 0) {
|
||||
this.src = this.imgsUrl[this.imgsUrl.length - 1]
|
||||
} else {
|
||||
this.src = this.imgsUrl[index - 1]
|
||||
}
|
||||
},
|
||||
changeRight() {
|
||||
const index = this.imgsUrl.indexOf(this.src)
|
||||
if (index === this.imgsUrl.length - 1) {
|
||||
this.src = this.imgsUrl[0]
|
||||
} else {
|
||||
this.src = this.imgsUrl[index + 1]
|
||||
}
|
||||
},
|
||||
async getBlobUri() {
|
||||
if (typeof this.urls === 'string' && this.urls.startsWith('http')) {
|
||||
this.src = this.urls
|
||||
return
|
||||
}
|
||||
if (!this.urls) {
|
||||
this.showChangeBtn = false
|
||||
this.showNoImg = true
|
||||
return
|
||||
}
|
||||
|
||||
// 检查是否为数组
|
||||
if (Array.isArray(this.urls)) {
|
||||
if (this.urls.length) {
|
||||
this.showChangeBtn = true
|
||||
this.imgsUrl = []
|
||||
for (let index = 0; index < this.urls.length; index++) {
|
||||
await handleVerAutoImg(this.buildImageUrl(this.urls[index])).then(res => {
|
||||
this.imgsUrl[index] = res
|
||||
this.src = this.imgsUrl[0]
|
||||
this.showNoImg = false
|
||||
})
|
||||
}
|
||||
} else {
|
||||
this.showChangeBtn = false
|
||||
this.showNoImg = true
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
const imageUrl = this.buildImageUrl(this.urls)
|
||||
const baseUri = await handleVerAutoImg(imageUrl)
|
||||
if (baseUri && baseUri.length) {
|
||||
this.src = baseUri
|
||||
this.showNoImg = false
|
||||
} else {
|
||||
this.showNoImg = true
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Error loading image:', e)
|
||||
}
|
||||
}
|
||||
},
|
||||
// 查看媒体
|
||||
async checkMedia() {
|
||||
if (this.urls) { // 判断是否存在
|
||||
if (typeof (this.urls) === 'string') { // 判断是单张图片还是数组
|
||||
this.$refs.dialog.open(this.src)
|
||||
} else {
|
||||
this.$refs.dialog.open(this.imgsUrl, 'img')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.img-wrap {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
|
||||
.changeLeft,
|
||||
.changeRight {
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
line-height: 15px;
|
||||
margin-top: 15%;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.showImg {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
.image-slot {
|
||||
background: #f5f7fa;
|
||||
font-size: 12px;
|
||||
color: #c0c4cc;
|
||||
}
|
||||
|
||||
.el-image__error {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.el-image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,154 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-dialog
|
||||
:title="title"
|
||||
align="center"
|
||||
:visible.sync="dialogVisible"
|
||||
top="5vh"
|
||||
width="40%"
|
||||
:before-close="handleClose"
|
||||
:close-on-click-modal="false"
|
||||
append-to-body>
|
||||
<div :data="myData" class="my_data">
|
||||
<span>视频高度:{{ this.myData.height }}</span>
|
||||
<span>视频宽度:{{ this.myData.width }}</span>
|
||||
<span>视频时长:{{ this.myData.videoTime + "s" }}</span>
|
||||
</div>
|
||||
<div v-if="mediaUrl" class="media-box">
|
||||
<DPlayer
|
||||
ref="player"
|
||||
:video="{
|
||||
url: mediaUrl,
|
||||
type: type === 'mp4' ? '' : 'hls',
|
||||
pic: '',
|
||||
}"
|
||||
hotkey
|
||||
:autoplay="true"
|
||||
@playing="onPlayerPlay"
|
||||
@pause="onPlayerPause"
|
||||
@loadeddata="onPlayerLoadeddata"
|
||||
@error="onPlayerError"
|
||||
@ended="onPlayerEnded"
|
||||
@waiting="onPlayerWaiting"></DPlayer>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// import videojs from 'video.js'
|
||||
// import 'videojs-contrib-hls'
|
||||
import { videoFeviewList } from '@/api/video.js'
|
||||
import DPlayer from '../VueDplayerHls/index'
|
||||
|
||||
// import API from '@/api'
|
||||
export default {
|
||||
name: 'ShowVideo',
|
||||
components: {
|
||||
DPlayer
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
dialogVisible: false,
|
||||
mediaUrl: '',
|
||||
title: '封面图查看',
|
||||
params: {},
|
||||
myData: {},
|
||||
type: undefined,
|
||||
domain: '/api/web/m3u8/' // 存放图片的域名
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
token() {
|
||||
return this.$store.state.user.token
|
||||
},
|
||||
aspectRatio() {
|
||||
if (!this.myData || !this.myData.width || !this.myData.height) return 16 / 9
|
||||
return this.myData.width / this.myData.height
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
// / 监听视频播放的回调函数
|
||||
onPlayerPlay() { },
|
||||
// / 监听暂停播放的回调函数
|
||||
onPlayerPause() { },
|
||||
// / 监听当前视频数据加载完成
|
||||
onPlayerLoadeddata() { },
|
||||
// / 监听当前视频数据加载失败
|
||||
onPlayerError() { },
|
||||
// / 监听当前视频数据加载ing
|
||||
onPlayerWaiting() { },
|
||||
// / 监听当前视频播放完成
|
||||
onPlayerEnded() { },
|
||||
// 视频审查列表
|
||||
videoFeviewList() {
|
||||
videoFeviewList(this.params, this.id).then((res) => {
|
||||
// this.myData = res.data,
|
||||
})
|
||||
},
|
||||
handleClose() {
|
||||
if (this.player) {
|
||||
this.player.dispose()
|
||||
}
|
||||
this.dialogVisible = false
|
||||
this.mediaUrl = ''
|
||||
this.type = undefined
|
||||
},
|
||||
getMp4Url(url, options = {}) {
|
||||
if (!url) {
|
||||
return ''
|
||||
}
|
||||
if (options.directUrl || /^https?:\/\//i.test(url)) {
|
||||
return url
|
||||
}
|
||||
const left = ((options.mp4Domain || this.$store.getters.getSystemConfig.mp4Addr) || '').replace(/\/+$/, '')
|
||||
const right = String(url).replace(/^\/+/, '')
|
||||
return left ? `${left}/${right}` : right
|
||||
},
|
||||
getM3u8Url(url, options = {}) {
|
||||
if (!url) {
|
||||
return ''
|
||||
}
|
||||
if (options.directUrl || /^https?:\/\//i.test(url)) {
|
||||
return /\.m3u8($|\?)/i.test(url) ? url : `${url}.m3u8`
|
||||
}
|
||||
let mediaUrl = this.domain + (url.match(RegExp(/.m3u8/)) ? url : url + '.m3u8')
|
||||
// 短剧原片使用 conf/newm3u8.key 解密
|
||||
if (options.useNewKey) {
|
||||
mediaUrl += (mediaUrl.indexOf('?') >= 0 ? '&' : '?') + 'useNewKey=1'
|
||||
}
|
||||
return mediaUrl
|
||||
},
|
||||
open(url, data, id, options = {}) {
|
||||
this.myData = { ...(data.video || data) }
|
||||
this.dialogVisible = true
|
||||
this.title = options.title || '视频查看'
|
||||
const currentUrl = url || ''
|
||||
if (options.type === 'mp4' || /\.mp4($|\?)/i.test(currentUrl)) {
|
||||
this.mediaUrl = this.getMp4Url(currentUrl, options)
|
||||
this.type = 'mp4'
|
||||
} else {
|
||||
this.mediaUrl = this.getM3u8Url(currentUrl, options)
|
||||
this.type = 'hls'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.my_data {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.media-box {
|
||||
padding-top: 10px;
|
||||
width: 100%;
|
||||
height: 400px;
|
||||
text-align: center;
|
||||
overflow: hidden;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,62 @@
|
||||
<template>
|
||||
<div v-if="isExternal" :style="styleExternalIcon" class="svg-external-icon svg-icon" v-on="$listeners" />
|
||||
<svg v-else :class="svgClass" aria-hidden="true" v-on="$listeners">
|
||||
<use :xlink:href="iconName" />
|
||||
</svg>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// doc: https://panjiachen.github.io/vue-element-admin-site/feature/component/svg-icon.html#usage
|
||||
import { isExternal } from '@/utils/validate'
|
||||
|
||||
export default {
|
||||
name: 'SvgIcon',
|
||||
props: {
|
||||
iconClass: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
className: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
isExternal() {
|
||||
return isExternal(this.iconClass)
|
||||
},
|
||||
iconName() {
|
||||
return `#icon-${this.iconClass}`
|
||||
},
|
||||
svgClass() {
|
||||
if (this.className) {
|
||||
return 'svg-icon ' + this.className
|
||||
} else {
|
||||
return 'svg-icon'
|
||||
}
|
||||
},
|
||||
styleExternalIcon() {
|
||||
return {
|
||||
mask: `url(${this.iconClass}) no-repeat 50% 50%`,
|
||||
'-webkit-mask': `url(${this.iconClass}) no-repeat 50% 50%`
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.svg-icon {
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
vertical-align: -0.15em;
|
||||
fill: currentColor;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.svg-external-icon {
|
||||
background-color: currentColor;
|
||||
mask-size: cover!important;
|
||||
display: inline-block;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,167 @@
|
||||
<!--
|
||||
* @Author: your name
|
||||
* @Date: 2020-09-10 16:03:32
|
||||
* @LastEditTime: 2021-03-24 11:27:17
|
||||
* @LastEditors: 江涛
|
||||
* @Description: In User Settings Edit
|
||||
* @FilePath: /web-admin-MDDSP/src/components/TagSelect/index.vue
|
||||
-->
|
||||
<template>
|
||||
<div class="reason-action-box">
|
||||
<el-row :gutter="24">
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="二级标签:" label-width="75px">
|
||||
<div style="max-width:470px;max-height:100px;overflow: auto">
|
||||
<el-tag :key="index" v-for="(item,index) in useselectTag" closable :disable-transitions="false" @close="clickselectTag(item,index)">{{item}}</el-tag>
|
||||
<el-button class="button-new-tag" size="mini" @click="showInput">+ 新增标签</el-button>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="24" v-if="inputVisible">
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="搜索:" label-width="45px">
|
||||
<el-autocomplete
|
||||
class="inline-input"
|
||||
v-model="inputValue"
|
||||
:fetch-suggestions="querySearch"
|
||||
placeholder="请输入内容"
|
||||
:trigger-on-focus="false"></el-autocomplete>
|
||||
<el-button @click="addTag">添加</el-button>
|
||||
</el-form-item>
|
||||
<el-form-item label-width="50px" style="margin-top:15px">
|
||||
<div style="max-width:470px;height:500px;overflow: auto;min-width:300px">
|
||||
<div v-for="(val, key, index) in tagsObj" :key='index'>
|
||||
<el-button style="widht:120px" plain size="mini" type="info" v-for="(item,indexl) in val" :key="indexl" @click="clickCusTag(item,indexl,key)">{{item}}</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
// import API from '@/api'
|
||||
import { mediatagList } from '@/api/mediaLibrary/mediaTag'
|
||||
export default {
|
||||
props: {
|
||||
selectTag: {
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
mediatagRes: [], // 模糊查询使用的数据
|
||||
allCusTag: {}, // 所有的标签
|
||||
useselectTag: this.selectTag.length ? this.selectTag.split(',') : [], // 存储已选择标签
|
||||
tagsObj: {}, // 剩余未选择的标签
|
||||
inputValue: '',
|
||||
inputVisible: false
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
mediatagList({ pageNum: 1, pageSize: 1000, status: true,
|
||||
type: 2 }).then(res => {
|
||||
if (res.code === 200) {
|
||||
const aaa = {}
|
||||
const bbb = []
|
||||
res.data.list.filter(item => {
|
||||
bbb.push({ value: item.name, label: item.name })
|
||||
if (aaa[item.type]) {
|
||||
aaa[item.type].push(item.name)
|
||||
} else {
|
||||
aaa[item.type] = []
|
||||
aaa[item.type].push(item.name)
|
||||
}
|
||||
})
|
||||
this.allCusTag = JSON.parse(JSON.stringify(aaa))
|
||||
this.tagsObj = JSON.parse(JSON.stringify(aaa))
|
||||
this.mediatagRes = bbb
|
||||
this.removeTag()
|
||||
}
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
querySearch(queryString, cb) {
|
||||
var restaurants = this.mediatagRes
|
||||
var results = queryString ? restaurants.filter(this.createFilter(queryString)) : restaurants
|
||||
// 调用 callback 返回建议列表的数据
|
||||
cb(results)
|
||||
},
|
||||
createFilter(queryString) {
|
||||
return (restaurant) => {
|
||||
return (restaurant.value.toLowerCase().indexOf(queryString.toLowerCase()) === 0)
|
||||
}
|
||||
},
|
||||
addTag() {
|
||||
this.useselectTag.push(this.inputValue)
|
||||
this.removeTag()
|
||||
},
|
||||
|
||||
showInput() {
|
||||
this.inputVisible = true
|
||||
},
|
||||
// 第一次渲染时从标签列表中移除已有标签
|
||||
removeTag() {
|
||||
this.useselectTag.forEach(item => {
|
||||
Object.keys(this.tagsObj).forEach(key => {
|
||||
if (this.tagsObj[key].indexOf(item) !== -1 || this.tagsObj[key].indexOf(item) === 0) {
|
||||
this.tagsObj[key].splice(this.tagsObj[key].indexOf(item), 1)
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
// 删除已选择标签
|
||||
clickselectTag(data, index) {
|
||||
this.useselectTag.splice(index, 1)
|
||||
Object.keys(this.tagsObj).forEach(item => {
|
||||
if (this.allCusTag[item].indexOf(data) !== -1 || this.allCusTag[item].indexOf(data) === 0) {
|
||||
this.tagsObj[item].push(data)
|
||||
}
|
||||
})
|
||||
},
|
||||
// 点击客服标签
|
||||
clickCusTag(data, index, key) {
|
||||
this.tagsObj[key].splice(index, 1)
|
||||
this.useselectTag.push(data)
|
||||
},
|
||||
// 返回已选择但不是客服标签的标签
|
||||
NotCusTag() {
|
||||
const arry = []
|
||||
this.useselectTag.forEach((item) => {
|
||||
if (this.allCusTag.indexOf(item) === -1) {
|
||||
arry.push(item)
|
||||
}
|
||||
})
|
||||
return arry
|
||||
},
|
||||
// 返回已选择的标签
|
||||
returnSelectTag() {
|
||||
return this.useselectTag
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.reason-action-box {
|
||||
.el-tag {
|
||||
padding: 0 10px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
.input {
|
||||
width: 90px;
|
||||
margin-left: 30px;
|
||||
}
|
||||
button {
|
||||
padding: 9px 15px;
|
||||
}
|
||||
}
|
||||
.reason-action-box button[data-v-2b5b3839]{
|
||||
width: 80px;
|
||||
padding: 9px 15px;
|
||||
margin-right: 10px;
|
||||
margin-left: 0px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -0,0 +1,303 @@
|
||||
<template>
|
||||
<el-form>
|
||||
<div class="reason-action-box">
|
||||
|
||||
<el-row :gutter="24">
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="已选标签" v-if="type !== 'resourceManagement'">
|
||||
<el-tag
|
||||
:key="index + 'tag'"
|
||||
v-for="(item, index) in selectTags"
|
||||
:disable-transitions="true"
|
||||
closable
|
||||
style="margin: 2px"
|
||||
@close="handleTagClose(item)">
|
||||
{{ item | changeName(allTags, 'id', 'name') }}
|
||||
</el-tag>
|
||||
</el-form-item>
|
||||
<el-form-item label="已选标签" v-else>
|
||||
<el-tag
|
||||
:key="index + 'tag'"
|
||||
v-for="(item, index) in selectTags"
|
||||
:disable-transitions="true"
|
||||
closable
|
||||
style="margin: 2px"
|
||||
@close="handleTagClose(item)">
|
||||
{{ item | changeName(newAllTags, 'id', 'name') }}
|
||||
</el-tag>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||
<el-form-item label="可选标签">
|
||||
<el-button :type="showTagsFlag ? 'warning' : 'success'" @click="showTagsFun">{{ showTagsFlag ? '隐藏标签' :
|
||||
'展示标签'
|
||||
}}</el-button>
|
||||
<el-form-item label="标签分类过滤">
|
||||
<el-select
|
||||
placeholder="标签分类"
|
||||
@change="changeTagsCategory"
|
||||
multiple
|
||||
v-model="tagCategory"
|
||||
clearable
|
||||
filterable
|
||||
@clear="tagCategory = null">
|
||||
<el-option :key="index" :label="item.name" :value="item.id" v-for="(item, index) in mediatagCategory" />
|
||||
</el-select>
|
||||
|
||||
</el-form-item>
|
||||
<el-form-item label="关键字过滤">
|
||||
<el-input v-model="searchTagTxt" placeholder="请输入标签名称" clearable />
|
||||
|
||||
</el-form-item>
|
||||
<el-form-item >
|
||||
<el-button @click="tagFilter">搜索标签</el-button>
|
||||
</el-form-item>
|
||||
<div style="width: 1000px;height: 500px;overflow-y: auto;" v-if="type !== 'resourceManagement'">
|
||||
<template v-for="(itemList, index) in newTagList">
|
||||
<div v-if="itemList.showItem && tagCategory.length" :key="index">
|
||||
<span v-show="showTagsFlag">{{ itemList.id | changeName(newTagList, 'id', 'name') }}</span>
|
||||
<el-tag
|
||||
v-show="showTagsFlag"
|
||||
:key="index + 'tagData'"
|
||||
style="margin: 2px; cursor: pointer"
|
||||
v-for="(item, index) in itemList.tags"
|
||||
:disable-transitions="true"
|
||||
:effect="item && item.hasTopic ? 'dark' : 'light'"
|
||||
:type="fliterTagType(item, item.id, item.topicIds)"
|
||||
@click="handleClickTag(item.id)">
|
||||
{{ item.name }}
|
||||
</el-tag>
|
||||
</div>
|
||||
<div v-else-if="!itemList.showItem && !tagCategory.length" :key="index">
|
||||
<span v-show="showTagsFlag">{{ itemList.id | changeName(newTagList, 'id', 'name') }}</span>
|
||||
<el-tag
|
||||
v-show="showTagsFlag"
|
||||
:key="index + 'tagData'"
|
||||
style="margin: 2px; cursor: pointer"
|
||||
v-for="(item, index) in itemList.tags"
|
||||
:disable-transitions="true"
|
||||
:effect="item && item.hasTopic ? 'dark' : 'light'"
|
||||
:type="fliterTagType(item, item.id, item.topicIds)"
|
||||
@click="handleClickTag(item.id)">
|
||||
{{ item.name }}
|
||||
</el-tag>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
</div>
|
||||
<div style="width: 1000px;height: 500px;overflow-y: auto;" v-else>
|
||||
<template v-for="(itemList, index) in newAllTagsCopy">
|
||||
<div :key="index" v-if="itemList.showItem && tagCategory.length">
|
||||
<span v-show="showTagsFlag">{{ itemList.id | changeName(allTags, 'id', 'name') }}</span>
|
||||
<el-tag
|
||||
v-show="showTagsFlag"
|
||||
:key="index + 'tagData'"
|
||||
style="margin: 2px; cursor: pointer"
|
||||
v-for="(item, index) in itemList.list"
|
||||
:disable-transitions="true"
|
||||
:effect="item && item.hasTopic ? 'dark' : 'light'"
|
||||
:type="fliterTagType(item, item.id, item.topicIds)"
|
||||
@click="handleClickTag(item.id)">
|
||||
{{ item.name }}
|
||||
</el-tag>
|
||||
</div>
|
||||
<div v-else-if="!itemList.showItem && !tagCategory.length" :key="index">
|
||||
<span v-show="showTagsFlag">{{ itemList.id | changeName(newAllTagsCopy, 'id', 'name') }}</span>
|
||||
<el-tag
|
||||
v-show="showTagsFlag"
|
||||
:key="index + 'tagData'"
|
||||
style="margin: 2px; cursor: pointer"
|
||||
v-for="(item, index) in itemList.list"
|
||||
:disable-transitions="true"
|
||||
:effect="item && item.hasTopic ? 'dark' : 'light'"
|
||||
:type="fliterTagType(item, item.id, item.topicIds)"
|
||||
@click="handleClickTag(item.id)">
|
||||
{{ item.name }}
|
||||
</el-tag>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</el-form>
|
||||
</template>
|
||||
<script>
|
||||
// import API from '@/api'
|
||||
import {
|
||||
|
||||
videotagList
|
||||
} from '@/api/videoManagement/videotag.js'
|
||||
export default {
|
||||
props: {
|
||||
formTags: {// 传入以选择标签
|
||||
default: []
|
||||
},
|
||||
allTags: {// 所有标签
|
||||
default: []
|
||||
},
|
||||
mediatagCategory: {// 标签分类
|
||||
default: []
|
||||
},
|
||||
type: {// 标签分类
|
||||
default: String
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
selectTags: [], // 已选择标签
|
||||
newTagList: [], // 经过分类的标签组
|
||||
showTagsFlag: true,
|
||||
tagCategory: [],
|
||||
searchTagTxt: '',
|
||||
newAllTagsCopy: []
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
if (this.type !== 'resourceManagement') {
|
||||
// 标签绑定标签分类
|
||||
if (this.mediatagCategory.length) {
|
||||
this.newTagList = JSON.parse(JSON.stringify(this.mediatagCategory))
|
||||
this.newTagList.forEach(item => {
|
||||
item.showItem = false
|
||||
item.tags = this.allTags.filter(sItem => {
|
||||
return item.id === sItem.categoryId
|
||||
})
|
||||
})
|
||||
} else {
|
||||
this.newTagList = [{ id: 0, name: '全部' }]
|
||||
this.newTagList.forEach(item => {
|
||||
item.showItem = false
|
||||
item.tags = this.allTags
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
'formTags': {
|
||||
handler(n, o) {
|
||||
this.selectTags = n
|
||||
},
|
||||
immediate: true
|
||||
},
|
||||
'allTags': {
|
||||
handler(n, o) {
|
||||
this.newAllTagsCopy = JSON.parse(JSON.stringify(n))
|
||||
},
|
||||
immediate: true
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
newAllTags() {
|
||||
let arr = []
|
||||
if (this.type == 'resourceManagement') {
|
||||
this.allTags.map(item => {
|
||||
item.showItem = false
|
||||
if (item.list && item.list.length) {
|
||||
arr = [...arr, ...item.list]
|
||||
}
|
||||
})
|
||||
return arr
|
||||
} else {
|
||||
return []
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
changeTagsCategory() {
|
||||
if (this.type !== 'resourceManagement') {
|
||||
this.newTagList.forEach(element => {
|
||||
if (this.tagCategory.includes(element.id)) {
|
||||
element.showItem = true
|
||||
} else {
|
||||
element.showItem = false
|
||||
}
|
||||
})
|
||||
} else {
|
||||
for (let index = 0; index < this.newAllTagsCopy.length; index++) {
|
||||
if (this.tagCategory.includes(this.newAllTagsCopy[index].id)) {
|
||||
this.newAllTagsCopy[index].showItem = true
|
||||
} else {
|
||||
this.newAllTagsCopy[index].showItem = false
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
handleTagClose(tag) {
|
||||
this.selectTags.splice(this.selectTags.indexOf(tag), 1)
|
||||
this.$emit('selectTags', this.selectTags)
|
||||
},
|
||||
showTagsFun() {
|
||||
this.showTagsFlag = !this.showTagsFlag
|
||||
},
|
||||
// 点击可选择列表中的标签
|
||||
handleClickTag(tagID) {
|
||||
if (this.selectTags.indexOf(tagID) === -1) {
|
||||
this.selectTags.push(tagID)
|
||||
} else {
|
||||
this.selectTags.splice(this.selectTags.indexOf(tagID), 1)
|
||||
}
|
||||
this.$emit('selectTags', this.selectTags)
|
||||
},
|
||||
fliterTagType(item, tagID, topicIds) {
|
||||
if (this.selectTags.indexOf(tagID) !== -1) {
|
||||
return 'danger'
|
||||
} else {
|
||||
if (topicIds) { return 'default' } else {
|
||||
if (this.searchTagTxt) {
|
||||
if (item.name.indexOf(this.searchTagTxt) !== -1) {
|
||||
return 'warning'
|
||||
}
|
||||
} else {
|
||||
return 'info'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
getValue() {
|
||||
return this.selectTags
|
||||
},
|
||||
// 标签搜索
|
||||
async tagFilter() {
|
||||
// TODO:请求所有分类标签列表
|
||||
await videotagList({ pageNum: 1, pageSize: 100, name: this.searchTagTxt }).then((res) => {
|
||||
if (res.code === 200) {
|
||||
this.newAllTagsCopy = res.data.list
|
||||
} else {
|
||||
this.newAllTagsCopy = []
|
||||
this.$message.error('请求标签分类失败')
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.reason-action-box {
|
||||
|
||||
// height: 200px;
|
||||
.el-tag {
|
||||
padding: 0 10px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.input {
|
||||
width: 90px;
|
||||
margin-left: 30px;
|
||||
}
|
||||
|
||||
button {
|
||||
padding: 9px 15px;
|
||||
}
|
||||
}
|
||||
|
||||
.reason-action-box button[data-v-2b5b3839] {
|
||||
width: 80px;
|
||||
padding: 9px 15px;
|
||||
margin-right: 10px;
|
||||
margin-left: 0px;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,111 @@
|
||||
<template>
|
||||
<div class="upload-container">
|
||||
<el-button :style="{background:color,borderColor:color}" icon="el-icon-upload" size="mini" type="primary" @click=" dialogVisible=true">
|
||||
upload
|
||||
</el-button>
|
||||
<el-dialog :visible.sync="dialogVisible" append-to-body>
|
||||
<el-upload
|
||||
:multiple="true"
|
||||
:file-list="fileList"
|
||||
:show-file-list="true"
|
||||
:on-remove="handleRemove"
|
||||
:on-success="handleSuccess"
|
||||
:before-upload="beforeUpload"
|
||||
class="editor-slide-upload"
|
||||
action="https://httpbin.org/post"
|
||||
list-type="picture-card">
|
||||
<el-button size="small" type="primary">
|
||||
Click upload
|
||||
</el-button>
|
||||
</el-upload>
|
||||
<el-button @click="dialogVisible = false">
|
||||
Cancel
|
||||
</el-button>
|
||||
<el-button type="primary" @click="handleSubmit">
|
||||
Confirm
|
||||
</el-button>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// import { getToken } from 'api/qiniu'
|
||||
|
||||
export default {
|
||||
name: 'EditorSlideUpload',
|
||||
props: {
|
||||
color: {
|
||||
type: String,
|
||||
default: '#1890ff'
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
dialogVisible: false,
|
||||
listObj: {},
|
||||
fileList: []
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
checkAllSuccess() {
|
||||
return Object.keys(this.listObj).every(item => this.listObj[item].hasSuccess)
|
||||
},
|
||||
handleSubmit() {
|
||||
const arr = Object.keys(this.listObj).map(v => this.listObj[v])
|
||||
if (!this.checkAllSuccess()) {
|
||||
this.$message('Please wait for all images to be uploaded successfully. If there is a network problem, please refresh the page and upload again!')
|
||||
return
|
||||
}
|
||||
this.$emit('successCBK', arr)
|
||||
this.listObj = {}
|
||||
this.fileList = []
|
||||
this.dialogVisible = false
|
||||
},
|
||||
handleSuccess(response, file) {
|
||||
const uid = file.uid
|
||||
const objKeyArr = Object.keys(this.listObj)
|
||||
for (let i = 0, len = objKeyArr.length; i < len; i++) {
|
||||
if (this.listObj[objKeyArr[i]].uid === uid) {
|
||||
this.listObj[objKeyArr[i]].url = response.files.file
|
||||
this.listObj[objKeyArr[i]].hasSuccess = true
|
||||
return
|
||||
}
|
||||
}
|
||||
},
|
||||
handleRemove(file) {
|
||||
const uid = file.uid
|
||||
const objKeyArr = Object.keys(this.listObj)
|
||||
for (let i = 0, len = objKeyArr.length; i < len; i++) {
|
||||
if (this.listObj[objKeyArr[i]].uid === uid) {
|
||||
delete this.listObj[objKeyArr[i]]
|
||||
return
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
beforeUpload(file) {
|
||||
const _self = this
|
||||
const _URL = window.URL || window.webkitURL
|
||||
const fileName = file.uid
|
||||
this.listObj[fileName] = {}
|
||||
return new Promise((resolve, reject) => {
|
||||
const img = new Image()
|
||||
img.src = _URL.createObjectURL(file)
|
||||
img.onload = function() {
|
||||
_self.listObj[fileName] = { hasSuccess: false, uid: file.uid, width: this.width, height: this.height }
|
||||
}
|
||||
resolve(true)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.editor-slide-upload {
|
||||
margin-bottom: 20px;
|
||||
::v-deep .el-upload--picture-card {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,59 @@
|
||||
let callbacks = []
|
||||
|
||||
function loadedTinymce() {
|
||||
// to fixed https://github.com/PanJiaChen/vue-element-admin/issues/2144
|
||||
// check is successfully downloaded script
|
||||
return window.tinymce
|
||||
}
|
||||
|
||||
const dynamicLoadScript = (src, callback) => {
|
||||
const existingScript = document.getElementById(src)
|
||||
const cb = callback || function() {}
|
||||
|
||||
if (!existingScript) {
|
||||
const script = document.createElement('script')
|
||||
script.src = src // src url for the third-party library being loaded.
|
||||
script.id = src
|
||||
document.body.appendChild(script)
|
||||
callbacks.push(cb)
|
||||
const onEnd = 'onload' in script ? stdOnEnd : ieOnEnd
|
||||
onEnd(script)
|
||||
}
|
||||
|
||||
if (existingScript && cb) {
|
||||
if (loadedTinymce()) {
|
||||
cb(null, existingScript)
|
||||
} else {
|
||||
callbacks.push(cb)
|
||||
}
|
||||
}
|
||||
|
||||
function stdOnEnd(script) {
|
||||
script.onload = function() {
|
||||
// this.onload = null here is necessary
|
||||
// because even IE9 works not like others
|
||||
this.onerror = this.onload = null
|
||||
for (const cb of callbacks) {
|
||||
cb(null, script)
|
||||
}
|
||||
callbacks = null
|
||||
}
|
||||
script.onerror = function() {
|
||||
this.onerror = this.onload = null
|
||||
cb(new Error('Failed to load ' + src), script)
|
||||
}
|
||||
}
|
||||
|
||||
function ieOnEnd(script) {
|
||||
script.onreadystatechange = function() {
|
||||
if (this.readyState !== 'complete' && this.readyState !== 'loaded') return
|
||||
this.onreadystatechange = null
|
||||
for (const cb of callbacks) {
|
||||
cb(null, script) // there is no way to catch loading errors in IE8
|
||||
}
|
||||
callbacks = null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default dynamicLoadScript
|
||||
@@ -0,0 +1,291 @@
|
||||
<template>
|
||||
<div
|
||||
:class="{ fullscreen: fullscreen }"
|
||||
class="tinymce-container"
|
||||
:style="{ width: containerWidth }">
|
||||
<textarea :id="tinymceId" class="tinymce-textarea" />
|
||||
<div class="editor-custom-btn-container">
|
||||
<editorImage
|
||||
color="#1890ff"
|
||||
class="editor-upload-btn"
|
||||
@successCBK="imageSuccessCBK"/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
/**
|
||||
* docs:
|
||||
* https://panjiachen.github.io/vue-element-admin-site/feature/component/rich-editor.html#tinymce
|
||||
*/
|
||||
import editorImage from './components/EditorImage'
|
||||
import plugins from './plugins'
|
||||
import toolbar from './toolbar'
|
||||
import load from './dynamicLoadScript'
|
||||
// import './plugins/media-plugin-magic-by-snowmile'
|
||||
|
||||
// why use this cdn, detail see https://github.com/PanJiaChen/tinymce-all-in-one
|
||||
const tinymceCDN =
|
||||
'https://cdn.jsdelivr.net/npm/tinymce-all-in-one@4.9.3/tinymce.min.js'
|
||||
|
||||
export default {
|
||||
name: 'Tinymce',
|
||||
components: { editorImage },
|
||||
props: {
|
||||
id: {
|
||||
type: String,
|
||||
default: function() {
|
||||
return (
|
||||
'vue-tinymce-' +
|
||||
+new Date() +
|
||||
((Math.random() * 1000).toFixed(0) + '')
|
||||
)
|
||||
}
|
||||
},
|
||||
value: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
toolbar: {
|
||||
type: Array,
|
||||
required: false,
|
||||
default() {
|
||||
return []
|
||||
}
|
||||
},
|
||||
menubar: {
|
||||
type: String,
|
||||
default: 'file edit insert view format table'
|
||||
},
|
||||
height: {
|
||||
type: [Number, String],
|
||||
required: false,
|
||||
default: 360
|
||||
},
|
||||
width: {
|
||||
type: [Number, String],
|
||||
required: false,
|
||||
default: 'auto'
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
hasChange: false,
|
||||
hasInit: false,
|
||||
tinymceId: this.id,
|
||||
fullscreen: false,
|
||||
domain: this.$store.getters.getSystemConfig.imgWebCdn, // 存放图片的域名
|
||||
languageTypeList: {
|
||||
en: 'en',
|
||||
zh: 'zh_CN',
|
||||
es: 'es_MX',
|
||||
ja: 'ja'
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
containerWidth() {
|
||||
const width = this.width
|
||||
if (/^[\d]+(\.[\d]+)?$/.test(width)) {
|
||||
// matches `100`, `'100'`
|
||||
return `${width}px`
|
||||
}
|
||||
return width
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
value(val) {
|
||||
if (!this.hasChange && this.hasInit) {
|
||||
this.$nextTick(() =>
|
||||
window.tinymce.get(this.tinymceId).setContent(val || '')
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.init()
|
||||
},
|
||||
activated() {
|
||||
if (window.tinymce) {
|
||||
this.initTinymce()
|
||||
}
|
||||
},
|
||||
deactivated() {
|
||||
this.destroyTinymce()
|
||||
},
|
||||
destroyed() {
|
||||
this.destroyTinymce()
|
||||
},
|
||||
methods: {
|
||||
init() {
|
||||
// dynamic load tinymce from cdn
|
||||
load(tinymceCDN, (err) => {
|
||||
if (err) {
|
||||
this.$message.error(err.message)
|
||||
return
|
||||
}
|
||||
this.initTinymce()
|
||||
})
|
||||
},
|
||||
initTinymce() {
|
||||
const _this = this
|
||||
window.tinymce.init({
|
||||
selector: `#${this.tinymceId}`,
|
||||
language: this.languageTypeList['zh'],
|
||||
height: this.height,
|
||||
body_class: 'panel-body ',
|
||||
object_resizing: false,
|
||||
toolbar: this.toolbar.length > 0 ? this.toolbar : toolbar,
|
||||
menubar: this.menubar,
|
||||
plugins: plugins,
|
||||
end_container_on_empty_block: true,
|
||||
powerpaste_word_import: 'clean',
|
||||
code_dialog_height: 450,
|
||||
code_dialog_width: 1000,
|
||||
file_picker_types: 'file image media',
|
||||
advlist_bullet_styles: 'square',
|
||||
advlist_number_styles: 'default',
|
||||
imagetools_cors_hosts: ['www.tinymce.com', 'codepen.io'],
|
||||
default_link_target: '_blank',
|
||||
link_title: false,
|
||||
nonbreaking_force_tab: true, // inserting nonbreaking space need Nonbreaking Space Plugin
|
||||
|
||||
init_instance_callback: (editor) => {
|
||||
if (_this.value) {
|
||||
editor.setContent(_this.value)
|
||||
}
|
||||
|
||||
_this.hasInit = true
|
||||
editor.on('NodeChange Change KeyUp SetContent', (event) => {
|
||||
this.hasChange = true
|
||||
this.$emit('input', editor.getContent())
|
||||
})
|
||||
},
|
||||
setup(editor) {
|
||||
editor.on('FullscreenStateChanged', (e) => {
|
||||
_this.fullscreen = e.state
|
||||
})
|
||||
},
|
||||
|
||||
images_upload_handler: function(blobInfo, succFun, failFun) {
|
||||
const file = blobInfo.blob() // 转化为易于理解的file对象
|
||||
const xhr = new XMLHttpRequest()
|
||||
xhr.withCredentials = false
|
||||
xhr.open('POST', '/api/web/mediafile/uploadImg')
|
||||
xhr.onload = function() {
|
||||
if (xhr.status !== 200) {
|
||||
failFun('HTTP Error: ' + xhr.status)
|
||||
return
|
||||
}
|
||||
const json = JSON.parse(xhr.responseText)
|
||||
|
||||
succFun(`${_this.domain}${json.data.path}`)
|
||||
_this.$emit('addPictur', json.data.path)
|
||||
}
|
||||
const formData = new FormData()
|
||||
formData.append('file', file, file.name) // 此处与源文档不一样
|
||||
xhr.send(formData)
|
||||
},
|
||||
|
||||
// it will try to keep these URLs intact
|
||||
// https://www.tiny.cloud/docs-3x/reference/configuration/Configuration3x@convert_urls/
|
||||
// https://stackoverflow.com/questions/5196205/disable-tinymce-absolute-to-relative-url-conversions
|
||||
convert_urls: false
|
||||
// 整合七牛上传
|
||||
// images_dataimg_filter(img) {
|
||||
// setTimeout(() => {
|
||||
// const $image = $(img);
|
||||
// $image.removeAttr('width');
|
||||
// $image.removeAttr('height');
|
||||
// if ($image[0].height && $image[0].width) {
|
||||
// $image.attr('data-wscntype', 'image');
|
||||
// $image.attr('data-wscnh', $image[0].height);
|
||||
// $image.attr('data-wscnw', $image[0].width);
|
||||
// $image.addClass('wscnph');
|
||||
// }
|
||||
// }, 0);
|
||||
// return img
|
||||
// },
|
||||
// images_upload_handler(blobInfo, success, failure, progress) {
|
||||
// progress(0);
|
||||
// const token = _this.$store.getters.token;
|
||||
// getToken(token).then(response => {
|
||||
// const url = response.data.qiniu_url;
|
||||
// const formData = new FormData();
|
||||
// formData.append('token', response.data.qiniu_token);
|
||||
// formData.append('key', response.data.qiniu_key);
|
||||
// formData.append('file', blobInfo.blob(), url);
|
||||
// upload(formData).then(() => {
|
||||
// success(url);
|
||||
// progress(100);
|
||||
// })
|
||||
// }).catch(err => {
|
||||
// failure('出现未知问题,刷新页面,或者联系程序员')
|
||||
// console.log(err);
|
||||
// });
|
||||
// },
|
||||
})
|
||||
},
|
||||
destroyTinymce() {
|
||||
const tinymce = window.tinymce.get(this.tinymceId)
|
||||
if (this.fullscreen) {
|
||||
tinymce.execCommand('mceFullScreen')
|
||||
}
|
||||
|
||||
if (tinymce) {
|
||||
tinymce.destroy()
|
||||
}
|
||||
},
|
||||
setContent(value) {
|
||||
window.tinymce.get(this.tinymceId).setContent(value)
|
||||
},
|
||||
getContent() {
|
||||
window.tinymce.get(this.tinymceId).getContent()
|
||||
},
|
||||
imageSuccessCBK(arr) {
|
||||
console.log(arr, '===========')
|
||||
// arr.forEach((v) =>
|
||||
// window.tinymce
|
||||
// .get(this.tinymceId)
|
||||
// .insertContent(`<img class="wscnph" style="width:164px;height:92px;margin-right:15px;" src="${v.url}" >`)
|
||||
// );
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.tinymce-container {
|
||||
position: relative;
|
||||
line-height: normal;
|
||||
}
|
||||
|
||||
.tinymce-container {
|
||||
::v-deep {
|
||||
.mce-fullscreen {
|
||||
z-index: 10000;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tinymce-textarea {
|
||||
visibility: hidden;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
.editor-custom-btn-container {
|
||||
position: absolute;
|
||||
right: 4px;
|
||||
top: 4px;
|
||||
/*z-index: 2005;*/
|
||||
}
|
||||
|
||||
.fullscreen .editor-custom-btn-container {
|
||||
z-index: 10000;
|
||||
position: fixed;
|
||||
}
|
||||
|
||||
.editor-upload-btn {
|
||||
display: inline-block;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,7 @@
|
||||
// Any plugins you want to use has to be imported
|
||||
// Detail plugins list see https://www.tinymce.com/docs/plugins/
|
||||
// Custom builds see https://www.tinymce.com/download/custom-builds/
|
||||
|
||||
const plugins = ['advlist anchor autolink autosave code codesample colorpicker colorpicker contextmenu directionality emoticons fullscreen hr image imagetools insertdatetime link lists media nonbreaking noneditable pagebreak paste preview print save searchreplace spellchecker tabfocus table template textcolor textpattern visualblocks visualchars wordcount']
|
||||
|
||||
export default plugins
|
||||
@@ -0,0 +1,6 @@
|
||||
// Here is a list of the toolbar
|
||||
// Detail list see https://www.tinymce.com/docs/advanced/editor-control-identifiers/#toolbarcontrols
|
||||
|
||||
const toolbar = ['searchreplace bold italic underline strikethrough alignleft aligncenter alignright outdent indent blockquote undo redo removeformat subscript superscript code codesample', 'hr bullist numlist link image charmap preview anchor pagebreak insertdatetime media table emoticons forecolor backcolor fullscreen']
|
||||
|
||||
export default toolbar
|
||||
@@ -0,0 +1,84 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
:close-on-click-modal="false"
|
||||
:title="dialogTitle"
|
||||
:visible.sync="visible"
|
||||
@close="close"
|
||||
width="520px"
|
||||
center>
|
||||
<el-form
|
||||
ref="form"
|
||||
:model="form"
|
||||
label-width="100px">
|
||||
<el-form-item label="Slug">
|
||||
<el-input
|
||||
v-model="form.slug"
|
||||
placeholder="请输入slug,可为空"
|
||||
@input="handleSlugInput" />
|
||||
</el-form-item>
|
||||
<el-form-item label="谷歌验证码">
|
||||
<el-input
|
||||
v-model.trim="form.googleCode"
|
||||
placeholder="请输入谷歌验证码" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="close">取 消</el-button>
|
||||
<el-button type="primary" @click="submit">确 定</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'UpdateSlugDialog',
|
||||
props: {
|
||||
data: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
visible: true,
|
||||
form: {
|
||||
id: undefined,
|
||||
slug: '',
|
||||
googleCode: ''
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
dialogTitle() {
|
||||
const moduleName = this.data.title || 'Slug'
|
||||
return `${moduleName}配置`
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
const row = this.data.data || {}
|
||||
this.form = {
|
||||
id: row.id,
|
||||
slug: this.sanitizeSlug(row.slug),
|
||||
googleCode: ''
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
sanitizeSlug(slug) {
|
||||
return typeof slug === 'string' ? slug.replace(/\s+/g, '') : ''
|
||||
},
|
||||
handleSlugInput(value) {
|
||||
this.form.slug = this.sanitizeSlug(value)
|
||||
},
|
||||
submit() {
|
||||
this.$emit('submit', {
|
||||
id: this.form.id,
|
||||
slug: this.sanitizeSlug(this.form.slug),
|
||||
googleCode: this.form.googleCode
|
||||
})
|
||||
},
|
||||
close() {
|
||||
this.$emit('close', false)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,236 @@
|
||||
<!--
|
||||
* @Author: 王涛
|
||||
* @Mail: no
|
||||
* @Date: 2020-09-29 19:56:44
|
||||
* @LastEditors: Please set LastEditors
|
||||
* @LastEditTime: 2022-03-29 15:47:16
|
||||
-->
|
||||
<template>
|
||||
<div>
|
||||
<draggable v-model="locaImg" class="list-group" tag="ul" v-bind="dragOptions" @start="drag = true" @end="drag = false">
|
||||
<div v-for="(item,index) in locaImg" :key="index" class="image-list" style="float: left;">
|
||||
<img class="el-upload-list__item-thumbnail image-detail" :src="domain+item.comicsPic" alt="">
|
||||
|
||||
<!-- 遮罩层 -->
|
||||
<a href="#">
|
||||
<div class="image-mask">
|
||||
<span class="add" @click="handlePictureCardPreview(domain+item.comicsPic)">
|
||||
<i class="el-icon-view"></i>
|
||||
</span>
|
||||
<span class="delete" @click="removeImage(index)">
|
||||
<i class="el-icon-delete"></i>
|
||||
</span>
|
||||
</div>
|
||||
</a>
|
||||
<el-dialog :visible.sync="dialogVisible" append-to-body>
|
||||
<img width="100%" :src="dialogImageUrl" alt="">
|
||||
</el-dialog>
|
||||
<el-input v-model.number="item.high" placeholder="高" style="width: 70px" />
|
||||
<el-input v-model.number="item.width" placeholder="宽" style="width: 70px" />
|
||||
</div>
|
||||
</draggable>
|
||||
<el-upload action="/api/web/file/uploadImg" :show-file-list="false" list-type="picture-card" :file-list="fileList" :on-preview="handlePictureCardPreview" :on-change="handleChange" multiple :limit='100'>
|
||||
<i class="el-icon-plus"></i>
|
||||
</el-upload>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import draggable from 'vuedraggable'
|
||||
export default {
|
||||
components: { draggable },
|
||||
data() {
|
||||
return {
|
||||
domain: this.$store.getters.getSystemConfig.imgWebCdn, // 播放视频的域名
|
||||
returnURL: [],
|
||||
dialogImageUrl: '',
|
||||
dialogVisible: false,
|
||||
fileList: [
|
||||
// { name: 'food.jpeg', url: 'https://fuss10.elemecdn.com/3/63/4e7f3a15429bfda99bce42a18cdd1jpeg.jpeg?imageMogr2/thumbnail/360x360/format/webp/quality/100' },
|
||||
// { name: 'food2.jpeg', url: 'https://fuss10.elemecdn.com/3/63/4e7f3a15429bfda99bce42a18cdd1jpeg.jpeg?imageMogr2/thumbnail/360x360/format/webp/quality/100' }
|
||||
],
|
||||
drag: false, // 拖拽效果是否开启
|
||||
locaImg: []
|
||||
}
|
||||
},
|
||||
props: {
|
||||
img: {
|
||||
type: Array,
|
||||
default: function() {
|
||||
return []
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
dragOptions() {
|
||||
return {
|
||||
animation: 200,
|
||||
group: 'description',
|
||||
disabled: false,
|
||||
ghostClass: 'ghost'
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
// 监听拖动事件改变时,传出新的图片数组
|
||||
drag() {
|
||||
this.changeImgUrl()
|
||||
},
|
||||
img(New, old) {
|
||||
this.locaImg = []
|
||||
New.filter((item) => {
|
||||
this.locaImg.push(item)
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.locaImg = []
|
||||
if (this.img) {
|
||||
this.img.filter((item) => {
|
||||
this.locaImg.push(item)
|
||||
})
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleChange(file, fileList) {
|
||||
if (file.status === 'success') {
|
||||
// this.locaImg.push(file.response.data.path)
|
||||
this.locaImg.push({
|
||||
high: undefined,
|
||||
width: undefined,
|
||||
comicsPic: file.response.data.path
|
||||
})
|
||||
this.changeImgUrl()
|
||||
}
|
||||
},
|
||||
|
||||
// 移除图片
|
||||
removeImage(val) {
|
||||
this.locaImg.splice(val, 1)
|
||||
this.changeImgUrl()
|
||||
},
|
||||
// 预览
|
||||
handlePictureCardPreview(url) {
|
||||
this.dialogImageUrl = url
|
||||
this.dialogVisible = true
|
||||
},
|
||||
changeImgUrl(arr) {
|
||||
this.$emit('changeImgUrl', this.locaImg)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.list-group {
|
||||
padding: 0px;
|
||||
margin: 0px;
|
||||
}
|
||||
.avatar-uploader .el-upload {
|
||||
border: 1px dashed #d9d9d9;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
.avatar-uploader .el-upload:hover {
|
||||
border-color: #409eff;
|
||||
}
|
||||
.avatar-uploader-icon {
|
||||
font-size: 28px;
|
||||
color: #8c939d;
|
||||
width: 148px;
|
||||
height: 148px;
|
||||
line-height: 148px;
|
||||
text-align: center;
|
||||
}
|
||||
.avatar {
|
||||
width: 148px;
|
||||
height: 148px;
|
||||
display: block;
|
||||
}
|
||||
.image-list {
|
||||
overflow: hidden;
|
||||
background-color: #fff;
|
||||
border: 1px solid #c0ccda;
|
||||
border-radius: 6px;
|
||||
box-sizing: border-box;
|
||||
width: 148px;
|
||||
height: 202px;
|
||||
margin: 0 8px 8px 0;
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
img {
|
||||
width: 148px;
|
||||
height: 148px;
|
||||
}
|
||||
}
|
||||
.image-list a:hover .image-mask {
|
||||
opacity: 1;
|
||||
}
|
||||
.el-icon-check {
|
||||
color: #fff;
|
||||
}
|
||||
.input-box {
|
||||
width: 80%;
|
||||
}
|
||||
.el-upload--picture-card {
|
||||
background-color: #fbfdff;
|
||||
border: 1px dashed #c0ccda;
|
||||
border-radius: 6px;
|
||||
box-sizing: border-box;
|
||||
width: 148px;
|
||||
height: 148px;
|
||||
line-height: 146px;
|
||||
vertical-align: top;
|
||||
}
|
||||
.image-mask {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
left: 0;
|
||||
top: 0;
|
||||
cursor: default;
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
opacity: 0;
|
||||
font-size: 20px;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
transition: opacity 0.3s;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
.image-detail {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
}
|
||||
.image-mask::after {
|
||||
display: inline-block;
|
||||
content: '';
|
||||
height: 100%;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.image-mask span {
|
||||
display: block;
|
||||
cursor: pointer;
|
||||
margin: 40% auto;
|
||||
}
|
||||
.image-mask .el-upload-list__item-delete {
|
||||
position: static;
|
||||
font-size: inherit;
|
||||
color: inherit;
|
||||
}
|
||||
.add {
|
||||
padding-left: 20px;
|
||||
}
|
||||
.delete {
|
||||
padding-right: 20px;
|
||||
}
|
||||
// .el-icon-delete {
|
||||
// z-index: 9999999;
|
||||
// position: absolute;
|
||||
// bottom: 70px;
|
||||
// right: 10px;
|
||||
// color: red;
|
||||
// }
|
||||
</style>
|
||||
@@ -0,0 +1,393 @@
|
||||
<template>
|
||||
<div>
|
||||
<div v-loading="loading" element-loading-text="图片上传中" customClass >
|
||||
<div style="display: block;overflow: hidden;max-width: 655px;padding-top: 25px;">
|
||||
<draggable
|
||||
v-model="locaImg"
|
||||
class="list-group"
|
||||
tag="ul"
|
||||
v-bind="dragOptions"
|
||||
@start="drag = true"
|
||||
@end="drag = false">
|
||||
<div v-for="(item, index) in locaImg" :key="index" class="image-list" style="float: left;">
|
||||
<img class="el-upload-list__item-thumbnail image-detail" @load="imgLoad(item)" :src="item.imgLocalUrl||domain + item.comicsPic" alt="">
|
||||
<!-- 遮罩层 -->
|
||||
<a href="#">
|
||||
<div class="image-mask">
|
||||
<span class="add" @click="handlePictureCardPreview(item.imgLocalUrl||domain + item.comicsPic)">
|
||||
<i class="el-icon-view"></i>
|
||||
</span>
|
||||
<span class="delete" @click="removeImage(index)">
|
||||
<i class="el-icon-delete"></i>
|
||||
</span>
|
||||
</div>
|
||||
</a>
|
||||
<el-dialog :visible.sync="dialogVisible" append-to-body>
|
||||
<img width="100%" :src="dialogImageUrl" alt="">
|
||||
</el-dialog>
|
||||
<el-input v-model.number="item.high" placeholder="高" style="width: 70px" />
|
||||
<el-input v-model.number="item.width" placeholder="宽" style="width: 70px" />
|
||||
</div>
|
||||
</draggable>
|
||||
</div>
|
||||
<div style="display: block;overflow: hidden;max-width: 655px;">
|
||||
<el-upload
|
||||
action="/api/web/file/uploadImg"
|
||||
ref="upload"
|
||||
:httpRequest="httpRequest"
|
||||
:show-file-list="false"
|
||||
:auto-upload="false"
|
||||
list-type="text"
|
||||
:on-preview="handlePictureCardPreview"
|
||||
:on-change="handleChange"
|
||||
multiple
|
||||
:limit='10000'>
|
||||
<!-- <i class="el-icon-plus"></i> -->
|
||||
|
||||
<el-button slot="trigger" icon="el-icon-folder-opened" size="small" style="font-weight: bold;" type="primary">选取图片</el-button>
|
||||
<el-button size="small" icon="el-icon-delete" style="margin-left: 10px;font-weight: bold;" @click="clearFiles" type="primary">清空选择图片</el-button>
|
||||
<el-button size="small" icon="el-icon-delete" style="margin-left: 10px;font-weight: bold;" @click="clearUploadFiles" type="primary">清空上传图片
|
||||
</el-button>
|
||||
<el-button style="margin-left: 10px;font-weight: bold;" size="small" icon="el-icon-upload" type="primary" @click="submitUpload">上传图片</el-button>
|
||||
</el-upload>
|
||||
</div>
|
||||
</div>
|
||||
<div style="display: block;overflow: hidden;width: 655px;margin-top: 45px;">
|
||||
<el-table
|
||||
:data="fileList"
|
||||
empty-text="暂无选择图片"
|
||||
:header-row-style="{ 'height': '30px !important' }"
|
||||
header-cell-class-name="uploadHeader"
|
||||
height="200"
|
||||
size="mini"
|
||||
style="width: 100%">
|
||||
<el-table-column prop="name" :label="`已选择图片(${fileList.length}张)`">
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import draggable from 'vuedraggable'
|
||||
import axios from 'axios'
|
||||
const CancelToken = axios.CancelToken
|
||||
export const source = CancelToken.source()
|
||||
import { upLoadFile } from '@/api/common'
|
||||
|
||||
export default {
|
||||
components: { draggable },
|
||||
data() {
|
||||
const source = axios.CancelToken.source()
|
||||
return {
|
||||
domain: this.$store.getters.getSystemConfig.imgWebCdn, // 播放视频的域名
|
||||
returnURL: [],
|
||||
dialogImageUrl: '',
|
||||
dialogVisible: false,
|
||||
fileList: [],
|
||||
drag: false, // 拖拽效果是否开启
|
||||
locaImg: [],
|
||||
loading: false,
|
||||
source
|
||||
}
|
||||
},
|
||||
props: {
|
||||
img: {
|
||||
type: Array,
|
||||
default: function() {
|
||||
return []
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
dragOptions() {
|
||||
return {
|
||||
animation: 200,
|
||||
group: 'description',
|
||||
disabled: false,
|
||||
ghostClass: 'ghost'
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
// 监听拖动事件改变时,传出新的图片数组
|
||||
drag() {
|
||||
this.changeImgUrl()
|
||||
},
|
||||
img(New, old) {
|
||||
this.locaImg = []
|
||||
New.filter((item) => {
|
||||
this.locaImg.push(item)
|
||||
})
|
||||
}
|
||||
// locaImg: {
|
||||
// handler: function (val, oldVal) {
|
||||
// if (this.fileList.length !== 0 && val.length === this.fileList.length) {
|
||||
// this.setIsUploadIng(false)
|
||||
// }
|
||||
// },
|
||||
// deep: true
|
||||
// }
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.locaImg = []
|
||||
if (this.img) {
|
||||
this.img.filter((item) => {
|
||||
this.locaImg.push(item)
|
||||
})
|
||||
}
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.source.cancel('组件关闭取消所有请求')
|
||||
this.source = axios.CancelToken.source()
|
||||
},
|
||||
methods: {
|
||||
handleChange(file, fileList) {
|
||||
this.fileList = fileList
|
||||
},
|
||||
imgLoad(item) {
|
||||
// if (item.imgLocalUrl) {
|
||||
// URL.revokeObjectURL(item.imgLocalUrl)
|
||||
// }
|
||||
},
|
||||
clearFiles() {
|
||||
if (this.$refs.upload && this.$refs.upload.clearFiles) {
|
||||
this.$refs.upload.clearFiles()
|
||||
}
|
||||
this.fileList = []
|
||||
},
|
||||
clearUploadFiles() {
|
||||
this.locaImg = []
|
||||
this.changeImgUrl()
|
||||
},
|
||||
httpRequest() {
|
||||
return false
|
||||
},
|
||||
async upLoad() {
|
||||
this.loading = true
|
||||
this.setIsUploadIng(true)
|
||||
let isUploadFail = false
|
||||
const filePathPromises = this.fileList.map(async item => {
|
||||
try {
|
||||
const fd = new FormData()
|
||||
fd.append('file', item.raw)
|
||||
fd.append('filename', item.name)
|
||||
const response = await upLoadFile(fd, this.source)
|
||||
response.data.imgLocalUrl = URL.createObjectURL(item.raw)
|
||||
return response.data
|
||||
} catch (error) {
|
||||
isUploadFail = true
|
||||
if (axios.isCancel(error)) {
|
||||
console.log('CancelToken canceled', error.message)
|
||||
} else {
|
||||
this.source.cancel('有任意一个图片上传错误,取消所有请求')
|
||||
this.source = axios.CancelToken.source()
|
||||
this.$notify.error({
|
||||
title: '上传失败',
|
||||
message: '请您重新上传图片!',
|
||||
duration: 0
|
||||
})
|
||||
}
|
||||
this.loading = false
|
||||
this.locaImg = []
|
||||
}
|
||||
})
|
||||
for (const filePathPromise of filePathPromises) {
|
||||
try {
|
||||
const res = await filePathPromise
|
||||
if (res && res.path) {
|
||||
this.locaImg.push({
|
||||
high: undefined,
|
||||
width: undefined,
|
||||
comicsPic: res.path,
|
||||
imgLocalUrl: res.imgLocalUrl
|
||||
})
|
||||
} else {
|
||||
isUploadFail = true
|
||||
throw new Error('locaImg.push阶段错误,请求无返回数据')
|
||||
}
|
||||
} catch (error) {
|
||||
isUploadFail = true
|
||||
this.loading = false
|
||||
this.locaImg = []
|
||||
console.log(error)
|
||||
}
|
||||
}
|
||||
!isUploadFail && this.clearFiles()
|
||||
if (isUploadFail) {
|
||||
this.locaImg = []
|
||||
}
|
||||
this.loading = false
|
||||
this.setIsUploadIng(false)
|
||||
this.changeImgUrl()
|
||||
},
|
||||
submitUpload() {
|
||||
this.upLoad()
|
||||
},
|
||||
// 移除图片
|
||||
removeImage(val) {
|
||||
this.locaImg.splice(val, 1)
|
||||
this.changeImgUrl()
|
||||
},
|
||||
// 预览
|
||||
handlePictureCardPreview(url) {
|
||||
this.dialogImageUrl = url
|
||||
this.dialogVisible = true
|
||||
},
|
||||
changeImgUrl(arr) {
|
||||
this.$emit('changeImgUrl', this.locaImg)
|
||||
},
|
||||
setIsUploadIng(status) {
|
||||
this.$emit('setIsUploadIng', status)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.list-group {
|
||||
padding: 0px;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
.avatar-uploader .el-upload {
|
||||
border: 1px dashed #d9d9d9;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.avatar-uploader .el-upload:hover {
|
||||
border-color: #409eff;
|
||||
}
|
||||
|
||||
.avatar-uploader-icon {
|
||||
font-size: 28px;
|
||||
color: #8c939d;
|
||||
width: 148px;
|
||||
height: 148px;
|
||||
line-height: 148px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
width: 148px;
|
||||
height: 148px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.image-list {
|
||||
overflow: hidden;
|
||||
background-color: #fff;
|
||||
border: 1px solid #c0ccda;
|
||||
border-radius: 6px;
|
||||
box-sizing: border-box;
|
||||
width: 148px;
|
||||
height: 202px;
|
||||
margin: 0 8px 8px 0;
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
|
||||
img {
|
||||
width: 148px;
|
||||
height: 148px;
|
||||
}
|
||||
}
|
||||
|
||||
.image-list a:hover .image-mask {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.el-icon-check {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.input-box {
|
||||
width: 80%;
|
||||
}
|
||||
|
||||
.el-upload--picture-card {
|
||||
background-color: #fbfdff;
|
||||
border: 1px dashed #c0ccda;
|
||||
border-radius: 6px;
|
||||
box-sizing: border-box;
|
||||
width: 148px;
|
||||
height: 148px;
|
||||
line-height: 146px;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.image-mask {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
left: 0;
|
||||
top: 0;
|
||||
cursor: default;
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
opacity: 0;
|
||||
font-size: 20px;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
transition: opacity 0.3s;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.image-detail {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.image-mask::after {
|
||||
display: inline-block;
|
||||
content: '';
|
||||
height: 100%;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.image-mask span {
|
||||
display: block;
|
||||
cursor: pointer;
|
||||
margin: 40% auto;
|
||||
}
|
||||
|
||||
.image-mask .el-upload-list__item-delete {
|
||||
position: static;
|
||||
font-size: inherit;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.add {
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
.delete {
|
||||
padding-right: 20px;
|
||||
}
|
||||
|
||||
// .el-icon-delete {
|
||||
// z-index: 9999999;
|
||||
// position: absolute;
|
||||
// bottom: 70px;
|
||||
// right: 10px;
|
||||
// color: red;
|
||||
// }
|
||||
// .el-table .uploadHeader{
|
||||
// background-color: #d9d9d9 !important;
|
||||
// }
|
||||
</style>
|
||||
<style lang="scss" >
|
||||
.el-table .uploadHeader {
|
||||
background-color: #666 !important;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.el-table .uploadHeader+th {
|
||||
padding: 0;
|
||||
background-color: #666 !important;
|
||||
border-bottom: 1px solid #dfdfdf !important;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,242 @@
|
||||
<!--
|
||||
* @Author: 王涛
|
||||
* @Mail: no
|
||||
* @Date: 2020-09-29 19:56:44
|
||||
* @LastEditors: Administrator admin@example.com
|
||||
* @LastEditTime: 2024-11-19 10:14:08
|
||||
-->
|
||||
<template>
|
||||
<!-- 使用方法 <UploadImg @changeImgUrl='changeMobileAvatar' :img='form.mobileAvatar' :width='"100px"' :height='"100px"'></UploadImg>
|
||||
changeMobileAvatar(data) {
|
||||
this.form.mobileAvatar = data
|
||||
}, -->
|
||||
<el-upload
|
||||
class="avatar-uploader"
|
||||
:action="action"
|
||||
:show-file-list="false"
|
||||
:on-success="handleAvatarSuccess"
|
||||
:data="{ appId: $store.getters.appId }"
|
||||
:before-upload="beforeAvatarUpload"
|
||||
:disabled="displayOnly">
|
||||
<div ref="uploader">
|
||||
<img v-if="newImg" :src="newImg" class="avatar" />
|
||||
<i v-if="imageUrl && !displayOnly" @click.stop="handleRemove" class="el-icon-delete"></i>
|
||||
<i v-if="!newImg && !displayOnly" class="el-icon-plus avatar-uploader-icon"></i>
|
||||
</div>
|
||||
</el-upload>
|
||||
</template>
|
||||
<script>
|
||||
import { handleVerAutoImg } from '@/utils/index.js'
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
imageUrl: '',
|
||||
newImg: ''
|
||||
}
|
||||
},
|
||||
props: {
|
||||
img: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
width: {
|
||||
type: String,
|
||||
default: '180px'
|
||||
},
|
||||
height: {
|
||||
type: String,
|
||||
default: '180px'
|
||||
},
|
||||
index: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
showIndex: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
action: {
|
||||
type: String,
|
||||
default: '/media/web/upload/image'
|
||||
},
|
||||
domain: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
displayOnly: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
currentDomain() {
|
||||
return this.domain || this.$store.getters.getSystemConfig.imgWebCdn || ''
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
img: function(val, oldval) {
|
||||
this.imageUrl = val
|
||||
},
|
||||
imageUrl: async function(val, oldval) {
|
||||
if (!val) {
|
||||
this.newImg = ''
|
||||
return
|
||||
}
|
||||
const a = await handleVerAutoImg(this.buildImageUrl(val))
|
||||
this.newImg = a
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.$refs['uploader'].style.width = this.width
|
||||
this.$refs['uploader'].style.height = this.height
|
||||
this.$refs['uploader'].style.lineHeight = this.height
|
||||
if (this.img) {
|
||||
this.imageUrl = this.img
|
||||
} else {
|
||||
this.imageUrl = ''
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
buildImageUrl(path) {
|
||||
if (!path) return ''
|
||||
if (/^(blob:|https?:\/\/|data:)/.test(path)) return path
|
||||
const base = this.currentDomain || ''
|
||||
if (!base) return path
|
||||
const normalizedBase = base.endsWith('/') ? base.slice(0, -1) : base
|
||||
const normalizedPath = path.startsWith('/') ? path : `/${path}`
|
||||
return `${normalizedBase}${normalizedPath}`
|
||||
},
|
||||
async changeImg(url) {
|
||||
|
||||
},
|
||||
handleAvatarSuccess(res, file) {
|
||||
if (res.code === 200) {
|
||||
this.$message({
|
||||
type: 'success',
|
||||
message: '上传成功!'
|
||||
})
|
||||
|
||||
this.imageUrl = res.data.path
|
||||
this.changeImgUrl()
|
||||
} else {
|
||||
this.$message({
|
||||
type: 'error',
|
||||
message: '上传失败!'
|
||||
})
|
||||
this.imageUrl = ''
|
||||
}
|
||||
},
|
||||
changeImgUrl() {
|
||||
if (this.showIndex) {
|
||||
this.$emit('changeImgUrl', { url: this.imageUrl, index: this.index })
|
||||
} else {
|
||||
this.$emit('changeImgUrl', this.imageUrl)
|
||||
}
|
||||
},
|
||||
handleRemove() {
|
||||
this.imageUrl = ''
|
||||
this.changeImgUrl()
|
||||
if (this.showIndex) {
|
||||
this.$emit('onRemove', { key: '', index: this.index })
|
||||
} else {
|
||||
this.$emit('onRemove')
|
||||
}
|
||||
},
|
||||
// 上传前进行压缩
|
||||
beforeAvatarUpload(file) {
|
||||
const isJPG =
|
||||
file.type === 'image/jpeg' ||
|
||||
file.type === 'image/png' ||
|
||||
file.type === 'image/gif' ||
|
||||
file.type === 'image/webp'
|
||||
// const isLt2M = file.size / 1024 / 1024 < 2
|
||||
if (!isJPG) {
|
||||
this.$message({
|
||||
type: 'error',
|
||||
message: '上传图片只能是 JPG 格式!!'
|
||||
})
|
||||
}
|
||||
// if (!isLt2M) {
|
||||
// this.$message({
|
||||
// type: 'error',
|
||||
// message: '上传图片大小不能超过 2MB!!'
|
||||
// })
|
||||
// }
|
||||
return isJPG
|
||||
},
|
||||
|
||||
// 图片等比压缩
|
||||
handleCompressImage(file, type) {
|
||||
return new Promise((resolve, reject) => {
|
||||
try {
|
||||
const reader = new FileReader()
|
||||
reader.readAsDataURL(file)
|
||||
reader.onload = (e) => {
|
||||
const image = new Image()
|
||||
image.src = e.target.result
|
||||
image.onload = () => {
|
||||
if (image.width > 720) {
|
||||
const canvas = document.createElement('canvas')
|
||||
const context = canvas.getContext('2d')
|
||||
const imageWidth = 720
|
||||
const imageHeight = (720 / image.width) * image.height
|
||||
canvas.width = imageWidth
|
||||
canvas.height = imageHeight
|
||||
context.drawImage(image, 0, 0, imageWidth, imageHeight)
|
||||
canvas.toBlob(
|
||||
(blob) => {
|
||||
resolve(new Blob([blob], { type: type }))
|
||||
},
|
||||
'image/jpeg',
|
||||
0.9
|
||||
)
|
||||
} else {
|
||||
resolve(file)
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
reject(e)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style scoped>
|
||||
.avatar-uploader {
|
||||
.el-upload {
|
||||
border: 1px dashed #d9d9d9;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
.el-upload:hover {
|
||||
border-color: #409eff;
|
||||
}
|
||||
}
|
||||
.avatar-uploader-icon {
|
||||
font-size: 28px;
|
||||
color: #d9d9d9;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
line-height: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
.avatar {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
display: block;
|
||||
object-fit: contain;
|
||||
}
|
||||
.el-icon-delete {
|
||||
z-index: 9999999;
|
||||
position: absolute;
|
||||
bottom: 10px;
|
||||
right: 10px;
|
||||
color: red;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,256 @@
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<draggable v-model="locaImg" class="list-group" tag="ul" v-bind="dragOptions" @start="drag=true" @end="drag=false">
|
||||
<div v-for="(img,index) in imgSrc" :key="index" class="image-list" style="float: left;">
|
||||
<img class="el-upload-list__item-thumbnail image-detail" :src="img" alt="">
|
||||
<!-- 遮罩层 -->
|
||||
<a href="#">
|
||||
<div class="image-mask">
|
||||
<span class="add" @click="handlePictureCardPreview(img)">
|
||||
<i class="el-icon-view"></i>
|
||||
</span>
|
||||
<span class="delete" @click="removeImage(index)">
|
||||
<i class="el-icon-delete"></i>
|
||||
</span>
|
||||
</div>
|
||||
</a>
|
||||
<el-dialog :visible.sync="dialogVisible" append-to-body>
|
||||
<img :src="dialogImageUrl" alt="">
|
||||
</el-dialog>
|
||||
</div>
|
||||
</draggable>
|
||||
<el-upload :data="{ appId: $store.getters.appId }" :action="action" :show-file-list="false" list-type="picture-card" :file-list="fileList" :on-preview="handlePictureCardPreview" :on-change="handleChange" multiple :limit='100'>
|
||||
<i class="el-icon-plus"></i>
|
||||
</el-upload>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import draggable from 'vuedraggable'
|
||||
import { handleVerAutoImg } from '@/utils/index.js'
|
||||
export default {
|
||||
components: { draggable },
|
||||
data() {
|
||||
return {
|
||||
returnURL: [],
|
||||
dialogImageUrl: '',
|
||||
dialogVisible: false,
|
||||
fileList: [
|
||||
|
||||
],
|
||||
drag: false, // 拖拽效果是否开启
|
||||
locaImg: [],
|
||||
imgSrc: []
|
||||
|
||||
}
|
||||
},
|
||||
props: {
|
||||
img: {
|
||||
type: Array,
|
||||
default: function() {
|
||||
return []
|
||||
}
|
||||
},
|
||||
keyName: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
action: {
|
||||
type: String,
|
||||
default: '/media/web/upload/image'
|
||||
},
|
||||
domain: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
index: {
|
||||
type: Number,
|
||||
default: function() {
|
||||
return 0
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
currentDomain() {
|
||||
return this.domain || this.$store.getters.getSystemConfig.imgWebCdn || ''
|
||||
},
|
||||
dragOptions() {
|
||||
return {
|
||||
animation: 200,
|
||||
group: 'description',
|
||||
disabled: false,
|
||||
ghostClass: 'ghost'
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
watch: {
|
||||
// 监听拖动事件改变时,传出新的图片数组
|
||||
drag(event) {
|
||||
this.changeImgUrl()
|
||||
},
|
||||
img(New, old) {
|
||||
this.locaImg = []
|
||||
New.filter((item) => {
|
||||
this.locaImg.push(item)
|
||||
})
|
||||
},
|
||||
locaImg: {
|
||||
async handler(n, old) {
|
||||
this.imgSrc = await Promise.all(n.map(img => this.changeImg(img)))
|
||||
},
|
||||
immediate: true
|
||||
}
|
||||
},
|
||||
|
||||
async mounted() {
|
||||
this.locaImg = []
|
||||
if (this.img) {
|
||||
this.img.filter((item) => {
|
||||
this.locaImg.push(item)
|
||||
})
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
buildImageUrl(path) {
|
||||
if (!path) return ''
|
||||
if (/^(blob:|https?:\/\/|data:)/.test(path)) return path
|
||||
const base = this.currentDomain || ''
|
||||
if (!base) return path
|
||||
const normalizedBase = base.endsWith('/') ? base.slice(0, -1) : base
|
||||
const normalizedPath = path.startsWith('/') ? path : `/${path}`
|
||||
return `${normalizedBase}${normalizedPath}`
|
||||
},
|
||||
async changeImg(img) {
|
||||
// 这里应该替换为真实的异步代码
|
||||
const a = await handleVerAutoImg(this.buildImageUrl(img))
|
||||
return a
|
||||
},
|
||||
|
||||
handleChange(file, fileList) {
|
||||
if (file.status === 'success') {
|
||||
this.locaImg.push(file.response.data.path)
|
||||
this.changeImgUrl()
|
||||
}
|
||||
},
|
||||
|
||||
// 移除图片
|
||||
removeImage(val) {
|
||||
this.locaImg.splice(val, 1)
|
||||
this.changeImgUrl()
|
||||
},
|
||||
// 预览
|
||||
handlePictureCardPreview(url) {
|
||||
this.dialogImageUrl = url
|
||||
this.dialogVisible = true
|
||||
},
|
||||
changeImgUrl(arr) {
|
||||
this.$emit('changeImgUrl', this.locaImg, this.index, this.keyName)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.list-group {
|
||||
padding: 0px;
|
||||
margin: 0px;
|
||||
}
|
||||
.avatar-uploader .el-upload {
|
||||
border: 1px dashed #d9d9d9;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
.avatar-uploader .el-upload:hover {
|
||||
border-color: #409eff;
|
||||
}
|
||||
.avatar-uploader-icon {
|
||||
font-size: 28px;
|
||||
color: #8c939d;
|
||||
width: 148px;
|
||||
height: 148px;
|
||||
line-height: 148px;
|
||||
text-align: center;
|
||||
}
|
||||
.avatar {
|
||||
width: 148px;
|
||||
height: 148px;
|
||||
display: block;
|
||||
}
|
||||
.image-list {
|
||||
overflow: hidden;
|
||||
background-color: #fff;
|
||||
border: 1px solid #c0ccda;
|
||||
border-radius: 6px;
|
||||
box-sizing: border-box;
|
||||
width: 148px;
|
||||
height: 148px;
|
||||
margin: 0 8px 8px 0;
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
}
|
||||
.image-list a:hover .image-mask {
|
||||
opacity: 1;
|
||||
}
|
||||
.el-icon-check {
|
||||
color: #fff;
|
||||
}
|
||||
.input-box {
|
||||
width: 80%;
|
||||
}
|
||||
.el-upload--picture-card {
|
||||
background-color: #fbfdff;
|
||||
border: 1px dashed #c0ccda;
|
||||
border-radius: 6px;
|
||||
box-sizing: border-box;
|
||||
width: 148px;
|
||||
height: 148px;
|
||||
line-height: 146px;
|
||||
vertical-align: top;
|
||||
}
|
||||
.image-mask {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
left: 0;
|
||||
top: 0;
|
||||
cursor: default;
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
opacity: 0;
|
||||
font-size: 20px;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
transition: opacity 0.3s;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
.image-detail {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
}
|
||||
.image-mask::after {
|
||||
display: inline-block;
|
||||
content: '';
|
||||
height: 100%;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.image-mask span {
|
||||
display: block;
|
||||
cursor: pointer;
|
||||
margin: 40% auto;
|
||||
}
|
||||
.image-mask .el-upload-list__item-delete {
|
||||
position: static;
|
||||
font-size: inherit;
|
||||
color: inherit;
|
||||
}
|
||||
.add {
|
||||
padding-left: 20px;
|
||||
}
|
||||
.delete {
|
||||
padding-right: 20px;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,192 @@
|
||||
<!--
|
||||
* @Author: 王涛
|
||||
* @Mail: no
|
||||
* @Date: 2020-09-29 19:56:44
|
||||
* @LastEditors: 王涛
|
||||
* @LastEditTime: 2021-01-07 22:22:03
|
||||
-->
|
||||
<template>
|
||||
<div class="box">
|
||||
<div v-on:paste="handlePaste" v-drag="handleDrag" >
|
||||
<img v-if='imageUrl' ref="preview" :src="domain+imageUrl" alt="" style="width:300px;height:300px;">
|
||||
<div v-else style="width:300px;height:300px;border:1px solid;padding:20px;">
|
||||
<div style="text-indent:2em;">将图片按<span style="color:red">cmd+C复制</span>到粘贴板,<span style="color:red">cmd+V粘贴</span>至此处;</div>
|
||||
<div style="text-indent:2em;">或者将图片拖拽至此处</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { mediaUploadImg } from '@/api/components/UploadImgPaste'
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
domain: this.$store.getters.getSystemConfig.imgWebCdn, // 存放图片的域名
|
||||
imageUrl: ''
|
||||
}
|
||||
},
|
||||
props: {
|
||||
img: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
img: function(val) {
|
||||
this.imageUrl = val
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
if (this.img) {
|
||||
this.imageUrl = this.img
|
||||
} else {
|
||||
this.imageUrl = ''
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleDrag(event) {
|
||||
const items = Array.from(event.dataTransfer.items)
|
||||
let file = null
|
||||
if (!items || items.length === 0) {
|
||||
this.$message.error('当前浏览器不支持本地')
|
||||
return
|
||||
}
|
||||
// 搜索剪切板items
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
if (items[i].type.indexOf('image') !== -1) {
|
||||
file = items[i].getAsFile()
|
||||
break
|
||||
}
|
||||
}
|
||||
if (!file) {
|
||||
this.$message.error('粘贴内容非图片')
|
||||
return
|
||||
}
|
||||
// 此时file就是我们的剪切板中的图片对象
|
||||
// 如果需要预览,可以执行下面代码
|
||||
this.file = file
|
||||
this.uploadPlans()
|
||||
},
|
||||
// 图片等比压缩
|
||||
handleCompressImage(file, type) {
|
||||
return new Promise((resolve, reject) => {
|
||||
try {
|
||||
const reader = new FileReader()
|
||||
reader.readAsDataURL(file)
|
||||
reader.onload = (e) => {
|
||||
const image = new Image()
|
||||
image.src = e.target.result
|
||||
|
||||
image.onload = () => {
|
||||
if (image.width > 720) {
|
||||
const canvas = document.createElement('canvas')
|
||||
const context = canvas.getContext('2d')
|
||||
const imageWidth = 720
|
||||
const imageHeight = (720 / image.width) * image.height
|
||||
canvas.width = imageWidth
|
||||
canvas.height = imageHeight
|
||||
console.log(imageWidth, imageHeight)
|
||||
context.drawImage(image, 0, 0, imageWidth, imageHeight)
|
||||
canvas.toBlob(
|
||||
(blob) => {
|
||||
resolve(new Blob([blob], { type: type }))
|
||||
},
|
||||
'image/jpeg',
|
||||
0.9
|
||||
)
|
||||
} else {
|
||||
resolve(file)
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
reject(e)
|
||||
}
|
||||
})
|
||||
},
|
||||
async handlePaste(event) {
|
||||
const items = (event.clipboardData || window.clipboardData).items
|
||||
let file = null
|
||||
if (!items || items.length === 0) {
|
||||
this.$message.error('当前浏览器不支持本地')
|
||||
return
|
||||
}
|
||||
// 搜索剪切板items
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
if (items[i].type.indexOf('image') !== -1) {
|
||||
file = items[i].getAsFile()
|
||||
break
|
||||
}
|
||||
}
|
||||
if (!file) {
|
||||
this.$message.error('粘贴内容非图片')
|
||||
return
|
||||
}
|
||||
// 此时file就是我们的剪切板中的图片对象
|
||||
// 如果需要预览,可以执行下面代码
|
||||
// 先进行压缩再上传
|
||||
// const res = await this.handleCompressImage(file)
|
||||
// this.file = res
|
||||
this.file = file
|
||||
this.uploadPlans()
|
||||
},
|
||||
// 上传文件成功后回调
|
||||
uploadPlans() {
|
||||
const file = this.file
|
||||
if (!file) {
|
||||
this.$message.error('请粘贴图片后上传')
|
||||
return
|
||||
}
|
||||
this.loading = true
|
||||
const form = new FormData()
|
||||
form.append('file', file)
|
||||
form.append('type', this.type)
|
||||
mediaUploadImg(form).then((res) => {
|
||||
if (res.code === 200) {
|
||||
this.$message({
|
||||
type: 'success',
|
||||
message: '上传成功!'
|
||||
})
|
||||
this.imageUrl = res.data.path
|
||||
this.changeImgUrl()
|
||||
} else {
|
||||
this.$message({
|
||||
type: 'error',
|
||||
message: '上传失败!'
|
||||
})
|
||||
this.imageUrl = ''
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
changeImgUrl() {
|
||||
this.$emit('changeImgUrl', this.imageUrl)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
.avatar-uploader .el-upload {
|
||||
border: 1px dashed #d9d9d9;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
.avatar-uploader .el-upload:hover {
|
||||
border-color: #409eff;
|
||||
}
|
||||
.avatar-uploader-icon {
|
||||
font-size: 28px;
|
||||
color: #8c939d;
|
||||
width: 148px;
|
||||
height: 148px;
|
||||
line-height: 148px;
|
||||
text-align: center;
|
||||
}
|
||||
.avatar {
|
||||
width: 148px;
|
||||
height: 148px;
|
||||
display: block;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,106 @@
|
||||
<!--
|
||||
* @Author: 王涛
|
||||
* @Mail: no
|
||||
* @Date: 2020-09-30 11:10:55
|
||||
* @LastEditors: 江涛
|
||||
* @LastEditTime: 2021-03-24 11:39:53
|
||||
-->
|
||||
<template>
|
||||
<uploader
|
||||
:options="options"
|
||||
class="uploader-example"
|
||||
@file-success="fileSuccess"
|
||||
@file-added="fileAdd">
|
||||
<uploader-unsupport></uploader-unsupport>
|
||||
<uploader-drop>
|
||||
<uploader-btn>选择文件</uploader-btn>
|
||||
</uploader-drop>
|
||||
<uploader-list></uploader-list>
|
||||
</uploader>
|
||||
</template>
|
||||
<script>
|
||||
// import { resumeUploadIsSuccess } from '@/api/video/video'
|
||||
import { videoOk } from '@/api/video.js'
|
||||
import { getToken } from '@/utils/auth'
|
||||
export default {
|
||||
props: {
|
||||
type: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// 视频校验唯一码
|
||||
trackId: '',
|
||||
duration: 0
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
options() {
|
||||
return {
|
||||
target: '/api/web/mediafile/videoBody',
|
||||
method: 'application/json',
|
||||
chunkSize: 2 * 1024 * 1024,
|
||||
testChunks: false,
|
||||
forceChunkSize: true,
|
||||
maxChunkRetries: 3,
|
||||
singleFile: true,
|
||||
query: this.uploadQuery,
|
||||
headers: {
|
||||
Authorization: getToken()
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
uploadQuery(file, chunk) {
|
||||
return {
|
||||
pos: chunk.offset,
|
||||
taskId: this.trackId,
|
||||
type: 1,
|
||||
data: 'flie',
|
||||
uploadUserName: this.$store.getters.getCreator
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 上传视频-点击上传视频
|
||||
*/
|
||||
async fileSuccess(rootFile, file, message, chunk) {
|
||||
const video = document.createElement('video')
|
||||
video.preload = 'metadata'
|
||||
video.src = URL.createObjectURL(rootFile.file)
|
||||
video.onloadedmetadata = () => {
|
||||
window.URL.revokeObjectURL(video.src)
|
||||
// eslint-disable-next-line no-const-assign
|
||||
|
||||
this.duration = video.duration
|
||||
}
|
||||
|
||||
const data = {
|
||||
id: this.trackId,
|
||||
videoUrl: JSON.parse(message).data.videoUri
|
||||
}
|
||||
videoOk(data).then((res) => {
|
||||
if (res.code === 200) {
|
||||
const param = {
|
||||
id: video.id,
|
||||
width: video.videoWidth,
|
||||
height: video.videoHeight,
|
||||
duration: this.duration,
|
||||
videoUri: JSON.parse(message).data.videoUri,
|
||||
size: file.size
|
||||
}
|
||||
this.$emit('changeVideoUrl', param)
|
||||
} else {
|
||||
this.$message.error('视频上传失败!')
|
||||
}
|
||||
})
|
||||
},
|
||||
fileAdd() {
|
||||
this.trackId = new Date().getTime() + ''
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,203 @@
|
||||
|
||||
<template>
|
||||
<uploader ref="uploader" :options="options" @fileError="fileError" class="uploader-example" @file-success="fileSuccess" @file-added="fileAdd">
|
||||
<uploader-unsupport></uploader-unsupport>
|
||||
<uploader-drop>
|
||||
<uploader-btn>选择文件</uploader-btn>
|
||||
</uploader-drop>
|
||||
<uploader-list></uploader-list>
|
||||
</uploader>
|
||||
</template>
|
||||
<script>
|
||||
// import { resumeUploadIsSuccess } from '@/api/video/video'
|
||||
import { videoOk } from '@/api/video.js'
|
||||
import { getToken } from '@/utils/auth'
|
||||
import SparkMD5 from 'spark-md5'
|
||||
export default {
|
||||
props: {
|
||||
type: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
// 视频校验唯一码
|
||||
trackId: '',
|
||||
duration: 0
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
options() {
|
||||
return {
|
||||
target: '/media/web/upload/videoBody',
|
||||
method: 'application/json',
|
||||
chunkSize: 2 * 1024 * 1024,
|
||||
testChunks: false,
|
||||
forceChunkSize: true,
|
||||
maxChunkRetries: 3,
|
||||
singleFile: true,
|
||||
query: this.uploadQuery,
|
||||
|
||||
headers: {
|
||||
Authorization: getToken()
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
uploadQuery(file, chunk) {
|
||||
return {
|
||||
pos: chunk.offset,
|
||||
taskId: this.trackId,
|
||||
type: this.type,
|
||||
data: 'file',
|
||||
appId: this.$store.getters.appId,
|
||||
uploadUserName: this.$store.getters.getCreator
|
||||
}
|
||||
},
|
||||
handleSuccess(response) {
|
||||
console.log(response, 'response')
|
||||
},
|
||||
/**
|
||||
* 上传视频-点击上传视频
|
||||
*/
|
||||
readVideoMeta(rawFile) {
|
||||
return new Promise(resolve => {
|
||||
const video = document.createElement('video')
|
||||
video.preload = 'metadata'
|
||||
const objectUrl = URL.createObjectURL(rawFile)
|
||||
const done = (width, height, duration) => {
|
||||
window.URL.revokeObjectURL(objectUrl)
|
||||
resolve({
|
||||
width: width || 0,
|
||||
height: height || 0,
|
||||
duration: duration || 0
|
||||
})
|
||||
}
|
||||
video.onloadedmetadata = () => {
|
||||
done(video.videoWidth, video.videoHeight, video.duration)
|
||||
}
|
||||
video.onerror = () => {
|
||||
done(0, 0, 0)
|
||||
}
|
||||
video.src = objectUrl
|
||||
})
|
||||
},
|
||||
async fileSuccess(rootFile, file, message, chunk) {
|
||||
let parsed
|
||||
try {
|
||||
parsed = JSON.parse(message)
|
||||
} catch (e) {
|
||||
this.$message.error('上传响应解析失败')
|
||||
return
|
||||
}
|
||||
if (!parsed || parsed.code !== 200 || !parsed.data) {
|
||||
alert(`任务ID:${this.trackId}上传出错!`)
|
||||
file.cancel()
|
||||
if (this.$refs.uploader.uploader) {
|
||||
const uploaderInstance = this.$refs.uploader.uploader
|
||||
uploaderInstance.cancel()
|
||||
}
|
||||
return
|
||||
}
|
||||
const meta = await this.readVideoMeta(rootFile.file)
|
||||
this.duration = meta.duration
|
||||
const data = {
|
||||
id: parsed.data.id,
|
||||
videoUrl: parsed.data.videoUri
|
||||
}
|
||||
videoOk(data).then(res => {
|
||||
if (res.code === 200) {
|
||||
this.$emit('changeVideoUrl', {
|
||||
id: data.id,
|
||||
width: meta.width,
|
||||
height: meta.height,
|
||||
duration: meta.duration,
|
||||
videoUri: parsed.data.videoUri,
|
||||
size: file.size,
|
||||
md5: this.trackId
|
||||
})
|
||||
} else {
|
||||
alert(`任务id:${this.trackId}重复上传!`)
|
||||
if (this.$refs.uploader.uploader) {
|
||||
const uploaderInstance = this.$refs.uploader.uploader
|
||||
uploaderInstance.cancel()
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
async fileAdd(file) {
|
||||
const fileReader = new FileReader()
|
||||
const time = new Date().getTime()
|
||||
const blobSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice
|
||||
let currentChunk = 0
|
||||
const chunkSize = 10 * 1024 * 1000
|
||||
const chunks = Math.ceil(file.size / chunkSize)
|
||||
const spark = new SparkMD5.ArrayBuffer()
|
||||
file.pause()
|
||||
loadNext()
|
||||
fileReader.onload = e => {
|
||||
if (this.type === 4 && file.fileType.indexOf('audio') === -1) {
|
||||
file.cancel()
|
||||
return this.$message.error('此视频归类仅可上传MP3格式内容!')
|
||||
}
|
||||
spark.append(e.target.result)
|
||||
if (currentChunk < chunks) {
|
||||
currentChunk++
|
||||
loadNext()
|
||||
console.log('校验MD5 ' + ((currentChunk / chunks) * 100).toFixed(0) + '%')
|
||||
} else {
|
||||
this.trackId = spark.end()
|
||||
if (this.trackId) {
|
||||
this.$message('开始上传,请等待')
|
||||
file.resume()
|
||||
console.log(`MD5计算完毕:${file.name} \nMD5:${spark} \n分片:${chunks} 大小:${file.size} 用时:${new Date().getTime() - time} ms`)
|
||||
} else {
|
||||
this.$message.error('读取本地文件错误,请重新上传!')
|
||||
file.cancel()
|
||||
}
|
||||
}
|
||||
}
|
||||
fileReader.onerror = () => {
|
||||
this.$message.error(`文件${file.name}读取出错,请检查该文件`)
|
||||
file.cancel()
|
||||
}
|
||||
|
||||
function loadNext() {
|
||||
const start = currentChunk * chunkSize
|
||||
const end = start + chunkSize >= file.size ? file.size : start + chunkSize
|
||||
fileReader.readAsArrayBuffer(blobSlice.call(file.file, start, end))
|
||||
}
|
||||
},
|
||||
async fileError(file) {
|
||||
this.$message.error(`文件${file.name}读取出错,请检查该文件`)
|
||||
file.cancel()
|
||||
if (this.$refs.uploader.uploader) {
|
||||
const uploaderInstance = this.$refs.uploader.uploader
|
||||
uploaderInstance.cancel()
|
||||
}
|
||||
}
|
||||
}
|
||||
// beforeDestroy() {
|
||||
// // 终止上传
|
||||
// if (this.$refs.uploader.uploader) {
|
||||
// const uploaderInstance = this.$refs.uploader.uploader
|
||||
// uploaderInstance.cancel();
|
||||
// }
|
||||
// }
|
||||
}
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.uploader-example{
|
||||
::v-deep{
|
||||
/* 在你的样式文件中 */
|
||||
.uploader-file-actions {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -0,0 +1,106 @@
|
||||
<!--
|
||||
* @Author: 王涛
|
||||
* @Mail: no
|
||||
* @Date: 2020-09-30 11:10:55
|
||||
* @LastEditors: 江涛
|
||||
* @LastEditTime: 2021-03-03 20:26:11
|
||||
-->
|
||||
<template>
|
||||
<div class="upload-video-mp4">
|
||||
<el-upload class="upload-demo" :action="action" :data="{ appId: $store.getters.appId }" :on-success='success' :file-list="fileList">
|
||||
<el-button size="mini" type="primary">{{ buttonText }}</el-button>
|
||||
</el-upload>
|
||||
<div v-if="previewUrl" class="preview-box">
|
||||
<video class="preview-player" :src="previewUrl" controls preload="metadata"></video>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
action: {
|
||||
type: String,
|
||||
default: '/api/web/media/uploadImg'
|
||||
},
|
||||
buttonText: {
|
||||
type: String,
|
||||
default: '点击上传'
|
||||
},
|
||||
domain: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
value: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
fileList: [],
|
||||
currentPath: ''
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
previewUrl() {
|
||||
return this.joinUrl(this.domain || this.$store.getters.getSystemConfig.mp4Addr, this.currentPath)
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
value: {
|
||||
handler(val) {
|
||||
this.currentPath = val || ''
|
||||
},
|
||||
immediate: true
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
joinUrl(base, path) {
|
||||
if (!path) return ''
|
||||
if (/^(blob:|https?:\/\/|data:)/.test(path)) return path
|
||||
const prefix = base || ''
|
||||
if (!prefix) return path
|
||||
const normalizedBase = prefix.endsWith('/') ? prefix.slice(0, -1) : prefix
|
||||
const normalizedPath = path.startsWith('/') ? path : `/${path}`
|
||||
return `${normalizedBase}${normalizedPath}`
|
||||
},
|
||||
success(response, file, fileList) {
|
||||
if (response.code === 200) {
|
||||
this.currentPath = response.data.path
|
||||
const param = {
|
||||
width: undefined,
|
||||
height: undefined,
|
||||
duration: undefined,
|
||||
videoUri: response.data.path,
|
||||
path: response.data.path,
|
||||
size: undefined
|
||||
}
|
||||
this.$message({
|
||||
type: 'success',
|
||||
message: '视频上传成功!'
|
||||
})
|
||||
this.$emit('changeVideoUrl', param)
|
||||
} else {
|
||||
this.$message({
|
||||
type: 'error',
|
||||
message: '视频上传失败!'
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style scoped>
|
||||
.preview-box {
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
.preview-player {
|
||||
width: 320px;
|
||||
max-width: 100%;
|
||||
max-height: 220px;
|
||||
background: #000;
|
||||
border-radius: 6px;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,181 @@
|
||||
<template>
|
||||
<div id="dplayer" ref="dplayer"></div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import DPlayer from 'dplayer'
|
||||
import Hls from 'hls.js'
|
||||
|
||||
export default {
|
||||
props: {
|
||||
autoplay: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
theme: { // 主题色
|
||||
type: String,
|
||||
default: '#FADFA3'
|
||||
},
|
||||
loop: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
lang: {
|
||||
type: String,
|
||||
default: 'zh'
|
||||
},
|
||||
screenshot: { // 是否开启截图
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
hotkey: { // 是否开启热键
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
preload: {
|
||||
type: String,
|
||||
default: 'auto'
|
||||
},
|
||||
contextmenu: { // 自定义右键菜单
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
logo: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
video: {
|
||||
type: Object, // 可选值:‘auto’,'hls','flv','dash','webtorrent','normal'
|
||||
required: true,
|
||||
validator(value) {
|
||||
return typeof value.url === 'string'
|
||||
}
|
||||
},
|
||||
option: {
|
||||
type: Object,
|
||||
require: false,
|
||||
default() {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
dp: null
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
video(val) {
|
||||
if (this.dp) {
|
||||
this.dp.switchVideo(val) // 切换到其他视频
|
||||
}
|
||||
}
|
||||
},
|
||||
beforeDestroy() {
|
||||
if (this.dp) {
|
||||
this.dp.destroy()
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
playHls(video, player) {
|
||||
if (Hls.isSupported()) {
|
||||
const source = video.src
|
||||
const previousHls = player.plugins.hls
|
||||
|
||||
if (previousHls) {
|
||||
previousHls.destroy()
|
||||
}
|
||||
|
||||
const hls = new Hls(player.options.pluginOptions.hls)
|
||||
player.plugins.hls = hls
|
||||
hls.loadSource(source)
|
||||
hls.attachMedia(video)
|
||||
player.events.on('destroy', () => {
|
||||
hls.destroy()
|
||||
if (player.plugins.hls === hls) {
|
||||
delete player.plugins.hls
|
||||
}
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// Safari 等具备可靠原生 HLS 支持的环境仍使用原生播放。
|
||||
if (
|
||||
video.canPlayType('application/vnd.apple.mpegurl') ||
|
||||
video.canPlayType('application/x-mpegurl')
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
||||
player.notice('Error: HLS is not supported.')
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
const optionVideo = this.option.video || {}
|
||||
const video = {
|
||||
url: this.video.url,
|
||||
pic: this.video.pic,
|
||||
type: this.video.type,
|
||||
...optionVideo,
|
||||
customType: {
|
||||
...(optionVideo.customType || {}),
|
||||
hls: this.playHls
|
||||
}
|
||||
}
|
||||
const player = (this.dp = new DPlayer({
|
||||
container: this.$refs.dplayer,
|
||||
autoplay: false,
|
||||
theme: this.theme,
|
||||
loop: this.loop,
|
||||
lang: this.lang,
|
||||
screenshot: this.screenshot,
|
||||
hotkey: this.hotkey,
|
||||
preload: this.preload,
|
||||
contextmenu: this.contextmenu,
|
||||
logo: this.logo,
|
||||
...this.option,
|
||||
// DPlayer 1.26 会先信任 canPlayType(),Chrome 可能因此错误进入原生 HLS。
|
||||
// 将合并后的视频配置放在最后,确保 HLS 始终先由 Hls.isSupported() 判断。
|
||||
video
|
||||
}))
|
||||
player.video.muted = true
|
||||
player.on('play', () => {
|
||||
this.$emit('play')
|
||||
})
|
||||
player.on('playing', () => {
|
||||
this.$emit('playing')
|
||||
})
|
||||
player.on('pause', () => {
|
||||
this.$emit('pause')
|
||||
})
|
||||
player.on('canplay', () => {
|
||||
this.$emit('canplay')
|
||||
})
|
||||
player.on('ended', () => {
|
||||
this.$emit('ended')
|
||||
})
|
||||
player.on('error', () => {
|
||||
this.$emit('error')
|
||||
})
|
||||
player.on('loadeddata', () => {
|
||||
this.$emit('loadeddata')
|
||||
if (this.autoplay) {
|
||||
player.play()
|
||||
player.video.muted = false
|
||||
}
|
||||
})
|
||||
player.on('loadedmetadata', () => {
|
||||
this.$emit('loadedmetadata')
|
||||
})
|
||||
player.on('waiting', () => {
|
||||
this.$emit('waiting')
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
#dplayer {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,26 @@
|
||||
export function jumptabChange(val) {
|
||||
switch (val) {
|
||||
case 1:
|
||||
return '漫画'
|
||||
case 2:
|
||||
return '动漫'
|
||||
case 3:
|
||||
return '视频'
|
||||
}
|
||||
}
|
||||
export function jumptabChangeList() {
|
||||
return [
|
||||
{
|
||||
value: 1,
|
||||
label: '漫画'
|
||||
},
|
||||
{
|
||||
value: 2,
|
||||
label: '动漫'
|
||||
},
|
||||
{
|
||||
value: 3,
|
||||
label: '视频'
|
||||
}
|
||||
]
|
||||
}
|
||||
Executable
+49
@@ -0,0 +1,49 @@
|
||||
// Inspired by https://github.com/Inndy/vue-clipboard2
|
||||
const Clipboard = require('clipboard')
|
||||
if (!Clipboard) {
|
||||
throw new Error('you should npm install `clipboard` --save at first ')
|
||||
}
|
||||
|
||||
export default {
|
||||
bind(el, binding) {
|
||||
if (binding.arg === 'success') {
|
||||
el._v_clipboard_success = binding.value
|
||||
} else if (binding.arg === 'error') {
|
||||
el._v_clipboard_error = binding.value
|
||||
} else {
|
||||
const clipboard = new Clipboard(el, {
|
||||
text() { return binding.value },
|
||||
action() { return binding.arg === 'cut' ? 'cut' : 'copy' }
|
||||
})
|
||||
clipboard.on('success', e => {
|
||||
const callback = el._v_clipboard_success
|
||||
callback && callback(e) // eslint-disable-line
|
||||
})
|
||||
clipboard.on('error', e => {
|
||||
const callback = el._v_clipboard_error
|
||||
callback && callback(e) // eslint-disable-line
|
||||
})
|
||||
el._v_clipboard = clipboard
|
||||
}
|
||||
},
|
||||
update(el, binding) {
|
||||
if (binding.arg === 'success') {
|
||||
el._v_clipboard_success = binding.value
|
||||
} else if (binding.arg === 'error') {
|
||||
el._v_clipboard_error = binding.value
|
||||
} else {
|
||||
el._v_clipboard.text = function() { return binding.value }
|
||||
el._v_clipboard.action = function() { return binding.arg === 'cut' ? 'cut' : 'copy' }
|
||||
}
|
||||
},
|
||||
unbind(el, binding) {
|
||||
if (binding.arg === 'success') {
|
||||
delete el._v_clipboard_success
|
||||
} else if (binding.arg === 'error') {
|
||||
delete el._v_clipboard_error
|
||||
} else {
|
||||
el._v_clipboard.destroy()
|
||||
delete el._v_clipboard
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user