Commit 54c7dcc8 authored by xinla's avatar xinla
Browse files

Merge remote-tracking branch 'origin/front_end_dev_2.0' into develop

parents 8b12f7cc f8010414
Showing with 1401 additions and 1151 deletions
+1401 -1151
......@@ -39,15 +39,14 @@
"url": "https://gitee.com/LinkWeChat/link-wechat.git"
},
"dependencies": {
"@liripeng/vue-audio-player": "^1.2.8",
"@riophae/vue-treeselect": "0.4.0",
"awesome-qr": "^2.0.1-rc.0",
"axios": "0.18.1",
"benz-amr-recorder": "^1.1.3",
"clipboard": "2.0.4",
"core-js": "3.6.5",
"core-js": "^3.20.2",
"echarts": "4.2.1",
"element-ui": "^2.15.2",
"element-ui": "^2.15.6",
"fabric": "^4.6.0",
"file-saver": "2.0.1",
"fuse.js": "3.4.4",
......@@ -95,9 +94,9 @@
"husky": "1.3.1",
"lint-staged": "8.1.5",
"mockjs": "1.0.1-beta3",
"node-sass": "4.14.1",
"plop": "2.3.0",
"runjs": "4.3.2",
"sass": "^1.47.0",
"sass-loader": "8.0.2",
"sass-resources-loader": "^2.1.0",
"script-ext-html-webpack-plugin": "2.1.3",
......
<template>
<div :class="{'show':show}" class="header-search">
<div :class="{ show: show }" class="header-search">
<svg-icon class-name="search-icon" icon-class="search" @click.stop="click" />
<el-select
ref="headerSearchSelect"
......@@ -25,67 +25,67 @@
<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";
import Fuse from 'fuse.js'
import path from 'path'
export default {
name: "HeaderSearch",
name: 'HeaderSearch',
data() {
return {
search: "",
search: '',
options: [],
searchPool: [],
show: false,
fuse: undefined,
};
fuse: undefined
}
},
computed: {
routes() {
return this.$store.getters.permission_routes;
},
return this.$store.getters.permission_routes
}
},
watch: {
routes() {
this.searchPool = this.generateRoutes(this.routes);
this.searchPool = this.generateRoutes(this.routes)
},
searchPool(list) {
this.initFuse(list);
this.initFuse(list)
},
show(value) {
if (value) {
document.body.addEventListener("click", this.close);
document.body.addEventListener('click', this.close)
} else {
document.body.removeEventListener("click", this.close);
document.body.removeEventListener('click', this.close)
}
},
}
},
mounted() {
this.searchPool = this.generateRoutes(this.routes);
this.searchPool = this.generateRoutes(this.routes)
},
methods: {
click() {
this.show = !this.show;
this.show = !this.show
if (this.show) {
this.$refs.headerSearchSelect && this.$refs.headerSearchSelect.focus();
this.$refs.headerSearchSelect && this.$refs.headerSearchSelect.focus()
}
},
close() {
this.$refs.headerSearchSelect && this.$refs.headerSearchSelect.blur();
this.options = [];
this.show = false;
this.$refs.headerSearchSelect && this.$refs.headerSearchSelect.blur()
this.options = []
this.show = false
},
change(val) {
if (this.ishttp(val.path)) {
// http(s):// 路径新窗口打开
window.open(val.path, "_blank");
window.open(val.path, '_blank')
} else {
this.$router.push(val.path);
this.$router.push(val.path)
}
this.search = "";
this.options = [];
this.search = ''
this.options = []
this.$nextTick(() => {
this.show = false;
});
this.show = false
})
},
initFuse(list) {
this.fuse = new Fuse(list, {
......@@ -97,70 +97,64 @@ export default {
minMatchCharLength: 1,
keys: [
{
name: "title",
weight: 0.7,
name: 'title',
weight: 0.7
},
{
name: "path",
weight: 0.3,
},
],
});
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 = [];
generateRoutes(routes, basePath = '/', prefixTitle = []) {
let res = []
for (const router of routes) {
// skip hidden router
if (router.hidden) {
continue;
continue
}
const data = {
path: !this.ishttp(router.path)
? path.resolve(basePath, router.path)
: router.path,
title: [...prefixTitle],
};
path: !this.ishttp(router.path) ? path.resolve(basePath, router.path) : router.path,
title: [...prefixTitle]
}
if (router.meta && router.meta.title) {
data.title = [...data.title, router.meta.title];
data.title = [...data.title, router.meta.title]
if (router.redirect !== "noRedirect") {
if (router.redirect !== 'noRedirect') {
// only push the routes with title
// special case: need to exclude parent router without redirect
res.push(data);
res.push(data)
}
}
// recursive child routes
if (router.children) {
const tempRoutes = this.generateRoutes(
router.children,
data.path,
data.title
);
const tempRoutes = this.generateRoutes(router.children, data.path, data.title)
if (tempRoutes.length >= 1) {
res = [...res, ...tempRoutes];
res = [...res, ...tempRoutes]
}
}
}
return res;
return res
},
querySearch(query) {
if (query !== "") {
this.options = this.fuse.search(query);
if (query !== '') {
this.options = this.fuse.search(query)
} else {
this.options = [];
this.options = []
}
},
ishttp(url) {
return url.indexOf("http://") !== -1 || url.indexOf("https://") !== -1;
},
},
};
return url.indexOf('http://') !== -1 || url.indexOf('https://') !== -1
}
}
}
</script>
<style lang="scss" scoped>
......@@ -183,7 +177,7 @@ export default {
display: inline-block;
vertical-align: middle;
/deep/ .el-input__inner {
::v-deep .el-input__inner {
border-radius: 0;
border: 0;
padding-left: 0;
......
<script>
import { getList } from '@/api/customer/tag'
import list from './list'
import { getList } from '@/api/customer/tag'
import list from './list'
export default {
components: { list },
props: {
// 添加标签显隐
visible: {
type: Boolean,
default: false
},
// title: {
// type: String,
// default: '',
// },
type: {
type: String | Number,
default: '4'
},
// 显示哪些素材类型标签
showArr: {
type: Array,
default: () => []
}
export default {
components: { list },
props: {
// 添加标签显隐
visible: {
type: Boolean,
default: false
},
data () {
return {
text: {},
image: {},
file: {}
// title: {
// type: String,
// default: '',
// },
type: {
type: String | Number,
default: '4'
},
// 显示哪些素材类型标签
showArr: {
type: Array,
default: () => []
}
},
data() {
return {
text: {},
image: {},
file: {}
}
},
watch: {},
computed: {
title() {
const titleMap = {
4: '文本',
0: '图片',
8: '图文',
9: '小程序'
}
return titleMap[this.type] || '素材'
},
watch: {},
computed: {
title () {
const titleMap = {
4: '文本',
0: '图片',
8: '图文',
9: '小程序'
}
return titleMap[this.type] || '素材'
Pvisible: {
get() {
return this.visible
},
Pvisible: {
get () {
return this.visible
},
set (val) {
this.$emit('update:visible', val)
}
},
Ptype: {
get () {
return this.type
},
set (val) {
this.$emit('update:type', val)
}
set(val) {
this.$emit('update:visible', val)
}
},
created () { },
mounted () { },
methods: {
submit () {
this.Pvisible = false
this.$emit('success', this.selectedData)
Ptype: {
get() {
return this.type
},
onChange (data) {
this.selectedData = data
set(val) {
this.$emit('update:type', val)
}
}
},
created() {},
mounted() {},
methods: {
submit() {
this.Pvisible = false
this.$emit('success', this.selectedData)
},
onChange(data) {
this.selectedData = data
}
}
}
</script>
<template>
<el-dialog :title="`选择${title}`" :visible.sync="Pvisible" width="680px" append-to-body destroy-on-close>
<el-dialog
:title="`选择${title}`"
:visible.sync="Pvisible"
width="680px"
append-to-body
destroy-on-close
>
<div>
<list v-if="showArr.length <= 1" :type="showArr[0] || type" @change="onChange"> </list>
<el-tabs v-else-if="showArr.length > 1" v-model="Ptype">
......@@ -96,18 +102,18 @@
</template>
<style lang="scss" scoped>
.user-list {
.el-row {
line-height: 26px;
}
}
.mr30 {
margin-right: 30px;
.user-list {
.el-row {
line-height: 26px;
}
}
.mr30 {
margin-right: 30px;
}
/deep/.el-dialog__body {
padding: 5px 20px;
height: 76vh;
overflow: auto;
}
::v-deep.el-dialog__body {
padding: 5px 20px;
height: 76vh;
overflow: auto;
}
</style>
<script>
import { getTree, getList } from '@/api/material'
export default {
components: {},
props: {
type: {
type: String | Number,
default: '4'
}
},
data () {
return {
loading: true, // 遮罩层
// 查询条件
query: {
pageNum: 1,
pageSize: 10,
categoryId: '',
search: '',
mediaType: '4'
},
list: [], // 列表
total: 0, // 总条数
treeData: [], // 树
// 树props
treeProps: {
children: 'children',
label: 'name'
},
// 分组props
groupProps: {
// expandTrigger: 'hover',
checkStrictly: true,
children: 'children',
label: 'name',
value: 'id',
emitPath: false
},
radio: ''
}
},
watch: {
radio (val) {
this.$emit('change', val)
import { getTree, getList } from '@/api/material'
export default {
components: {},
props: {
type: {
type: String | Number,
default: '4'
}
},
data() {
return {
loading: true, // 遮罩层
// 查询条件
query: {
pageNum: 1,
pageSize: 10,
categoryId: '',
search: '',
mediaType: '4'
},
type (val) {
this.query.mediaType = this.type
this.query.pageNum = 1
this.list = []
this.getList()
}
},
computed: {
list: [], // 列表
total: 0, // 总条数
treeData: [], // 树
// 树props
treeProps: {
children: 'children',
label: 'name'
},
// 分组props
groupProps: {
// expandTrigger: 'hover',
checkStrictly: true,
children: 'children',
label: 'name',
value: 'id',
emitPath: false
},
radio: ''
}
},
watch: {
radio(val) {
this.$emit('change', val)
},
created () {
type(val) {
this.query.mediaType = this.type
this.query.pageNum = 1
this.list = []
this.getList()
},
mounted () { },
methods: {
// 获取素材列表
getList (page) {
page && (this.query.pageNum = page)
this.loading = true
getList(this.query)
.then(({ rows, total }) => {
this.list = rows.map(i => {
i.checked = false
return i
})
this.total = +total
this.loading = false
this.$emit('listChange', this.list)
})
.catch(() => {
this.loading = false
}
},
computed: {},
created() {
this.query.mediaType = this.type
this.getList()
},
mounted() {},
methods: {
// 获取素材列表
getList(page) {
page && (this.query.pageNum = page)
this.loading = true
getList(this.query)
.then(({ rows, total }) => {
this.list = rows.map((i) => {
i.checked = false
return i
})
},
onRowClick (row, column, event) {
const evTarget = event.target.nodeName.toUpperCase(0)
if (evTarget == 'INPUT') {
return
}
this.total = +total
this.loading = false
this.$emit('listChange', this.list)
})
.catch(() => {
this.loading = false
})
},
onRowClick(row, column, event) {
const evTarget = event.target.nodeName.toUpperCase(0)
if (evTarget == 'INPUT') {
return
}
const checked = row.checked
if (!checked) {
this.list.forEach(i => i.checked = false)
}
row.checked = !checked
this.$emit('change', row.checked ? row : null)
const checked = row.checked
if (!checked) {
this.list.forEach((i) => (i.checked = false))
}
row.checked = !checked
this.$emit('change', row.checked ? row : null)
}
}
}
</script>
<template>
<div>
<template v-if="type == 4">
<el-input v-model="query.search" class="ml10 mr10 mb20" style="width: 260px;" placeholder="请输入文本内容" @keydown.enter.native="getList(1)"></el-input>
<el-input
v-model="query.search"
class="ml10 mr10 mb20"
style="width: 260px"
placeholder="请输入文本内容"
@keydown.enter.native="getList(1)"
></el-input>
</template>
<!-- 文本 -->
......@@ -142,7 +146,7 @@
<el-table-column prop="updateTime" label="最近更新时间"></el-table-column>
</el-table>
<!--
<!--
<el-radio-group
v-if="type == 0"
v-loading="loading"
......@@ -166,28 +170,35 @@
</el-radio>
</el-radio-group> -->
<el-pagination class="fr" @current-change="getList" :current-page="query.pageNum" :page-size="query.pageSize" layout="prev, pager, next" :total="total"></el-pagination>
<el-pagination
class="fr"
@current-change="getList"
:current-page="query.pageNum"
:page-size="query.pageSize"
layout="prev, pager, next"
:total="total"
></el-pagination>
</div>
</template>
<style lang="scss" scoped>
// .img-wrap {
// /deep/.el-radio__input {
// position: absolute;
// left: 50%;
// top: 50%;
// transform: translate(-50%, -50%);
// }
// }
.ma-img {
width: 120px;
height: 120px;
border-radius: 8px;
border: 1px solid #e6ebf5;
justify-content: center;
}
.img-li {
// max-width: 100%;
// height: 160px;
}
// .img-wrap {
// ::v-deep.el-radio__input {
// position: absolute;
// left: 50%;
// top: 50%;
// transform: translate(-50%, -50%);
// }
// }
.ma-img {
width: 120px;
height: 120px;
border-radius: 8px;
border: 1px solid #e6ebf5;
justify-content: center;
}
.img-li {
// max-width: 100%;
// height: 160px;
}
</style>
......@@ -262,7 +262,7 @@ export default {
<style lang="scss" scoped>
// .img-wrap {
// /deep/.el-radio__input {
// ::v-deep.el-radio__input {
// position: absolute;
// left: 50%;
// top: 50%;
......@@ -289,7 +289,7 @@ export default {
top: 0;
}
}
/deep/ .el-checkbox__label {
::v-deep .el-checkbox__label {
vertical-align: text-top;
}
.label {
......
<script>
import { upload } from '@/api/material'
import Video from 'video.js'
import BenzAMRRecorder from 'benz-amr-recorder'
export default {
name: 'Upload',
components: {},
props: {
fileUrl: {
type: String,
default: ''
},
fileName: {
type: String,
default: ''
},
// 0 图片(image)、1 语音(voice)、2 视频(video),3 普通文件(file)
type: {
type: String,
default: '0'
},
// 上传文件大小不能超过 maxSize MB
maxSize: {
type: Number,
default: 2
},
// 图片的宽高像素限制 [width(number), height(number)],默认null不限制
maxImgPx: {
type: Array,
default: null // () => [100, 100]
},
// 限制允许上传的文件格式 eg:["bmp", "jpg", "png", "jpeg", "gif"]
format: {
type: Array,
default: null
}
// beforeUpload: {
// type: Function,
// default: function() {
// return function() {}
// },
// },
import { upload } from '@/api/material'
import Video from 'video.js'
import BenzAMRRecorder from 'benz-amr-recorder'
export default {
name: 'Upload',
components: {},
props: {
fileUrl: {
type: String,
default: ''
},
data () {
return {
loading: false,
action: process.env.VUE_APP_BASE_API + '/common/uploadFile2Cos',
// (this.type == 0
// ? '/wecom/material/uploadimg'
// : '/common/uploadFile2Cos'),
headers: window.CONFIG.headers,
domain: process.env.VUE_APP_BASE_API
}
fileName: {
type: String,
default: ''
},
watch: {},
computed: {
accept () {
return ['image/*', 'amr/*', 'video/*', '*'][this.type]
}
// 0 图片(image)、1 语音(voice)、2 视频(video),3 普通文件(file)
type: {
type: String,
default: '0'
},
created () { },
mounted () { },
methods: {
async handleBeforeUpload (file) {
this.loading = true
let isFormat = true
let isSize = true
// 上传文件大小不能超过 maxSize MB
maxSize: {
type: Number,
default: 2
},
// 图片的宽高像素限制 [width(number), height(number)],默认null不限制
maxImgPx: {
type: Array,
default: null // () => [100, 100]
},
// 限制允许上传的文件格式 eg:["bmp", "jpg", "png", "jpeg", "gif"]
format: {
type: Array,
default: null
}
// beforeUpload: {
// type: Function,
// default: function() {
// return function() {}
// },
// },
},
data() {
return {
loading: false,
action: process.env.VUE_APP_BASE_API + '/common/uploadFile2Cos',
// (this.type == 0
// ? '/wecom/material/uploadimg'
// : '/common/uploadFile2Cos'),
headers: window.CONFIG.headers,
domain: process.env.VUE_APP_BASE_API
}
},
watch: {},
computed: {
accept() {
return ['image/*', 'amr/*', 'video/*', '*'][this.type]
}
},
created() {},
mounted() {},
methods: {
async handleBeforeUpload(file) {
this.loading = true
let isFormat = true
let isSize = true
if (this.format && this.format.length) {
// 校验格式
let reg = /\.(\w+)$/g
let match = file.name.match(reg)
let fileFormat = match && match[0].replace('.', '').toLowerCase()
if (!(isFormat = this.format.includes(fileFormat))) {
this.$message.error('文件格式不正确,请重新选择')
}
if (this.format && this.format.length) {
// 校验格式
let reg = /\.(\w+)$/g
let match = file.name.match(reg)
let fileFormat = match && match[0].replace('.', '').toLowerCase()
if (!(isFormat = this.format.includes(fileFormat))) {
this.$message.error('文件格式不正确,请重新选择')
}
}
if (this.type === '0') {
// 图片
isFormat = file.type === 'image/jpeg' || file.type === 'image/png'
isSize = file.size / 1024 / 1024 < this.maxSize
if (this.type === '0') {
// 图片
isFormat = file.type === 'image/jpeg' || file.type === 'image/png'
isSize = file.size / 1024 / 1024 < this.maxSize
if (!isFormat) {
this.$message.error('上传文件只能是 JPG 格式!')
}
if (!isSize) {
this.$message.error('上传文件大小不能超过 2MB!')
}
if (!isFormat) {
this.$message.error('上传文件只能是 JPG 格式!')
}
if (!isSize) {
this.$message.error('上传文件大小不能超过 2MB!')
}
if (this.maxImgPx) {
try {
await new Promise((resolve) => {
let width, height
let image = new Image()
//加载图片获取图片真实宽度和高度
image.onload = () => {
width = image.width
height = image.height
if (width > this.maxImgPx[0]) {
isSize = false
this.$message.error('图片“宽”度超限,请重新选择')
} else if (height > this.maxImgPx[1]) {
this.$message.error('图片“高”度超限,请重新选择')
isSize = false
}
window.URL && window.URL.revokeObjectURL(image.src)
resolve()
if (this.maxImgPx) {
try {
await new Promise((resolve) => {
let width, height
let image = new Image()
//加载图片获取图片真实宽度和高度
image.onload = () => {
width = image.width
height = image.height
if (width > this.maxImgPx[0]) {
isSize = false
this.$message.error('图片“宽”度超限,请重新选择')
} else if (height > this.maxImgPx[1]) {
this.$message.error('图片“高”度超限,请重新选择')
isSize = false
}
if (window.URL) {
let url = window.URL.createObjectURL(file)
image.src = url
} else if (window.FileReader) {
let reader = new FileReader()
reader.onload = function (e) {
let data = e.target.result
image.src = data
}
reader.readAsDataURL(file)
window.URL && window.URL.revokeObjectURL(image.src)
resolve()
}
if (window.URL) {
let url = window.URL.createObjectURL(file)
image.src = url
} else if (window.FileReader) {
let reader = new FileReader()
reader.onload = function (e) {
let data = e.target.result
image.src = data
}
})
} catch (e) {
console.error(e)
}
}
} else if (this.type === '1') {
// 语音
isFormat = /.amr$/gi.test(file.name)
isSize = file.size / 1024 / 1024 < 2
if (!isFormat) {
this.$message.error('上传文件只能是 amr 格式!')
reader.readAsDataURL(file)
}
})
} catch (e) {
console.error(e)
}
if (!isSize) {
this.$message.error('上传文件大小不能超过 2MB!')
}
let amr = new BenzAMRRecorder()
try {
await amr.initWithBlob(file)
isSize = amr.getDuration() <= 60
if (!isSize) {
this.$message.error('上传文件时长不能超过 60秒!')
}
} catch (error) {
console.log(error)
this.$message.error('文件损坏')
}
} else if (this.type === '2') {
// 视频
isFormat = file.type === 'video/mp4'
isSize = file.size / 1024 / 1024 < 10
}
} else if (this.type === '1') {
// 语音
isFormat = /.amr$/gi.test(file.name)
isSize = file.size / 1024 / 1024 < 2
if (!isFormat) {
this.$message.error('上传文件只能是 mp4 格式!')
}
if (!isFormat) {
this.$message.error('上传文件只能是 amr 格式!')
}
if (!isSize) {
this.$message.error('上传文件大小不能超过 2MB!')
}
let amr = new BenzAMRRecorder()
try {
await amr.initWithBlob(file)
isSize = amr.getDuration() <= 60
if (!isSize) {
this.$message.error('上传文件大小不能超过 10MB!')
this.$message.error('上传文件时长不能超过 60秒!')
}
} else if (this.type === '3') {
// 普通文件
isSize = file.size / 1024 / 1024 < 20
} catch (error) {
console.log(error)
this.$message.error('文件损坏')
}
} else if (this.type === '2') {
// 视频
isFormat = file.type === 'video/mp4'
isSize = file.size / 1024 / 1024 < 10
if (!isSize) {
this.$message.error('上传文件大小不能超过 20MB!')
}
if (!isFormat) {
this.$message.error('上传文件只能是 mp4 格式!')
}
if (!isFormat || !isSize) {
this.loading = false
if (!isSize) {
this.$message.error('上传文件大小不能超过 10MB!')
}
} else if (this.type === '3') {
// 普通文件
isSize = file.size / 1024 / 1024 < 20
// if (beforeUpload) {
// return beforeUpload(file)
// }
return (isFormat && isSize) || Promise.reject()
},
onSuccess (res, file) {
if (res.code === 200) {
this.loading = false
// this.$emit('update:fileUrl', res.data.materialUrl)
// this.$emit('update:fileName', res.data.materialName)
// if (this.type == 0) {
// res.url = res.data.url
// res.fileName = res.data.url
// }
this.$emit('update:fileUrl', res.data.url)
this.$emit('update:fileName', res.data.fileName)
this.$emit('update:file', file)
// this.fileUrl = URL.createObjectURL(file.raw)
} else {
this.loading = false
this.$message.error(res.msg)
if (!isSize) {
this.$message.error('上传文件大小不能超过 20MB!')
}
},
onError (err, file, fileList) {
}
if (!isFormat || !isSize) {
this.loading = false
this.$message.error('上传文件失败')
}
// if (beforeUpload) {
// return beforeUpload(file)
// }
return (isFormat && isSize) || Promise.reject()
},
onSuccess(res, file) {
if (res.code === 200) {
this.loading = false
// this.$emit('update:fileUrl', res.data.materialUrl)
// this.$emit('update:fileName', res.data.materialName)
// if (this.type == 0) {
// res.url = res.data.url
// res.fileName = res.data.url
// }
this.$emit('update:fileUrl', res.data.url)
this.$emit('update:fileName', res.data.fileName)
this.$emit('update:file', file)
// this.fileUrl = URL.createObjectURL(file.raw)
} else {
this.loading = false
this.$message.error(res.msg)
}
},
onError(err, file, fileList) {
this.loading = false
this.$message.error('上传文件失败')
}
}
}
</script>
<template>
<div>
<el-upload v-loading="loading" element-loading-text="正在上传..." class="uploader" :accept="accept" :action="action" :headers="headers" :data="{ mediaType: type }" :show-file-list="false" :on-success="onSuccess" :on-error="onError" :before-upload="handleBeforeUpload">
<el-upload
v-loading="loading"
element-loading-text="正在上传..."
class="uploader"
:accept="accept"
:action="action"
:headers="headers"
:data="{ mediaType: type }"
:show-file-list="false"
:on-success="onSuccess"
:on-error="onError"
:before-upload="handleBeforeUpload"
>
<slot>
<template v-if="fileUrl">
<img v-if="type === '0'" :src="fileUrl" class="upload-img" />
<div v-else-if="type === '2'">
<video id="myVideo" class="video-js vjs-default-skin
vjs-big-play-centered" width="100%" controls webkit-playsinline="true" playsinline="true" :autoplay="false" preload="auto">
<video
id="myVideo"
class="video-js vjs-default-skin vjs-big-play-centered"
width="100%"
controls
webkit-playsinline="true"
playsinline="true"
:autoplay="false"
preload="auto"
>
<source :src="fileUrl" type="video/mp4" />
</video>
</div>
......@@ -224,36 +244,36 @@
</template>
<style lang="scss" scoped>
/deep/.uploader {
display: inline-block;
.el-upload {
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
&:hover {
border-color: #409eff;
}
::v-deep.uploader {
display: inline-block;
.el-upload {
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
&:hover {
border-color: #409eff;
}
}
}
.uploader-icon {
font-size: 28px;
color: #8c939d;
width: 178px;
height: 178px;
line-height: 178px;
text-align: center;
border-radius: 6px;
border: 1px dashed #d9d9d9;
}
.upload-img {
width: 178px;
height: 178px;
display: block;
}
.tip {
color: #aaa;
font-size: 12px;
}
.uploader-icon {
font-size: 28px;
color: #8c939d;
width: 178px;
height: 178px;
line-height: 178px;
text-align: center;
border-radius: 6px;
border: 1px dashed #d9d9d9;
}
.upload-img {
width: 178px;
height: 178px;
display: block;
}
.tip {
color: #aaa;
font-size: 12px;
}
</style>
This diff is collapsed.
......@@ -193,7 +193,7 @@ export default {
.nav-scrollbar {
width: calc(100% - 450px);
/deep/.el-scrollbar__view {
::v-deep.el-scrollbar__view {
white-space: nowrap;
line-height: 58px;
}
......
<template>
<el-scrollbar ref="scrollContainer" :vertical="false" class="scroll-container" @wheel.native.prevent="handleScroll">
<el-scrollbar
ref="scrollContainer"
:vertical="false"
class="scroll-container"
@wheel.native.prevent="handleScroll"
>
<slot />
</el-scrollbar>
</template>
......@@ -55,12 +60,13 @@ export default {
$scrollWrapper.scrollLeft = $scrollWrapper.scrollWidth - $containerWidth
} else {
// find preTag and nextTag
const currentIndex = tagList.findIndex(item => item === currentTag)
const currentIndex = tagList.findIndex((item) => item === currentTag)
const prevTag = tagList[currentIndex - 1]
const nextTag = tagList[currentIndex + 1]
// the tag's offsetLeft after of nextTag
const afterNextTagOffsetLeft = nextTag.$el.offsetLeft + nextTag.$el.offsetWidth + tagAndTagSpacing
const afterNextTagOffsetLeft =
nextTag.$el.offsetLeft + nextTag.$el.offsetWidth + tagAndTagSpacing
// the tag's offsetLeft before of prevTag
const beforePrevTagOffsetLeft = prevTag.$el.offsetLeft - tagAndTagSpacing
......@@ -82,7 +88,7 @@ export default {
position: relative;
overflow: hidden;
width: 100%;
/deep/ {
::v-deep {
.el-scrollbar__bar {
bottom: 0px;
}
......
......@@ -53,15 +53,15 @@ Vue.prototype.selectDictLabels = selectDictLabels
Vue.prototype.download = download
Vue.prototype.handleTree = handleTree
Vue.prototype.msgSuccess = function(msg) {
Vue.prototype.msgSuccess = function (msg) {
this.$message({ showClose: true, message: msg, type: 'success' })
}
Vue.prototype.msgError = function(msg) {
Vue.prototype.msgError = function (msg) {
this.$message({ showClose: true, message: msg, type: 'error' })
}
Vue.prototype.msgInfo = function(msg) {
Vue.prototype.msgInfo = function (msg) {
this.$message.info(msg)
}
......@@ -69,10 +69,10 @@ import { pickerOptions } from '@/utils/index'
Vue.prototype.pickerOptions = pickerOptions
import VideoPlayer from 'vue-video-player'
Vue.use(VideoPlayer)
import AudioPlayer from '@liripeng/vue-audio-player'
import '@liripeng/vue-audio-player/lib/vue-audio-player.css'
// import AudioPlayer from '@liripeng/vue-audio-player'
// import '@liripeng/vue-audio-player/lib/vue-audio-player.css'
Vue.use(AudioPlayer)
// Vue.use(AudioPlayer)
import VueAMap from 'vue-amap'
Vue.use(VueAMap)
......
This diff is collapsed.
......@@ -179,7 +179,7 @@ export default {
form: {
taskName: '', // 任务名称
welcomeMsg: '', // 加群引导语
sendType: 0, // 发送方式
sendType: 1, // 发送方式
groupCodeId: '', // 群活码ID
tagList: [], // 标签
scopeList: [], // 员工
......@@ -252,7 +252,7 @@ export default {
getDetail(id).then(({ data }) => {
this.form.taskName = data.taskName || ''
this.form.welcomeMsg = data.welcomeMsg || ''
this.form.sendType = data.sendType || 0
this.form.sendType = data.sendType || 1
this.form.sendScope = data.sendScope || 0
this.form.sendGender = data.sendGender || 0
......
......@@ -153,7 +153,7 @@ export default {
this.$confirm('是否确认删除吗?', '警告', {
type: 'warning'
})
.then(function() {
.then(function () {
return api.remove(id)
})
.then(() => {
......@@ -187,7 +187,7 @@ export default {
this.$confirm('是否确认删除吗?', '警告', {
type: 'warning'
})
.then(function() {
.then(function () {
return api.removeDepart(id)
})
.then(() => {
......@@ -571,7 +571,7 @@ export default {
.img-wrap {
height: 340px;
overflow: auto;
/deep/.el-radio__input {
::v-deep.el-radio__input {
position: absolute;
right: 0;
}
......
......@@ -5,10 +5,9 @@
<!-- <span v-if="item.fromInfo.name">{{item.fromInfo.name}}</span> -->
<div class="mb15">
<span class="mr20">{{ item.name }}</span>
<span
:style="{ color: item.action == 'send' ? '#199ed8' : '#999' }"
>{{ item.msgTime }}</span
>
<span :style="{ color: item.action == 'send' ? '#199ed8' : '#999' }">{{
item.msgTime
}}</span>
</div>
<ChatContent :message="item"></ChatContent>
......@@ -37,7 +36,7 @@ export default {
}
</script>
<style lang="scss" scoped>
#videoPlayer /deep/ .vjs-tech {
#videoPlayer ::v-deep .vjs-tech {
height: 450px;
}
......
......@@ -6,7 +6,7 @@
<span class="fr download" @click="exportList()">下载会话</span>
</div>
</div>
<el-tabs v-model="activeTab" @tab-click="v => opened.includes(v.name) || opened.push(v.name)">
<el-tabs v-model="activeTab" @tab-click="(v) => opened.includes(v.name) || opened.push(v.name)">
<el-tab-pane v-for="(item, index) of list" :key="index" :label="item.label" :name="item.type">
<chatListClassTab
v-if="opened.includes(item.type)"
......@@ -73,10 +73,10 @@ export default {
.then(() => {
return api.exportList(this.queryChat)
})
.then(response => {
.then((response) => {
this.download(response.msg)
})
.catch(function(err) {
.catch(function (err) {
console.log(err)
})
}
......@@ -84,7 +84,7 @@ export default {
}
</script>
<style lang="scss" scoped>
/deep/ .el-tabs__header {
::v-deep .el-tabs__header {
margin: 0;
}
......
......@@ -15,11 +15,7 @@
</li>
</ul>
</div>
<div
style="margin-left:8px;line-height:60px"
class="toe"
:title="item.name"
>
<div style="margin-left: 8px; line-height: 60px" class="toe" :title="item.name">
{{ item.name }}
<!-- <p>
<span class="fr gray">{{ item.msgTime }}</span>
......@@ -95,7 +91,7 @@ export default {
display: none;
}
/deep/ .el-loading-spinner {
::v-deep .el-loading-spinner {
margin-top: 20px;
}
......
......@@ -53,7 +53,7 @@ export default {
display: none;
}
/deep/ .el-loading-spinner {
::v-deep .el-loading-spinner {
margin-top: 20px;
}
......
......@@ -29,7 +29,7 @@
<img v-if="item.avatar" :src="item.avatar" alt="头像" />
</el-col>
<el-col :span="10" v-if="item" class="toe">
<span style="line-height:40px">{{ item.customerName }}</span>
<span style="line-height: 40px">{{ item.customerName }}</span>
</el-col>
<el-col :span="10" class="ar">
<span :style="{ color: item.customerType === 1 ? '#4bde03' : '#f9a90b' }"
......@@ -203,7 +203,7 @@ export default {
}
</script>
<style lang="scss" scoped>
/deep/.el-tabs__nav-scroll {
::v-deep.el-tabs__nav-scroll {
padding-left: 15px;
}
......@@ -217,7 +217,7 @@ export default {
.el-tabs {
background: #fff;
}
/deep/ .el-tabs__header {
::v-deep .el-tabs__header {
margin: 0;
}
......
......@@ -157,7 +157,7 @@ export default {
this.loading = false
this.personList = data
})
.catch(err => {
.catch((err) => {
this.loading = false
})
} else if (this.activeName == 1) {
......@@ -167,7 +167,7 @@ export default {
this.loading = false
this.personList = data
})
.catch(err => {
.catch((err) => {
this.loading = false
})
} else {
......@@ -177,7 +177,7 @@ export default {
this.loading = false
this.personList = data
})
.catch(err => {
.catch((err) => {
this.loading = false
})
}
......@@ -212,7 +212,7 @@ export default {
// data.children.push(...rows)
let arr = node.data.children ? node.data.children.concat(rows || []) : rows || []
arr.forEach(element => {
arr.forEach((element) => {
element.isLeaf = !!element.userId
})
resolve(arr)
......@@ -236,14 +236,14 @@ export default {
}
</script>
<style lang="scss" scoped>
/deep/.el-tabs__nav-scroll {
::v-deep.el-tabs__nav-scroll {
padding-left: 15px;
}
.borderR {
border-right: 2px solid #ccc;
}
/deep/ .el-tabs__header {
::v-deep .el-tabs__header {
margin: 0;
}
.employ {
......
......@@ -217,7 +217,7 @@ export default {
.then((response) => {
this.download(response.msg)
})
.catch(function() {})
.catch(function () {})
}
}
}
......@@ -268,13 +268,13 @@ export default {
}
.noborder {
/deep/ .el-input--mini .el-input__inner {
::v-deep .el-input--mini .el-input__inner {
width: 2px;
border: none;
}
}
.emcode /deep/ em {
.emcode ::v-deep em {
color: #ff0000;
}
</style>
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment