多租户商城-商户端
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

1071 lines
31 KiB

<template>
<div class="customTool" :class="'terminal' + terminal">
<h3 class="toolTit">自定义</h3>
<div class="toolBox">
<div class="selectBox">
<div class="selectLayTit">选择模板<span>{{selectTemplateName}}</span></div>
<div class="layoutList">
<span class="item iconfont" :class="{active: activeComponent.componentContent.layoutType === item.type}" @click="selectLayout(item, index)" v-for="(item, index) of layoutList" :key="item.id" v-html="item.Icon"></span>
</div>
</div>
<div class="itemBox flexStyle">
<label>图片间隙</label>
<div class="block">
<el-slider
:show-input-controls=false
input-size="mini"
v-model="activeComponent.componentContent.imgClearance"
show-input>
</el-slider>
</div>
</div>
<div class="itemBox flexStyle">
<label>页面间距</label>
<div class="block">
<el-slider
:show-input-controls=false
input-size="mini"
v-model="activeComponent.componentContent.pageSpacing"
show-input>
</el-slider>
</div>
</div>
<div class="itemBox">
<div v-if="activeComponent.componentContent.layoutType !== 'average'">
<div class="textTit">布局</div>
<p>选定布局区域,在下方添加图片,建议添加比例一致的图片</p>
<div class="layoutBox"
:class="activeComponent.componentContent.layoutType"
>
<div class="item" :class="{active: activeComponent.componentContent.imgBoxActive === index-1}" @click="changeLayout(index-1)" v-for="index of activeComponent.componentContent.elementNum" :key="index">
<!--<span>宽度375px</span>-->
<img class="img" :src="activeComponent.componentContent.imgData[index-1].src" v-show="activeComponent.componentContent.imgData[index-1].src">
</div>
</div>
</div>
<div v-else>
<dl class="densityLiist">
<dt>密度</dt>
<dd>
<el-select v-model="activeComponent.componentContent.density" placeholder="" @change="densityChange">
<el-option label="4*4" value="4"></el-option>
<el-option label="5*5" value="5"></el-option>
<el-option label="6*6" value="6"></el-option>
<el-option label="7*7" value="7"></el-option>
<el-option label="10*10" value="10"></el-option>
</el-select>
</dd>
</dl>
<div class="textTit">布局</div>
<p>移动鼠标选定布局区域大小</p>
<div class="averageBoxWarp">
<div class="averageBox" @mouseleave="averageBoxLeave">
<ul v-for="i of parseInt(activeComponent.componentContent.density)" :key="'y'+i" :class="'col'+activeComponent.componentContent.density">
<li v-for="j of parseInt(activeComponent.componentContent.density)" :key="'x'+j" :class="{'on':activeComponent.componentContent.averageBoxData[i-1][j-1].hover}" @click="averageBoxClick(i-1,j-1)" @mouseover="averageBoxMouseover(i-1,j-1)"></li>
</ul>
</div>
<div class="selectedCube">
<ul>
<li v-for="(item,index) of activeComponent.componentContent.imgData" :class="{active: activeComponent.componentContent.imgBoxActive === index}" :key="index" :style="{'width':getItemValue(item.width) + '%','height':getItemValue(item.height) + '%','left':getItemValue(item.left) + '%','top':getItemValue(item.top) + '%'}">
<div class="box" @click="changeLayout(index)">
<span>
{{parseInt(getItemValue(item.width) * 12)}}x{{parseInt(getItemValue(item.height) * 12)}}
</span>
<img class="img" :src="activeComponent.componentContent.imgData[index].src" v-if="activeComponent.componentContent.imgData[index].src">
</div>
<a class="btn-close" @click="delsSlectedCube(item,index)"><i class="icon iconfont icon-close"></i></a>
</li>
</ul>
</div>
</div>
</div>
<div v-if="activeComponent.componentContent.imgData.length !== 0">
<div class="addImgTit">请添加图片</div>
<div class="addImgBox">
<div class="addImgBoxInner">
<div class="addImg">
<el-upload
drag
:headers="headers"
:action="fileUploadApi.fileUpload"
:on-success="handleAvatarSuccess"
:before-upload="beforeAvatarUpload"
:show-file-list="false"
>
<img v-if="activeComponent.componentContent.imgData[activeComponent.componentContent.imgBoxActive].src" :src="activeComponent.componentContent.imgData[activeComponent.componentContent.imgBoxActive].src" class="avatar">
<div v-if="activeComponent.componentContent.imgData[activeComponent.componentContent.imgBoxActive].src" class="tips">更换图片</div>
<i v-else class="el-icon-plus avatar-uploader-icon"></i>
<span>添加图片</span>
</el-upload>
</div>
<div class="addLink">
<tool-select-link :linkObj.sync='activeComponent.componentContent.imgData[activeComponent.componentContent.imgBoxActive].linkObj' title="链接"></tool-select-link>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import { mapGetters } from 'vuex'
import {toolMixin} from '@@/config/mixin'
import ToolSelectLink from '../toolModule/tool-select-link'
import api from '@@/components/canvasShow/config/api'
import { getToken } from '@/utils/auth'
export default {
name: 'customTool',
mixins: [toolMixin],
components: {
ToolSelectLink
},
data () {
return {
title: '', // 标题内容
// imgClearance: 0, // 图片间隙
// pageSpacing: 0, // 页面间距
imgBoxActive: 0,
imageUrl: '', // 图片地址
linkValue: '', // 链接地址
linkOptions: [
{
value: '/index',
label: '首页'
},
{
value: '/list',
label: '列表页'
},
{
value: '/detail',
label: '详情页'
},
{
value: '/about',
label: '关于我们'
}
],
layoutList: [
{
id: 0,
type: 'L1',
name: '单图',
number: 1, // 显示格子数
Icon: '&#xe607;'
},
{
id: 1,
type: 'L2',
name: '一行二个',
number: 2, // 显示格子数
Icon: '&#xe643;'
},
{
id: 2,
type: 'L3',
name: '一行三个',
number: 3,
Icon: '&#xe644;'
},
{
id: 3,
type: 'L4',
name: '一行四个',
number: 4,
Icon: '&#xe645;'
},
{
id: 4,
type: 'T2B2',
name: '二左二右',
number: 4,
Icon: '&#xe647;'
},
{
id: 5,
type: 'L1R2',
name: '一左二右',
number: 3,
Icon: '&#xe646;'
},
{
id: 6,
type: 'T1B2',
name: '一上二下',
number: 3,
Icon: '&#xe648;'
},
{
id: 7,
type: 'L1T1B2',
name: '一左三右',
number: 4,
Icon: '&#xe646;'
},
{
id: 8,
type: 'average',
name: '自定义',
number: 0,
Icon: '&#xe642;'
}
],
activeLay: 0,
elementNum: 2, // 生成格子数量
// layoutType: 'L2',
// density: '4',
// averageBoxData: [], // 记录格子的激活状态
beginAverageBox: [], // 记录开始点击的格子
endAverageBox: [], // 记录结束点击的格子
imgData: [], // 图片数据
fileUploadApi: {
fileUpload: ''
},
headers: {
'Authorization-business': getToken()
},
}
},
computed: {
...mapGetters([
'terminal'
]),
selectTemplateName () {
for (let i = 0; i < this.layoutList.length; i++) {
if (this.layoutList[i].type === this.activeComponent.componentContent.layoutType) {
return this.layoutList[i].name
}
}
}
},
mounted () {
this.fileUploadApi = api
},
methods: {
handleAvatarSuccess (res, file) {
this.activeComponent.componentContent.imgData[this.activeComponent.componentContent.imgBoxActive].src = res.data.url
},
beforeAvatarUpload (file) {
const isLt1M = file.size / 1024 / 1024 < 1
if (!isLt1M) {
this.$message.error('上传图片大小不能超过 1MB!')
}
return isLt1M
},
// 计算生成格子百分比
getItemValue (val) {
const density = parseInt(this.activeComponent.componentContent.density)
if (val === 0 || density === 0) {
return 0
}
return (val / density * 10000 / 100.00)// 小数点后两位百分比
},
// 选择布局
selectLayout (item, index) {
this.activeComponent.componentContent.imgBoxActive = 0
this.activeComponent.componentContent.maxH = 0
this.activeLay = index
this.activeComponent.componentContent.elementNum = item.number
this.activeComponent.componentContent.layoutType = item.type
if (item.type === 'average') {
this.densityChange(this.activeComponent.componentContent.density)
} else {
this.activeComponent.componentContent.imgData = []
let obj = {
src: '',
linkObj: {
selsectValue: '',
selectName: '',
typeText: '',
url: ''
}
}
for (let i = 0; i < item.number; i++) {
this.activeComponent.componentContent.imgData.push(JSON.parse(JSON.stringify(obj)))
}
}
},
// 选择格子
changeLayout (index) {
this.activeComponent.componentContent.imgBoxActive = index
},
// 添加图片
imgChange (file, fileList) {
this.activeComponent.componentContent.imgData[this.activeComponent.componentContent.imgBoxActive].src = URL.createObjectURL(file.raw)
},
// 切换密度
densityChange (val) {
this.activeComponent.componentContent.imgBoxActive = 0
const densityVal = parseInt(val)
this.activeComponent.componentContent.averageBoxData = []
for (let i = 0; i < densityVal; i++) {
this.activeComponent.componentContent.averageBoxData[i] = []
for (let j = 0; j < densityVal; j++) {
this.activeComponent.componentContent.averageBoxData[i].push({
hover: false, // 判断经过激活的位置
takeUp: false // 判断占击占用的位置
})
}
}
this.activeComponent.componentContent.maxH = 0
this.activeComponent.componentContent.imgData = []
},
// 自定义格子点击
averageBoxClick (x, y) {
if (this.beginAverageBox.length === 0) {
this.beginAverageBox = [x, y]
this.endAverageBox = [x, y]
this.activeComponent.componentContent.averageBoxData[x][y].hover = true
this.activeComponent.componentContent.averageBoxData = this.activeComponent.componentContent.averageBoxData.concat([]) // 触发视图更新
} else {
const bx = this.beginAverageBox[0] // 起点X
const by = this.beginAverageBox[1] // 起点Y
// 使用最后一次合理经过的位置
x = this.endAverageBox[0]
y = this.endAverageBox[1]
// 计算占用位置
if (x >= bx) {
for (let i = bx; i <= x; i++) {
if (y >= by) {
for (let j = by; j <= y; j++) {
this.activeComponent.componentContent.averageBoxData[i][j].takeUp = true
}
} else {
for (let j = y; j <= by; j++) {
this.activeComponent.componentContent.averageBoxData[i][j].takeUp = true
}
}
}
} else {
for (let i = x; i <= bx; i++) {
if (y >= by) {
for (let j = by; j <= y; j++) {
this.activeComponent.componentContent.averageBoxData[i][j].takeUp = true
}
} else {
for (let j = y; j <= by; j++) {
this.activeComponent.componentContent.averageBoxData[i][j].takeUp = true
}
}
}
}
// 生成图片框
var obj = {
src: '',
linkObj: {
selsectValue: '',
selectName: '',
typeText: '',
url: ''
}
}
if (x >= bx) {
obj.width = x - bx + 1
obj.left = bx
} else {
obj.width = bx - x + 1
obj.left = x
}
const maxH = this.activeComponent.componentContent.maxH
if (y >= by) {
obj.height = y - by + 1
obj.top = by
if (y + 1 > maxH) {
this.activeComponent.componentContent.maxH = y + 1
}
} else {
obj.height = by - y + 1
obj.top = y
if (by + 1 > maxH) {
this.activeComponent.componentContent.maxH = by + 1
}
}
this.activeComponent.componentContent.imgData.push(JSON.parse(JSON.stringify(obj)))
this.beginAverageBox = []
}
},
// 自定义格子经过
averageBoxMouseover (x, y) {
if (this.beginAverageBox.length !== 0) {
// 计算有没有经过有占用的位置
let flag = this.isBoxTakeUp(x, y)
if (!flag) {
return false
}
// 每次经过洗白格子
const bx = this.beginAverageBox[0] // 起点X
const by = this.beginAverageBox[1] // 起点Y
const densityVal = parseInt(this.activeComponent.componentContent.density)
for (let i = 0; i < densityVal; i++) {
for (let j = 0; j < densityVal; j++) {
this.activeComponent.componentContent.averageBoxData[i][j].hover = false
}
}
this.activeComponent.componentContent.averageBoxData[x][y].hover = true
// 起终点中间位置激活
if (x >= bx) {
for (let i = bx; i <= x; i++) {
if (y >= by) {
for (let j = by; j <= y; j++) {
this.activeComponent.componentContent.averageBoxData[i][j].hover = true
}
} else {
for (let j = y; j <= by; j++) {
this.activeComponent.componentContent.averageBoxData[i][j].hover = true
}
}
}
} else {
for (let i = x; i <= bx; i++) {
if (y >= by) {
for (let j = by; j <= y; j++) {
this.activeComponent.componentContent.averageBoxData[i][j].hover = true
}
} else {
for (let j = y; j <= by; j++) {
this.activeComponent.componentContent.averageBoxData[i][j].hover = true
}
}
}
}
this.endAverageBox = [x, y] // 记录结束位置
this.activeComponent.componentContent.averageBoxData = this.activeComponent.componentContent.averageBoxData.concat([]) // 触发视图更新
}
},
// 计算有没有经过有占用的位置
isBoxTakeUp (x, y) {
if (this.beginAverageBox.length !== 0) {
const bx = this.beginAverageBox[0] // 起点X
const by = this.beginAverageBox[1] // 起点Y
let flag = true
if (x >= bx) {
for (let i = bx; i <= x; i++) {
if (y >= by) {
for (let j = by; j <= y; j++) {
if (this.activeComponent.componentContent.averageBoxData[i][j].takeUp) {
flag = false
break
}
}
} else {
for (let j = y; j <= by; j++) {
if (this.activeComponent.componentContent.averageBoxData[i][j].takeUp) {
flag = false
break
}
}
}
}
} else {
for (let i = x; i <= bx; i++) {
if (y >= by) {
for (let j = by; j <= y; j++) {
if (this.activeComponent.componentContent.averageBoxData[i][j].takeUp) {
flag = false
break
}
}
} else {
for (let j = y; j <= by; j++) {
if (this.activeComponent.componentContent.averageBoxData[i][j].takeUp) {
flag = false
break
}
}
}
}
}
return flag
}
},
// 移出盒子清空
averageBoxLeave () {
this.beginAverageBox = []
this.endAverageBox = []
const densityVal = parseInt(this.activeComponent.componentContent.density)
for (let i = 0; i < densityVal; i++) {
for (let j = 0; j < densityVal; j++) {
this.activeComponent.componentContent.averageBoxData[i][j].hover = false
}
}
},
// 删除选中格子
delsSlectedCube (item, index) {
// 清除占用位置
let bx = item.left
let by = item.top
let xl = item.width
let yl = item.height
for (let i = bx; i < bx + xl; i++) {
for (let j = by; j < by + yl; j++) {
this.activeComponent.componentContent.averageBoxData[i][j].takeUp = false
}
}
this.activeComponent.componentContent.imgBoxActive = 0
this.activeComponent.componentContent.imgData.splice(index, 1)
// 重新计算最大高度
const imgData = this.activeComponent.componentContent.imgData
let maxH = 0
for (let i = 0; i < imgData.length; i++) {
if (imgData[i].top + imgData[i].height > maxH) {
maxH = imgData[i].top + imgData[i].height
}
}
this.activeComponent.componentContent.maxH = maxH
}
}
}
</script>
<style lang="scss" scoped>
.customTool {
padding: 20px 20px 0 20px;
h3 {
font-size: 18px;
font-weight: 500;
height: 35px;
line-height: 35px;
color: #333333;
margin-bottom: 20px;
}
.toolBox {
.selectLayTit {
margin-bottom: 20px;
font-size: 14px;
color: #333333;
span {
font-size: 14px;
color: $mainColor;
margin-left: 20px;
}
}
.layoutList {
display: flex;
flex-direction: row;
flex-wrap: wrap;
margin-bottom: 30px;
span {
margin: -1px 0 0 -1px;
flex: 0 0 15.9%;
display: flex;
align-items: center;
justify-content: center;
border: 1px solid #E8EAEC;
color: #999999;
font-size: 18px;
text-align: center;
height: 28px;
cursor: pointer;
position: relative;
&.active,&:hover {
color: $mainColor;
&:after{
content: '';
width: 100%;
height: 100%;
border: 1px solid $mainColor;
position: absolute;
left: 0;
top: 0;
z-index: 2;
}
}
}
}
padding-bottom: 10px;
.flexStyle {
display: flex;
label {
margin-right: 20px;
}
.block {
flex: 1;
}
::v-deep .el-slider__input {
width: 50px;
}
::v-deep .el-slider__runway {
height: 4px;
margin: 18px 65px 18px 0;
}
::v-deep .el-slider__bar {
height: 4px;
}
::v-deep .el-slider__button-wrapper {
top: -17px;
}
::v-deep .el-slider__button {
width: 12px;
height: 12px;
}
::v-deep .el-input-number.is-without-controls .el-input__inner {
padding: 10px;
}
}
.itemBox {
width: 100%;
label {
font-size: 14px;
color: #666666;
height: 40px;
line-height: 40px;
}
margin-bottom: 15px;
p {
font-size: 12px;
color: #666666;
}
.layoutBox {
margin-top: 20px;
display: flex;
.item {
margin: -1px 0 0 -1px;
flex: 0 0 50%;
height: 125px;
border: 1px solid #E8EAEC;
box-sizing: border-box;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
position: relative;
&:before {
content: '600px';
font-size: 12px;
color: #666666;
padding: 0 10px;
text-align: center;
}
.img{
position: absolute;
width: 100%;
height: 100%;
left: 0;
top: 0;
}
&.active {
background: #FBF9F8;
&:before {
color: $mainColor;
}
&:after{
content: '';
width: 100%;
height: 100%;
border: 1px solid $mainColor;
position: absolute;
left: 0;
top: 0;
z-index: 2;
}
}
}
}
.L1 {
.item {
flex: 0 0 100%;
height: 93px;
&:before {
content: '1200px';
}
}
}
.L3 {
.item {
flex: 0 0 33.3%;
height: 93px;
&:before {
content: '400px';
}
}
}
.L4 {
.item {
flex:0 0 25%;
height: 71px;
&:before {
content: '300px';
}
}
}
.T2B2 {
flex-wrap: wrap;
.item {
flex: 0 0 50%;
height: 142px;
&:before {
content: '600x600px';
}
}
}
.L1R2 {
flex-wrap: wrap;
.item{
&:before {
content: '600x600px';
}
}
.item:nth-child(1) {
height: 284px;
&:before {
content: '600x1200px';
}
}
.item:nth-child(3) {
margin-left: 138px;
margin-top: -143px;
}
}
.T1B2 {
flex-wrap: wrap;
.item{
&:before {
content: '600x500px';
}
}
.item:nth-child(1) {
flex: 0 0 100%;
&:before {
content: '1200x500px';
}
}
}
.L1T1B2 {
flex-wrap: wrap;
.item{
&:before {
content: '300x300px';
}
}
.item:nth-child(1) {
&:before {
content: '600x600px';
}
}
.item:nth-child(2) {
height: 72px;
&:before {
content: '600x300px';
}
}
.item:nth-child(3) {
flex: 0 0 25%;
height: 72px;
margin: -71px 0 0 138px;
}
.item:nth-child(4) {
margin-top: -71px;
flex: 0 0 25%;
height: 72px;
}
}
.average {
flex-wrap: wrap;
.item {
flex: 0 0 33.33%;
height: 93px;
}
}
.addImgTit {
margin-top: 20px;
color: #FF3737;
font-size: 12px;
}
.addImgBox {
width: 100%;
margin-top: 10px;
box-sizing: border-box;
position: relative;
padding-bottom: 50px;
.addImgBoxInner{
background: #F6F7F9;
display: flex;
}
.addImg {
width: 60px;
height: 60px;
margin-right: 10px;
::v-deep .el-upload-dragger {
width: 60px;
height: 60px;
text-align: center;
.avatar{
width: 100%;
height: 100%;
}
i {
margin-top: 10px;
}
.el-icon-plus:before {
color: $mainColor;
}
span {
display: block;
font-size: 12px;
color: $mainColor;
}
.tips{
}
}
}
.addLink {
flex:1;
::v-deep .link-select{
margin-bottom: 0;
line-height: 60px;
width: 100%;
&__warp{
display: flex;
}
.module-box__title{
font-size: 12px;
color: #333333;
margin-bottom: 0;
.module-box__label{
line-height: 60px;
}
}
&__select{
flex: 1;
.el-input__inner {
border: none;
background: none;
font-size: 12px;
color: $mainColor;
}
.el-input__inner::placeholder {
color: $mainColor;
}
.el-icon-arrow-up:before {
color: $mainColor;
}
}
&__confirm{
position: absolute;
bottom: 0;
left: 0;
width: 100%;
}
}
}
}
.averageBoxWarp{
position: relative;
}
.averageBox{
margin-top: 20px;
display: flex;
flex-wrap: wrap;
ul{
li{
margin: -1px 0 0 -1px;
border: 1px solid #E8EAEC;
background-color: #f8f8f8;
&.on{
background-color: #fbbe73;
}
}
&.col4{
flex: 0 0 25%;
li{
height: 70px;
}
}
&.col5{
flex: 0 0 20%;
li{
height: 56px;
}
}
&.col6{
flex: 0 0 16.6%;
li{
height: 46px;
}
}
&.col7{
flex: 0 0 14.2%;
li{
height: 40px;
}
}
&.col10{
flex: 0 0 10%;
li{
height: 29px;
}
}
}
}
.selectedCube{
li{
position: absolute;
font-size: 12px;
border: 1px solid #E8EAEC;
background-color: #fff;
z-index: 2;
margin: -1px 0 0 -1px;
box-sizing: content-box;
.box{
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
}
span{
/*transform: scale(0.9);*/
/*white-space: nowrap;*/
/*text-align: center;*/
}
.img{
position: absolute;
width: 100%;
height: 100%;
left: 0;
top: 0;
}
.btn-close{
position: absolute;
top: -10px;
right: -10px;
z-index: 4;
cursor: pointer;
opacity: 0.6;
font-size: 20px;
display: none;
}
&.active {
z-index: 3;
background: #FBF9F8;
&:hover{
.btn-close{
display: block;
}
}
span {
color: $mainColor;
}
&:after{
content: '';
width: 100%;
height: 100%;
border: 1px solid $mainColor;
position: absolute;
left: 0;
top: 0;
z-index: 2;
}
}
}
}
}
.textTit {
height: 35px;
line-height: 35px;
font-size: 16px;
color: #333333;
margin-top: 30px;
font-weight: bold;
}
}
.densityLiist{
display: flex;
justify-content: space-between;
dt{
line-height: 40px;
}
}
}
.terminal1,.terminal2,.terminal3{
&.customTool {
.toolBox {
.itemBox {
.layoutBox {
.item {
&:before {
content: '360px';
}
}
}
.L1 {
.item {
&:before {
content: '720px';
}
}
}
.L3 {
.item {
&:before {
content: '240px';
}
}
}
.L4 {
.item {
&:before {
content: '180px';
}
}
}
.T2B2 {
.item {
&:before {
content: '360x360px';
}
}
}
.L1R2 {
.item{
&:before {
content: '360x360px';
}
}
.item:nth-child(1) {
&:before {
content: '360x720px';
}
}
}
.T1B2 {
.item{
&:before {
content: '360x360px';
}
}
.item:nth-child(1) {
&:before {
content: '720x360px';
}
}
}
.L1T1B2 {
.item{
&:before {
content: '180x180px';
}
}
.item:nth-child(1) {
&:before {
content: '360x360px';
}
}
.item:nth-child(2) {
&:before {
content: '360x180px';
}
}
}
}
}
}
}
</style>