装起全部商城菜单

This commit is contained in:
2022-04-21 18:07:40 +08:00
parent 1b6f8f0ed9
commit 05fdb1d9e7
436 changed files with 50845 additions and 63 deletions
@@ -0,0 +1,174 @@
<template>
<div class="layout hom-layout">
<draggable
class="dragArea list-group"
:list="componentsData"
group="pageEdit"
@change="pageChange"
>
<div
class="list-group-item"
v-for="(item,index) in componentsData"
:key="index" :class="{'on':activeComponent == index}"
@click="selectComponent(item,index)">
<component
:is="componentMap[terminal-3].get(item.type)"
:componentContent="item.componentContent"
:terminal="terminal"></component>
<div class="btns">
<span @click="delComponent(item,index)">
<i class="iconfont icon-shanchu"></i>
</span>
</div>
</div>
</draggable>
</div>
</template>
<script>
import draggable from 'vuedraggable'
import componentMap from '@/views/theme/components/canvasShow/componentMap.js'
import { mapGetters, mapMutations } from 'vuex'
export default {
name: 'canvasEditPage',
components: {
draggable
},
props: {
terminal: {
type: Number,
default: 4
}
},
data () {
return {
activeComponent: -1,
componentMap: componentMap
}
},
computed: {
...mapGetters([
'componentsData'
])
},
methods: {
...mapMutations({
setActiveComponent: 'SET_ACTIVECOMPONENT',
setComponentsData: 'SET_COMPONENTSDATA'
}),
pageChange (e) {
if (e.added) {
this.activeComponent = e.added.newIndex
e.added.element.index = e.added.newIndex
this.setActiveComponent(e.added.element)
}
if (e.moved) {
this.activeComponent = e.moved.newIndex
e.moved.element.index = e.moved.newIndex
this.setActiveComponent(e.moved.element)
}
},
selectComponent (item, index) {
this.activeComponent = index
item.index = index
this.setActiveComponent(item)
},
delComponent (item, index) {
this.$confirm('确定删除吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.activeComponent = -1
this.componentsData.splice(index, 1)
}).catch(() => {
})
}
}
}
</script>
<style lang="scss" scoped>
.hom-layout{
background-color: #fff;
>>> .sortable-chosen{
.contentBox {
display: none;
}
.cloneText{
display: block;
width: 100%;
height: 50px;
line-height: 50px;
font-size: 18px;
text-align: center;
background-color: $mainColor;
color: #fff;
}
}
.list-group{
min-height: calc(100vh - 50px);
}
.list-group-item{
position: relative;
cursor: move;
.btns{
display: none;
}
&:hover{
&:after{
content: '';
position: absolute;
width: 100%;
height: 100%;
left: 0;
top: 0;
border:1px $mainColor dashed;
z-index: 2;
}
}
&.on{
&:after{
content: '';
position: absolute;
width: 100%;
height: 100%;
left: 0;
top: 0;
border:1px $mainColor solid;
z-index: 2;
}
.btns{
display: block;
position: absolute;
right: -13px;
top: 50%;
margin-top: -13px;
z-index: 3;
span{
display: block;
width: 26px;
height: 26px;
line-height: 26px;
text-align: center;
color: #666;
background-color: #fff;
box-shadow: 0 0 2px rgba(51,51,51,.2);
cursor: pointer;
}
}
}
}
}
</style>
<style lang="scss">
.warp{
width: 1252px;
margin: 0 auto;
max-width: 96%;
}
.flex-box{
display: flex;
}
</style>
@@ -0,0 +1,49 @@
const componentMap = [
// 手机端
new Map([
['header', () => import('@/views/theme/components/canvasShow/mobile/Header.vue')], // 店铺头部
['search', () => import('@/views/theme/components/canvasShow/mobile/Search.vue')], // 搜索商品
['banner', () => import('@/views/theme/components/canvasShow/mobile/Banner.vue')], // 轮播图
['noticeBar', () => import('@/views/theme/components/canvasShow/mobile/NoticeBar.vue')], // 滚动新闻
['menu', () => import('@/views/theme/components/canvasShow/mobile/Menu.vue')], // 菜单
['adv', () => import('@/views/theme/components/canvasShow/mobile/Adv.vue')], // 广告
['groupon', () => import('@/views/theme/components/canvasShow/mobile/Groupon.vue')], // 超值拼团
[
'hotCommodity',
() => import('@/views/theme/components/canvasShow/mobile/HotCommodity.vue')
], // 热门榜单
[
'firstNewProduct',
() => import('@/views/theme/components/canvasShow/mobile/FirstNewProduct.vue')
], // 秒杀
[
'productsRecommended',
() => import('@/views/theme/components/canvasShow/mobile/ProductsRecommended.vue')
], // 精品推荐
[
'promoteProduct',
() => import('@/views/theme/components/canvasShow/mobile/PromoteProduct.vue')
], // 促销单品
['live', () => import('@/views/theme/components/canvasShow/mobile/Live.vue')], // 直播
[
'promotionGood',
() => import('@/views/theme/components/canvasShow/mobile/PromotionGood.vue')
] // 为您推荐
]),
// PC
new Map([
// pc单商户改版
['NavPersonal', () => import('@/views/theme/components/canvasShow/pc/NavPersonal.vue')], // 个人中心
['NavType', () => import('@/views/theme/components/canvasShow/pc/NavType.vue')], // 分类导航
['PcBanner', () => import('@/views/theme/components/canvasShow/pc/Banner.vue')], // 轮播图
['ProductNew', () => import('@/views/theme/components/canvasShow/pc/ProductNew.vue')], // 新品首发
['ProductHot', () => import('@/views/theme/components/canvasShow/pc/ProductHot.vue')], // 人气爆款
['ProductSeckill', () => import('@/views/theme/components/canvasShow/pc/ProductSeckill.vue')], // 秒杀专区
['ProductComb', () => import('@/views/theme/components/canvasShow/pc/ProductComb.vue')], // 拼团专区
['ProductDiscount', () => import('@/views/theme/components/canvasShow/pc/ProductDiscount.vue')], // 折扣专区
['ProductBargin', () => import('@/views/theme/components/canvasShow/pc/ProductBargin.vue')], // 砍价专区
['Footer', () => import('@/views/theme/components/canvasShow/pc/Footer.vue')] // 底部版权相关
])
]
export default componentMap
@@ -0,0 +1,80 @@
<template>
<div class="layout hom-layout">
<div
class="list-group-item"
v-for="(item, index) in componentsData"
:key="index"
>
<component
:is="componentMap[terminal - 1].get(item.type)"
:componentContent="item.componentContent"
:terminal="terminal"
></component>
</div>
</div>
</template>
<script>
import componentMap from './componentMap'
import { mapMutations } from 'vuex'
import { getCanvasData, getProducts } from '@/api/canvasApi.js'
export default {
name: 'canvasPage',
data () {
return {
terminal: 3,
componentsData: [],
activeComponent: -1,
componentMap: componentMap
}
},
mounted () {
this.canvasGet()
},
methods: {
...mapMutations({
setComponentsData: 'SET_COMPONENTSDATA'
}),
// 读取画布
async canvasGet () {
const res = await getCanvasData({'terminal': this.terminal})
if (JSON.stringify(res.data) !== '{}') {
this.canvasId = res.data.canvasId
this.componentsData = JSON.parse(res.data.json)
var componentsData = this.componentsData
for (let i = 0; i < componentsData.length; i++) {
if (componentsData[i].type === 'productList') {
if (componentsData[i].componentContent.categoryId) {
let params = {
page: 1,
pageSize: 20,
classifyId: componentsData[i].componentContent.categoryId
}
getProducts(params).then(rres => {
componentsData[i].componentContent.imgTextData = rres.data.list
})
}
}
}
}
}
}
}
</script>
<style lang="scss" scoped>
.hom-layout {
background-color: #f5f5f5;
}
</style>
<style lang="scss">
.warp {
width: 1252px;
margin: 0 auto;
max-width: 96%;
}
.flex-box {
display: flex;
}
</style>
@@ -0,0 +1,252 @@
<template>
<div class="adv-box mx20 mb10">
<!-- 模板1-->
<div class="x-f" v-if="componentContent.detail.style == 1">
<img
@tap="jump(componentContent.detail.list[0].path)"
:src="componentContent.detail.list[0].image" />
</div>
<!-- 模板2-->
<div class="type1 x-f" v-if="componentContent.detail.style == 2">
<img
class="type1-img"
@tap="jump(componentContent.detail.list[0].path)"
:src="componentContent.detail.list[0].image" />
<img
class="type1-img"
@tap="jump(componentContent.detail.list[1].path)"
:src="componentContent.detail.list[1].image" />
</div>
<!-- 模板3-->
<div class="type2 x-bc" v-if="componentContent.detail.style == 3">
<img
class="type2-img1"
@tap="jump(componentContent.detail.list[0].path)"
:src="componentContent.detail.list[0].image" />
<div class="y-f type2-box">
<img
class="type2-img2"
@tap="jump(componentContent.detail.list[1].path)"
:src="componentContent.detail.list[1].image"
style="border-bottom: 1px solid #f6f6f6" />
<img
class="type2-img2"
@tap="jump(componentContent.detail.list[2].path)"
:src="componentContent.detail.list[2].image" />
</div>
</div>
<!-- 模板4-->
<div class="type3 x-bc" v-if="componentContent.detail.style == 4">
<div class="type3-box y-f">
<img
class="type3-img1"
@tap="jump(componentContent.detail.list[0].path)"
:src="componentContent.detail.list[0].image" />
<img
class="type3-img1"
@tap="jump(componentContent.detail.list[1].path)"
:src="componentContent.detail.list[1].image" />
</div>
<img
class="type3-img2"
@tap="jump(componentContent.detail.list[2].path)"
:src="componentContent.detail.list[2].image" />
</div>
<!-- 模板5-->
<div class="type4 y-f" v-if="componentContent.detail.style == 5">
<div class="type4-box x-f">
<img
class="type4-img1"
@tap="jump(componentContent.detail.list[0].path)"
:src="componentContent.detail.list[0].image" />
<img
class="type4-img1"
@tap="jump(componentContent.detail.list[1].path)"
:src="componentContent.detail.list[1].image" />
</div>
<img
class="type4-img2"
@tap="jump(componentContent.detail.list[2].path)"
:src="componentContent.detail.list[2].image" />
</div>
<!-- 模板6-->
<div class="type5 y-f" v-if="componentContent.detail.style == 6">
<img
class="type5-img1"
@tap="jump(componentContent.detail.list[0].path)"
:src="componentContent.detail.list[0].image" />
<div class="type5-box x-bc">
<img
class="type5-img2"
@tap="jump(componentContent.detail.list[1].path)"
:src="componentContent.detail.list[1].image"
style="border-bottom: 1px solid #f6f6f6" />
<img
class="type5-img2"
@tap="jump(componentContent.detail.list[2].path)"
:src="componentContent.detail.list[2].image" />
</div>
</div>
<!-- 模板7-->
<div class="type6 y-f" v-if="componentContent.detail.style == 7">
<div class="x-f type6-box1">
<img
class="type6-img1"
@tap="jump(componentContent.detail.list[0].path)"
:src="componentContent.detail.list[0].image" />
<img
class="type6-img1"
@tap="jump(componentContent.detail.list[1].path)"
:src="componentContent.detail.list[1].image" />
</div>
<div class="x-f type6-box2">
<img
class="type6-img2"
@tap="jump(componentContent.detail.list[2].path)"
:src="componentContent.detail.list[2].image" />
<img
class="type6-img2"
@tap="jump(componentContent.detail.list[3].path)"
:src="componentContent.detail.list[3].image" />
<img
class="type6-img2"
@tap="jump(componentContent.detail.list[4].path)"
:src="componentContent.detail.list[4].image" />
</div>
</div>
</div>
</template>
<script>
export default {
props: {
componentContent: {
type: Object
}
},
methods: {
// 路由跳转
jump (path) {}
}
}
</script>
<style lang="scss" scoped>
.y-f {
display: flex;
flex-direction: column;
align-items: center;
}
.x-bc {
display: flex;
justify-content: space-between;
align-items: center;
}
.adv-box {
background-color: #fff;
border-radius: 20/750 * 500px;
overflow: hidden;
image {
width: 100%;
}
.type1 {
.type1-img {
flex: 1;
height: 220/750 * 500px;
&:first-child {
border-right: 1px solid #f6f6f6;
}
}
}
.type2 {
.type2-img1 {
width: 249px;
height: 249px;
border-right: 1px solid #f6f6f6;
}
.type2-box {
flex: 1;
height: 249px;
width: 249px;
.type2-img2 {
width: 100%;
}
}
}
.type3 {
.type3-box {
width: (710/750 * 500px);
border-right: 1px solid #f6f6f6;
.type3-img1 {
flex: 1;
height: (340/750 * 500px);
&:first-child {
border-bottom: 1px solid #f6f6f6;
}
}
}
.type3-img2 {
flex: 1;
height: 340/750 * 500px;
width: (710/750 * 500px);
}
}
.type4 {
.type4-box {
border-bottom: 1px solid #f6f6f6;
.type4-img1 {
flex: 1;
height: (340/750 * 500px);
&:first-child {
border-right: 1px solid #f6f6f6;
}
}
}
.type4-img2 {
flex: 1;
height: (340/750 * 500px);
width: 710/750 * 500px;
}
}
.type5 {
.type5-img1 {
width: 710/750 * 500px;
height: (340/750 * 500px);
border-bottom: 1px solid #f6f6f6;
}
.type5-box {
flex: 1;
height: (340/750 * 500px);
width: 710/750 * 500px;
.type5-img2 {
height: (340/750 * 500px);
&:first-child {
border-right: 1px solid #f6f6f6;
}
}
}
}
.type6 {
.type6-box1 {
.type6-img1 {
width: (710/750 * 500px);
height: (340/750 * 500px);
&:first-child {
border-right: 1px solid #f6f6f6;
}
}
}
.type6-box2 {
border-top: 1px solid #f6f6f6;
.type6-img2 {
width: (710/750 * 500 / 3) px;
height: (340/750 * 500px);
border-right: 1px solid #f6f6f6;
&:last-child {
border-right: 0;
}
}
}
}
}
</style>
@@ -0,0 +1,59 @@
<template>
<div class="banner" :class="[{ on: componentContent.categoryShow }]">
<el-carousel>
<el-carousel-item
v-for="(item, index) in bannerList"
:key="index"
:style="{ backgroundImage: 'url(' + item.pic + ')' }" >
<img class="img" :src="item.pic" v-show="item.pic" />
</el-carousel-item>
</el-carousel>
</div>
</template>
<script>
export default {
name: 'cereBanner',
props: {
componentContent: {
type: Object
}
},
computed: {
bannerList() {
return this.componentContent.bannerData.filter(function (item) {
return item.pic
})
}
}
}
</script>
<style lang="scss" scoped>
.banner {
width: 100%;
.el-carousel {
height: auto;
&.el-carousel--horizontal {
height: 234px;
}
>>> .el-carousel__container {
height: 234px;
.el-carousel__item {
height: auto;
background-color: #fff;
background-repeat: no-repeat;
background-position: center;
.img {
display: block;
width: 100%;
height: auto;
}
}
}
}
.el-carousel__indicators {
bottom: 0;
}
}
</style>
@@ -0,0 +1,156 @@
<template>
<div class="hotCommodity card">
<div class="card-header">
<p class="title">首发新品</p>
<span class="more">更多</span>
</div>
<div class="card-body">
<el-carousel height="170px">
<el-carousel-item>
<div class="goods-list">
<div class="min-goods">
<div class="img-box">
<div class="tag">hot</div>
<img class="img" src="https://image.dayouqiantu.cn/3.jpg" />
</div>
<div class="price-box">
<div class="y-f">
<span class="seckill-current">0.50</span>
<span class="original">销量133张</span>
</div>
</div>
<div class="title"></div>
</div>
<div class="min-goods">
<div class="img-box">
<div class="tag">hot</div>
<img class="img" src="https://image.dayouqiantu.cn/3.jpg" />
</div>
<div class="price-box">
<div class="y-f">
<span class="seckill-current">0.50</span>
<span class="original">销量133张</span>
</div>
</div>
<div class="title"></div>
</div>
<div class="min-goods">
<div class="img-box">
<div class="tag">hot</div>
<img class="img" src="https://image.dayouqiantu.cn/3.jpg" />
</div>
<div class="price-box">
<div class="y-f">
<span class="seckill-current">0.50</span>
<span class="original">销量133张</span>
</div>
</div>
<div class="title"></div>
</div>
<div class="min-goods">
<div class="img-box">
<div class="tag">hot</div>
<img class="img" src="https://image.dayouqiantu.cn/3.jpg" />
</div>
<div class="price-box">
<div class="y-f">
<span class="seckill-current">0.50</span>
<span class="original">销量133张</span>
</div>
</div>
<div class="title"></div>
</div>
</div>
</el-carousel-item>
</el-carousel>
</div>
</div>
</template>
<script>
export default {
}
</script>
<style lang="scss" scoped>
.y-f {
display: flex;
flex-direction: column;
align-items: center;
}
.card {
margin-top: 5/375 * 500px;
background: #fff;
border-radius: 10px;
overflow: hidden;
margin-left: 10px;
margin-right: 10px;
padding: 10px;
margin-bottom: 5px;
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
padding-bottom: 10/375 * 500px;
.title {
font-size: 17/375 * 500px;
font-weight: 700;
}
.more {
font-size: 15/375 * 500px;
padding-left: 16/375 * 500px;
color: #666;
}
}
}
.min-goods {
width: 25%;
background: #fff;
.img-box {
width: 83/375 * 500px;
height: 83/375 * 500px;
overflow: hidden;
position: relative;
.tag {
position: absolute;
left: 0;
bottom: 0/375 * 500px;
z-index: 2;
line-height: 19/375 * 500px;
background: linear-gradient(132deg, #f3dfb1, #f3dfb1, #ecbe60);
border-radius: 0 9/375 * 500px 9/375 * 500px 0;
padding: 0 5/375 * 500px;
font-size: 13/375 * 500px;
font-family: PingFang SC;
font-weight: 700;
color: #784f06;
}
.img {
width: 100%;
background-color: #ccc;
display: block;
}
}
.price-box {
width: 100%;
margin-top: 5/375 * 500px;
.seckill-current {
font-size: 16/375 * 500px;
font-weight: 500;
color: #e1212b;
}
.original {
font-size: 10/375 * 500px;
font-weight: 400;
text-decoration: line-through;
color: #999;
margin-left: 7/375 * 500px;
}
}
}
.goods-list {
display: flex;
justify-content: space-between;
}
</style>
@@ -0,0 +1,168 @@
<template>
<div class="hotCommodity card">
<div class="card-header">
<p class="title">超值拼团</p>
<span class="more">更多</span>
</div>
<div class="card-body">
<el-carousel height="170px">
<el-carousel-item>
<div class="goods-list">
<div class="min-goods">
<div class="img-box">
<div class="tag">hot</div>
<img
class="img"
src="https://image.dayouqiantu.cn/3.jpg"
/>
</div>
<div class="price-box">
<div class="y-f">
<span class="seckill-current">0.50</span>
<span class="original">销量133张</span>
</div>
</div>
<div class="title"></div>
</div>
<div class="min-goods">
<div class="img-box">
<div class="tag">hot</div>
<img
class="img"
src="https://image.dayouqiantu.cn/3.jpg"
/>
</div>
<div class="price-box">
<div class="y-f">
<span class="seckill-current">0.50</span>
<span class="original">销量133张</span>
</div>
</div>
<div class="title"></div>
</div>
<div class="min-goods">
<div class="img-box">
<div class="tag">hot</div>
<img
class="img"
src="https://image.dayouqiantu.cn/3.jpg"
/>
</div>
<div class="price-box">
<div class="y-f">
<span class="seckill-current">0.50</span>
<span class="original">销量133张</span>
</div>
</div>
<div class="title"></div>
</div>
<div class="min-goods">
<div class="img-box">
<div class="tag">hot</div>
<img
class="img"
src="https://image.dayouqiantu.cn/3.jpg"
/>
</div>
<div class="price-box">
<div class="y-f">
<span class="seckill-current">0.50</span>
<span class="original">销量133张</span>
</div>
</div>
<div class="title"></div>
</div>
</div>
</el-carousel-item>
</el-carousel>
</div>
</div>
</template>
<script>
export default {
}
</script>
<style lang="scss" scoped>
.y-f {
display: flex;
flex-direction: column;
align-items: center;
}
.card {
margin-top: 5/375 * 500px;
background: #fff;
border-radius: 10px;
overflow: hidden;
margin-left: 10px;
margin-right: 10px;
padding: 10px;
margin-bottom: 5px;
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
padding-bottom: 10/375 * 500px;
.title {
font-size: 17/375 * 500px;
font-weight: 700;
}
.more {
font-size: 15/375 * 500px;
padding-left: 16/375 * 500px;
color: #666;
}
}
}
.min-goods {
width: 25%;
background: #fff;
.img-box {
width: 83/375 * 500px;
height: 83/375 * 500px;
overflow: hidden;
position: relative;
.tag {
position: absolute;
left: 0;
bottom: 0/375 * 500px;
z-index: 2;
line-height: 19/375 * 500px;
background: linear-gradient(132deg, #f3dfb1, #f3dfb1, #ecbe60);
border-radius: 0 9/375 * 500px 9/375 * 500px 0;
padding: 0 5/375 * 500px;
font-size: 13/375 * 500px;
font-family: PingFang SC;
font-weight: 700;
color: #784f06;
}
.img {
width: 100%;
background-color: #ccc;
display: block;
}
}
.price-box {
width: 100%;
margin-top: 5/375 * 500px;
.seckill-current {
font-size: 16/375 * 500px;
font-weight: 500;
color: #e1212b;
}
.original {
font-size: 10/375 * 500px;
font-weight: 400;
text-decoration: line-through;
color: #999;
margin-left: 7/375 * 500px;
}
}
}
.goods-list {
display: flex;
justify-content: space-between;
}
</style>
@@ -0,0 +1,31 @@
<template>
<div class="header">
<h1>{{ componentContent.title }}</h1>
</div>
</template>
<script>
export default {
props: {
componentContent: {
type: Object
}
}
}
</script>
<style lang="scss" scoped>
.header {
height: 45px;
padding-top: 0px;
background: rgb(196, 4, 20);
h1 {
font-size: 20px;
line-height: 45px;
font-family: PingFang SC;
font-weight: 500;
color: #fff;
margin-left: 15px;
}
}
</style>
@@ -0,0 +1,169 @@
<template>
<div class="hotCommodity card">
<div class="card-header">
<p class="title">热门榜单</p>
<span class="more">更多</span>
</div>
<div class="card-body">
<el-carousel height="170px">
<el-carousel-item>
<div class="goods-list">
<div class="min-goods">
<div class="img-box">
<div class="tag">hot</div>
<img
class="img"
src="https://image.dayouqiantu.cn/3.jpg"
/>
</div>
<div class="price-box">
<div class="y-f">
<span class="seckill-current">0.50</span>
<span class="original">销量133张</span>
</div>
</div>
<div class="title"></div>
</div>
<div class="min-goods">
<div class="img-box">
<div class="tag">hot</div>
<img
class="img"
src="https://image.dayouqiantu.cn/3.jpg"
/>
</div>
<div class="price-box">
<div class="y-f">
<span class="seckill-current">0.50</span>
<span class="original">销量133张</span>
</div>
</div>
<div class="title"></div>
</div>
<div class="min-goods">
<div class="img-box">
<div class="tag">hot</div>
<img
class="img"
src="https://image.dayouqiantu.cn/3.jpg"
/>
</div>
<div class="price-box">
<div class="y-f">
<span class="seckill-current">0.50</span>
<span class="original">销量133张</span>
</div>
</div>
<div class="title"></div>
</div>
<div class="min-goods">
<div class="img-box">
<div class="tag">hot</div>
<img
class="img"
src="https://image.dayouqiantu.cn/3.jpg"
/>
</div>
<div class="price-box">
<div class="y-f">
<span class="seckill-current">0.50</span>
<span class="original">销量133张</span>
</div>
</div>
<div class="title"></div>
</div>
</div>
</el-carousel-item>
</el-carousel>
</div>
</div>
</template>
<script>
export default {
}
</script>
<style lang="scss" scoped>
.y-f {
display: flex;
flex-direction: column;
align-items: center;
}
.card {
margin-top: 5/375 * 500px;
background: #fff;
border-radius: 10px;
overflow: hidden;
margin-left: 10px;
margin-right: 10px;
padding: 10px;
margin-bottom: 5px;
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
padding-bottom: 10/375 * 500px;
.title {
font-size: 17/375 * 500px;
font-weight: 700;
}
.more {
font-size: 15/375 * 500px;
padding-left: 16/375 * 500px;
color: #666;
}
}
}
.min-goods {
width: 25%;
background: #fff;
.img-box {
width: 83/375 * 500px;
height: 83/375 * 500px;
overflow: hidden;
position: relative;
.tag {
position: absolute;
left: 0;
bottom: 0/375 * 500px;
z-index: 2;
line-height: 19/375 * 500px;
background: linear-gradient(132deg, #f3dfb1, #f3dfb1, #ecbe60);
border-radius: 0 9/375 * 500px 9/375 * 500px 0;
padding: 0 5/375 * 500px;
font-size: 13/375 * 500px;
font-family: PingFang SC;
font-weight: 700;
color: #784f06;
}
.img {
width: 100%;
background-color: #ccc;
display: block;
}
}
.price-box {
width: 100%;
margin-top: 5/375 * 500px;
.seckill-current {
font-size: 16/375 * 500px;
font-weight: 500;
color: #e1212b;
}
.original {
font-size: 10/375 * 500px;
font-weight: 400;
text-decoration: line-through;
color: #999;
margin-left: 7/375 * 500px;
}
}
}
.goods-list {
display: flex;
justify-content: space-between;
}
</style>
@@ -0,0 +1,262 @@
<template>
<div class="live-el mx20 mb10">
<div class="head">
<span class="head-title">热门直播</span>
<div class="head-more">
<span>更多</span>
<span class="cuIcon-right"></span>
</div>
</div>
<div class="content-one">
<div
class="content-one__item"
v-for="live in liveList"
:key="live.roomId" >
<img class="item-cover" :src="live.shareImge" mode="widthFix" />
<div class="item-status">
<img class="status-img" :src="liveStatus[live.liveStatus].img" />
<span class="status-span">{{
liveStatus[live.liveStatus].title
}}</span>
</div>
<div class="item-title">{{ live.name }}</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'shopLiveCard',
data () {
return {
liveList: [
{
roomId: '28',
id: null,
name: '打印资料',
coverImge: 'https://image.dayouqiantu.cn/WechatIMG229.jpeg',
shareImge: 'https://image.dayouqiantu.cn/WechatIMG229.jpeg',
liveStatus: 107,
startTime: 1600358400,
endTime: 1600441200,
anchorName: 'yshop',
anchorWechat: 'zimengzhiqiu',
anchorImge: 'https://image.dayouqiantu.cn/zj.png',
type: 0,
screenType: 0,
closeLike: 0,
closeComment: 0,
closeGoods: 0,
closeReplay: 0,
closeShare: 0,
closeKf: 0,
productId: '9,8,7',
product: null
},
{
roomId: '29',
id: null,
name: '我们能印什么',
coverImge: 'https://image.dayouqiantu.cn/WechatIMG230.jpeg',
shareImge: 'https://image.dayouqiantu.cn/WechatIMG230.jpeg',
liveStatus: 107,
startTime: 1600358400,
endTime: 1600441200,
anchorName: 'yshop',
anchorWechat: 'zimengzhiqiu',
anchorImge: 'https://image.dayouqiantu.cn/zj.png',
type: 0,
screenType: 0,
closeLike: 0,
closeComment: 0,
closeGoods: 0,
closeReplay: 0,
closeShare: 0,
closeKf: 0,
productId: '9,8,7',
product: null
},
{
roomId: '27',
id: null,
name: '广告布定制',
coverImge: 'https://image.dayouqiantu.cn/WechatIMG232.jpeg',
shareImge: 'https://image.dayouqiantu.cn/WechatIMG232.jpeg',
liveStatus: 107,
startTime: 1600272000,
endTime: 1600354800,
anchorName: 'yshop',
anchorWechat: 'zimengzhiqiu',
anchorImge: 'https://image.dayouqiantu.cn/zj.png',
type: 0,
screenType: 0,
closeLike: 0,
closeComment: 0,
closeGoods: 0,
closeReplay: 0,
closeShare: 0,
closeKf: 0,
productId: '9,8,7',
product: null
},
{
roomId: '30',
id: null,
name: '专业打印',
coverImge: 'https://image.dayouqiantu.cn/3.jpg',
shareImge: 'https://image.dayouqiantu.cn/3.jpg',
liveStatus: 103,
startTime: 1600077780,
endTime: 1600077820,
anchorName: 'yshop',
anchorWechat: 'zimengzhiqiu',
anchorImge: 'https://image.dayouqiantu.cn/zj.png',
type: 0,
screenType: 0,
closeLike: 0,
closeComment: 0,
closeGoods: 0,
closeReplay: 0,
closeShare: 0,
closeKf: 0,
productId: '9,8,7',
product: null
}
],
liveStatus: {
101: {
img: 'https://wx.yixiang.co/static/images/live.png',
title: '直播中'
},
102: {
img: 'https://wx.yixiang.co/static/images/prevue.png',
title: '未开始'
},
103: {
img: 'https://wx.yixiang.co/static/images/playback.png',
title: '已结束'
},
104: {
img: 'https://wx.yixiang.co/static/images/104.png',
title: '禁播'
},
105: {
img: 'https://wx.yixiang.co/static/images/105.png',
title: '暂停中'
},
106: {
img: 'https://wx.yixiang.co/static/images/106.png',
title: '异常'
},
107: {
img: 'https://wx.yixiang.co/static/images/past.png',
title: '已过期'
}
}
}
},
props: {
componentContent: Object
}
}
</script>
<style lang="scss" scoped>
.live-el {
background: #fff;
border-radius: 20/750 * 500px;
padding: 30/750 * 500px 20/750 * 500px 25/750 * 500px;
.head {
display: flex;
justify-content: space-between;
align-items: center;
&-title {
font-size: 32/750 * 500px;
font-weight: bold;
font-family: PingFang SC;
color: rgba(51, 51, 51, 1);
}
&-more {
font-size: 26/750 * 500px;
font-family: PingFang SC;
font-weight: 500;
color: rgba(51, 51, 51, 1);
}
}
// 单个大图直播
.content-one {
.content-one__item {
position: relative;
height: 280/750 * 500px;
border-radius: 20/750 * 500px;
margin-top: 25/750 * 500px;
overflow: hidden;
.item-cover {
background-color: #eee;
width: 100%;
height: 100%;
}
.item-status {
position: absolute;
top: 20/750 * 500px;
left: 10/750 * 500px;
height: 40/750 * 500px;
background: rgba(0, 0, 0, 0.4);
border-radius: 20/750 * 500px;
display: flex;
justify-content: center;
align-items: center;
.status-img {
width: 38/750 * 500px;
height: 38/750 * 500px;
}
.status-span {
font-size: 22/750 * 500px;
font-family: PingFang SC;
font-weight: 500;
color: rgba(255, 255, 255, 1);
padding: 0 10/750 * 500px;
}
}
.item-title {
width: 680/750 * 500px;
position: absolute;
bottom: 0;
line-height: 60/750 * 500px;
padding: 0 20/750 * 500px;
font-size: 26/750 * 500px;
font-family: PingFang SC;
font-weight: 500;
color: rgba(255, 255, 255, 1);
background: linear-gradient(transparent, rgba(#000, 0.5));
}
.like-img {
position: absolute;
bottom: 20/750 * 500px;
right: 10/750 * 500px;
width: 60/750 * 500px;
height: 130/750 * 500px;
}
}
}
// 双图直播
.content-two {
width: 100%;
// -moz-column-count: 2;
// -webkit-column-count: 2;
// column-count: 2;
// padding-top: 20/750*500px;
display: flex;
flex-wrap: wrap;
&__item {
margin-right: 30/750 * 500px;
margin-top: 20/750 * 500px;
&:nth-child(2n) {
margin-right: 0;
}
}
}
}
</style>
@@ -0,0 +1,51 @@
<template>
<div class="menu-tab-box">
<div class="tab-list" v-for="(item,index) in componentContent.menus" :key="index">
<div class="tab-img Shop-selector-circular">
<img :src="item.pic" />
<!---->
</div>
<p class="Shop-selector-rect">
<span>{{item.name}}</span>
</p>
</div>
</div>
</template>
<script>
export default {
props: {
componentContent: {
type: Object
}
}
}
</script>
<style lang="scss" scoped>
.menu-tab-box {
display: grid;
grid-template-columns: repeat(4, 25%);
grid-template-rows: repeat(2, 170/750 * 500px);
text-align: center;
.tab-list {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.tab-img {
border-radius: 26/750 * 500px;
margin-bottom: 10/750 * 500px;
width: 96/750 * 500px;
img {
width: 100%;
height: auto;
}
}
p {
display: block;
text-align: center;
}
}
</style>
@@ -0,0 +1,43 @@
<template>
<div class="noticeBar">
<div class="noticeBar-icon"></div>
<div class="noticeBar-text">
{{componentContent.roll[0].info}}
</div>
</div>
</template>
<script>
export default {
props: {
componentContent: {
type: Object
}
}
}
</script>
<style lang="scss" scoped>
.noticeBar {
display: flex;
width: 100%;
box-sizing: border-box;
flex-direction: row;
align-items: center;
padding: 6/750 * 500px 12/750 * 500px;
margin-bottom: 10/750 * 500px;
background-color: rgb(255, 251, 232);
height: 60/750 * 500px;
.noticeBar-icon {
width: 14/750 * 500px;
height: 14/750 * 500px;
margin-right: 5/750 * 500px;
}
.noticeBar-text {
flex: 1;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
}
</style>
@@ -0,0 +1,155 @@
<template>
<div class="hotCommodity card">
<div class="card-header">
<p class="title">精品推荐</p>
<span class="more">更多</span>
</div>
<div class="card-body">
<el-carousel height="170px">
<el-carousel-item>
<div class="goods-list">
<div class="min-goods">
<div class="img-box">
<div class="tag">hot</div>
<img class="img" src="https://image.dayouqiantu.cn/3.jpg" />
</div>
<div class="price-box">
<div class="y-f">
<span class="seckill-current">0.50</span>
<span class="original">销量133张</span>
</div>
</div>
<div class="title"></div>
</div>
<div class="min-goods">
<div class="img-box">
<div class="tag">hot</div>
<img class="img" src="https://image.dayouqiantu.cn/3.jpg" />
</div>
<div class="price-box">
<div class="y-f">
<span class="seckill-current">0.50</span>
<span class="original">销量133张</span>
</div>
</div>
<div class="title"></div>
</div>
<div class="min-goods">
<div class="img-box">
<div class="tag">hot</div>
<img class="img" src="https://image.dayouqiantu.cn/3.jpg" />
</div>
<div class="price-box">
<div class="y-f">
<span class="seckill-current">0.50</span>
<span class="original">销量133张</span>
</div>
</div>
<div class="title"></div>
</div>
<div class="min-goods">
<div class="img-box">
<div class="tag">hot</div>
<img class="img" src="https://image.dayouqiantu.cn/3.jpg" />
</div>
<div class="price-box">
<div class="y-f">
<span class="seckill-current">0.50</span>
<span class="original">销量133张</span>
</div>
</div>
<div class="title"></div>
</div>
</div>
</el-carousel-item>
</el-carousel>
</div>
</div>
</template>
<script>
export default {
}
</script>
<style lang="scss" scoped>
.y-f {
display: flex;
flex-direction: column;
align-items: center;
}
.card {
margin-top: 5/375 * 500px;
background: #fff;
border-radius: 10px;
overflow: hidden;
margin-left: 10px;
margin-right: 10px;
padding: 10px;
margin-bottom: 5px;
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
padding-bottom: 10/375 * 500px;
.title {
font-size: 17/375 * 500px;
font-weight: 700;
}
.more {
font-size: 15/375 * 500px;
padding-left: 16/375 * 500px;
color: #666;
}
}
}
.min-goods {
width: 25%;
background: #fff;
.img-box {
width: 83/375 * 500px;
height: 83/375 * 500px;
overflow: hidden;
position: relative;
.tag {
position: absolute;
left: 0;
bottom: 0/375 * 500px;
z-index: 2;
line-height: 19/375 * 500px;
background: linear-gradient(132deg, #f3dfb1, #f3dfb1, #ecbe60);
border-radius: 0 9/375 * 500px 9/375 * 500px 0;
padding: 0 5/375 * 500px;
font-size: 13/375 * 500px;
font-family: PingFang SC;
font-weight: 700;
color: #784f06;
}
.img {
width: 100%;
background-color: #ccc;
display: block;
}
}
.price-box {
width: 100%;
margin-top: 5/375 * 500px;
.seckill-current {
font-size: 16/375 * 500px;
font-weight: 500;
color: #e1212b;
}
.original {
font-size: 10/375 * 500px;
font-weight: 400;
text-decoration: line-through;
color: #999;
margin-left: 7/375 * 500px;
}
}
}
.goods-list {
display: flex;
justify-content: space-between;
}
</style>
@@ -0,0 +1,155 @@
<template>
<div class="hotCommodity card">
<div class="card-header">
<p class="title">促销单品</p>
<span class="more">更多</span>
</div>
<div class="card-body">
<el-carousel height="170px">
<el-carousel-item>
<div class="goods-list">
<div class="min-goods">
<div class="img-box">
<div class="tag">hot</div>
<img class="img" src="https://image.dayouqiantu.cn/3.jpg" />
</div>
<div class="price-box">
<div class="y-f">
<span class="seckill-current">0.50</span>
<span class="original">销量133张</span>
</div>
</div>
<div class="title"></div>
</div>
<div class="min-goods">
<div class="img-box">
<div class="tag">hot</div>
<img class="img" src="https://image.dayouqiantu.cn/3.jpg" />
</div>
<div class="price-box">
<div class="y-f">
<span class="seckill-current">0.50</span>
<span class="original">销量133张</span>
</div>
</div>
<div class="title"></div>
</div>
<div class="min-goods">
<div class="img-box">
<div class="tag">hot</div>
<img class="img" src="https://image.dayouqiantu.cn/3.jpg" />
</div>
<div class="price-box">
<div class="y-f">
<span class="seckill-current">0.50</span>
<span class="original">销量133张</span>
</div>
</div>
<div class="title"></div>
</div>
<div class="min-goods">
<div class="img-box">
<div class="tag">hot</div>
<img class="img" src="https://image.dayouqiantu.cn/3.jpg" />
</div>
<div class="price-box">
<div class="y-f">
<span class="seckill-current">0.50</span>
<span class="original">销量133张</span>
</div>
</div>
<div class="title"></div>
</div>
</div>
</el-carousel-item>
</el-carousel>
</div>
</div>
</template>
<script>
export default {
}
</script>
<style lang="scss" scoped>
.y-f {
display: flex;
flex-direction: column;
align-items: center;
}
.card {
margin-top: 5/375 * 500px;
background: #fff;
border-radius: 10px;
overflow: hidden;
margin-left: 10px;
margin-right: 10px;
padding: 10px;
margin-bottom: 5px;
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
padding-bottom: 10/375 * 500px;
.title {
font-size: 17/375 * 500px;
font-weight: 700;
}
.more {
font-size: 15/375 * 500px;
padding-left: 16/375 * 500px;
color: #666;
}
}
}
.min-goods {
width: 25%;
background: #fff;
.img-box {
width: 83/375 * 500px;
height: 83/375 * 500px;
overflow: hidden;
position: relative;
.tag {
position: absolute;
left: 0;
bottom: 0/375 * 500px;
z-index: 2;
line-height: 19/375 * 500px;
background: linear-gradient(132deg, #f3dfb1, #f3dfb1, #ecbe60);
border-radius: 0 9/375 * 500px 9/375 * 500px 0;
padding: 0 5/375 * 500px;
font-size: 13/375 * 500px;
font-family: PingFang SC;
font-weight: 700;
color: #784f06;
}
.img {
width: 100%;
background-color: #ccc;
display: block;
}
}
.price-box {
width: 100%;
margin-top: 5/375 * 500px;
.seckill-current {
font-size: 16/375 * 500px;
font-weight: 500;
color: #e1212b;
}
.original {
font-size: 10/375 * 500px;
font-weight: 400;
text-decoration: line-through;
color: #999;
margin-left: 7/375 * 500px;
}
}
}
.goods-list {
display: flex;
justify-content: space-between;
}
</style>
@@ -0,0 +1,242 @@
<template>
<div class="recommended">
<div class="recommended-title-card mb10">
<div class="title-box">
<img
class="title-bg"
src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAsYAAABUCAMAAAC2hwHmAAAC+lBMVEUAAAB46Zvnm5r/vymo+WJF5ctU57voYfz/xCsXwvf/vDQbxfSj+Gf/uC/sa/zvtkiM9n//syyv+VpZ8raY93IUzvjeUf7/nhn7hPkVyfgTz/jjWP3/ny8Zu/fiWP3/uSb/tCcXwvf/mhfzdvoXwveb928auPb9ifkeqPWx+VkVyfh79ZH/sjHjWP0drvbxcvum+GT6g/kdrfZ69JP/kleY93IWxPet+Vx89ZD/sieh+Gql+GV39JYeqPUgx+/ta/v5gPoUzfj/pBz9ifnvbvv5gPn/xi3/lRVu85//h2Gr+V7/wiv/nU36g/nZR/7/nxoVyff/yi/+i/jdTv7/rT3/tzSE9Yha8rQZuvb/tzRN8MEdrvb6g/obtPb+ifn/eG//uCZ29Jer+V9P8cCl+GX/fWph8q2i+Gj/yy//uDP/eHAaufbcTf7xc/oXxff2fPoYv/f/il4Yv/cUzfj/eHCp+GGv+Vv/lBX/nhr5Z41V8br/cnVW8bj/llOv+VqA9YuM9n/7aIkWxvcVyfgYwPcauPYYvvcbtfYZvPd+9Y8csvZx9JsUzPgZuvag+Gqq+F9e8rDpY/z7hPlZ8rXsaft29JfjWP3hVf3nYPzmXfzxcvvwb/sXwvdq86N59JOC9Yqj+Gel+GTeUP7gUv3ubPv0ePrzdfoXxPeR9nqZ93Ku+VvdTf7bS/72evr3ffoeqvVt86CV93ad9276gvn4f/lO8cGJ9oL/kFn/llP/ph3qZvz9iPkVy/gXw/cdrfVV8blm86f/fWr/hGSn+GP/il7/tyUUzvgWyPcWxfccr/aG9Yb/cnX/eHD/nU3/okdS8b1i8qyL9oH/qEL/wyv/mBb/aX//bXr/rT3/siPkWv2N9n6O9n2W93Sb92//oRvaSP6F9Yf/sTn/qx/kW/xk8qn/yC3/riH/nhmS9nn/tTb/vCj/mxjrZ/z/ZYH6X5XZRv4jwe0tx+MtzuJC6M3kT9xA1dAuu+TiTeHxWLTXRP3tavsdv/JP1MHrVr+q95v8AAAAgnRSTlMABwb+jBH767JMLCIaGRUN7OjT0c6vqqKZh3p4b25fTUI7MywrIxj6+Pbs393UycK4t7SysaqcmYmGd2ZlZFQ8Ivj08fDw8O/t7ejm4+Lh29PSz8fHwb+9u6Ggk4p+bmplR0c0E/Tz8/Lw7+rp4d/d3NTT0tLPxcLAso+IfVZORDcbzkOW1gAABPFJREFUeNrt2wVTVFEYxvF3VwRE0kCQFsHu7u7u7u7uRjEwsLtbjLVb7A7EDmxUbECxnfHuLsvuvfcs4swyzJ55fl9h//PMmXPuEgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJO/T9k0PqkJwGylde0/afmxCwEB9V3TEoA58i86depkIeNNFwLOTzyfMSsBmJ00vWbOFDKetFzIWOj4aAVXBfGsvFs+q8NzrPI4u/kS8KJNYGDgTIM5nnh0xiCOB7lcvqXLfs4/PGfxkvsLF+XxVBKYo86limTIUKSkX0LFU6YIGevnWJ3xjApliU/2Lhs2Ll22XpfxurW93RCyGSrZbdajLbs2P9jfdBypeQSpMw4UMtbMcYB2jmecy0w88u23XZLx1m11yxGYF0X+NavjM366Kleh4h3KBgUJHaszFs/xOS47LldlhzzjJ3XtiRzaFa5x4GDtwu42BClO6ZWpXsXX9TJlIbZipw0ynrZywfSdkZZxcbEx0dG/9HPMbce+VfayMv7kTO16njx15sDBq9du3G3sQJCiHEo4PT/0+PHrd7dueROLRbAs4xWR12fPm3c8bN++z7HiOT7H2w2yfZ097Ix/jLh8JSHjZy2IRdHRIr+jo2OuQqX5vsZJee2d7r3SZTyMGMaGMDI+EZ+x0LFkjj2ILwX2GMn4zx3DjN/YkFypmmtmPdr1cP+qaQuqlyZINnbWZ++pMz6kybgaMeQ3zPgSI2PxHBclrrSdayTjb7fFGZcgGWXN4ISMp69ohjf75OJd6+2/Mlbm0Ga820jGsZLTcUbiiX2luXPZGX+UZNyEZDqGGGYcmR4dJw/vVKlEGWciOduQRDP+rL+s4DFjlyNGMv7yQZKxE8kU02QcsTk+49npcUBODjZVbwoZn9VnnOV/Mp6tyThaenfMVcblsxnL+Ls04x4kk06X8VNtxvNGEpicXa2b4ozdiUGRaMYx+rvj+IxdiSOtj8gyfqHN+KM049wkk0Od8e6IzeG6jI93IjA165fijN2JKZ0+44fSjGOFJxDJHKchjjRMesYtmBmfFmfcjMDEvF6KMh6ehdgsQoKDdRmHizIOi9E/5ek+EMrJ1fmvUtIz9mYPwGptxiu1GYdhjk3N2iDjipoXPDa/hIyjxBlbRgsv0tI55usVL5s44/fqjNln4yYkV1KecUsC0+quyzh3CS8lJaIYO+M49YcV0jmuz9UYU0NGxsybCic7klMMNch45wl1xpYEptVAk7F1ezv6B0U6bcYRhhlbfr14MShINMfCnVtOzp6i2zIyZt0b57YhFoWFkPGWqPBLmoyvY42TgU2DqtZeDpQEtkNOSzK2jAkNDRU6lsxxTh/ii7KAPGPGK15ju8S+0456kJAxXkBSkoOFYcbTf39VqVShobI57svf3z+ULtmMZPzpy+34jGu7KykxivGlixfKVf1E1/SjUXHK8rPIoMnYsWnxDmmzqwSyOV5elMsfqbxLHWbGjTwnjBrcpcaAwmPwRxBzorD1s1WQWhmVSj7HA7m6MBbx9WxdIF+fypWFjK2srPI0cnZ287QnMHdlskvnuDm/EQO3shbMbjDHzT38CcAM+ZdpVTBv3rwFW3n48HVVDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8J/+Aj7mNENzIoDkAAAAAElFTkSuQmCC"
/>
<div class="title-text">为你推荐</div>
</div>
</div>
<div class="recommended-body">
<div class="goods-list">
<div class="min-goods">
<div class="min-goods-box">
<div class="img-box">
<img
class="img"
src="https://image.dayouqiantu.cn/3.jpg"
/>
</div>
<div class="price-box">
<div class="tip one-t">黑白彩色专业高速打印复印</div>
<div class="title more-t">黑白彩色专业高速打印复印</div>
<div class="price-box">
<span class="seckill-current">0.50</span>
<span class="original">销量133张</span>
</div>
</div>
</div>
</div>
<div class="min-goods">
<div class="min-goods-box">
<div class="img-box">
<img
class="img"
src="https://image.dayouqiantu.cn/3.jpg"
/>
</div>
<div class="price-box">
<div class="tip one-t">黑白彩色专业高速打印复印</div>
<div class="title more-t">黑白彩色专业高速打印复印</div>
<div class="price-box">
<span class="seckill-current">0.50</span>
<span class="original">销量133张</span>
</div>
</div>
</div>
</div>
<div class="min-goods">
<div class="min-goods-box">
<div class="img-box">
<img
class="img"
src="https://image.dayouqiantu.cn/3.jpg"
/>
</div>
<div class="price-box">
<div class="tip one-t">黑白彩色专业高速打印复印</div>
<div class="title more-t">黑白彩色专业高速打印复印</div>
<div class="price-box">
<span class="seckill-current">0.50</span>
<span class="original">销量133张</span>
</div>
</div>
</div>
</div>
<div class="min-goods">
<div class="min-goods-box">
<div class="img-box">
<img
class="img"
src="https://image.dayouqiantu.cn/3.jpg"
/>
</div>
<div class="price-box">
<div class="tip one-t">黑白彩色专业高速打印复印</div>
<div class="title more-t">黑白彩色专业高速打印复印</div>
<div class="price-box">
<span class="seckill-current">0.50</span>
<span class="original">销量133张</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
}
</script>
<style lang="scss" scoped>
.recommended-title-card {
width: 100%;
margin-bottom: 5/375 * 500px;
}
.title-box {
width: 389/375 * 500px;
height: 48/375 * 500px;
margin: 0 auto;
position: relative;
border-radius: 16/375 * 500px;
text-align: center;
.title-bg {
width: 100%;
}
.title-text {
position: absolute;
left: 0;
right: 0;
top: 0;
line-height: 48/375 * 500px;
font-weight: 700;
font-size: 20/375 * 500px;
}
}
.recommended-body {
overflow-x: hidden;
}
.min-goods {
background: #fff;
.img-box {
width: 100%;
height: auto;
overflow: hidden;
position: relative;
.tag {
position: absolute;
left: 0;
bottom: 0/375 * 500px;
z-index: 2;
line-height: 19/375 * 500px;
background: linear-gradient(132deg, #f3dfb1, #f3dfb1, #ecbe60);
border-radius: 0 9/375 * 500px 9/375 * 500px 0;
padding: 0 5/375 * 500px;
font-size: 13/375 * 500px;
font-family: PingFang SC;
font-weight: 700;
color: #784f06;
}
.img {
width: 100%;
background-color: #ccc;
display: block;
}
}
.price-box {
width: 100%;
margin-top: 5/375 * 500px;
.seckill-current {
font-size: 16/375 * 500px;
font-weight: 500;
color: #e1212b;
}
.original {
font-size: 10/375 * 500px;
font-weight: 400;
text-decoration: line-through;
color: #999;
margin-left: 7/375 * 500px;
}
}
}
.goods-list {
display: flex;
justify-content: space-between;
padding: 0 7.5/375 * 500px;
flex-wrap: wrap;
.min-goods {
width: 50%;
flex: 0 0 50%;
padding: 0 7.5/375 * 500px;
}
.min-goods-box {
margin-right: 10/375 * 500px;
margin-bottom: 10/375 * 500px;
width: 189/375 * 500px;
box-shadow: 0 0 5px 2px rgba(0, 0, 0, 0.1);
border-radius: 10/375 * 500px;
width: 100%;
overflow: hidden;
padding-bottom: 10/375 * 500px;
img {
width: 100%;
}
}
}
.price-box {
.tip {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
transition: all linear 0.2s;
width: 100%;
line-height: 30/375 * 500px;
background: #f6f2ea;
font-size: 12/375 * 500px;
font-family: PingFang SC;
font-weight: 400;
color: #a8700d;
padding: 0 10/375 * 500px;
}
.title {
overflow: hidden;
text-overflow: ellipsis;
transition: all linear 0.2s;
font-size: 13/375 * 500px;
font-family: PingFang SC;
font-weight: 500;
line-height: 19/375 * 500px;
height: 39/375 * 500px;
margin: 10/375 * 500px 10/375 * 500px 5/375 * 500px;
}
.price-box {
padding: 5/375 * 500px 10/375 * 500px 0;
width: 188/375 * 500px;
box-sizing: border-box;
}
.seckill-current {
font-size: 16/375 * 500px;
font-weight: 500;
color: #e1212b;
line-height: 16/375 * 500px;
margin-bottom: 10/375 * 500px;
}
.original {
font-size: 10/375 * 500px;
font-family: PingFang SC;
font-weight: 400;
color: #999;
line-height: 10/375 * 500px;
margin-bottom: 10/375 * 500px;
}
}
</style>
@@ -0,0 +1,63 @@
<template>
<div class="header-search">
<div class="search">
<span class="iconfont icon-xiazai5"><span></span></span>搜索商品
</div>
<div class="qr">
<img
src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAANl0lEQVR4Xu2dbYhc1RnHn3MvQ15aX6uC2hKMDcFotaDYNFZxN+fc2dUuWNso9UOLVtEWlFo1/dCCkRZajFZrKVRbiyCCKH0jW5OZc8cN02LrW0VR0apBpGrVGrTQmEl27lMuJJBuMy97c55755z5D+yn3PN/nuf33F9mdmaTVYQHCIBATwIKbEAABHoTgCC4O0CgDwEIgtsDBCAI7gEQKEYAzyDFuOHUmBCAIGOyaIxZjAAEKcYNp8aEAAQZk0VjzGIEIEgxbjg1JgQgyJgsGmMWIwBBinHDqTEhAEHGZNEYsxgBCFKMG06NCQEIMiaLxpjFCECQYtxwakwIQJAxWTTGLEYAghTjhlNjQgCCjMmiMWYxAhCkGDecGhMCEGRMFo0xixGAIMW44dSYEIAgY7JojFmMwMgJ0m63j+10OqcqpdZ0u93jio0lfyqO47f27t3bnJ6efl2+WrEKs7OzR9VqtZVRFB1WLKG8U1EU7el2u+/VarX3JiYmPiivcv9KlQuyZcuWY5YuXTrDzGcrpQwRnTwqcIbpQyn1sNb6kmGuLfOaNE0fYuYNZdZ0WOsdIrpfKdXQWqcOcxcdVakg1toriGgjEa1edOcjdICZr0qS5Fej0lKz2bxSKfXLUennUPpQSj1NRPdore85lJyiZysRpNFoHBfH8d3MfFHRxkfs3HPGmDNGpSdr7bNEdPqo9OOij1wUZr7RGLPdRd6wGaUL0mw2z1JKWSI6ctgmfbjOGFM6y15crLXsA7MCPe4loqRMSUpdapqma5j5hQJgRvpI/reb1vqsUWkyTdOnmPnMUenHdR9KqZO11jtc5x4srzRB9smRv55cWsZgZdbIsuyWer2+qcya/WpZa28loptGpR+BPt4iojXGmA8Fsv8nsjRBrLVPEtHI/C3rCiwzX5IkycOu8lzlWGuvJaK7XOWNYM5vjDFfke6rFEGstZcR0QNDDJO/xsxvtheJ6CUien+IM5VckmXZR8z8ytTU1M5KGhii6LZt245WSq2KomjZEJdXekkcx4dnWXYOM59DRPnXMI9vGGN+PcyFRa8pS5BtRFQf0OTbzHxlkiSPFB0G58IgYK3N75U7iOiUARO9vHv37i/MzMz8S2pycUGstecT0dyAAf5sjDlXakjk+knAWnszEQ363u47xphcJpFHGYL8nIi+1af7N4wxK0SmQ6j3BKy1g159bDfGTEgNKi5Is9l8Vyl1bJ8BJsp8X1sKJHJlCDz66KOru93uE0R0eK8K3W73hKmpqbclOhAVxFp7BBH1/MEzZn41SZJVEoMhMxwCaZo+yMyX9poojuMLJycnRb53FRUkTdOVzPxar8GUUlu11heEs0pMIkHAWvtDIvper2xmvjxJkvskaosK0mq1zs6y7PE+jd9mjAn5Ay2JnY1dZpqmlzLzg30G32iM2SwBRlSQQe9gjdon0BKAkXnoBKq8jyDIoe8PCcIEIIgwYMT7TQCC+L0/dC9MAIIIA0a83wQgiN/7Q/fCBCCIMGDE+00Agvi9P3QvTACCCANGvN8EIIjf+0P3wgQgiDBgxPtNAIL4vT90L0wAgggDRrzfBCCI3/tD98IEIIgwYMT7TQCC+L0/dC9MAIIIA0a83wQgiN/7Q/fCBCCIMGDE+00Agvi9P3QvTACCCANGvN8EIIjf+0P3wgQgiDBgxPtNAIL4vT90L0wAgggDRrzfBCCI3/tD98IEIIgwYMT7TQCC+L0/dC9MAIIIA0a83wQgiN/7Q/fCBCCIMGDE+00Agvi9P3QvTACCCANGvN8EIIjf+0P3wgQgiDBgxPtNAIL4vT90L0wAgggDRrzfBBqNxplRFD3VawpmvjFJktslphT9HYVD/BrodVrrv0gMhsxwCMzOzh61ZMmSnb0mUkrNaK1nJSYWFSRvOE3T55n51IXNK6Ve0FqfJjEUMsMj0Gg0NkVRdPNB7qPXtdYnSU1chiCfZ+bc7qMPGGKnUuqLePaQWmuYuc1mc4NS6vtEdDoRvczMf0iS5LuS04oLkjf/2GOPLdu1a9fF3W53VRzHryxfvvy369at+0hyMGSDgAsCpQjiolFkgEAVBCBIFdRR0xsCEMSbVaHRKghAkCqoo6Y3BCCIN6tCo1UQgCBVUEdNbwhAEG9WhUarIABBqqCOmt4QgCDerAqNVkEAglRBHTW9IQBBvFkVGq2CAASpgjpqekMAgnizKjRaBQEIUgV11PSGgKgg1tpTsixb7g0NNOolgVqtNj85OfmsRPMigqRp+nVmzv/1l9i/9JKAgUyvCfxbKXWb1voHLqdwLkir1ZrOsuwRl00iCwQWQWCjMWbzIq7ve6lzQdI0/R0zX+SqQeSAwCIJvGGMWbHIMz0vdy6ItfYNIvqUqwaRAwKLJcDMJyZJ8tZizx3seueCpGnaYuZJF80hAwQKEPjQGHNkgXMHPeJcEGvtFUR0r6sGkQMCiyRwpzHm+kWeKe8lVl6p2Wz+WCkl+t+xuAKAnHAIMPODSZJ81eVEzp9B9jfXarVWZFl2jlLq4y4bRhYILCTAzHuVUk9rrZ9zTUdMENeNIg8EqiAAQaqgjpreEIAg3qwKjVZBAIJUQR01vSEAQbxZFRqtggAEqYI6anpDAIJ4syo0WgUBCFIFddT0hgAE8WZVaLQKAhCkCuqo6Q0BCOLNqtBoFQRKE6Tdbh/f6XRWL1my5OXzzjvv7SqGRU3/CZR9H5UiiLV2jojOP2A9240xE/6vCxOUSWDhb7qV+OndhfOIC2KtvYuIrj0IyJ8ZY64rEzBq+Uug16+BzrLslnq9vklqMlFBWq3WiVmW/aNX81EUfXL9+vVvSg2H3DAIDLqPsixbW6/XH5eYVlQQa23+sip/edXrMWGM2S4xGDLDITDoPpJ8FoEg4dxHwU4CQYJdLQZzQQCCuKCIjGAJQJBgV4vBXBCAIC4oIiNYAhAk2NViMBcEIIgLisgIlgAECXa1GMwFAQjigiIygiUAQYJdLQZzQQCCuKCIjGAJQJBgV4vBXBCAIC4oIiNYAhAk2NViMBcEIIgLisgIlgAECXa1GMwFAQjigiIygiUAQYJdLQZzQQCCuKCIjGAJQJBgV4vBXBCAIC4oIiNYAhAk2NViMBcEIIgLisgIlgAECXa1GMwFAQjigiIygiUAQYJdLQZzQQCCuKCIjGAJQJBgV4vBXBCAIC4oIiNYAhAk2NViMBcEIIgLisgIlgAECXa1GMwFAQjigiIygiUAQYJdLQZzQQCCuKCIjGAJQJBgV4vBXBCAIC4oIiNYAhAk2NViMBcEIIgLisgIlgAECXa1GMwFAQjigiIygiUAQYJdLQZzQQCCuKCIjGAJBCtIq9U6O8uyx3ttjpm/liTJ/cFuFoM5IdBsNi9QSv2xT9hGY8xmJ8UWhCiJ0P2ZaZquZObX+ghyd5Ik10j2gGz/CVhrryein/SaJI7jCycnJx+RmFRUEGvtEUT0QZ/GnzfGfEZiMGSGQ8Baew8RXdVrovn5+ZOmp6dfl5hYVJC8YWvtm0R0Qq/mlVJXaq3vlRgOmf4TaLfbx3c6nSYRndZjmveNMcdITSouSKPR2BRF0c19BPmn1vp4qQGR6zcBa+0cEZ3f5/65T2t9udSUZQjyuSiK/jpggE3GmFukhkSunwQG/eWaTyX9CkRckH0vs7YRUX3Amv6ulLpBaz3r5zrRtSsCc3NzR87Pz99ORFf0y1RK5d93rNVav+Oq9sKcsgS5jIgeGHKIl5j5KWbeHkVRz3fAhswSu0wp9W4cxzsmJiZ2ixU5xODZ2dmjarXayiiKDjvEqDKOf4yZz4iiaBUzf5aI8q++D2a+IUmSnu9uDTo/zJ+XIsi+Z5EnieisYZry5Rpmfk8p9SNjzB2j1rO1Nv++b9Oo9eWwn7/t2LFj7dVXX73XYeb/RZUpSP6NVv5uRE1yoCqysyxbW6/Xe34gWnZPzWZzg1LqobLrllkvy7Iv1ev130vXLE2Qfc8iuST5uxJBPZj5F0mSfHNUhrLWPktEp49KPwJ9XG+MuVMgt7pnkP2V9326/qd+n42UMbjjGtuNMROOMwvHWWu58OERP6iUminzjZxSn0H2s9/3CXv+4eCXR3wfQ7WnlPqp1vrbQ11cwkVpmuZvcpxZQqkySzwTRdE169evf6LMopUIcoAo+dt4G4lodZlDu67FzJckSfKw69yiedbaW4nopqLnR+zcrizLNu/Zs+fWmZmZXWX3Vqkg+bBbtmw5ZtmyZRcT0bn5FzOvKBtC0XrM/CozX1ev17cWzZA6Z629lojuksoXzv1QKdVm5vyleGqMeUa4Xs/4ygVZ2Fm73T620+mcqpRa0+12j6sKzKC6cRy/Mj8/v3VqamrnoGur+vO5ublPz8/PT2dZ9omqehi2bhRF/4nj+IVOp/Oi1A8eDtvLgdeNnCBFhsAZEJAiAEGkyCI3CAIQJIg1YggpAhBEiixygyAAQYJYI4aQIgBBpMgiNwgCECSINWIIKQIQRIoscoMgAEGCWCOGkCIAQaTIIjcIAhAkiDViCCkCEESKLHKDIABBglgjhpAiAEGkyCI3CAIQJIg1YggpAhBEiixygyAAQYJYI4aQIgBBpMgiNwgCECSINWIIKQIQRIoscoMgAEGCWCOGkCIAQaTIIjcIAv8FuipjMnygmtYAAAAASUVORK5CYII="
/>
</div>
</div>
</template>
<script>
export default {
}
</script>
<style lang="scss" scoped>
.header-search {
height: 53px;
width: 100%;
padding: 0 16px;
box-sizing: border-box;
display: flex;
flex-wrap: wrap /* 辅助类 */;
align-items: center;
justify-content: center;
height: 53px;
width: 100%;
padding: 0 16px;
box-sizing: border-box;
transition: all linear 0.3s;
background: rgb(196, 4, 20);
.search {
flex: 1;
box-sizing: border-box;
height: 35px;
background-color: #f7f7f7;
border-radius: 27px;
padding: 0 15px;
font-size: 15px;
color: #bbb;
line-height: 35px;
}
.qr {
width: 27px;
height: 27px;
font-size: 18px;
margin-left: 8px;
img {
width: 100%;
}
}
}
</style>
@@ -0,0 +1,44 @@
<template>
<div class="canvasBannerBox">
<el-carousel
height="755px"
arrow="never">
<el-carousel-item v-for="(item, index) in this.componentContent.bannerList" :key="index">
<div carContant>
<img class="bcimg" :src="item.pic" alt="轮播图">
<span>{{ item.pic }}</span>
</div>
</el-carousel-item>
</el-carousel>
</div>
</template>
<script>
export default {
props: {
componentContent: Object
}
}
</script>
<style lang="scss" scoped>
.canvasBannerBox{
.el-carousel {
// height: 755px;
img{
width: 100%;
height: 755px;
}
.el-carousel__button{
height: 2px;
opacity: 1;
background-color: #CCCCCC;
}
.is-active{
.el-carousel__button{
background-color: #333333;
}
}
}
}
</style>
@@ -0,0 +1,106 @@
<template>
<div class="canvasFooter">
<div class="content">
<div class="lab-group">
<label class="fs24">{{ this.componentContent.publicList[0].title}}</label>
<label class="fs50 mar-top-40">{{this.componentContent.publicList[0].des}}</label>
<label class="col-ccc fs28 mar-top-10">{{this.componentContent.publicList[1].des}}</label>
<div class="consult mar-top-40">咨询客服</div>
</div>
<div class="verticalline"></div>
<div class="icon-group">
<img class="gzh-icon" :src="componentContent.publicList[2].pic"/>
<label class="des">{{this.componentContent.publicList[2].des}}</label>
</div>
<div class="icon-group">
<img class="xcxm-icon" :src="componentContent.publicList[3].pic"/>
<label class="des">{{this.componentContent.publicList[3].des}}</label>
</div>
</div>
<div class="foot-box">
<span style="font-family:arial;">&copy; </span>2016-2020CERESHOP版权所有并保留所有权利 粤ICP备D51DD288号
</div>
</div>
</template>
<script>
export default {
props: {
componentContent: Object
}
}
</script>
<style lang="scss" scoped>
.canvasFooter{
margin-top: 30px;
height: 454px;
background-color: #333333;
color: #ffffff;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
.content{
display: flex;
// width: 60%;
// justify-content: space-between;
width: 1240px;
justify-content: space-around;
.lab-group{
display: flex;
flex-direction: column;
justify-content: center;
label{
font-weight: 400;
margin: 10px;
}
.fs24{
font-size: 24px;
}
.fs50{
font-size: 50px;
}
.fs28{
font-size: 28px;
}
.consult{
width: 164px;
height: 50px;
margin-top: 40px;
color: #cccccc;
border: 1px #cccccc solid;
line-height: 50px;
text-align: center;
cursor: pointer;
}
}
.icon-group{
display: flex;
flex-direction: column;
align-items: center;
label{
font-size: 20px;
font-weight: 400;
}
.des{
margin-top: 20px;
}
}
.gzh-icon{
height: 196px;
width: 196px;
}
.xcxm-icon{
height: 196px;
width: 196px;
}
.verticalline{
height: 238px;
width: 1px;
background-color:#666666;
}
}
}
.foot-box{
margin-top: 80px;
}
</style>
@@ -0,0 +1,86 @@
/**
顶部个人中心组件
*/
<template>
<div class="canvasNavPersonal">
<div class="TPNleft" >
<svg t="1618193747145" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1380" width="13" height="13"><path d="M494.808475 0.002204a59.729531 59.729531 0 0 1 59.729531 59.729531v241.0487a59.729531 59.729531 0 0 1-119.385595 0V59.731735A59.656063 59.656063 0 0 1 494.808475 0.002204zM106.823659 723.22177h810.499619a59.729531 59.729531 0 0 1 0 119.385594H106.823659a59.729531 59.729531 0 0 1 0-119.385594z m394.890813-541.82693a307.684228 307.684228 0 0 1 307.684228 307.684228v234.142702H194.103712V489.0056a307.61076 307.61076 0 0 1 307.61076-307.61076zM343.317338 964.270469h303.055741a29.828032 29.828032 0 0 1 0 59.729531H343.317338a29.828032 29.828032 0 0 1 0-59.729531z" fill="#333333" p-id="1381"></path></svg>
<div class="warpper">通知公告</div>
</div>
<div class="TPNright">
<div class="content"
v-for="(item,index) in componentContent.txtRoute"
:key="index">
<div class="personalText" v-if="item.des != ''">
{{ item.des }}<Badge class="zxbadge" :num="item.notice" :size="'regular'"/>
</div>
<div class="container" v-if="index != componentContent.txtRoute.length -1">/</div>
</div>
<!-- icon部分 -->
<div class="personalText iconLeft">
<svg t="1618194176792" class="icon" viewBox="0 0 1170 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1815" width="16" height="16"><path d="M1119.085714 138.313143H269.165714L239.177143 42.861714a60.928 60.928 0 0 0-58.514286-42.715428H40.96a40.594286 40.594286 0 1 0 0 81.115428h124.342857l229.668572 727.04h656.822857a40.521143 40.521143 0 1 0 0-81.115428H455.68l-33.645714-105.398857 705.828571-118.637715a51.2 51.2 0 0 0 42.422857-50.029714V189.001143a51.2 51.2 0 0 0-51.2-50.688z m-587.337143 707.876571a88.795429 88.795429 0 1 0 89.965715 88.795429 89.380571 89.380571 0 0 0-89.965715-88.795429z m430.08 0a88.795429 88.795429 0 1 0 89.965715 88.795429 89.380571 89.380571 0 0 0-89.965715-88.795429z" fill="#333333" p-id="1816"></path></svg><Badge class="zxbadge" :num="this.componentContent.cartNum" :size="'regular'"/>
</div>
<div class="personalText">
<svg t="1618196116210" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1480" width="16" height="16"><path d="M980.114286 277.942857c-29.257143-51.2-65.828571-102.4-109.714286-146.285714-51.2-43.885714-102.4-73.142857-160.914286-95.085714C585.142857-14.628571 438.857143-14.628571 314.514286 36.571429c-58.514286 21.942857-117.028571 51.2-160.914286 95.085714-51.2 36.571429-87.771429 87.771429-109.714286 146.285714-29.257143 51.2-43.885714 109.714286-43.885714 175.542857 0 160.914286 87.771429 299.885714 226.742857 373.028572 21.942857 14.628571 51.2 29.257143 73.142857 36.571428l175.542857 146.285715c14.628571 7.314286 21.942857 14.628571 36.571429 14.628571s21.942857-7.314286 36.571429-14.628571l153.6-138.971429c87.771429-29.257143 168.228571-87.771429 226.742857-160.914286 58.514286-73.142857 95.085714-168.228571 95.085714-263.314285 0-58.514286-14.628571-117.028571-43.885714-168.228572zM665.6 614.4c-87.771429 73.142857-219.428571 73.142857-314.514286 0-36.571429-36.571429-58.514286-87.771429-58.514285-138.971429 0-21.942857 21.942857-36.571429 36.571428-36.571428s29.257143 14.628571 29.257143 29.257143c14.628571 80.457143 95.085714 138.971429 175.542857 124.342857 65.828571-7.314286 117.028571-58.514286 124.342857-117.028572 7.314286-21.942857 21.942857-36.571429 43.885715-36.571428 14.628571 0 29.257143 14.628571 29.257142 29.257143 0 58.514286-21.942857 109.714286-65.828571 146.285714z" fill="#333333" p-id="1481"></path></svg><Badge class="zxbadge" :num="0" :size="'regular'"/>
</div>
<div class="personalText el-dropdown-link">
<svg t="1618194347551" class="icon" viewBox="0 0 1054 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2126" width="16" height="16"><path d="M527.058824 0c150.588235 0 271.058824 120.470588 271.058823 271.058824S677.647059 542.117647 527.058824 542.117647 256 421.647059 256 271.058824 376.470588 0 527.058824 0zM0 1024v-225.882353c0-82.823529 67.764706-150.588235 150.588235-150.588235h752.941177c82.823529 0 150.588235 67.764706 150.588235 150.588235v225.882353H0z" fill="#333333" p-id="2127"></path></svg><Badge class="zxbadge" :num="0" :size="'regular'"/>
</div>
</div>
</div>
</template>
<script>
import Badge from '@/views/theme/components/canvasShow/pc/components/Badge.vue'
export default {
components: { Badge },
name: 'TopPersonalNav',
props: {
componentContent: Object
}
}
</script>
<style lang="scss" scoped>
.canvasNavPersonal{
height: 40px;
line-height: 40px;
font-size: 14px;
background-color: #F6F6F8;
div{
display: inline-block;
}
.TPNleft{
cursor: pointer;
margin-left: 135px;
line-height: 40px;
}
.TPNright{
float: right;
margin-right: 135px;
cursor: pointer;
.content{
margin-right: 10px;
.container{
padding-left: 5px;
}
}
.iconLeft{
margin-left: 20px;
}
.zxbadge{
display: inline-block;
height: 20px;
position: relative;
left: -5px;
}
.personalText{
margin-right: 15px;
}
}
>>>.el-dropdown-menu__item:focus, .el-dropdown-menu__item:not(.is-disabled):hover{
background-color: #F6F6F6;
color: #333333;
}
}
</style>
@@ -0,0 +1,138 @@
/**
画布_顶部路由组件
*/
<template>
<div class="canvasNavType">
<div class="wrapper">
<div class="TPNleft">
<div>
<router-link to="/">
<img src="../../../../../assets/canvasImg/logo.png" style="width:58px;height:23px;" alt="logo">
</router-link>
</div>
</div>
<div class="TPNright">
<div class="content"
v-for="item in componentContent.typeRoute"
:key="item.value"
@click="routLinkTo(item.route)">
<div class="personalText"
v-if="item.des != ''"
:class="{active_path : activeRoute === item.linkTo }">
{{ item.des }}
</div>
</div>
<div class="searchItem">
<input type="text" placeholder="请输入"><button>搜索</button>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'TopTypeNav',
props: {
componentContent: Object
},
data () {
return {
arr: {
'type': [
{
'value': 0,
'des': '首页',
'route': '/indexpage/index'
},
{
'value': 1,
'des': '全部商品',
'route': '/indexpage/productlist'
},
{
'value': 2,
'des': '秒杀专区',
'route': '/indexpage/seckill'
},
{
'value': 3,
'des': '拼团专区',
'route': '/indexpage/combination'
},
// {
// 'value': 4,
// 'des': '折扣专区',
// 'route': '/indexpage/discount'
// },
{
'value': 5,
'des': '领券中心',
'route': '/indexpage/getcoupon'
},
{
'value': 6,
'des': '图文详情',
'route': '/indexpage/noticedetail'
}
]
},
activeRoute: '/indexpage/index'
}
}
}
</script>
<style lang="scss" scoped>
.canvasNavType{
height: 100px;
line-height: 100px;
background-color: #FFFFFF;
.wrapper{
margin: auto;
div{
display: inline-block;
}
.TPNleft{
cursor: pointer;
margin-left: 135px;
}
.TPNright{
float: right;
margin-right: 135px;
cursor: pointer;
color: #666666;
font-size: 16px;
font-family: PingFang SC;
font-weight: 400;
.content{
margin-right: 30px;
.personalText{
height: 80px;
}
.active_path{
border-bottom: 2px solid #F26E47;
}
}
.searchItem{
margin: 0;
padding: 0;
input{
width: 200px;
height: 34px;
padding-left: 20px;
background-color: #F6F6F8;
}
button{
font-size: 16px;
width: 62px;
height: 34px;
color: #FFFFFF;
background-color: #333333;
cursor: pointer;
}
}
}
}
}
</style>
@@ -0,0 +1,28 @@
<template>
<div class="canvanProductDiscount">
<product-slot
:obj="obj">
<div>砍价专区</div>
</product-slot>
</div>
</template>
<script>
import ProductSlot from '@/views/theme/components/canvasShow/pc/components/IndexSlot.vue'
export default {
components: {ProductSlot},
data () {
return {
obj: {
'title': '砍价专区',
'bcText': 'BARGAINING ZONE',
'interface': ''
}
}
}
}
</script>
<style lang="scss">
</style>
@@ -0,0 +1,49 @@
<template>
<div class="canvanProductComb">
<product-slot
:obj="obj">
<ul class="container">
<li class="combItem"
v-for="(item, index) in componentContent.product"
:key="index"
>
<CombItem :obj="item"/>
</li>
</ul>
</product-slot>
</div>
</template>
<script>
import ProductSlot from '@/views/theme/components/canvasShow/pc/components/IndexSlot.vue'
import CombItem from '@/views/theme/components/canvasShow/pc/components/CombItem.vue'
export default {
components: {ProductSlot, CombItem},
props: {
componentContent: Object
},
data () {
return {
obj: {
'title': '拼团专区',
'bcText': 'SPELL GROUP ZONE',
'interface': ''
}
}
}
}
</script>
<style lang="scss">
.canvanProductComb{
.container{
display: flex;
flex-wrap: wrap;
justify-content: space-around;
margin: 30px 0;
.combItem{
margin: 5px 0;
}
}
}
</style>
@@ -0,0 +1,28 @@
<template>
<div class="canvanProductDiscount">
<product-slot
:obj="obj">
<div>折扣专区</div>
</product-slot>
</div>
</template>
<script>
import ProductSlot from '@/views/theme/components/canvasShow/pc/components/IndexSlot.vue'
export default {
components: {ProductSlot},
data () {
return {
obj: {
'title': '折扣专区',
'bcText': 'DISCOUNT ZONE',
'interface': ''
}
}
}
}
</script>
<style lang="scss">
</style>
@@ -0,0 +1,103 @@
<template>
<div class="canvanProductHot">
<product-slot
:obj="obj">
<div class="hotContainer">
<div class="left">
<div class="title">{{ componentContent.product[0].storeName }}</div>
<div class="price">
{{ `${componentContent.product[0].price}` }}
<div class="putCart">
<svg
t="1618572221481" class="icon" viewBox="0 0 1170 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1604" width="16" height="16"><path d="M1119.085714 138.313143H269.165714L239.177143 42.861714a60.928 60.928 0 0 0-58.514286-42.715428H40.96a40.594286 40.594286 0 1 0 0 81.115428h124.342857l229.668572 727.04h656.822857a40.521143 40.521143 0 1 0 0-81.115428H455.68l-33.645714-105.398857 705.828571-118.637715a51.2 51.2 0 0 0 42.422857-50.029714V189.001143a51.2 51.2 0 0 0-51.2-50.688z m-587.337143 707.876571a88.795429 88.795429 0 1 0 89.965715 88.795429 89.380571 89.380571 0 0 0-89.965715-88.795429z m430.08 0a88.795429 88.795429 0 1 0 89.965715 88.795429 89.380571 89.380571 0 0 0-89.965715-88.795429z" fill="#333333" p-id="1605"></path></svg>
</div>
</div>
<img
class="imgPro"
:src="componentContent.product[0].pic"
alt="商品图片">
</div>
<!-- 人气爆款右边部分 -->
<div class="right" v-if="componentContent.product.length > 1">
<div v-for="(i, index2) in componentContent.product" :key="index2">
<div v-if="index2 !== 0"><ProductItem class="wrapItem" :obj="i" :type="0"/></div>
</div>
</div>
</div>
</product-slot>
</div>
</template>
<script>
import ProductSlot from '@/views/theme/components/canvasShow/pc/components/IndexSlot.vue'
import ProductItem from '@/views/theme/components/canvasShow/pc/components/ProductItem.vue'
export default {
components: {ProductSlot, ProductItem},
props: {
componentContent: Object
},
data () {
return {
obj: {
'title': '人气爆款',
'bcText': 'POPULAR STYLE',
'interface': '/indexpage/productlist'
}
}
}
}
</script>
<style lang="scss" scoped>
.canvanProductHot{
.hotContainer{
display: flex;
margin: 30px 0;
.left{
width: 500px;
height: 695px;
margin: 0 15px;
background-color: #EEE;
display: flex;
flex-direction: column;
.title{
margin: 50px 10px 0 50px;
text-align: left;
font-size: 30px;
overflow: hidden;
white-space:nowrap;
text-overflow: ellipsis;
}
.price{
margin: 30px 50px;
color: #333333;
font-size: 22px;
font-weight: 500;
.putCart{
float: right;
cursor: pointer;
}
}
.imgPro{
width: 375px;
height: 375px;
margin: auto;
cursor: pointer;
}
}
.right{
width: 650px;
height: 675px;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
.wrapItem{
width: 315px;
background-color: #EEE;
padding-bottom: 10px;
margin-bottom: 20px;
}
}
}
}
</style>
@@ -0,0 +1,49 @@
/**
画布_新品首发模块
*/
<template>
<div class="canvasNewProduct">
<product-slot
class="NewGroup"
:obj="obj">
<ul class="Container">
<li class="newItem"
v-for="(item, index) in componentContent.product"
:key="index" >
<NewItem :obj="item"/>
</li>
</ul>
</product-slot>
</div>
</template>
<script>
import ProductSlot from '@/views/theme/components/canvasShow/pc/components/IndexSlot.vue'
import NewItem from '@/views/theme/components/canvasShow/pc/components/ProductItem.vue'
export default {
components: {ProductSlot, NewItem},
props: {
componentContent: Object
},
data() {
return {
obj: {
'title': '新品首发',
'bcText': 'THE NEW START',
'interface': ''
}
}
}
}
</script>
<style lang="scss" scoped>
.canvasNewProduct{
.Container{
display: flex;
flex: wrap;
margin: 30px 0;
justify-content: space-around;
}
}
</style>
@@ -0,0 +1,46 @@
<template>
<div class="canvanProductSeckill">
<product-slot
:obj="obj">
<ul class="Container">
<!-- <li class="seckillItem">倒计时</li> -->
<li class="seckillItem"
v-for="(item, index) in componentContent.product"
:key="index" >
<ProductItem :obj="item"/>
</li>
</ul>
</product-slot>
</div>
</template>
<script>
import ProductSlot from '@/views/theme/components/canvasShow/pc/components/IndexSlot.vue'
import ProductItem from '@/views/theme/components/canvasShow/pc/components/ProductItem.vue'
export default {
components: {ProductSlot, ProductItem},
props: {
componentContent: Object
},
data () {
return {
obj: {
'title': '秒杀专区',
'bcText': 'SECONDS KILL ZONE',
'interface': '/indexpage/productlist'
}
}
}
}
</script>
<style lang="scss">
.canvanProductSeckill{
.Container{
display: flex;
flex: wrap;
margin: 30px 0;
justify-content: space-around;
}
}
</style>
@@ -0,0 +1,65 @@
/**
右上角角标组件
*/
<template>
<div class="canvasBadge">
<sup class="badge red" :class="bgwidth" v-if="sum != 0">{{ sum }}</sup>
</div>
</template>
<script>
export default {
name: 'zxBadge',
props: {
num: Number,
size: String
},
computed: {
sum: function () {
if (this.num > 99) {
return '99+'
} else {
return this.num
}
},
bgwidth: function () {
if (!this.size) {
return 'small'
} else {
return this.size
}
}
}
}
</script>
<style lang="scss" scoped>
.canvasBadge{
text-align: center;
.badge{
border-radius: 48px;
padding: 0 3px;
}
.red{
color: #FFFFFF;
background-color: #FF0000;
}
.big{
width: 48px;
height: 48px;
line-height: 32px;
}
.regular{
font-size: 14px;
width: 32px;
height: 32px;
line-height: 32px;
}
.small{
font-size: 12px;
width: 18px;
height: 18px;
line-height: 18px;
}
}
</style>
@@ -0,0 +1,95 @@
/**
拼团专区组件
*/
<template>
<div class="combItem">
<div class="leftCon">
<img
class="leftImg"
:src="obj.pic"
alt="拼团商品" />
</div>
<div class="rightCon">
<div class="name">{{ obj.storeName }}</div>
<div class="price">{{ obj.price}}</div>
<div class="footer">
<div class="left">
<span>{{ obj.people }}人团</span>
<br>
{{ obj.sales }}购买
</div>
<button class="getComb">去开团</button>
</div>
</div>
</div>
</template>
<script>
export default {
props: {
obj: Object
}
}
</script>
<style lang="scss">
.combItem{
display: flex;
.leftCon{
width: 274px;
height: 290px;
padding: 20px 15px;
background-color: #F3F3F3;
.leftImg{
width: 100%;
height: 100%;
cursor: pointer;
}
}
.rightCon{
width: 255px;
margin: 30px 0;
position: relative;
.name{
color: #666666;
font-size: 24px;
overflow: hidden;
white-space:nowrap;
text-overflow: ellipsis;
}
.price{
font-size: 22px;
color: #333333;
font-family: PingFang SC;
margin-top: 20px;
}
.footer{
width: 100%;
position: absolute;
bottom: 0;
font-size: 16px;
.left{
display: inline-block;
color: #999999;
span{
color: #666666;
font-size: 20px;
}
}
.getComb{
float: right;
width: 100px;
height: 40px;
color: #FFF;
background-color: #000;
cursor: pointer;
&:hover{
color: #FFF;
background-color: #F26E47;
border: 1px solid #FFF;
}
}
}
}
}
</style>
@@ -0,0 +1,83 @@
<template>
<div class="canvasIndexSlot">
<nav class="title">
<div class="bcGra">{{ obj.bcText }}</div>
<div class="des">{{ obj.title }}</div>
<span></span>
</nav>
<section class="son">
<slot class="section"></slot>
</section>
<footer class="foot">
<button class="slotBtn" @click="NavTo(obj.interface)">查看更多</button>
</footer>
</div>
</template>
<script>
export default {
props: {obj: Object},
methods: {
NavTo (paths) {
// if (!paths) { return }
// window.scrollTo(0, 0)
// this.$router.push({path: paths})
}
}
}
</script>
<style lang="scss">
.canvasIndexSlot{
.title{
text-align: center;
.bcGra{
margin: auto;
font-size: 60px;
font-weight: 400;
font-family: UTM Bebas;
background-image: linear-gradient(#DFDFDF, #EEE, transparent, transparent);
color: transparent;
-webkit-background-clip: text;
background-clip: text;
position: relative;
top: 30px;
z-index: 0;
}
.des{
font-size: 40px;
color: #333333;
background-color: transparent;
font-weight: 500;
cursor: default;
}
span{
display: block;
width: 30px;
height: 4px;
background-color: #F26E47;
margin: 20px auto 0;
}
}
.foot{
display: flex;
align-items: center;
margin-top: 30px;
.slotBtn{
width: 160px;
height: 50px;
margin: auto;
font-size: 18px;
color: #666666;
background-color: #FFFFFF;
border: 1px solid #E6E6E6;
cursor: pointer;
&:hover{
color: #FFFFFF;
background-color: #666666;
border: 1px solid #666666;
}
}
}
}
</style>
@@ -0,0 +1,62 @@
<template>
<div class="productItem">
<img class="imgPro" :src="obj.pic || ''" alt="商品图片" @click="toDetail(obj.id,type)">
<div class="title">{{ obj.storeName }}</div>
<div class="price">
{{ `${obj.price}` }}
<div class="putCart" @click="toDetail(obj.id, type)">
<svg
t="1618572221481" class="icon" viewBox="0 0 1170 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1604" width="16" height="16">
<path d="M1119.085714 138.313143H269.165714L239.177143 42.861714a60.928 60.928 0 0 0-58.514286-42.715428H40.96a40.594286 40.594286 0 1 0 0 81.115428h124.342857l229.668572 727.04h656.822857a40.521143 40.521143 0 1 0 0-81.115428H455.68l-33.645714-105.398857 705.828571-118.637715a51.2 51.2 0 0 0 42.422857-50.029714V189.001143a51.2 51.2 0 0 0-51.2-50.688z m-587.337143 707.876571a88.795429 88.795429 0 1 0 89.965715 88.795429 89.380571 89.380571 0 0 0-89.965715-88.795429z m430.08 0a88.795429 88.795429 0 1 0 89.965715 88.795429 89.380571 89.380571 0 0 0-89.965715-88.795429z" fill="#333333" p-id="1605"></path>
</svg>
</div>
</div>
</div>
</template>
<script>
export default {
props: {
obj: Object,
type: Number
},
methods: {
toDetail (id, type) {
this.$router.push({
path: '/productDetail',
query: {
productId: id,
type: type
}
})
}
}
}
</script>
<style lang="scss">
.productItem{
width: 278px;
.imgPro{
width: 100%;
height: 250px;
cursor: pointer;
}
.title{
margin: 15px 20px;
overflow: hidden;
white-space:nowrap;
text-overflow: ellipsis;
}
.price{
margin: 0 20px;
color: #333333;
font-size: 22px;
font-weight: 500;
.putCart{
float: right;
cursor: pointer;
}
}
}
</style>
@@ -0,0 +1,270 @@
<template>
<div class="panelBoxWarp">
<div class="panelBox" :class="{ on: sidebarShow }">
<div class="componentList">
<ul>
<li
v-for="(item, index) of componentList"
:key="index"
:class="{ on: componentActive == index }"
@click="componentActive = index"
>
<i class="iconfont icon-fangkuai"></i>
<span>{{ item }}</span>
</li>
</ul>
</div>
<div class="categoryList">
<div class="itemBox" v-for="(item, index) of categoryList" :key="index">
<h3>{{ item.title }}</h3>
<div class="childList">
<draggable
class="dragArea list-group"
:list="item.classList"
:clone="cloneItem"
:group="{ name: 'pageEdit', pull: 'clone', put: false }"
:options="{ sort: false }"
>
<div
@mouseover="hoverItem(classItem)"
@mouseout="hoverItemOut"
class="childItem list-group-item"
v-for="(classItem, index) of item.classList"
:key="index"
>
<div class="contentBox">
<img
:src="
isHover === classItem.title
? classItem.iconH
: classItem.icon
"
alt=""
/>
<span>{{ classItem.title }}</span>
</div>
<div class="cloneText">组件放置区域</div>
</div>
</draggable>
</div>
</div>
</div>
</div>
<!-- 是否展开 -->
<div
class="btnToggle"
@click="sidebarShow = !sidebarShow"
:class="{ on: sidebarShow }"
>
<i class="el-icon-arrow-right iconfont icon-arrow-right"></i>
<i class="el-icon-arrow-left iconfont icon-arrow-left"></i>
</div>
</div>
</template>
<script>
import draggable from 'vuedraggable'
import { mapGetters } from 'vuex'
// 默认配置文件
import panelList from './panelList.js'
export default {
name: 'panel',
components: {
draggable
},
data () {
return {
sidebarShow: true,
componentActive: 0,
componentList: ['组件'],
isHover: ''
}
},
methods: {
hoverItem (classItem) {
this.isHover = classItem.title
},
hoverItemOut () {
this.isHover = ''
},
cloneItem (item) {
return JSON.parse(JSON.stringify(item))
}
},
computed: {
...mapGetters([
'terminal'
]),
categoryList () {
if (this.terminal === 3) {
return panelList[0]
} else if (this.terminal === 4) {
return panelList[1]
}
}
}
}
</script>
<style lang="scss" scoped>
.panelBoxWarp {
position: relative;
height: 100%;
}
.panelBox {
width: 0px;
height: 100%;
display: flex;
overflow: hidden;
transition: 0.2s width ease;
&.on {
width: 250px;
}
.componentList {
width: 64px;
padding: 17px 0;
text-align: center;
ul{
margin: 0;
padding: 0;
}
li {
list-style: none;
position: relative;
margin-bottom: 18px;
.iconfont {
font-size: 24px;
}
span {
font-size: 12px;
display: block;
}
&.on,
&:hover {
color: $mainColor;
:after {
content: "";
position: absolute;
left: 0;
top: 0;
width: 2px;
height: 100%;
background-color: $mainColor;
}
}
}
}
.categoryList {
border-left: 1px solid #f0f3f4;
width: 186px;
padding: 20px 0;
height: auto;
overflow-y: auto;
padding-bottom:40px;
.itemBox {
h3 {
padding-left: 20px;
height: 35px;
line-height: 35px;
font-size: 16px;
color: #333333;
position: relative;
&:before {
content: "";
border-left: 5px solid $mainColor;
border-top: 4px solid transparent;
border-bottom: 4px solid transparent;
position: absolute;
left: 10px;
top: 50%;
margin-top: -4px;
}
}
.childList {
font-size: 14px;
color: #333333;
padding: 20px 10px;
.list-group {
display: flex;
flex-wrap: wrap;
:hover {
background: #ff7800;
color: #ffffff;
border-radius: 3px;
cursor: move;
}
.childItem {
height: 80px;
width: 50%;
cursor: pointer;
.contentBox {
height: 100%;
display: flex;
flex-flow: column;
align-items: center;
justify-content: center;
img {
width: 20px;
height: 20px;
}
span {
margin-top: 10px;
}
}
.cloneText {
display: none;
}
}
}
}
}
}
}
.btnToggle {
width: 20px;
height: 66px;
background-color: #fff;
border-radius: 0 20px 20px 0;
position: absolute;
right: -20px;
top: 50%;
margin-top: -33px;
display: flex;
align-items: center;
cursor: pointer;
z-index: 9;
.icon-arrow-left {
display: none;
}
&.on {
.icon-arrow-left {
display: block;
}
.icon-arrow-right {
display: none;
}
}
}
</style>
@@ -0,0 +1,607 @@
// 导入api接口模块
import imageSrc from '@/assets/canvasImg/index.js'
export const panelList = [
// 小程序
[
{
title: '基础组件',
classList: [
{
title: '店铺头部',
icon: imageSrc.shopIcon,
iconH: imageSrc.shopIconH,
type: 'header',
componentContent: {
title: 'store'
}
},
{
title: '搜索商品',
icon: imageSrc.shopIcon,
iconH: imageSrc.shopIconH,
type: 'search',
componentContent: {}
},
{
title: '轮播图',
icon: imageSrc.textIcon,
iconH: imageSrc.textIconH,
type: 'banner',
componentContent: {
bannerData: [
{
pic: require('@/assets/canvasImg/cereshop/banner.png'),
name: '0',
sort: 0,
url: '/',
status: 1
}
]
}
},
// 滚动新闻
{
title: '滚动新闻',
icon: imageSrc.brandIcon,
iconH: imageSrc.brandIconH,
type: 'noticeBar',
componentContent: {
roll: [
{
uniapp_url: '/pages/shop/news/NewsList/index',
url: '/news_list',
info:
'武设特价电商',
wxapp_url: '/pages/shop/news/NewsList/main'
}
]
}
},
// 菜单
{
title: '菜单',
icon: imageSrc.textImgIcon,
iconH: imageSrc.textImgIconH,
type: 'menu',
componentContent: {
menus: [
{
imageArr: [
'https://image.dayouqiantu.cn/5e85bfa61251d.png'
],
uniapp_url: '/pages/shop/GoodsList/index',
name: '全部商品',
id: 180,
pic: 'https://image.dayouqiantu.cn/all.png',
sort: 9,
url: '/goods_list',
wxapp_url: '/pages/shop/GoodsClass/main',
status: 1
},
{
imageArr: ['https://image.dayouqiantu.cn/news.png'],
uniapp_url: '/pages/shop/news/NewsList/index',
name: '图文资讯',
id: 196,
pic: 'https://image.dayouqiantu.cn/xw.png',
sort: 8,
url: '/news_list',
wxapp_url: '/pages/shop/news/NewsList/main',
status: 1
},
{
imageArr: [
'https://image.dayouqiantu.cn/5e4e939507b5e.png'
],
uniapp_url: '/pages/shop/GoodsCollection/index',
name: '我的收藏',
id: 197,
pic: 'https://image.dayouqiantu.cn/colle.png',
sort: 7,
url: '/collection',
wxapp_url: '/pages/shop/GoodsCollection/main',
status: 1
},
{
imageArr: ['https://image.dayouqiantu.cn/coupon.png'],
uniapp_url: '',
name: '优惠券',
id: 199,
pic: 'https://image.dayouqiantu.cn/cou.png',
sort: 6,
url: '/user/get_coupon',
wxapp_url: '/pages/user/coupon/GetCoupon/main',
status: 1
},
{
imageArr: ['https://image.dayouqiantu.cn/pink.png'],
uniapp_url: '/pages/activity/GoodsGroup/index',
name: '拼团专区',
id: 200,
pic:
'https://image.dayouqiantu.cn/62ac09d2914d36c65b9b59d2147d809a.png',
sort: 5,
url: '/activity/group',
wxapp_url: '/pages/activity/GoodsGroup/main',
status: 1
},
{
imageArr: ['https://image.dayouqiantu.cn/sign.png'],
uniapp_url: '/pages/user/signIn/Sign/index',
name: '积分签到',
id: 209,
pic:
'https://image.dayouqiantu.cn/29ea4acebbf99e7eaf6f85af2b6d79ae.png',
sort: 4,
url: '/user/sign',
wxapp_url: '/pages/user/signIn/Sign/main',
status: 1
},
{
imageArr: ['https://image.dayouqiantu.cn/sekill.png'],
uniapp_url: '/pages/activity/GoodsSeckill/index',
name: '秒杀专区',
id: 216,
pic:
'https://image.dayouqiantu.cn/b0344c148141b50d68db9722708ea49e.png',
sort: 3,
url: '/activity/goods_seckill',
wxapp_url: '/pages/activity/GoodsSeckill/main',
status: 1
},
{
imageArr: ['https://image.dayouqiantu.cn/bargin.png'],
uniapp_url: '/pages/activity/GoodsBargain/index',
name: '砍价专区',
id: 217,
pic: 'https://image.dayouqiantu.cn/bar.png',
sort: 2,
url: '/activity/bargain',
wxapp_url: '/pages/activity/GoodsBargain/main',
status: 1
}
]
}
},
// 广告
{
title: '广告',
icon: imageSrc.twListIcon,
iconH: imageSrc.twListIconH,
type: 'adv',
componentContent: {
detail: {
list: [
{
image: 'https://wx.yixiang.co/static/images/index001.png',
url: '',
uniapp_url: '',
wxapp_url: '',
path_type: 1
},
{
image: 'https://wx.yixiang.co/static/images/index002.png',
url: '',
uniapp_url: '',
wxapp_url: '',
path_type: 1
},
{
image: 'https://wx.yixiang.co/static/images/index003.png',
url: '',
uniapp_url: '',
wxapp_url: '',
path_type: 1
}
],
name: '',
style: 3
}
}
},
// 超值拼团
{
title: '超值拼团',
icon: imageSrc.customIcon,
iconH: imageSrc.customIconH,
type: 'groupon',
componentContent: {}
},
// 热门榜单
{
title: '热门榜单',
icon: imageSrc.customIcon,
iconH: imageSrc.customIconH,
type: 'hotCommodity',
componentContent: {}
},
// 秒杀
// 新品
{
// title: '秒杀',
title: '首发新品',
icon: imageSrc.videoIcon,
iconH: imageSrc.videoIconH,
type: 'firstNewProduct',
componentContent: {}
},
// 精品推荐
{
title: '精品推荐',
icon: imageSrc.videoIcon,
iconH: imageSrc.videoIconH,
type: 'productsRecommended',
componentContent: {}
},
// 促销单品
{
title: '促销单品',
icon: imageSrc.videoIcon,
iconH: imageSrc.videoIconH,
type: 'promoteProduct',
componentContent: {}
},
// 直播
{
title: '直播',
icon: imageSrc.videoIcon,
iconH: imageSrc.videoIconH,
type: 'live',
componentContent: {}
},
// 为您推荐
{
title: '为您推荐',
icon: imageSrc.videoIcon,
iconH: imageSrc.videoIconH,
type: 'promotionGood',
componentContent: {}
}
]
}
],
// PC
[
// 店铺组件
{
title: '店铺组件',
type: 1,
classList: [
// 个人中心导航
{
title: '个人中心',
icon: imageSrc.videoIcon,
iconH: imageSrc.videoIconH,
type: 'NavPersonal',
componentContent: {
txtRoute: [
{
'title': '优惠卷',
'des': '优惠卷', // 展示内容
'linkTo': '',
'pic': '',
'notice': 0,
'editors': [
{
'editorTitle': '优惠卷',
'editorDes': '', // 编辑内容
'editorUrl': '',
'editorPic': ''
}
]
},
{
'title': '会员中心',
'des': '会员中心',
'linkTo': '',
'pic': '',
'notice': 0,
'editors': [
{
'editorTitle': '会员中心',
'editorDes': '' // 编辑内容
}
]
},
{
'title': '我的订单',
'des': '我的订单',
'linkTo': '',
'pic': '',
'notice': 0,
'editors': [
{
'editorTitle': '我的订单',
'editorDes': '' // 编辑内容
}
]
}
],
cartNum: 4
}
},
// 专区导航
{
title: '专区导航',
icon: imageSrc.videoIcon,
iconH: imageSrc.videoIconH,
type: 'NavType',
componentContent: {
typeRoute: [
{
'title': '首页',
'des': '首页',
'linkTo': '/indexpage/index',
'pic': ''
},
{
'title': '全部商品',
'des': '全部商品',
'linkTo': '/indexpage/productlist',
'pic': ''
},
{
'title': '秒杀专区',
'des': '秒杀专区',
'linkTo': '/indexpage/seckill',
'pic': ''
},
{
'title': '拼团专区',
'des': '拼团专区',
'linkTo': '/indexpage/combination',
'pic': ''
},
{
'title': '领卷中心',
'des': '领卷中心',
'linkTo': '/indexpage/getcoupon',
'pic': ''
},
{
'title': '图文详情',
'des': '图文详情',
'linkTo': '/indexpage/noticedetail',
'pic': ''
}
]
}
},
// 联系方式
{
title: '联系方式',
icon: imageSrc.videoIcon,
iconH: imageSrc.videoIconH,
type: 'Footer',
componentContent: {
publicList: [
{
'title': '客服电话',
'des': '400 800 2100'
},
{
'title': '营业时间',
'des': '9:00-23:00'
},
{
'title': '微信公众号',
'des': '微信公众号',
'pic': '/static/img/erweima@2x.png',
'linkTo': ''
},
{
'title': '小程序码',
'des': '小程序码',
'pic': '/static/img/xcxm.png',
'linkTo': ''
}
]
}
},
// 轮播图
{
title: '轮播图',
icon: imageSrc.videoIcon,
iconH: imageSrc.videoIconH,
type: 'PcBanner',
componentContent: {
bannerList: [
{
title: '轮播1',
des: '',
pic: 'https://image.dayouqiantu.cn/1.jpg',
url: '',
linkTo: ''
},
{
title: '轮播2',
des: '',
pic: 'https://image.dayouqiantu.cn/5c9f05aee5059.jpg',
url: '',
linkTo: ''
}
]
}
},
// 新品上新
{
title: '新品上新',
icon: imageSrc.videoIcon,
iconH: imageSrc.videoIconH,
type: 'ProductNew',
componentContent: {
'product': [
{
'title': '新款商品1',
'id': '1',
'pic': 'https://wxapi.yixiang.co/api/file/pic/20210222213116280067.jpeg',
'storeName': '测试商品测试商品测试商品测试商品测试商品测试商品测试商品测试商品',
'price': '123'
},
{
'title': '新款商品2',
'id': '1',
'pic': 'https://wxapi.yixiang.co/api/file/pic/20210222213116280067.jpeg',
'storeName': '测试商品测试商品测试商品测试商品测试商品测试商品测试商品测试商品',
'price': '123'
},
{
'title': '新款商品3',
'id': '1',
'pic': 'https://wxapi.yixiang.co/api/file/pic/20210222213116280067.jpeg',
'storeName': '测试商品测试商品测试商品测试商品测试商品测试商品测试商品测试商品',
'price': '123',
'type': 0
},
{
'title': '新款商品4',
'id': '1',
'pic': 'https://wxapi.yixiang.co/api/file/pic/20210222213116280067.jpeg',
'storeName': '测试商品测试商品测试商品测试商品测试商品测试商品测试商品测试商品',
'price': '123'
}
]
}
},
// 人气爆款
{
title: '人气爆款',
icon: imageSrc.videoIcon,
iconH: imageSrc.videoIconH,
type: 'ProductHot',
componentContent: {
'product': [
{
'title': '爆款商品1',
'id': '1',
'pic': 'https://wxapi.yixiang.co/api/file/pic/20210222213116280067.jpeg',
'storeName': '测试商品测试商品测试商品测试商品测试商品测试商品测试商品测试商品',
'price': '123'
},
{
'title': '爆款商品2',
'id': '1',
'pic': 'https://wxapi.yixiang.co/api/file/pic/20210222213116280067.jpeg',
'storeName': '测试商品测试商品测试商品测试商品测试商品测试商品测试商品测试商品',
'price': '123'
},
{
'title': '爆款商品3',
'id': '1',
'pic': 'https://wxapi.yixiang.co/api/file/pic/20210222213116280067.jpeg',
'storeName': '测试商品测试商品测试商品测试商品测试商品测试商品测试商品测试商品',
'price': '123',
'type': 0
},
{
'title': '爆款商品4',
'id': '1',
'pic': 'https://wxapi.yixiang.co/api/file/pic/20210222213116280067.jpeg',
'storeName': '测试商品测试商品测试商品测试商品测试商品测试商品测试商品测试商品',
'price': '123'
}
]
}
},
// 秒杀专区
{
title: '秒杀专区',
icon: imageSrc.videoIcon,
iconH: imageSrc.videoIconH,
type: 'ProductSeckill',
componentContent: {
'product': [
{
'title': '秒杀商品1',
'id': '1',
'pic': 'https://wxapi.yixiang.co/api/file/pic/20210222213116280067.jpeg',
'storeName': '测试商品测试商品测试商品测试商品测试商品测试商品测试商品测试商品',
'price': '123'
},
{
'title': '秒杀商品2',
'id': '1',
'pic': 'https://wxapi.yixiang.co/api/file/pic/20210222213116280067.jpeg',
'storeName': '测试商品测试商品测试商品测试商品测试商品测试商品测试商品测试商品',
'price': '123'
},
{
'title': '秒杀商品3',
'id': '1',
'pic': 'https://wxapi.yixiang.co/api/file/pic/20210222213116280067.jpeg',
'storeName': '测试商品测试商品测试商品测试商品测试商品测试商品测试商品测试商品',
'price': '123',
'type': 0
}
]
}
},
// 拼团专区
{
title: '拼团专区',
icon: imageSrc.videoIcon,
iconH: imageSrc.videoIconH,
type: 'ProductComb',
componentContent: {
'product': [
{
'title': '拼团商品1',
'id': '1',
'pic': 'https://wxapi.yixiang.co/api/file/pic/20210222213116280067.jpeg',
'storeName': '测试商品测试商品测试商品测试商品测试商品测试商品测试商品测试商品',
'price': 123,
'people': 3,
'sales': 521
},
{
'title': '拼团商品2',
'id': '1',
'pic': 'https://wxapi.yixiang.co/api/file/pic/20210222213116280067.jpeg',
'storeName': '测试商品测试商品测试商品测试商品测试商品测试商品测试商品测试商品',
'price': 123,
'people': 3,
'sales': 521
},
{
'title': '拼团商品3',
'id': '1',
'pic': 'https://wxapi.yixiang.co/api/file/pic/20210222213116280067.jpeg',
'storeName': '测试商品测试商品测试商品测试商品测试商品测试商品测试商品测试商品',
'price': 123,
'people': 3,
'sales': 521
},
{
'title': '拼团商品4',
'id': '1',
'pic': 'https://wxapi.yixiang.co/api/file/pic/20210222213116280067.jpeg',
'storeName': '测试商品测试商品测试商品测试商品测试商品测试商品测试商品测试商品',
'price': 123,
'people': 3,
'sales': 521
}
]
}
}
// // 折扣专区
// {
// title: '折扣专区',
// icon: imageSrc.videoIcon,
// iconH: imageSrc.videoIconH,
// type: 'ProductDiscount',
// componentContent: {}
// },
// // 砍价专区
// {
// title: '砍价专区',
// icon: imageSrc.videoIcon,
// iconH: imageSrc.videoIconH,
// // iconClass: 'el-icon-shopping-bag-1',
// type: 'ProductBargin',
// componentContent: {}
// }
]
}
]
]
export default panelList
@@ -0,0 +1,357 @@
<template>
<div class="shopTopTool">
<h3 class="toolTit">广告</h3>
<div class="tabBox">
<div class="toolBox">
<div class="modelTit">图片设置</div>
<div class="imgListBox">
<draggable v-model="activeComponent.componentContent.adv">
<div
v-for="(item, index) in activeComponent.componentContent.detail.list"
:key="index"
class="item">
<div class="listItemBox">
<div class="addImgTit" @click="openAddImg(item, index)">
<div class="titLeft">
<span class="iconfont">&#xe703;</span>
<span class="iconfont">&#xe64a;</span>
<span>图片</span>
</div>
<div class="titRight">
<span
v-html="imgCurrent === index ? '&#xe660;' : '&#xe695;'"
class="iconfont"></span>
</div>
</div>
<div class="addBox" v-show="imgCurrent === index">
<div class="addContent">
<tool-single-img
:imageUrl.sync="item.image"
:tip="alignList[index]"></tool-single-img>
<div class="modelTit titleBox">跳转地址</div>
<el-input
placeholder="请输入新闻链接"
resize="none"
v-model="item.url" />
<div class="modelTit titleBox">uni链接</div>
<el-input
placeholder="请输入uni链接"
resize="none"
v-model="item.uniapp_url" />
<div class="modelTit titleBox">小程序链接</div>
<el-input
placeholder="请输入小程序链接"
resize="none"
v-model="item.wxapp_url" />
</div>
</div>
</div>
</div>
</draggable>
</div>
</div>
</div>
<el-dialog
title="提示"
:visible.sync="dialogVisible"
width="30%"
:before-close="deleteItem">
<span>点击确定删除此项</span>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false"> </el-button>
<el-button type="primary" @click="dialogVisible = false"> </el-button>
</span>
</el-dialog>
<el-dialog :visible.sync="dialogImageVisible">
<img width="100%" :src="dialogImageUrl" alt="" />
</el-dialog>
</div>
</template>
<script>
import Draggable from 'vuedraggable'
import { toolMixin } from '@/mixins/tool.js'
import ToolSelectLink from '@/views/theme/components/rootcompToolbar/toolModule/tool-select-link.vue'
import ToolSelectCategory from '@/views/theme/components/rootcompToolbar/toolModule/tool-select-category.vue'
import ToolSingleImg from '@/views/theme/components/rootcompToolbar/toolModule/tool-single-img.vue'
export default {
name: 'shopTopTool',
mixins: [toolMixin],
components: {
ToolSingleImg,
ToolSelectCategory,
ToolSelectLink,
Draggable
},
data() {
return {
dialogImageVisible: false,
dialogImageUrl: '',
alignList: [
{
id: 1,
label: '建议尺寸: 355*377px',
value: 'left'
},
{
id: 2,
label: '建议尺寸: 354*168px',
value: 'center'
},
{
id: 3,
label: '建议尺寸: 354*168px',
value: 'right'
}
],
textAlign: 'left',
imgCurrent: null,
labelCurrent: null,
dialogVisible: false
}
},
methods: {
// 添加类别
addCategory() {},
openAddImg(item, index) {
if (this.imgCurrent === index) {
this.imgCurrent = null
return false
}
this.imgCurrent = index
},
openAddLabel (item, index) {
if (this.labelCurrent === index) {
this.labelCurrent = null
return false
}
this.labelCurrent = index
},
// 添加图文
addImgText() {
this.activeComponent.componentContent.menus.push({
uniapp_url: '',
name: '',
pic: '',
url: '',
wxapp_url: ''
})
},
// 删除内容
deleteItem(item, index) {
this.$confirm('确定删除此项?')
.then((_) => {
this.activeComponent.componentContent.menus.splice(index, 1)
})
.catch((_) => {})
},
// 添加标签
addLabel() {
this.activeComponent.componentContent.labelList.push({
name: '',
url: ''
})
},
// 删除标签
deleteLabelItem(item, index) {
this.$confirm('确定删除此项?')
.then((_) => {
this.activeComponent.componentContent.labelList.splice(index, 1)
})
.catch((_) => {})
},
imgChange(file, index, key) {
this.activeComponent.componentContent.menus[index][key] = URL.createObjectURL(file.raw)
},
showImage(imgData) {
this.dialogImageUrl = imgData
this.dialogImageVisible = true
},
delImage(index, key) {
this.activeComponent.componentContent.menus[index][key] = ''
}
}
}
</script>
<style lang="scss" scoped>
.shopTopTool {
padding: 20px 20px 0px 20px;
.topTit {
display: flex;
justify-content: space-between;
border-bottom: 1px solid #eeeeee;
margin-bottom: 20px;
span {
height: 35px;
line-height: 35px;
font-size: 14px;
color: #333333;
}
span:last-child {
font-weight: bold;
width: 100px;
text-align: center;
cursor: pointer;
&:hover {
color: $mainColor;
}
}
}
h3 {
font-size: 18px;
font-weight: 500;
height: 35px;
line-height: 35px;
color: #333333;
margin-bottom: 20px;
}
.titleBox {
display: flex;
justify-content: space-between;
}
.btnSelect {
margin-top: 30px;
}
.toolBox {
padding-bottom: 10px;
.modelTit {
font-size: 14px;
color: #333333;
margin-top: 10px;
margin-bottom: 10px;
}
.itemBox {
label {
font-size: 14px;
color: #666666;
height: 40px;
line-height: 40px;
}
margin-bottom: 15px;
}
.imgListBox {
margin-top: 30px;
.item {
border: 1px solid #e8eaec;
border-radius: 4px;
margin-bottom: 10px;
}
.listItemBox {
.addImgTit {
padding: 10px;
display: flex;
justify-content: space-between;
align-items: center;
background: #f6f7f9;
cursor: pointer;
.titLeft {
display: flex;
align-items: center;
span {
color: #7d7e80;
}
span:nth-child(1) {
font-size: 28px;
}
span:nth-child(2) {
font-size: 25px;
margin: 0 6px;
}
span:nth-child(3) {
font-size: 14px;
}
}
.titRight {
display: flex;
align-items: center;
span:nth-child(1) {
width: 40px;
text-align: center;
display: block;
height: 30px;
line-height: 30px;
}
}
}
.addContent {
padding: 5px 13px;
.imgIsShow {
display: flex;
justify-content: space-between;
margin: 18px 0 22px 0;
span {
font-size: 14px;
color: #666666;
}
}
.deleteItem {
border-radius: 4px;
background: $mainColor;
text-align: center;
height: 36px;
color: #ffffff;
font-size: 14px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
margin-bottom: 10px;
span {
font-size: 18px;
color: #ffffff;
margin-right: 5px;
}
}
}
.deleteItem {
padding: 10px;
display: flex;
align-items: center;
justify-content: center;
background: #f6f7f9;
cursor: pointer;
color: $mainColor;
font-size: 14px;
span {
font-size: 16px;
margin-right: 5px;
}
}
}
}
.textTit {
height: 35px;
line-height: 35px;
font-size: 16px;
color: #333333;
font-weight: bold;
}
}
>>> .el-select {
width: 100%;
}
.addImgBtn {
border-radius: 4px;
background: $mainColor;
text-align: center;
height: 36px;
color: #ffffff;
font-size: 14px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
margin-bottom: 30px;
span {
font-size: 20px;
margin-right: 5px;
}
}
.labelList {
.addLabelBox {
padding: 10px;
}
}
}
</style>
@@ -0,0 +1,379 @@
<template>
<div class="shopTopTool">
<h3 class="toolTit">轮播图</h3>
<div class="tabBox">
<div class="toolBox">
<div class="modelTit">图片设置</div>
<div class="imgListBox">
<draggable v-model="activeComponent.componentContent.bannerData">
<div
v-for="(item, index) in activeComponent.componentContent
.bannerData"
:key="index"
class="item"
>
<div class="listItemBox">
<div class="addImgTit" @click="openAddImg(item, index)">
<div class="titLeft">
<span class="iconfont">&#xe703;</span>
<span class="iconfont">&#xe64a;</span>
<span>图片</span>
</div>
<div class="titRight">
<span class="iconfont" @click.stop="deleteItem(item, index)"
>&#xe633;</span
>
<span
v-html="imgCurrent === index ? '&#xe660;' : '&#xe695;'"
class="iconfont"
></span>
</div>
</div>
<div class="addBox" v-show="imgCurrent === index">
<div class="addContent">
<tool-single-img
:imageUrl.sync="item.pic"
></tool-single-img>
<div class="modelTit titleBox">跳转地址</div>
<el-input
placeholder="请输入新闻链接"
resize="none"
v-model="activeComponent.componentContent.bannerData[index].url"
/>
<div class="modelTit titleBox">uni链接</div>
<el-input
placeholder="请输入uni链接"
resize="none"
v-model="
activeComponent.componentContent.bannerData[index].uniapp_url
"
/>
<div class="modelTit titleBox">小程序链接</div>
<el-input
placeholder="请输入小程序链接"
resize="none"
v-model="
activeComponent.componentContent.bannerData[index].wxapp_url
"
/>
</div>
<div @click="deleteItem(item, index)" class="deleteItem">
<span class="iconfont">&#xe633;</span>删除内容
</div>
</div>
</div>
</div>
</draggable>
</div>
<div class="addImgBtn" @click="addImgText">
<span class="iconfont">&#xe64a;</span>添加图文
</div>
</div>
</div>
<!-- 弹框部分 -->
<el-dialog
title="提示"
:visible.sync="dialogVisible"
width="30%"
:before-close="deleteItem">
<span>点击确定删除此项</span>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false">取 消</el-button>
<el-button type="primary" @click="dialogVisible = false"
>确 定</el-button
>
</span>
</el-dialog>
<el-dialog
:visible.sync="dialogImageVisible">
<img width="100%" :src="dialogImageUrl" alt="" />
</el-dialog>
</div>
</template>
<script>
import Draggable from 'vuedraggable'
import { toolMixin } from '@/mixins/tool.js'
import ToolSelectLink from '@/views/theme/components/rootcompToolbar/toolModule/tool-select-link.vue'
import ToolSelectCategory from '@/views/theme/components/rootcompToolbar/toolModule/tool-select-category.vue'
import ToolSingleImg from '@/views/theme/components/rootcompToolbar/toolModule/tool-single-img.vue'
export default {
name: 'shopTopTool',
mixins: [toolMixin],
components: {
ToolSingleImg,
ToolSelectCategory,
ToolSelectLink,
Draggable
},
data () {
return {
dialogImageVisible: false,
dialogImageUrl: '',
alignList: [
{
id: 1,
label: '居左',
value: 'left'
},
{
id: 2,
label: '居中',
value: 'center'
},
{
id: 3,
label: '居右',
value: 'right'
}
],
textAlign: 'left',
imgCurrent: null,
labelCurrent: null,
dialogVisible: false
}
},
methods: {
// 添加类别
addCategory () {},
openAddImg (item, index) {
if (this.imgCurrent === index) {
this.imgCurrent = null
return false
}
this.imgCurrent = index
},
openAddLabel (item, index) {
if (this.labelCurrent === index) {
this.labelCurrent = null
return false
}
this.labelCurrent = index
},
// 添加图文
addImgText () {
this.activeComponent.componentContent.bannerData.push({
title: '',
imgData: '',
url: ''
})
},
// 删除内容
deleteItem (item, index) {
this.$confirm('确定删除此项?')
.then((_) => {
this.activeComponent.componentContent.bannerData.splice(index, 1)
})
.catch((_) => {})
},
// 添加标签
addLabel () {
this.activeComponent.componentContent.labelList.push({
name: '',
url: ''
})
},
// 删除标签
deleteLabelItem (item, index) {
this.$confirm('确定删除此项?')
.then((_) => {
this.activeComponent.componentContent.labelList.splice(index, 1)
})
.catch((_) => {})
},
imgChange (file, index, key) {
this.activeComponent.componentContent.bannerData[index][key] = URL.createObjectURL(file.raw)
},
showImage (imgData) {
this.dialogImageUrl = imgData
this.dialogImageVisible = true
},
delImage (index, key) {
this.activeComponent.componentContent.bannerData[index][key] = ''
}
}
}
</script>
<style lang="scss" scoped>
.shopTopTool {
padding: 20px 20px 0px 20px;
.topTit {
display: flex;
justify-content: space-between;
border-bottom: 1px solid #eeeeee;
margin-bottom: 20px;
span {
height: 35px;
line-height: 35px;
font-size: 14px;
color: #333333;
}
span:last-child {
font-weight: bold;
width: 100px;
text-align: center;
cursor: pointer;
&:hover {
color: $mainColor;
}
}
}
h3 {
font-size: 18px;
font-weight: 500;
height: 35px;
line-height: 35px;
color: #333333;
margin-bottom: 20px;
}
.titleBox {
display: flex;
justify-content: space-between;
}
.btnSelect {
margin-top: 30px;
}
.toolBox {
padding-bottom: 10px;
.modelTit {
font-size: 14px;
color: #333333;
margin-top: 10px;
margin-bottom: 10px;
}
.itemBox {
label {
font-size: 14px;
color: #666666;
height: 40px;
line-height: 40px;
}
margin-bottom: 15px;
}
.imgListBox {
margin-top: 30px;
.item {
border: 1px solid #e8eaec;
border-radius: 4px;
margin-bottom: 10px;
}
.listItemBox {
.addImgTit {
padding: 10px;
display: flex;
justify-content: space-between;
align-items: center;
background: #f6f7f9;
cursor: pointer;
.titLeft {
display: flex;
align-items: center;
span {
color: #7d7e80;
}
span:nth-child(1) {
font-size: 28px;
}
span:nth-child(2) {
font-size: 25px;
margin: 0 6px;
}
span:nth-child(3) {
font-size: 14px;
}
}
.titRight {
display: flex;
align-items: center;
span:nth-child(1) {
width: 40px;
text-align: center;
display: block;
height: 30px;
line-height: 30px;
}
}
}
.addContent {
padding: 5px 13px;
.imgIsShow {
display: flex;
justify-content: space-between;
margin: 18px 0 22px 0;
span {
font-size: 14px;
color: #666666;
}
}
.deleteItem {
border-radius: 4px;
background: $mainColor;
text-align: center;
height: 36px;
color: #ffffff;
font-size: 14px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
margin-bottom: 10px;
span {
font-size: 18px;
color: #ffffff;
margin-right: 5px;
}
}
}
.deleteItem {
padding: 10px;
display: flex;
align-items: center;
justify-content: center;
background: #f6f7f9;
cursor: pointer;
color: $mainColor;
font-size: 14px;
span {
font-size: 16px;
margin-right: 5px;
}
}
}
}
.textTit {
height: 35px;
line-height: 35px;
font-size: 16px;
color: #333333;
font-weight: bold;
}
}
>>> .el-select {
width: 100%;
}
.addImgBtn {
border-radius: 4px;
background: $mainColor;
text-align: center;
height: 36px;
color: #ffffff;
font-size: 14px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
margin-bottom: 30px;
span {
font-size: 20px;
margin-right: 5px;
}
}
.labelList {
.addLabelBox {
padding: 10px;
}
}
}
</style>
n
@@ -0,0 +1,325 @@
<template>
<div class="brandListTool">
<h3 class="toolTit">品牌列表</h3>
<div class="toolBox">
<div class="itemBox">
<label>标题</label>
<el-input v-model="activeComponent.componentContent.title" placeholder="请输入内容"></el-input>
</div>
<div class="itemBox">
<label>文字对齐方式</label>
<el-select :popper-append-to-body="false" v-model="activeComponent.componentContent.textAlign" placeholder="请选文字对齐方式">
<el-option
v-for="item in alignList"
:key="item.id"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</div>
<div class="textTit">内容</div>
<div class="imgListBox">
<draggable v-model="activeComponent.componentContent.imgList">
<div v-for="(item, index) in activeComponent.componentContent.imgList" :key="index" class="item">
<div class="listItemBox">
<div class="addImgTit" @click="openAddImg(item, index)">
<div class="titLeft">
<span class="iconfont">&#xe703;</span>
<span class="iconfont">&#xe64a;</span>
<span>图片</span>
</div>
<div class="titRight">
<span class="iconfont" @click.stop="deleteItem(item, index)">&#xe633;</span>
<span v-html="activeComponent.componentContent.imgCurrent === index ? '&#xe660;' : '&#xe695;'" class="iconfont"></span>
</div>
</div>
<div class="addBox" v-show="activeComponent.componentContent.imgCurrent === index">
<div class="addContent">
<tool-single-img :imageUrl.sync='item.imgData'></tool-single-img>
<tool-select-link :linkObj.sync='item.linkObj'></tool-select-link>
<div class="itemImgTit itemBox">
<label>标题</label>
<el-input v-model="item.title" placeholder="请输入内容"></el-input>
</div>
</div>
<div @click="deleteItem(item, index)" class="deleteItem"><span class="iconfont">&#xe633;</span>删除内容</div>
</div>
</div>
</div>
</draggable>
</div>
</div>
<div class="addImgBtn" @click="addImgText"><span class="iconfont">&#xe64a;</span>添加品牌图</div>
<el-dialog
title="提示"
:visible.sync="dialogVisible"
width="30%"
:before-close="deleteItem">
<span>点击确定删除此项</span>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false"> </el-button>
<el-button type="primary" @click="dialogVisible = false"> </el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import Draggable from 'vuedraggable'
import { toolMixin } from '@/mixins/tool.js'
import ToolSelectLink from '@/views/theme/components/rootcompToolbar/toolModule/tool-select-link.vue'
import ToolSingleImg from '@/views/theme/components/rootcompToolbar/toolModule/tool-single-img.vue'
export default {
mixins: [toolMixin],
name: 'brandListTool',
components: {
ToolSingleImg,
ToolSelectLink,
Draggable
},
data () {
return {
title: '', // 标题内容
imgTextData: [
{
title: '',
imgData: '',
url: ''
}
],
alignList: [
{
id: 1,
label: '居左',
value: 'left'
},
{
id: 2,
label: '居中',
value: 'center'
},
{
id: 3,
label: '居右',
value: 'right'
}
],
linkOptions: [
{
value: '/index',
label: '首页'
},
{
value: '/list',
label: '列表页'
},
{
value: '/detail',
label: '详情页'
},
{
value: '/about',
label: '关于我们'
}
],
textAlign: 'left',
imgCurrent: null,
dialogVisible: false
}
},
methods: {
openAddImg (item, index) {
if (this.activeComponent.componentContent.imgCurrent === index) {
this.activeComponent.componentContent.imgCurrent = null
return false
}
this.activeComponent.componentContent.imgCurrent = index
},
// 添加图文
addImgText () {
this.activeComponent.componentContent.imgList.push({
title: '标题',
imgData: '',
url: ''
})
},
// 删除内容
deleteItem (item, index) {
this.$confirm('确定删除此项?')
.then(_ => {
this.activeComponent.componentContent.imgList.splice(index, 1)
})
.catch(_ => {})
},
handleAvatarSuccess (res, file) {
this.imageUrl = URL.createObjectURL(file.raw)
},
beforeAvatarUpload (file) {
},
onEditorBlur () { // 失去焦点事件
},
onEditorFocus () { // 获得焦点事件
},
onEditorChange () { // 内容改变事件
}
}
}
</script>
<style lang="scss" scoped>
.brandListTool {
padding: 20px 20px 0px 20px;
h3 {
font-size: 18px;
font-weight: 500;
height: 35px;
line-height: 35px;
color: #333333;
margin-bottom: 20px;
}
.toolBox {
padding-bottom: 10px;
.itemBox {
label {
font-size: 14px;
color: #666666;
height: 40px;
line-height: 40px;
}
margin-bottom: 15px;
}
.imgListBox {
margin-top: 30px;
.item {
border: 1px solid #E8EAEC;
border-radius: 4px;
margin-bottom: 10px;
}
.listItemBox {
.addImgTit {
padding: 10px;
display: flex;
justify-content: space-between;
align-items: center;
background: #F6F7F9;
cursor: pointer;
.titLeft {
display: flex;
align-items: center;
span {
color: #7D7E80;
}
span:nth-child(1) {
font-size: 28px;
}
span:nth-child(2) {
font-size: 25px;
margin: 0 6px;
}
span:nth-child(3) {
font-size: 14px;
}
}
.titRight {
display: flex;
align-items: center;
span:nth-child(1) {
width: 40px;
text-align: center;
display: block;
height: 30px;
line-height: 30px;
}
}
}
.addContent {
padding: 5px 13px;
.imgIsShow {
display: flex;
justify-content: space-between;
margin: 18px 0 22px 0;
span {
font-size: 14px;
color: #666666;
}
}
.addImgBox {
margin-bottom: 10px;
>>> .el-upload {
width: 100%;
.el-upload-dragger {
width: 100%;
}
}
.uploadTip {
text-align: center;
font-size: 14px;
color: #999999;
line-height: 25px;
margin-bottom: 10px;
}
}
.deleteItem {
border-radius: 4px;
background: $mainColor;
text-align: center;
height: 36px;
color: #ffffff;
font-size: 14px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
margin-bottom: 10px;
span {
font-size: 18px;
color: #ffffff;
margin-right: 5px;
}
}
}
.deleteItem {
padding: 10px;
display: flex;
align-items: center;
justify-content: center;
background: #F6F7F9;
cursor: pointer;
color: $mainColor;
font-size: 14px;
span {
font-size: 16px;
margin-right: 5px;
}
}
}
}
.textTit {
height: 35px;
line-height: 35px;
font-size: 16px;
color: #333333;
font-weight: bold;
}
}
>>> .el-select {
width: 100%;
}
.addImgBtn {
border-radius: 4px;
background: $mainColor;
text-align: center;
height: 36px;
color: #ffffff;
font-size: 14px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
span {
font-size: 20px;
margin-right: 5px;
}
}
}
</style>
@@ -0,0 +1,446 @@
<template>
<div class="categoryTool">
<h3 class="toolTit">类别列表</h3>
<div class="toolBox">
<div class="itemBox">
<label>标题</label>
<el-input v-model="activeComponent.componentContent.title" placeholder="请输入内容"></el-input>
</div>
<div class="itemBox">
<label>文字对齐方式</label>
<el-select :popper-append-to-body="false" v-model="activeComponent.componentContent.textAlign" placeholder="请选文字对齐方式">
<el-option
v-for="item in alignList"
:key="item.id"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</div>
<div class="textTit">添加类别</div>
<div class="categoryListBox">
<draggable v-model="activeComponent.componentContent.categoryData">
<div v-for="(item, index) in activeComponent.componentContent.categoryData" :key="index" class="item">
<div class="listItemBox">
<div class="addImgTit" @click="openAddCategory(item, index)">
<div class="titLeft">
<span class="iconfont">&#xe703;</span>
<span class="iconfont">&#xe64a;</span>
<span>类别</span>
</div>
<div class="titRight">
<span class="iconfont" @click.stop="deleteItem(item, index)">&#xe633;</span>
<span v-html="categoryCurrent === index ? '&#xe660;' : '&#xe695;'" class="iconfont"></span>
</div>
</div>
<div class="addBox" v-show="categoryCurrent === index">
<div class="addContent">
<div v-if="item.name === ''" class="addCategoryBox" @click="addItemCategory(item, index)"><span class="iconfont">&#xe685;</span>添加类别</div>
<div v-else class="categoryName">
<span>{{item.name}}</span>
<div class="operation">
<span class="iconfont" @click="replaceCategory">&#xe66c;</span>
<span class="iconfont" @click="deleteCategory(index)">&#xe633;</span>
</div>
</div>
</div>
<div @click="deleteItem(item, index)" class="deleteItem"><span class="iconfont">&#xe633;</span>删除内容</div>
</div>
</div>
</div>
</draggable>
</div>
</div>
<div class="addImgBtn" v-show="activeComponent.componentContent.categoryData.length < 6" @click="addCategory"><span class="iconfont">&#xe64a;</span>添加类别</div>
<div class="addImgBtn" v-show="activeComponent.componentContent.categoryData.length === 6"><span class="iconfont">&#xe608;</span>最多只能添加6个</div>
<el-dialog
title="提示"
:visible.sync="dialogVisible"
width="30%"
:before-close="deleteItem">
<span>点击确定删除此项</span>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false"> </el-button>
<el-button type="primary" @click="dialogVisible = false"> </el-button>
</span>
</el-dialog>
<el-dialog title="选择类别" :visible.sync="dialogCategory" width="480px">
<div class="classList">
<div class="classTit">
<span>类别名称</span>
<span>数量</span>
</div>
<div class="classListBox">
<div class="classItemBox" v-for="(item, index) of categoryList" :key="item.id" @click="selectCategory(item, index)">
<span class="iconfont" v-html="currentCategory === index ? '&#xe661;' : '&#xe618;'"></span>
<div><span>{{item.name}}</span><span>{{item.num}}</span></div>
</div>
</div>
</div>
<div class="addSelectItem" @click="addCategoryData"><span>添加类别</span></div>
</el-dialog>
</div>
</template>
<script>
import Draggable from 'vuedraggable'
import { toolMixin } from '@/mixins/tool.js'
export default {
name: 'categoryTool',
mixins: [toolMixin],
components: {
Draggable
},
data () {
return {
title: '', // 标题内容
alignList: [
{
id: 1,
label: '居左',
value: 'left'
},
{
id: 2,
label: '居中',
value: 'center'
},
{
id: 3,
label: '居右',
value: 'right'
}
],
categoryList: [
{
id: '1',
name: '标签1',
num: '6'
},
{
id: '2',
name: '标签2',
num: '5'
},
{
id: '3',
name: '标签3',
num: '6'
},
{
id: '4',
name: '标签4',
num: '3'
},
{
id: '5',
name: '标签5',
num: '2'
},
{
id: '6',
name: '标签6',
num: '4'
}
],
textAlign: 'left',
categoryCurrent: null,
dialogVisible: false,
dialogCategory: false,
currentCategory: null,
selClassName: ''
}
},
methods: {
openAddCategory (item, index) {
if (this.categoryCurrent === index) {
this.categoryCurrent = null
return false
}
this.categoryCurrent = index
},
// 添加类别
addCategory () {
this.activeComponent.componentContent.categoryData.push({
name: '',
value: '',
img: ''
})
},
// 删除内容
deleteItem (item, index) {
this.$confirm('确定删除此项?')
.then(_ => {
this.activeComponent.componentContent.categoryData.splice(index, 1)
})
.catch(_ => {})
},
addItemCategory (item, index) {
this.dialogCategory = true
},
// 替换类别
replaceCategory (index) {
this.dialogCategory = true
},
// 删除已选类别
deleteCategory (index) {
this.activeComponent.componentContent.categoryData[index].name = ''
},
// 选择类别
selectCategory (item, index) {
if (this.currentCategory === index) {
this.currentCategory = null
this.selClassName = ''
} else {
this.selClassName = item.name
this.currentCategory = index
}
},
// 添加类别
addCategoryData () {
if (this.selClassName !== '') {
this.activeComponent.componentContent.categoryData[this.categoryCurrent].name = this.selClassName
this.dialogCategory = false
}
}
}
}
</script>
<style lang="scss" scoped>
.categoryTool {
padding: 20px 20px 0 20px;
h3 {
font-size: 18px;
font-weight: 500;
height: 35px;
line-height: 35px;
color: #333333;
margin-bottom: 20px;
}
.toolBox {
padding-bottom: 10px;
.textTit {
height: 35px;
line-height: 35px;
font-size: 16px;
color: #333333;
font-weight: bold;
}
.itemBox {
label {
font-size: 14px;
color: #666666;
height: 40px;
line-height: 40px;
}
margin-bottom: 15px;
}
}
>>> .ql-container {
height: 200px;
}
.categoryListBox {
margin-top: 30px;
.item {
border: 1px solid #E8EAEC;
border-radius: 4px;
margin-bottom: 10px;
}
.listItemBox {
.addImgTit {
padding: 10px;
display: flex;
justify-content: space-between;
align-items: center;
background: #F6F7F9;
cursor: pointer;
.titLeft {
display: flex;
align-items: center;
span {
color: #7D7E80;
}
span:nth-child(1) {
font-size: 28px;
}
span:nth-child(2) {
font-size: 25px;
margin: 0 6px;
}
span:nth-child(3) {
font-size: 14px;
}
}
.titRight {
display: flex;
align-items: center;
span:nth-child(1) {
width: 40px;
text-align: center;
display: block;
height: 30px;
line-height: 30px;
}
}
}
.addContent {
padding: 13px;
.addCategoryBox {
width: 100%;
height: 35px;
display: flex;
align-items: center;
justify-content: center;
color: #ffffff;
background: $mainColor;
border-radius: 4px;
margin: 15px 0;
cursor: pointer;
}
.deleteItem {
border-radius: 4px;
background: $mainColor;
text-align: center;
height: 36px;
color: #ffffff;
font-size: 14px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
margin-bottom: 10px;
span {
font-size: 18px;
color: #ffffff;
margin-right: 5px;
}
}
.categoryName {
height: 35px;
display: flex;
align-items: center;
background: #e9e9e9;
padding: 0 10px;
justify-content: space-between;
span {
color: #333333;
}
span {
color: #333333;
}
.operation {
display: flex;
span {
width: 35px;
display: block;
height: 35px;
line-height: 35px;
text-align: center;
cursor: pointer;
}
}
}
}
.deleteItem {
padding: 10px;
display: flex;
align-items: center;
justify-content: center;
background: #F6F7F9;
cursor: pointer;
color: $mainColor;
font-size: 14px;
span {
font-size: 16px;
margin-right: 5px;
}
}
}
}
.addImgBtn {
border-radius: 4px;
background: $mainColor;
text-align: center;
height: 36px;
color: #ffffff;
font-size: 14px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
span {
font-size: 20px;
margin-right: 5px;
}
}
.classList {
.classTit {
display: flex;
justify-content: space-between;
height: 50px;
align-items: center;
padding:0 20px;
background: #eeeeee;
span {
display: block;
width: 100px;
text-align: center;
}
}
.classListBox {
max-height: 300px;
overflow-y: auto;
.classItemBox {
display: flex;
padding: 0 20px;
align-items: center;
border-bottom: 1px solid #eeeeee;
div {
display: flex;
flex: 1;
justify-content: space-between;
height: 50px;
align-items: center;
span:nth-child(1) {
padding-left: 5px;
}
span {
display: block;
width: 100px;
text-align: left;
}
span:nth-child(2) {
text-align: center;
}
}
}
}
}
>>> .el-dialog__body {
padding: 0;
.addSelectItem {
width: 100%;
background: #f3f4f5;
text-align: right;
padding: 10px;
span {
display: inline-block;
width: 100px;
text-align: center;
color: #ffffff;
padding: 16px;
border-radius: 4px;
background: $mainColor;
cursor: pointer;
}
}
}
}
>>> .el-dialog {
border-radius: 4px;
}
>>> .el-select {
width: 100%;
}
</style>
@@ -0,0 +1,345 @@
<template>
<div class="couponTool">
<h3 class="toolTit">优惠券</h3>
<div class="toolBox">
<!--<tool-coupon></tool-coupon>-->
<div class="block topLine">
<div class="blockTit">
<span>排列样式</span>
<span>{{composeData[activeComponent.componentContent.arrangeActiveIndex].name}}</span>
</div>
<div class="selectCompose">
<div class="composeList">
<span class="item iconfont" :class="{active: activeComponent.componentContent.arrangeActiveIndex === index}" @click="selectCompose(item, index)" v-for="(item, index) of composeData" :key="item.id" v-html="item.Icon"></span>
</div>
</div>
</div>
<div class="block">
<div class="blockTit">
<span>卡片样式</span>
<span>{{cardType[activeComponent.componentContent.cardActiveIndex].name}}</span>
</div>
<div class="selectCompose">
<div class="composeList">
<span class="item iconfont" :class="{active: activeComponent.componentContent.cardActiveIndex === index}" @click="selectCard(item, index)" v-for="(item, index) of cardType" :key="item.id" v-html="item.Icon"></span>
</div>
</div>
</div>
<div class="block colorBox">
<div class="blockTit">
<span>颜色</span>
<span>{{colorList[activeComponent.componentContent.colorActiveIndex].name}}</span>
</div>
<div class="selectColor">
<div class="selectColor">
<div class="colorList">
<div :class="{active: activeComponent.componentContent.colorActiveIndex === index}" v-for="(item, index) of colorList" :key="item.value" @click="selectColor(item, index)"><span></span></div>
</div>
</div>
</div>
</div>
<div class="block showInvBox">
<div class="showInvalid">
<div class="blockTit">
<span>隐藏已抢完及失效的券</span>
<span v-text="isHideCoupon ? '隐藏' : '显示'"></span>
</div>
<div class="showHideBtn">
<el-checkbox v-model="isHideCoupon"></el-checkbox>
</div>
</div>
<p>当前无可显示的优惠券时优惠券区块将隐藏</p>
</div>
</div>
</div>
</template>
<script>
import { toolMixin } from '@/mixins/tool.js'
import ToolCoupon from '@/views/theme/components/rootcompToolbar/toolModule/tool-coupon.vue'
export default {
name: 'couponTool',
mixins: [toolMixin],
components: {
ToolCoupon
},
data () {
return {
title: '', // 标题内容
composeData: [
{
id: 1,
type: 'L1',
name: '一行一个',
Icon: '&#xe603'
},
{
id: 2,
type: 'L2',
name: '一行两个',
Icon: '&#xe603'
},
{
id: 3,
type: 'L3',
name: '一行三个',
Icon: '&#xe603'
},
{
id: 4,
type: 'L4',
name: '横向滑动',
Icon: '&#xe603;'
}
],
// 卡片样式
cardType: [
{
id: 1,
type: 'type1',
name: '样式一',
Icon: '&#xe61f;'
},
{
id: 2,
type: 'type2',
name: '样式二',
Icon: '&#xe645;'
},
{
id: 3,
type: 'type3',
name: '样式三',
Icon: '&#xe66d;'
},
{
id: 4,
type: 'type4',
name: '样式四',
Icon: '&#xe692;'
}
// {
// id: 5,
// type: 'type5',
// name: '样式五',
// Icon: '&#xe6cf;'
// },
// {
// id: 6,
// type: 'type6',
// name: '样式六',
// Icon: '&#xe60b;'
// },
// {
// id: 7,
// type: 'type7',
// name: '样式七',
// Icon: '&#xe624;'
// },
// {
// id: 8,
// type: 'type8',
// name: '样式八',
// Icon: '&#xe625;'
// }
],
colorList: [
{
name: '红色',
value: 'red'
},
{
name: '蓝色',
value: 'blue'
},
{
name: '绿色',
value: 'green'
},
{
name: '粉红色',
value: 'pink'
},
{
name: '灰色',
value: 'grey'
}
],
// arrangeActiveIndex: 0,
// cardActiveIndex: 0,
// colorActiveIndex: 0,
dialogVisible: false,
isHideCoupon: true
}
},
computed: {
},
methods: {
selectCompose (item, index) {
this.activeComponent.componentContent.arrangeActiveIndex = index
},
// 选择卡片样式
selectCard (item, index) {
this.activeComponent.componentContent.cardActiveIndex = index
},
selectColor (item, index) {
this.activeComponent.componentContent.colorActiveIndex = index
}
}
}
</script>
<style lang="scss" scoped>
.couponTool {
padding: 20px 20px 0 20px;
h3 {
font-size: 18px;
font-weight: 500;
height: 35px;
line-height: 35px;
color: #333333;
margin-bottom: 20px;
}
.toolBox {
padding-bottom: 10px;
.itemBox {
label {
font-size: 14px;
color: #666666;
height: 40px;
line-height: 40px;
}
margin-bottom: 15px;
}
}
.block {
.blockTit {
padding-top: 20px;
span {
margin-right: 16px;
}
span:last-child {
color: $mainColor;
}
}
}
.colorBox {
display: flex;
justify-content: space-between;
align-items: center;
.blockTit {
padding-top: 0;
}
}
.topLine {
border-top: 1px solid #eeeeee;
}
.composeList {
display: flex;
flex-direction: row;
flex-wrap: wrap;
margin-bottom: 30px;
padding-top: 20px;
span {
width: 50px;
height: 30px;
display: flex;
align-items: center;
justify-content: center;
border: 1px solid #E8EAEC;
color: #999999;
font-size: 18px;
text-align: center;
cursor: pointer;
}
span.active {
color: $mainColor;
border: 1px solid $mainColor;
}
span:hover {
color: $mainColor;
border: 1px solid $mainColor;
}
}
.selectColor {
display: flex;
align-items: center;
.colorList {
display: flex;
align-items: center;
div {
padding: 3px;
border: 1px solid #eeeeee;
border-radius: 50%;
font-style: normal;
margin-right: 10px;
cursor: pointer;
span {
width: 15px;
height: 15px;
border-radius: 50%;
background: #eeeeee;
display: block;
}
&:nth-child(1) {
span {
background: #FF3737;
}
}
&:nth-child(2) {
span {
background: #86A7FF;
}
}
&:nth-child(3) {
span {
background: #98D4CB;
}
}
&:nth-child(4) {
span {
background: #FF8888;
}
}
&:nth-child(5) {
span {
background: #AFAFAF;
}
}
}
div.active {
&:nth-child(1) {
border-color: #FF3737;
}
&:nth-child(2) {
border-color: #86A7FF;
}
&:nth-child(3) {
border-color: #98D4CB;
}
&:nth-child(4) {
border-color: #FF8888;
}
&:nth-child(5) {
border-color: #AFAFAF;
}
}
}
}
.showInvBox {
p {
color: #999999;
font-size: 14px;
}
}
.showInvalid {
display: flex;
justify-content: space-between;
align-items: center;
margin: 20px 0 13px 0;
.blockTit {
padding-top: 0;
}
}
}
</style>
@@ -0,0 +1,964 @@
<template>
<div class="customTool">
<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="{
L3: activeComponent.componentContent.layoutType === 'L3',
L4: activeComponent.componentContent.layoutType === 'L4',
T2B2: activeComponent.componentContent.layoutType === 'T2B2',
L1R2: activeComponent.componentContent.layoutType === 'L1R2',
T1B2: activeComponent.componentContent.layoutType === 'T1B2',
L1T1B2: activeComponent.componentContent.layoutType === 'L1T1B2',
average: activeComponent.componentContent.layoutType === 'average'}" >
<div class="item"
:class="{active: activeComponent.componentContent.imgBoxActive === index-1}"
@click="changeLayout(index-1)"
v-for="index of activeComponent.componentContent.elementNum"
:key="index">
<!--<span>宽度375像素</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-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}"
@click="changeLayout(index)"
:key="index"
:style="{
'width':getItemValue(item.width) + '%',
'height':getItemValue(item.height) + '%',
'left':getItemValue(item.left) + '%',
'top':getItemValue(item.top) + '%'}">
<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">
<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
action="#"
:show-file-list="false"
:on-change="imgChange"
:auto-upload="false">
<img class="avatar"
v-if="activeComponent.componentContent.imgData[activeComponent.componentContent.imgBoxActive].src"
:src="activeComponent.componentContent.imgData[activeComponent.componentContent.imgBoxActive].src" >
<div class="tips"
v-if="activeComponent.componentContent.imgData[activeComponent.componentContent.imgBoxActive].src" >更换图片</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 { toolMixin } from '@/mixins/tool.js'
import ToolSelectLink from '@/views/theme/components/rootcompToolbar/toolModule/tool-select-link.vue'
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: 1,
type: 'L2',
name: '一行二个',
number: 2, // 显示格子数
Icon: '&#xe603'
},
{
id: 2,
type: 'L3',
name: '一行三个',
number: 3,
Icon: '&#xe603'
},
{
id: 3,
type: 'L4',
name: '一行四个',
number: 4,
Icon: '&#xe603'
},
{
id: 4,
type: 'T2B2',
name: '二左二右',
number: 4,
Icon: '&#xe603;'
},
{
id: 5,
type: 'L1R2',
name: '一左二右',
number: 3,
Icon: '&#xe603'
},
{
id: 6,
type: 'T1B2',
name: '一上二下',
number: 3,
Icon: '&#xe603'
},
{
id: 7,
type: 'L1T1B2',
name: '一左三右',
number: 4,
Icon: '&#xe603'
},
{
id: 8,
type: 'average',
name: '自定义',
number: 0,
Icon: '&#xe603'
}
],
activeLay: 0,
elementNum: 2, // 生成格子数量
// layoutType: 'L2',
// density: '4',
// averageBoxData: [], // 记录格子的激活状态
beginAverageBox: [], // 记录开始点击的格子
endAverageBox: [], // 记录结束点击的格子
imgData: [] // 图片数据
}
},
computed: {
selectTemplateName () {
for (let i = 0; i < this.layoutList.length; i++) {
if (this.layoutList[i].type === this.activeComponent.componentContent.layoutType) {
return this.layoutList[i].name
}
}
}
},
methods: {
// 计算生成格子百分比
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.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.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
}
if (y >= by) {
obj.height = y - by + 1
obj.top = by
} else {
obj.height = by - y + 1
obj.top = y
}
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
console.log('111')
// 起终点中间位置激活
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
}
}
console.log(this.activeComponent.componentContent.averageBoxData)
},
// 删除选中格子
delsSlectedCube (item, index) {
console.log(this.activeComponent.componentContent.imgData)
// 清除占用位置
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.imgData.splice(index, 1)
}
},
watch: {
// 'activeComponent.componentContent.elementNum': function (val) {
// this.activeComponent.componentContent.imgData = []
// if (this.activeComponent.componentContent.layoutType !== 'average') {
// let obj = {
// src: '',
// link: ''
// }
// for (let i = 0; i < val; i++) {
// this.activeComponent.componentContent.imgData.push(JSON.parse(JSON.stringify(obj)))
// }
// }
// }
}
}
</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;
}
>>> .el-slider__input {
width: 50px;
}
>>> .el-slider__runway {
height: 4px;
margin: 18px 65px 18px 0;
}
>>> .el-slider__bar {
height: 4px;
}
>>> .el-slider__button-wrapper {
top: -17px;
}
>>> .el-slider__button {
width: 12px;
height: 12px;
}
>>> .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: 142px;
border: 1px solid #E8EAEC;
box-sizing: border-box;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
position: relative;
&:before {
content: '600像素';
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;
}
}
}
}
.L3 {
.item {
flex: 0 0 33.3%;
height: 93px;
&:before {
content: '400像素';
}
}
}
.L4 {
.item {
flex:0 0 25%;
height: 71px;
&:before {
content: '300像素';
}
}
}
.T2B2 {
flex-wrap: wrap;
.item {
flex: 0 0 50%;
height: 142px;
&:before {
content: '600x600像素';
}
}
}
.L1R2 {
flex-wrap: wrap;
.item{
&:before {
content: '600x600像素';
}
}
.item:nth-child(1) {
height: 284px;
&:before {
content: '600x1200像素';
}
}
.item:nth-child(3) {
margin-left: 138px;
margin-top: -143px;
}
}
.T1B2 {
flex-wrap: wrap;
.item{
&:before {
content: '600x600像素';
}
}
.item:nth-child(1) {
flex: 0 0 100%;
&:before {
content: '1200x600像素';
}
}
}
.L1T1B2 {
flex-wrap: wrap;
.item{
&:before {
content: '300x300像素';
}
}
.item:nth-child(1) {
&:before {
content: '600x600像素';
}
}
.item:nth-child(2) {
height: 72px;
&:before {
content: '600x300像素';
}
}
.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;
padding: 10px;
box-sizing: border-box;
position: relative;
padding-bottom: 50px;
.addImgBoxInner{
background: #F6F7F9;
display: flex;
}
.addImg {
width: 60px;
height: 60px;
margin-right: 10px;
>>> .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 {
>>> .link-select{
display: flex;
margin-bottom: 0;
line-height: 60px;
.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;
}
}
}
}
.selectedCube{
li{
position: absolute;
display: flex;
justify-content: center;
align-items: center;
font-size: 12px;
border: 1px solid #E8EAEC;
background-color: #fff;
z-index: 2;
margin: -1px 0 0 -1px;
box-sizing: content-box;
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;
}
}
}
</style>
@@ -0,0 +1,223 @@
<template>
<div class="imageTextTool">
<h3 class="toolTit">图文</h3>
<div class="toolBox">
<tool-single-img :imageUrl.sync='activeComponent.componentContent.imageUrl'></tool-single-img>
<tool-select-link :linkObj.sync='activeComponent.componentContent.linkObj' title="图片链接"></tool-select-link>
<tool-select :linkValue.sync='activeComponent.componentContent.positionValue' title="PC图片位置" :options="positionOpt"></tool-select>
<div class="textTit">文本设置</div>
<div class="itemBox">
<label>标题</label>
<el-input v-model="activeComponent.componentContent.title" placeholder="请输入内容"></el-input>
</div>
<div class="itemBox">
<label>正文</label>
<quill-editor
v-model="activeComponent.componentContent.content"
ref="myQuillEditor"
:options="editorOption"
@blur="onEditorBlur($event)" @focus="onEditorFocus($event)"
@change="onEditorChange($event)">
</quill-editor>
</div>
</div>
<el-dialog :visible.sync="dialogVisible">
<img width="100%" :src="dialogImageUrl" alt="">
</el-dialog>
</div>
</template>
<script>
import { quillEditor } from 'vue-quill-editor'
import { toolMixin } from '@/mixins/tool.js'
import ToolSelectLink from '@/views/theme/components/rootcompToolbar/toolModule/tool-select-link.vue'
import ToolSingleImg from '@/views/theme/components/rootcompToolbar/toolModule/tool-single-img.vue'
import ToolSelect from '@/views/theme/components/rootcompToolbar/toolModule/tool-select.vue'
export default {
name: 'videoTool',
mixins: [toolMixin],
components: {
ToolSelectLink,
ToolSelect,
ToolSingleImg,
quillEditor
},
data () {
return {
// imageUrl: '',
// title: '', // 标题内容
// linkValue: '',
// positionValue: '',
// content: null,
dialogVisible: false,
dialogImageUrl: '',
linkOptions: [
{
value: '/index',
label: '首页'
},
{
value: '/list',
label: '列表页'
},
{
value: '/detail',
label: '详情页'
},
{
value: '/about',
label: '关于我们'
}
],
positionOpt: [
{
value: 'left',
label: '左图右文'
},
{
value: 'right',
label: '右图左文'
}
// {
// value: 'top',
// label: '上图下文'
// },
// {
// value: 'bottom',
// label: '下图上文'
// }
],
editorOption: {
placeholder: '请输入',
modules: {
toolbar: [
['bold', 'italic', 'link'] // toggled buttons
]
}
}
}
}
}
</script>
<style lang="scss" scoped>
.imageTextTool {
padding: 20px 20px 0 20px;
h3 {
font-size: 18px;
font-weight: 500;
height: 35px;
line-height: 35px;
color: #333333;
margin-bottom: 20px;
}
.toolBox {
padding-bottom: 10px;
.textTit {
height: 35px;
line-height: 35px;
font-size: 16px;
color: #333333;
margin-top: 30px;
font-weight: bold;
}
.itemBox {
label {
font-size: 14px;
color: #666666;
height: 40px;
line-height: 40px;
}
margin-bottom: 15px;
>>> .el-select {
display: block;
}
}
.imgBox{
position: relative;
.overlay{
display: none;
}
&:hover .overlay{
position: absolute;
top:0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0,0,0,0.3);
color: #fff;
display: flex;
justify-content: center;
align-items: center;
.iconfont{
padding: 5px;
margin: 0 5px;
font-size: 20px;
cursor: pointer;
}
}
}
}
>>> .ql-container {
height: 150px;
}
>>> .avatar-uploader .el-upload {
border: 1px dashed #d9d9d9;
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
}
>>> .avatar-uploader-icon {
font-size: 28px;
color: #8c939d;
width: 178px;
height: 178px;
line-height: 178px;
text-align: center;
}
>>> .el-upload__tip {
height: auto;
margin-top: 0;
line-height: normal;
}
>>> .el-upload {
width: 100%;
}
>>> .el-upload-dragger {
width: 100%;
position: relative;
.avatar{
max-width: 100%;
height: 100%;
max-height: 100%;
position: absolute;
margin: auto;
top: 0;
right: 0;
bottom: 0;
left: 0;
}
}
>>> .ql-snow .ql-tooltip{
z-index: 8;
left: 5px!important;
}
>>> .ql-snow .ql-tooltip::before{
content: '链接';
}
>>> .ql-snow .ql-tooltip a.ql-action::after{
content: '编辑';
}
>>> .ql-snow .ql-tooltip a.ql-remove::before{
content: '移除';
}
>>> .ql-snow .ql-tooltip[data-mode=link]::before{
content: '链接';
}
>>> .ql-snow .ql-tooltip.ql-editing a.ql-action::after{
content: '确定';
}
}
</style>
@@ -0,0 +1,322 @@
<template>
<div class="brandListTool">
<h3 class="toolTit">图文列表</h3>
<div class="toolBox">
<div class="itemBox">
<label>标题</label>
<el-input v-model="activeComponent.componentContent.title" placeholder="请输入内容"></el-input>
</div>
<div class="itemBox">
<label>文字对齐方式</label>
<el-select :popper-append-to-body="false" v-model="activeComponent.componentContent.textAlign" placeholder="请选文字对齐方式">
<el-option
v-for="item in alignList"
:key="item.id"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</div>
<div class="textTit">内容</div>
<div class="imgListBox">
<draggable v-model="activeComponent.componentContent.imgTextData">
<div v-for="(item, index) in activeComponent.componentContent.imgTextData" :key="index" class="item">
<div class="listItemBox">
<div class="addImgTit" @click="openAddImg(item, index)">
<div class="titLeft">
<span class="iconfont">&#xe703;</span>
<span class="iconfont">&#xe64a;</span>
<span>图片</span>
</div>
<div class="titRight">
<span class="iconfont" @click.stop="deleteItem(item, index)">&#xe633;</span>
<span v-html="imgCurrent === index ? '&#xe660;' : '&#xe695;'" class="iconfont"></span>
</div>
</div>
<div class="addBox" v-show="imgCurrent === index">
<div class="addContent">
<div class="imgIsShow">
<span>图片是否展示</span>
<el-switch
v-model="item.isShow"
active-color="#FF7800"
inactive-color="#E8EAEC">
</el-switch>
</div>
<tool-single-img :imageUrl.sync='item.imgData'></tool-single-img>
<div class="itemImgTit itemBox">
<label>标题</label>
<el-input v-model="item.title" placeholder="请输入内容"></el-input>
</div>
<div class="itemBox">
<label>描述内容</label>
<el-input
type="textarea"
:rows="2"
placeholder="请输入内容"
resize="none"
v-model="item.describe">
</el-input>
</div>
<tool-select-link :linkObj.sync='item.linkObj'></tool-select-link>
</div>
<div @click="deleteItem(item, index)" class="deleteItem"><span class="iconfont">&#xe633;</span>删除内容</div>
</div>
</div>
</div>
</draggable>
</div>
</div>
<div class="addImgBtn" @click="addImgText"><span class="iconfont">&#xe64a;</span>添加图文</div>
<el-dialog
title="提示"
:visible.sync="dialogVisible"
width="30%"
:before-close="deleteItem">
<span>点击确定删除此项</span>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false"> </el-button>
<el-button type="primary" @click="dialogVisible = false"> </el-button>
</span>
</el-dialog>
<el-dialog :visible.sync="dialogImageVisible">
<img width="100%" :src="dialogImageUrl" alt="">
</el-dialog>
</div>
</template>
<script>
import Draggable from 'vuedraggable'
import { toolMixin } from '@/mixins/tool.js'
import ToolSelectLink from '@/views/theme/components/rootcompToolbar/toolModule/tool-select-link.vue'
import ToolSingleImg from '@/views/theme/components/rootcompToolbar/toolModule/tool-single-img.vue'
export default {
mixins: [toolMixin],
name: 'brandListTool',
components: {
ToolSelectLink,
ToolSingleImg,
Draggable
},
data () {
return {
title: '', // 标题内容
textInfo: '', // 文本
dialogImageVisible: false,
dialogImageUrl: '',
imgTextData: [
{
title: '',
isShow: true,
imgData: '',
describe: '',
url: ''
}
],
alignList: [
{
id: 1,
label: '居左',
value: 'left'
},
{
id: 2,
label: '居中',
value: 'center'
}
],
textAlign: 'left',
imgCurrent: null,
dialogVisible: false
}
},
computed: {
},
methods: {
openAddImg (item, index) {
if (this.imgCurrent === index) {
this.imgCurrent = null
return false
}
this.imgCurrent = index
},
// 添加图文
addImgText () {
this.activeComponent.componentContent.imgTextData.push({
title: '',
isShow: true,
imgData: '',
linkObj: {
selsectValue: '',
selectName: '',
typeText: '',
url: ''
}
})
},
// 删除内容
deleteItem (item, index) {
this.$confirm('确定删除此项?')
.then(_ => {
this.activeComponent.componentContent.imgTextData.splice(index, 1)
})
.catch(_ => {})
},
handleAvatarSuccess (res, file) {
this.imageUrl = URL.createObjectURL(file.raw)
},
imgChange (file, index, key) {
this.activeComponent.componentContent.imgTextData[index][key] = URL.createObjectURL(file.raw)
},
showImage (imgData) {
this.dialogImageUrl = imgData
this.dialogImageVisible = true
},
delImage (index, key) {
this.activeComponent.componentContent.imgTextData[index][key] = ''
}
}
}
</script>
<style lang="scss" scoped>
.brandListTool {
padding: 20px 20px 0px 20px;
h3 {
font-size: 18px;
font-weight: 500;
height: 35px;
line-height: 35px;
color: #333333;
margin-bottom: 20px;
}
.toolBox {
padding-bottom: 10px;
.itemBox {
label {
font-size: 14px;
color: #666666;
height: 40px;
line-height: 40px;
}
margin-bottom: 15px;
}
.imgListBox {
margin-top: 30px;
.item {
border: 1px solid #E8EAEC;
border-radius: 4px;
margin-bottom: 10px;
}
.listItemBox {
.addImgTit {
padding: 10px;
display: flex;
justify-content: space-between;
align-items: center;
background: #F6F7F9;
cursor: pointer;
.titLeft {
display: flex;
align-items: center;
span {
color: #7D7E80;
}
span:nth-child(1) {
font-size: 28px;
}
span:nth-child(2) {
font-size: 25px;
margin: 0 6px;
}
span:nth-child(3) {
font-size: 14px;
}
}
.titRight {
display: flex;
align-items: center;
span:nth-child(1) {
width: 40px;
text-align: center;
display: block;
height: 30px;
line-height: 30px;
}
}
}
.addContent {
padding: 5px 13px;
.imgIsShow {
display: flex;
justify-content: space-between;
margin: 18px 0 22px 0;
span {
font-size: 14px;
color: #666666;
}
}
.deleteItem {
border-radius: 4px;
background: $mainColor;
text-align: center;
height: 36px;
color: #ffffff;
font-size: 14px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
margin-bottom: 10px;
span {
font-size: 18px;
color: #ffffff;
margin-right: 5px;
}
}
}
.deleteItem {
padding: 10px;
display: flex;
align-items: center;
justify-content: center;
background: #F6F7F9;
cursor: pointer;
color: $mainColor;
font-size: 14px;
span {
font-size: 16px;
margin-right: 5px;
}
}
}
}
.textTit {
height: 35px;
line-height: 35px;
font-size: 16px;
color: #333333;
font-weight: bold;
}
}
>>> .el-select {
width: 100%;
}
.addImgBtn {
border-radius: 4px;
background: $mainColor;
text-align: center;
height: 36px;
color: #ffffff;
font-size: 14px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
span {
font-size: 20px;
margin-right: 5px;
}
}
}
</style>
@@ -0,0 +1,370 @@
<template>
<div class="shopTopTool">
<h3 class="toolTit">菜单</h3>
<div class="tabBox">
<div class="toolBox">
<div class="modelTit">图片设置</div>
<div class="imgListBox">
<draggable v-model="activeComponent.componentContent.menus">
<div
v-for="(item, index) in activeComponent.componentContent
.menus"
:key="index"
class="item"
>
<div class="listItemBox">
<div class="addImgTit" @click="openAddImg(item, index)">
<div class="titLeft">
<span class="iconfont">&#xe703;</span>
<span class="iconfont">&#xe64a;</span>
<span>图片</span>
</div>
<div class="titRight">
<span class="iconfont" @click.stop="deleteItem(item, index)">&#xe633;</span>
<span
v-html="imgCurrent === index ? '&#xe660;' : '&#xe695;'"
class="iconfont"></span>
</div>
</div>
<div class="addBox" v-show="imgCurrent === index">
<div class="addContent">
<tool-single-img :imageUrl.sync="item.pic"></tool-single-img>
<div class="modelTit titleBox">菜单名称</div>
<el-input
placeholder="请输入新闻链接"
resize="none"
v-model="activeComponent.componentContent.menus[index].name" />
<div class="modelTit titleBox">跳转地址</div>
<el-input
placeholder="请输入新闻链接"
resize="none"
v-model="activeComponent.componentContent.menus[index].url" />
<div class="modelTit titleBox">uni链接</div>
<el-input
placeholder="请输入uni链接"
resize="none"
v-model="activeComponent.componentContent.menus[index].uniapp_url"/>
<div class="modelTit titleBox">小程序链接</div>
<el-input
placeholder="请输入小程序链接"
resize="none"
v-model="activeComponent.componentContent.menus[index].wxapp_url"/>
</div>
<div @click="deleteItem(item, index)" class="deleteItem">
<span class="iconfont">&#xe633;</span>删除内容
</div>
</div>
</div>
</div>
</draggable>
</div>
<div class="addImgBtn" @click="addImgText">
<span class="iconfont">&#xe64a;</span>添加图文
</div>
</div>
</div>
<el-dialog
title="提示"
:visible.sync="dialogVisible"
width="30%"
:before-close="deleteItem" >
<span>点击确定删除此项</span>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false">取 消</el-button>
<el-button type="primary" @click="dialogVisible = false">确 定</el-button>
</span>
</el-dialog>
<el-dialog :visible.sync="dialogImageVisible">
<img width="100%" :src="dialogImageUrl" alt="" />
</el-dialog>
</div>
</template>
<script>
import Draggable from 'vuedraggable'
import { toolMixin } from '@/mixins/tool.js'
import ToolSelectLink from '@/views/theme/components/rootcompToolbar/toolModule/tool-select-link.vue'
import ToolSelectCategory from '@/views/theme/components/rootcompToolbar/toolModule/tool-select-category.vue'
import ToolSingleImg from '@/views/theme/components/rootcompToolbar/toolModule/tool-single-img.vue'
export default {
name: 'shopTopTool',
mixins: [toolMixin],
components: {
ToolSingleImg,
ToolSelectCategory,
ToolSelectLink,
Draggable
},
data () {
return {
dialogImageVisible: false,
dialogImageUrl: '',
alignList: [
{
id: 1,
label: '居左',
value: 'left'
},
{
id: 2,
label: '居中',
value: 'center'
},
{
id: 3,
label: '居右',
value: 'right'
}
],
textAlign: 'left',
imgCurrent: null,
labelCurrent: null,
dialogVisible: false
}
},
computed: {},
methods: {
// 添加类别
addCategory () {},
openAddImg (item, index) {
if (this.imgCurrent === index) {
this.imgCurrent = null
return false
}
this.imgCurrent = index
},
openAddLabel (item, index) {
if (this.labelCurrent === index) {
this.labelCurrent = null
return false
}
this.labelCurrent = index
},
// 添加图文
addImgText () {
this.activeComponent.componentContent.menus.push({
'uniapp_url': '',
'name': '',
'pic': '',
'url': '',
'wxapp_url': ''
})
},
// 删除内容
deleteItem (item, index) {
this.$confirm('确定删除此项?')
.then((_) => {
this.activeComponent.componentContent.menus.splice(index, 1)
})
.catch((_) => {})
},
// 添加标签
addLabel () {
this.activeComponent.componentContent.labelList.push({
name: '',
url: ''
})
},
// 删除标签
deleteLabelItem (item, index) {
this.$confirm('确定删除此项?')
.then((_) => {
this.activeComponent.componentContent.labelList.splice(index, 1)
})
.catch((_) => {})
},
imgChange (file, index, key) {
this.activeComponent.componentContent.menus[index][key] = URL.createObjectURL(file.raw)
},
showImage (imgData) {
this.dialogImageUrl = imgData
this.dialogImageVisible = true
},
delImage (index, key) {
this.activeComponent.componentContent.menus[index][key] = ''
}
}
}
</script>
<style lang="scss" scoped>
.shopTopTool {
padding: 20px 20px 0px 20px;
.topTit {
display: flex;
justify-content: space-between;
border-bottom: 1px solid #eeeeee;
margin-bottom: 20px;
span {
height: 35px;
line-height: 35px;
font-size: 14px;
color: #333333;
}
span:last-child {
font-weight: bold;
width: 100px;
text-align: center;
cursor: pointer;
&:hover {
color: $mainColor;
}
}
}
h3 {
font-size: 18px;
font-weight: 500;
height: 35px;
line-height: 35px;
color: #333333;
margin-bottom: 20px;
}
.titleBox {
display: flex;
justify-content: space-between;
}
.btnSelect {
margin-top: 30px;
}
.toolBox {
padding-bottom: 10px;
.modelTit {
font-size: 14px;
color: #333333;
margin-top: 10px;
margin-bottom: 10px;
}
.itemBox {
label {
font-size: 14px;
color: #666666;
height: 40px;
line-height: 40px;
}
margin-bottom: 15px;
}
.imgListBox {
margin-top: 30px;
.item {
border: 1px solid #e8eaec;
border-radius: 4px;
margin-bottom: 10px;
}
.listItemBox {
.addImgTit {
padding: 10px;
display: flex;
justify-content: space-between;
align-items: center;
background: #f6f7f9;
cursor: pointer;
.titLeft {
display: flex;
align-items: center;
span {
color: #7d7e80;
}
span:nth-child(1) {
font-size: 28px;
}
span:nth-child(2) {
font-size: 25px;
margin: 0 6px;
}
span:nth-child(3) {
font-size: 14px;
}
}
.titRight {
display: flex;
align-items: center;
span:nth-child(1) {
width: 40px;
text-align: center;
display: block;
height: 30px;
line-height: 30px;
}
}
}
.addContent {
padding: 5px 13px;
.imgIsShow {
display: flex;
justify-content: space-between;
margin: 18px 0 22px 0;
span {
font-size: 14px;
color: #666666;
}
}
.deleteItem {
border-radius: 4px;
background: $mainColor;
text-align: center;
height: 36px;
color: #ffffff;
font-size: 14px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
margin-bottom: 10px;
span {
font-size: 18px;
color: #ffffff;
margin-right: 5px;
}
}
}
.deleteItem {
padding: 10px;
display: flex;
align-items: center;
justify-content: center;
background: #f6f7f9;
cursor: pointer;
color: $mainColor;
font-size: 14px;
span {
font-size: 16px;
margin-right: 5px;
}
}
}
}
.textTit {
height: 35px;
line-height: 35px;
font-size: 16px;
color: #333333;
font-weight: bold;
}
}
>>> .el-select {
width: 100%;
}
.addImgBtn {
border-radius: 4px;
background: $mainColor;
text-align: center;
height: 36px;
color: #ffffff;
font-size: 14px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
margin-bottom: 30px;
span {
font-size: 20px;
margin-right: 5px;
}
}
.labelList {
.addLabelBox {
padding: 10px;
}
}
}
</style>
@@ -0,0 +1,370 @@
<template>
<div class="shopTopTool">
<h3 class="toolTit">滚动新闻</h3>
<div class="tabBox">
<div class="toolBox">
<div class="modelTit">内容设置</div>
<div class="imgListBox">
<draggable v-model="activeComponent.componentContent.roll">
<div
v-for="(item, index) in activeComponent.componentContent.roll"
:key="index"
class="item">
<div class="listItemBox">
<div class="addImgTit" @click="openAddImg(item, index)">
<div class="titLeft">
<span class="iconfont">&#xe703;</span>
<span class="iconfont">&#xe64a;</span>
<span>内容</span>
</div>
<div class="titRight">
<span class="iconfont" @click.stop="deleteItem(item, index)">&#xe633;</span>
<span
v-html="imgCurrent === index ? '&#xe660;' : '&#xe695;'"
class="iconfont"></span>
</div>
</div>
<div class="addBox" v-show="imgCurrent === index">
<div class="addContent">
<el-input
type="textarea"
:rows="10"
placeholder="请输入内容"
resize="none"
v-model="activeComponent.componentContent.roll[index].info" />
<div class="modelTit titleBox">跳转地址</div>
<el-input
placeholder="请输入新闻链接"
resize="none"
v-model="activeComponent.componentContent.roll[index].url" />
<div class="modelTit titleBox">uni链接</div>
<el-input
placeholder="请输入uni链接"
resize="none"
v-model="activeComponent.componentContent.roll[index].uniapp_url" />
<div class="modelTit titleBox">小程序链接</div>
<el-input
placeholder="请输入小程序链接"
resize="none"
v-model="activeComponent.componentContent.roll[index].wxapp_url" />
<!-- <tool-select-link
:linkObj.sync="item.linkObj"
title="小程序链接"
></tool-select-link> -->
</div>
<!-- <div @click="deleteItem(item, index)" class="deleteItem">
<span class="iconfont">&#xe633;</span>删除内容
</div> -->
</div>
</div>
</div>
</draggable>
</div>
<!-- <div class="addImgBtn" @click="addImgText">
<span class="iconfont">&#xe64a;</span>添加图文
</div> -->
</div>
</div>
<el-dialog
title="提示"
:visible.sync="dialogVisible"
width="30%"
:before-close="deleteItem" >
<span>点击确定删除此项</span>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false"> </el-button>
<el-button type="primary" @click="dialogVisible = false"> </el-button>
</span>
</el-dialog>
<el-dialog :visible.sync="dialogImageVisible">
<img width="100%" :src="dialogImageUrl" alt="" />
</el-dialog>
</div>
</template>
<script>
import Draggable from 'vuedraggable'
import { toolMixin } from '@/mixins/tool.js'
import ToolSelectLink from '@/views/theme/components/rootcompToolbar/toolModule/tool-select-link.vue'
import ToolSelectCategory from '@/views/theme/components/rootcompToolbar/toolModule/tool-select-category.vue'
import ToolSingleImg from '@/views/theme/components/rootcompToolbar/toolModule/tool-single-img.vue'
export default {
name: 'shopTopTool',
mixins: [toolMixin],
components: {
ToolSingleImg,
ToolSelectCategory,
ToolSelectLink,
Draggable
},
data () {
return {
dialogImageVisible: false,
dialogImageUrl: '',
alignList: [
{
id: 1,
label: '居左',
value: 'left'
},
{
id: 2,
label: '居中',
value: 'center'
},
{
id: 3,
label: '居右',
value: 'right'
}
],
textAlign: 'left',
imgCurrent: null,
labelCurrent: null,
dialogVisible: false
}
},
methods: {
// 添加类别
addCategory () {},
openAddImg (item, index) {
if (this.imgCurrent === index) {
this.imgCurrent = null
return false
}
this.imgCurrent = index
},
openAddLabel (item, index) {
if (this.labelCurrent === index) {
this.labelCurrent = null
return false
}
this.labelCurrent = index
},
// 添加图文
addImgText () {
this.activeComponent.componentContent.roll.push({
uniapp_url: '',
url: '',
info: '',
wxapp_url: ''
})
},
// 删除内容
deleteItem (item, index) {
this.$confirm('确定删除此项?')
.then((_) => {
this.activeComponent.componentContent.roll.splice(index, 1)
})
.catch((_) => {})
},
// 添加标签
addLabel () {
this.activeComponent.componentContent.labelList.push({
name: '',
url: ''
})
},
// 删除标签
deleteLabelItem (item, index) {
this.$confirm('确定删除此项?')
.then((_) => {
this.activeComponent.componentContent.labelList.splice(index, 1)
})
.catch((_) => {})
},
imgChange (file, index, key) {
this.activeComponent.componentContent.roll[index][key] = URL.createObjectURL(file.raw)
},
showImage (imgData) {
this.dialogImageUrl = imgData
this.dialogImageVisible = true
},
delImage (index, key) {
this.activeComponent.componentContent.roll[index][key] = ''
}
}
}
</script>
<style lang="scss" scoped>
.shopTopTool {
padding: 20px 20px 0px 20px;
.topTit {
display: flex;
justify-content: space-between;
border-bottom: 1px solid #eeeeee;
margin-bottom: 20px;
span {
height: 35px;
line-height: 35px;
font-size: 14px;
color: #333333;
}
span:last-child {
font-weight: bold;
width: 100px;
text-align: center;
cursor: pointer;
&:hover {
color: $mainColor;
}
}
}
h3 {
font-size: 18px;
font-weight: 500;
height: 35px;
line-height: 35px;
color: #333333;
margin-bottom: 20px;
}
.titleBox {
display: flex;
justify-content: space-between;
}
.btnSelect {
margin-top: 30px;
}
.toolBox {
padding-bottom: 10px;
.modelTit {
font-size: 14px;
color: #333333;
margin-top: 10px;
margin-bottom: 10px;
}
.itemBox {
label {
font-size: 14px;
color: #666666;
height: 40px;
line-height: 40px;
}
margin-bottom: 15px;
}
.imgListBox {
margin-top: 30px;
.item {
border: 1px solid #e8eaec;
border-radius: 4px;
margin-bottom: 10px;
}
.listItemBox {
.addImgTit {
padding: 10px;
display: flex;
justify-content: space-between;
align-items: center;
background: #f6f7f9;
cursor: pointer;
.titLeft {
display: flex;
align-items: center;
span {
color: #7d7e80;
}
span:nth-child(1) {
font-size: 28px;
}
span:nth-child(2) {
font-size: 25px;
margin: 0 6px;
}
span:nth-child(3) {
font-size: 14px;
}
}
.titRight {
display: flex;
align-items: center;
span:nth-child(1) {
width: 40px;
text-align: center;
display: block;
height: 30px;
line-height: 30px;
}
}
}
.addContent {
padding: 5px 13px;
.imgIsShow {
display: flex;
justify-content: space-between;
margin: 18px 0 22px 0;
span {
font-size: 14px;
color: #666666;
}
}
.deleteItem {
border-radius: 4px;
background: $mainColor;
text-align: center;
height: 36px;
color: #ffffff;
font-size: 14px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
margin-bottom: 10px;
span {
font-size: 18px;
color: #ffffff;
margin-right: 5px;
}
}
}
.deleteItem {
padding: 10px;
display: flex;
align-items: center;
justify-content: center;
background: #f6f7f9;
cursor: pointer;
color: $mainColor;
font-size: 14px;
span {
font-size: 16px;
margin-right: 5px;
}
}
}
}
.textTit {
height: 35px;
line-height: 35px;
font-size: 16px;
color: #333333;
font-weight: bold;
}
}
>>> .el-select {
width: 100%;
}
.addImgBtn {
border-radius: 4px;
background: $mainColor;
text-align: center;
height: 36px;
color: #ffffff;
font-size: 14px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
margin-bottom: 30px;
span {
font-size: 20px;
margin-right: 5px;
}
}
.labelList {
.addLabelBox {
padding: 10px;
}
}
}
</style>
@@ -0,0 +1,451 @@
<template>
<div class="brandListTool">
<h3 class="toolTit">商品列表</h3>
<div class="toolBox">
<div class="itemBox">
<label>标题</label>
<el-input v-model="activeComponent.componentContent.title" placeholder="请输入内容"></el-input>
</div>
<tool-select :linkValue.sync='activeComponent.componentContent.textAlign' title="文字对齐方式" :options="alignList"></tool-select>
<div class="single-img"></div>
<div class="textTit">商品来源</div>
<div class="porListBox">
<div class="addProduct">
<div v-if="!activeComponent.componentContent.categoryName" class="addProBtn addImgBtn" @click="addProductCls"><span class="iconfont">&#xe685;</span> 添加类别</div>
<div v-else class="categoryName">
<span>{{activeComponent.componentContent.categoryName}}</span>
<div class="operation">
<span class="iconfont" @click="replaceCategory">&#xe66c;</span>
<span class="iconfont" @click="deleteCategory">&#xe633;</span>
</div>
</div>
</div>
</div>
<div class="productTit">
<span>展示排数</span>
<span>{{activeComponent.componentContent.productRowNum}}</span>
</div>
<div class="itemBox">
<div class="block">
<el-slider :max="9" :min="1" v-model="activeComponent.componentContent.productRowNum"></el-slider>
</div>
</div>
<div class="productTit">
<span>每排商品数</span>
<span>{{activeComponent.componentContent.productNum}}</span>
</div>
<div class="itemBox">
<div class="block">
<el-slider :max="5" :min="2" v-model="activeComponent.componentContent.productNum"></el-slider>
</div>
</div>
</div>
<div class="labelLisTit titleBox">广告图配置
<el-switch
v-model="activeComponent.componentContent.bannerShow"
active-color="#FF7800"
inactive-color="#E8EAEC">
</el-switch>
</div>
<div v-show="activeComponent.componentContent.bannerShow">
<tool-single-img :imageUrl.sync='activeComponent.componentContent.bannerUrl'></tool-single-img>
<tool-select-link :linkObj.sync='activeComponent.componentContent.bannerLinkObj' title="图片链接"></tool-select-link>
</div>
<div class="labelLisTit titleBox">标签配置
<el-switch
v-model="activeComponent.componentContent.labelShow"
active-color="#FF7800"
inactive-color="#E8EAEC">
</el-switch>
</div>
<div class="labelListWarp" v-show="activeComponent.componentContent.labelShow">
<div class="labelList">
<div class="imgListBox">
<draggable v-model="activeComponent.componentContent.labelList">
<div v-for="(item, index) in activeComponent.componentContent.labelList" :key="index" class="item">
<div class="listItemBox">
<div class="addImgTit" @click="openAddLabel(item, index)">
<div class="titLeft">
<span class="iconfont">&#xe703;</span>
<span class="iconfont">&#xe64a;</span>
<span>标签</span>
</div>
<div class="titRight">
<span class="iconfont" @click.stop="deleteLabelItem(item, index)">&#xe633;</span>
<span v-html="labelCurrent === index ? '&#xe660;' : '&#xe695;'" class="iconfont"></span>
</div>
</div>
<div class="addLabelBox" v-show="labelCurrent === index">
<div class="itemBox">
<label>名称</label>
<el-input v-model="item.name" placeholder="请输入内容"></el-input>
</div>
<tool-select-link :linkObj.sync='item.linkObj'></tool-select-link>
</div>
</div>
</div>
</draggable>
</div>
</div>
<div class="addImgBtn" @click="addLabel"><span class="iconfont">&#xe64a;</span>添加标签</div>
</div>
<el-dialog
title="提示"
:visible.sync="dialogVisible"
width="30%"
:before-close="deleteItem">
<span>点击确定删除此项</span>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false"> </el-button>
<el-button type="primary" @click="dialogVisible = false"> </el-button>
</span>
</el-dialog>
<el-dialog title="选择类别" :visible.sync="dialogCategory" width="600px">
<el-cascader style="width: 100%"
ref="cascader"
:options="categoryList"
:props="{ checkStrictly: true,label: 'categoryName',value: 'id',children: 'childs' }"
clearable></el-cascader>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogCategory = false"> </el-button>
<el-button type="primary" @click="addCategoryData"> </el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import Draggable from 'vuedraggable'
import { toolMixin, checkEmptyChild } from '@/mixins/tool.js'
import ToolSelectLink from '@/views/theme/components/rootcompToolbar/toolModule/tool-select-link.vue'
import ToolSingleImg from '@/views/theme/components/rootcompToolbar/toolModule/tool-single-img.vue'
import ToolSelect from '@/views/theme/components/rootcompToolbar/toolModule/tool-select.vue'
import { getClassify, getProducts } from '@/api/canvasApi.js'
export default {
name: 'productListTool',
mixins: [toolMixin, checkEmptyChild],
components: {
ToolSelectLink,
ToolSingleImg,
ToolSelect,
Draggable
},
data () {
return {
title: '', // 标题内容
textInfo: '', // 文本
imgTextData: [
{
title: '',
isShow: true,
imgData: '',
describe: '',
url: ''
}
],
alignList: [
{
id: 1,
label: '居左',
value: 'left'
},
{
id: 2,
label: '居中',
value: 'center'
}
],
categoryList: [],
textAlign: 'left',
imgCurrent: null,
dialogVisible: false,
dialogCategory: false,
currentCategory: null,
// categoryName: '', // 类别名称
productList: [], // 产品列表
productNum: 2, // 商品展示数量
labelCurrent: null
}
},
methods: {
// 获取类别
getCategory () {
getClassify().then(res => {
this.categoryList = res.data
checkEmptyChild(this.categoryList)
this.dialogCategory = true
})
},
openAddImg (item, index) {
if (this.imgCurrent === index) {
this.imgCurrent = null
return false
}
this.imgCurrent = index
},
// 添加图文
addImgText () {
this.activeComponent.componentContent.imgTextData.push({
title: '',
isShow: true,
imgData: '',
url: ''
})
},
// 删除内容
deleteItem (item, index) {
this.$confirm('确定删除此项?')
.then(_ => {
this.activeComponent.componentContent.imgTextData.splice(index, 1)
})
.catch(_ => {})
},
// 添加类别
addCategoryData () {
let nodesObj = this.$refs['cascader'].getCheckedNodes()
if (nodesObj) {
var categoryId = nodesObj[0].value
var categoryName = nodesObj[0].label
this.activeComponent.componentContent.categoryId = categoryId
this.activeComponent.componentContent.categoryName = categoryName
this.dialogCategory = false
let params = {
page: 1,
pageSize: 20,
classifyId: this.activeComponent.componentContent.categoryId
}
getProducts(params).then(res => {
this.activeComponent.componentContent.imgTextData = res.data.list
})
}
},
// 替换类别
replaceCategory () {
this.getCategory()
},
// 删除已选类别
deleteCategory () {
this.activeComponent.componentContent.categoryName = ''
this.activeComponent.componentContent.imgTextData = []
},
handleAvatarSuccess (res, file) {
this.imageUrl = URL.createObjectURL(file.raw)
},
addProductCls () {
this.getCategory()
},
// 标签手风琴
openAddLabel (item, index) {
if (this.labelCurrent === index) {
this.labelCurrent = null
return false
}
this.labelCurrent = index
},
// 添加标签
addLabel () {
this.activeComponent.componentContent.labelList.push({
name: '',
url: ''
})
},
// 删除标签
deleteLabelItem (item, index) {
this.$confirm('确定删除此项?')
.then(_ => {
this.activeComponent.componentContent.labelList.splice(index, 1)
})
.catch(_ => {})
}
}
}
</script>
<style lang="scss" scoped>
.brandListTool {
padding: 20px 20px 0px 20px;
h3 {
font-size: 18px;
font-weight: 500;
height: 35px;
line-height: 35px;
color: #333333;
margin-bottom: 20px;
}
.toolBox {
padding-bottom: 10px;
.itemBox {
label {
font-size: 14px;
color: #666666;
height: 40px;
line-height: 40px;
}
margin-bottom: 15px;
}
.textTit {
height: 35px;
line-height: 35px;
font-size: 14px;
color: #333333;
display: flex;
justify-content: space-between;
span {
font-weight: normal;
font-size: 14px;
color: #666666;
}
}
.productTit {
margin-top: 20px;
color: #666666;
height: 35px;
display: flex;
align-items: center;
justify-content: space-between;
span {
font-size: 14px;
color: #666666;
}
}
.porListBox {
padding: 10px;
background: #F0F3F4;
.addProduct {
.categoryName {
height: 35px;
display: flex;
align-items: center;
background: #e9e9e9;
border-radius: 4px;
padding: 0 10px;
justify-content: space-between;
span {
color: #333333;
}
span {
color: #333333;
}
.operation {
display: flex;
span {
width: 35px;
display: block;
height: 35px;
line-height: 35px;
text-align: center;
cursor: pointer;
}
}
}
.addProBtn {}
}
}
}
>>> .el-select {
width: 100%;
}
.addImgBtn {
border-radius: 4px;
background: $mainColor;
text-align: center;
height: 36px;
color: #ffffff;
font-size: 14px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
span {
font-size: 20px;
margin-right: 5px;
}
}
.labelLisTit{
display: flex;
justify-content: space-between;
margin-bottom: 10px;
}
.labelListWarp{
padding-bottom: 20px;
.imgListBox {
margin-top: 20px;
.item {
border: 1px solid #E8EAEC;
border-radius: 4px;
margin-bottom: 10px;
}
.listItemBox {
.addImgTit {
padding: 10px;
display: flex;
justify-content: space-between;
align-items: center;
background: #F6F7F9;
cursor: pointer;
.titLeft {
display: flex;
align-items: center;
span {
color: #7D7E80;
}
span:nth-child(1) {
font-size: 28px;
}
span:nth-child(2) {
font-size: 25px;
margin: 0 6px;
}
span:nth-child(3) {
font-size: 14px;
}
}
.titRight {
display: flex;
align-items: center;
span:nth-child(1) {
width: 40px;
text-align: center;
display: block;
height: 30px;
line-height: 30px;
}
}
}
.addLabelBox{
padding:0 10px 10px;
.itemBox{
margin-bottom: 20px;
label{
font-size: 14px;
color: #666666;
height: 40px;
line-height: 40px;
}
}
>>> .module-box{
margin-bottom: 10px;
}
}
.deleteItem {
padding: 10px;
display: flex;
align-items: center;
justify-content: center;
background: #F6F7F9;
cursor: pointer;
color: $mainColor;
font-size: 14px;
span {
font-size: 16px;
margin-right: 5px;
}
}
}
}
}
}
</style>
@@ -0,0 +1,340 @@
<template>
<div class="shopTopTool">
<h3 class="toolTit">店铺头部</h3>
<div class="tabBox">
<div class="toolBox">
<div class="modelTit">标题设置</div>
<div
class="labelListWarp"
>
<div class="labelList">
<div class="imgListBox">
<draggable >
<div
class="item"
>
<div class="listItemBox">
<div class="addLabelBox" >
<div class="itemBox">
<label>名称</label>
<el-input
v-model="activeComponent.componentContent.title"
placeholder="请输入内容"
></el-input>
</div>
</div>
</div>
</div>
</draggable>
</div>
</div>
<div class="addImgBtn" @click="addLabel">
<span class="iconfont">&#xe64a;</span>添加标签
</div>
</div>
</div>
</div>
<el-dialog
title="提示"
:visible.sync="dialogVisible"
width="30%"
:before-close="deleteItem"
>
<span>点击确定删除此项</span>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false"> </el-button>
<el-button type="primary" @click="dialogVisible = false"
> </el-button
>
</span>
</el-dialog>
<el-dialog :visible.sync="dialogImageVisible">
<img width="100%" :src="dialogImageUrl" alt="" />
</el-dialog>
</div>
</template>
<script>
import Draggable from 'vuedraggable'
import { toolMixin } from '@/mixins/tool.js'
import ToolSelectLink from '@/views/theme/components/rootcompToolbar/toolModule/tool-select-link.vue'
import ToolSelectCategory from '@/views/theme/components/rootcompToolbar/toolModule/tool-select-category.vue'
import ToolSingleImg from '@/views/theme/components/rootcompToolbar/toolModule/tool-single-img.vue'
export default {
name: 'shopTopTool',
mixins: [toolMixin],
components: {
ToolSingleImg,
ToolSelectCategory,
ToolSelectLink,
Draggable
},
data () {
return {
dialogImageVisible: false,
dialogImageUrl: '',
alignList: [
{
id: 1,
label: '居左',
value: 'left'
},
{
id: 2,
label: '居中',
value: 'center'
},
{
id: 3,
label: '居右',
value: 'right'
}
],
textAlign: 'left',
imgCurrent: null,
labelCurrent: null,
dialogVisible: false
}
},
methods: {
// 添加类别
addCategory () {},
openAddImg (item, index) {
if (this.imgCurrent === index) {
this.imgCurrent = null
return false
}
this.imgCurrent = index
},
openAddLabel (item, index) {
if (this.labelCurrent === index) {
this.labelCurrent = null
return false
}
this.labelCurrent = index
},
// 添加图文
addImgText () {
this.activeComponent.componentContent.bannerData.push({
title: '',
imgData: '',
url: ''
})
},
// 删除内容
deleteItem (item, index) {
this.$confirm('确定删除此项?')
.then((_) => {
this.activeComponent.componentContent.bannerData.splice(index, 1)
})
.catch((_) => {})
},
// 添加标签
addLabel () {
this.activeComponent.componentContent.labelList.push({
name: '',
url: ''
})
},
// 删除标签
deleteLabelItem (item, index) {
this.$confirm('确定删除此项?')
.then((_) => {
this.activeComponent.componentContent.labelList.splice(index, 1)
})
.catch((_) => {})
},
imgChange (file, index, key) {
this.activeComponent.componentContent.bannerData[index][key] = URL.createObjectURL(file.raw)
},
showImage (imgData) {
this.dialogImageUrl = imgData
this.dialogImageVisible = true
},
delImage (index, key) {
this.activeComponent.componentContent.bannerData[index][key] = ''
}
}
}
</script>
<style lang="scss" scoped>
.shopTopTool {
padding: 20px 20px 0px 20px;
.topTit {
display: flex;
justify-content: space-between;
border-bottom: 1px solid #eeeeee;
margin-bottom: 20px;
span {
height: 35px;
line-height: 35px;
font-size: 14px;
color: #333333;
}
span:last-child {
font-weight: bold;
width: 100px;
text-align: center;
cursor: pointer;
&:hover {
color: $mainColor;
}
}
}
h3 {
font-size: 18px;
font-weight: 500;
height: 35px;
line-height: 35px;
color: #333333;
margin-bottom: 20px;
}
.titleBox {
display: flex;
justify-content: space-between;
}
.btnSelect {
margin-top: 30px;
}
.toolBox {
padding-bottom: 10px;
.modelTit {
font-size: 14px;
color: #333333;
margin-top: 10px;
}
.itemBox {
label {
font-size: 14px;
color: #666666;
height: 40px;
line-height: 40px;
}
margin-bottom: 15px;
}
.imgListBox {
margin-top: 30px;
.item {
border: 1px solid #e8eaec;
border-radius: 4px;
margin-bottom: 10px;
}
.listItemBox {
.addImgTit {
padding: 10px;
display: flex;
justify-content: space-between;
align-items: center;
background: #f6f7f9;
cursor: pointer;
.titLeft {
display: flex;
align-items: center;
span {
color: #7d7e80;
}
span:nth-child(1) {
font-size: 28px;
}
span:nth-child(2) {
font-size: 25px;
margin: 0 6px;
}
span:nth-child(3) {
font-size: 14px;
}
}
.titRight {
display: flex;
align-items: center;
span:nth-child(1) {
width: 40px;
text-align: center;
display: block;
height: 30px;
line-height: 30px;
}
}
}
.addContent {
padding: 5px 13px;
.imgIsShow {
display: flex;
justify-content: space-between;
margin: 18px 0 22px 0;
span {
font-size: 14px;
color: #666666;
}
}
.deleteItem {
border-radius: 4px;
background: $mainColor;
text-align: center;
height: 36px;
color: #ffffff;
font-size: 14px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
margin-bottom: 10px;
span {
font-size: 18px;
color: #ffffff;
margin-right: 5px;
}
}
}
.deleteItem {
padding: 10px;
display: flex;
align-items: center;
justify-content: center;
background: #f6f7f9;
cursor: pointer;
color: $mainColor;
font-size: 14px;
span {
font-size: 16px;
margin-right: 5px;
}
}
}
}
.textTit {
height: 35px;
line-height: 35px;
font-size: 16px;
color: #333333;
font-weight: bold;
}
}
>>> .el-select {
width: 100%;
}
.addImgBtn {
border-radius: 4px;
background: $mainColor;
text-align: center;
height: 36px;
color: #ffffff;
font-size: 14px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
margin-bottom: 30px;
span {
font-size: 20px;
margin-right: 5px;
}
}
.labelList {
.addLabelBox {
padding: 10px;
}
}
}
</style>
@@ -0,0 +1,340 @@
<template>
<div class="textTool">
<h3 class="toolTit">文本设置</h3>
<div class="toolBox">
<div class="itemBox">
<label>标题内容</label>
<el-input v-model="activeComponent.componentContent.title" placeholder="请输入内容"></el-input>
</div>
<div class="itemBox">
<label>描述内容</label>
<el-input
type="textarea"
:rows="2"
placeholder="请输入内容"
resize="none"
v-model="activeComponent.componentContent.describe">
</el-input>
</div>
</div>
<div class="operationBox">
<div class="itemBox">
<div class="Tit">显示位置</div>
<div class="Info">{{positionText}}显示</div>
<div class="modifyBox">
<span class="iconfont" :class="{textActive: activeComponent.componentContent.textPos === 'left'}" @click="textPosition(type = 'left')">&#xec86;</span>
<span class="iconfont" :class="{textActive: activeComponent.componentContent.textPos === 'center'}" @click="textPosition(type = 'center')">&#xe619;</span>
<span class="iconfont" :class="{textActive: activeComponent.componentContent.textPos === 'right'}" @click="textPosition(type = 'right')">&#xec82;</span>
</div>
</div>
<div class="itemBox">
<div class="Tit">标题大小</div>
<div class="Info">{{fontSize}}{{activeComponent.componentContent.fontSizeNum}}</div>
<div class="modifyBox fontSize">
<span class="iconfont" :class="{textActive: activeComponent.componentContent.fontSizeNum === 16}" @click="changeSize(sizeNum = 16)">&#xe600;</span>
<span class="iconfont" :class="{textActive: activeComponent.componentContent.fontSizeNum === 14}" @click="changeSize(sizeNum = 14)">&#xe600;</span>
<span class="iconfont" :class="{textActive: activeComponent.componentContent.fontSizeNum === 12}" @click="changeSize(sizeNum = 12)">&#xe600;</span>
</div>
</div>
<div class="itemBox">
<div class="Tit">描述大小</div>
<div class="Info">{{describeSize}}{{activeComponent.componentContent.describeSizeNum}}</div>
<div class="modifyBox fontSize">
<span class="iconfont" :class="{textActive: activeComponent.componentContent.describeSizeNum === 16}" @click="changeDescribe(sizeNum = 16)">&#xe600;</span>
<span class="iconfont" :class="{textActive: activeComponent.componentContent.describeSizeNum === 14}" @click="changeDescribe(sizeNum = 14)">&#xe600;</span>
<span class="iconfont" :class="{textActive: activeComponent.componentContent.describeSizeNum === 12}" @click="changeDescribe(sizeNum = 12)">&#xe600;</span>
</div>
</div>
<div class="itemBox">
<div class="Tit">标题粗细</div>
<div class="Info" v-text="activeComponent.componentContent.textFontW === 'bold' ? '加粗体' : '常规体'"></div>
<div class="modifyBox fontSize">
<span class="iconfont" :class="{textActive: activeComponent.componentContent.textFontW === 'bold'}" @click="changeFontW(type = 'bold')">&#xe649;</span>
<span class="iconfont" :class="{textActive: activeComponent.componentContent.textFontW === 'normal'}" @click="changeFontW(type = 'normal')">&#xe8c2;</span>
</div>
</div>
<div class="itemBox">
<div class="Tit">描述粗细</div>
<div class="Info" v-text="activeComponent.componentContent.describeFontW === 'bold' ? '加粗体' : '常规体'"></div>
<div class="modifyBox">
<span class="iconfont" :class="{textActive: activeComponent.componentContent.describeFontW === 'bold'}" @click="changeInfoFontW(type = 'bold')">&#xe649;</span>
<span class="iconfont" :class="{textActive: activeComponent.componentContent.describeFontW === 'normal'}" @click="changeInfoFontW(type = 'normal')">&#xe8c2;</span>
</div>
</div>
<div class="itemBox">
<div class="Tit">标题颜色</div>
<div class="Info">{{activeComponent.componentContent.titColor}}</div>
<div class="modifyBox">
<div class="colorBox">
<span @click="resetColor">重置</span>
<div class="block">
<el-color-picker v-model="activeComponent.componentContent.titColor"></el-color-picker>
</div>
</div>
</div>
</div>
<div class="itemBox">
<div class="Tit">描述颜色</div>
<div class="Info">{{activeComponent.componentContent.describeColor}}</div>
<div class="modifyBox">
<div class="colorBox">
<span @click="resetDescribeColor">重置</span>
<div class="block">
<el-color-picker v-model="activeComponent.componentContent.describeColor"></el-color-picker>
</div>
</div>
</div>
</div>
<div class="itemBox">
<div class="Tit">背景颜色</div>
<div class="Info">{{activeComponent.componentContent.bgColor}}</div>
<div class="modifyBox">
<div class="colorBox">
<span @click="resetBgColor">重置</span>
<div class="block">
<el-color-picker v-model="activeComponent.componentContent.bgColor"></el-color-picker>
</div>
</div>
</div>
</div>
<div class="itemBox">
<div class="Tit">底部分割线</div>
<div class="Info" v-text="activeComponent.componentContent.showLine ? '显示' : '隐藏'"></div>
<div class="modifyBox">
<el-checkbox v-model="activeComponent.componentContent.showLine"></el-checkbox>
</div>
</div>
<div class="itemBox">
<div class="Tit">查看更多</div>
<div class="Info" v-text="activeComponent.componentContent.showMore ? '显示' : '隐藏'"></div>
<div class="modifyBox">
<el-checkbox v-model="activeComponent.componentContent.showMore"></el-checkbox>
</div>
</div>
<div class="moreBox" v-show="activeComponent.componentContent.showMore">
<div class="radio">
<el-radio v-model="activeComponent.componentContent.styleValue" label="1">样式一</el-radio>
<el-radio v-model="activeComponent.componentContent.styleValue" label="2">样式二</el-radio>
<el-radio v-model="activeComponent.componentContent.styleValue" label="3">样式三</el-radio>
</div>
<div class="link">
<label>链接</label>
<el-select :popper-append-to-body="false" v-model="activeComponent.componentContent.link" placeholder="请选择跳转到的页面">
<el-option
v-for="item in linkOptions"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</div>
</div>
</div>
</div>
</template>
<script>
import { toolMixin } from '@/mixins/tool.js'
export default {
name: 'textTool',
mixins: [toolMixin],
data () {
return {
linkOptions: [
{
value: '/index',
label: '首页'
},
{
value: '/list',
label: '列表页'
},
{
value: '/detail',
label: '详情页'
},
{
value: '/about',
label: '关于我们'
}
]
}
},
computed: {
fontSize () {
if (this.activeComponent.componentContent.fontSizeNum === 16) {
return '大'
} else if (this.activeComponent.componentContent.fontSizeNum === 14) {
return '中'
} else {
return '小'
}
},
describeSize () {
if (this.activeComponent.componentContent.describeSizeNum === 16) {
return '大'
} else if (this.activeComponent.componentContent.describeSizeNum === 14) {
return '中'
} else {
return '小'
}
},
positionText () {
if (this.activeComponent.componentContent.textPos === 'left') {
return '左'
} else if (this.activeComponent.componentContent.textPos === 'center') {
return '中'
} else {
return '右'
}
}
},
methods: {
// 修改文字对齐方向
textPosition (type) {
this.activeComponent.componentContent.textPos = type
},
// 修改文本大小
changeSize (sizeNum) {
this.activeComponent.componentContent.fontSizeNum = sizeNum
},
// 修改描述大小
changeDescribe (sizeNum) {
this.activeComponent.componentContent.describeSizeNum = sizeNum
},
// 修改文本字体粗细
changeFontW (type) {
this.activeComponent.componentContent.textFontW = type
},
// 修改描述文字粗细
changeInfoFontW (type) {
this.activeComponent.componentContent.describeFontW = type
},
// 重置文本颜色
resetColor () {
this.activeComponent.componentContent.titColor = '#333333'
},
// 重置描述颜色
resetDescribeColor () {
this.activeComponent.componentContent.describeColor = '#333333'
},
// 重置背景颜色
resetBgColor () {
this.activeComponent.componentContent.bgColor = '#FFFFFF'
}
}
}
</script>
<style lang="scss" scoped>
.textTool {
padding: 20px 20px 0 20px;
h3 {
font-size: 18px;
font-weight: 500;
height: 35px;
line-height: 35px;
color: #333333;
margin-bottom: 20px;
}
.toolBox {
padding-bottom: 10px;
.itemBox {
label {
font-size: 14px;
color: #666666;
height: 40px;
line-height: 40px;
}
margin-bottom: 15px;
}
border-bottom: 1px solid #eeeeee;
}
.operationBox {
margin-top: 30px;
.itemBox {
font-size: 14px;
display: flex;
margin-bottom: 20px;
align-items: center;
.Tit {
color: #888888;
margin-right: 10px;
width: 70px;
}
.Info {
color: #222222;
}
.modifyBox {
text-align: right;
margin-left: auto;
span {
height: 26px;
line-height: 26px;
float: left;
display: block;
text-align: center;
cursor: pointer;
width: 30px;
border: 1px solid #E8EAEC;
}
/*span:last-child {*/
/* border-right: 1px solid #E8EAEC;*/
/*}*/
.textActive {
border: 1px solid $mainColor;
color: $mainColor;
}
.colorBox {
display: flex;
align-items: center;
justify-content: flex-end;
span {
margin-right: 10px;
cursor: pointer;
border: none;
color: $mainColor;
}
}
}
.fontSize {
span:nth-child(1) {
font-size: 16px;
}
span:nth-child(2) {
font-size: 14px;
}
span:nth-child(3) {
font-size: 12px;
}
}
}
.moreBox{
border: 1px solid #E8EAEC;
border-radius: 4px;
padding:20px 10px;
.radio{
margin-bottom: 20px;
}
.el-radio{
margin-right: 10px;
}
.link{
display: flex;
justify-content: space-between;
align-items: center;
}
}
}
.block {
height: 30px;
}
>>> .el-color-picker__trigger {
width: 45px;
height: 26px;
}
>>> .el-icon-arrow-down:before {
display: none;
}
}
</style>
@@ -0,0 +1,97 @@
<template>
<div class="videoTool">
<h3 class="toolTit">视频</h3>
<div class="toolBox">
<div class="itemBox">
<label>视频地址</label>
<el-input v-model="activeComponent.componentContent.videoUrl" placeholder="请输入内容"></el-input>
</div>
<!-- <div class="itemBox">-->
<!-- <label>文本</label>-->
<!-- <el-input-->
<!-- type="textarea"-->
<!-- :rows="2"-->
<!-- placeholder="请输入内容"-->
<!-- resize="none"-->
<!-- v-model="textInfo">-->
<!-- </el-input>-->
<!-- </div>-->
<div class="itemBox">
<label>标题</label>
<el-input v-model="activeComponent.componentContent.title" placeholder="请输入内容"></el-input>
</div>
<div class="itemBox">
<label>正文</label>
<quill-editor
v-model="activeComponent.componentContent.mainBody"
ref="myQuillEditor"
:options="editorOption"
@blur="onEditorBlur($event)" @focus="onEditorFocus($event)"
@change="onEditorChange($event)">
</quill-editor>
</div>
</div>
</div>
</template>
<script>
import { quillEditor } from 'vue-quill-editor'
import { toolMixin } from '@/mixins/tool.js'
export default {
mixins: [toolMixin],
name: 'videoTool',
components: {
quillEditor
},
data() {
return {
editorOption: {
placeholder: '请输入',
modules: {
toolbar: [
['bold', 'italic', 'link'] // toggled buttons
]
}
}
}
},
methods: {
onEditorBlur() { // 失去焦点事件
},
onEditorFocus() { // 获得焦点事件
},
onEditorChange() { // 内容改变事件
console.log(this.mainBody)
}
}
}
</script>
<style lang="scss" scoped>
.videoTool {
padding: 20px 20px 0 20px;
h3 {
font-size: 18px;
font-weight: 500;
height: 35px;
line-height: 35px;
color: #333333;
margin-bottom: 20px;
}
.toolBox {
padding-bottom: 10px;
.itemBox {
label {
font-size: 14px;
color: #666666;
height: 40px;
line-height: 40px;
}
margin-bottom: 15px;
}
}
>>> .ql-container {
height: 200px;
}
}
</style>
@@ -0,0 +1,134 @@
/**
轮播图编辑
*/
<template>
<div class="editorBannerBox">
<h2>轮播图</h2>
<ul class="editorList">
<draggable v-model="activeComponent.componentContent.bannerList">
<li
class="item"
v-for="(item, index) in activeComponent.componentContent.bannerList"
:key="index"
>
<DraggableSlot :obj="item" :index="index" @deleteIt="deleteIt">
<div class="addContent">
<ToolSingleImg
v-if="item.pic !== undefined && item.pic !== null"
:imageUrl.sync="item.pic" />
<div class="titleBox">{{ item.title }}</div>
<el-input
placeholder="描述"
resize="none"
v-model="item.des"
/>
<div class="titleBox">{{ '跳转地址' }}</div>
<el-input
placeholder="请输入新的内容"
resize="none"
v-model="item.linkTo"
/>
</div>
<div @click="deleteItem(item, index)" class="deleteItem">
<span class="iconfont">&#xe633;</span>删除内容
</div>
</DraggableSlot>
</li>
</draggable>
<div
class="addImgBtn"
@click="addImgText(activeComponent.componentContent.bannerList.length)">
<span class="iconfont">&#xe64a;</span>添加图文
</div>
</ul>
<el-dialog
title="提示"
:visible.sync="dialogVisible"
width="30%"
:before-close="deleteItem"
>
<span>点击确定删除此项</span>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false"> </el-button>
<el-button type="primary" @click="dialogVisible = false"
> </el-button
>
</span>
</el-dialog>
<el-dialog :visible.sync="dialogImageVisible">
<img width="100%" :src="dialogImageUrl" alt="" />
</el-dialog>
</div>
</template>
<script>
import Draggable from 'vuedraggable'
import { toolMixin } from '@/mixins/tool.js'
import ToolSingleImg from '@/views/theme/components/rootcompToolbar/toolModule/tool-single-img.vue'
import DraggableSlot from '@/views/theme/components/rootcompToolbar/pc/components/draggableSlot.vue'
export default {
name: 'PcBanner',
mixins: [toolMixin],
components: {Draggable, ToolSingleImg, DraggableSlot},
data () {
return {
dialogVisible: false,
dialogImageVisible: false,
dialogImageUrl: null
}
},
methods: {
// 添加图文
addImgText (index) {
console.log(index)
this.activeComponent.componentContent.bannerList.push({
title: `轮播${index + 1}`,
des: '',
pic: '',
url: '',
linkTo: ''
})
},
deleteItem (item, index) {
this.$confirm('确定删除此项?')
.then((_) => {
this.activeComponent.componentContent.bannerList.splice(index, 1)
})
.catch((_) => {})
},
deleteIt (index) {
this.activeComponent.componentContent.bannerList.splice(index, 1)
}
}
}
</script>
<style lang="scss">
.editorBannerBox{
padding: 8px 12px;
.editorList{
.item {
border: 1px solid #e8eaec;
border-radius: 4px;
margin: 10px 0;
}
.addImgBtn {
border-radius: 4px;
background: $mainColor;
text-align: center;
height: 36px;
color: #ffffff;
font-size: 14px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
margin-bottom: 30px;
span {
font-size: 20px;
margin-right: 5px;
}
}
}
}
</style>
@@ -0,0 +1,119 @@
/**
编辑器_联系方式组件
*/
<template>
<div class="editorFooter">
<h2>联系方式</h2>
<ul class="editorList">
<draggable v-model="activeComponent.componentContent.publicList">
<li
class="item"
v-for="(item, index) in activeComponent.componentContent.publicList"
:key="index"
>
<DraggableSlot :obj="item" :index="index" @deleteIt="deleteIt">
<div class="addContent">
<ToolSingleImg
v-if="item.pic !== undefined && item.pic !== null && item.pic !== ''"
:imageUrl.sync="item.pic" />
<div class="titleBox">{{ item.title }}</div>
<el-input
placeholder="描述"
resize="none"
v-model="item.des"
/>
</div>
</DraggableSlot>
</li>
</draggable>
</ul>
<el-dialog
title="提示"
:visible.sync="dialogVisible"
width="30%"
:before-close="deleteItem"
>
<span>点击确定删除此项</span>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false"> </el-button>
<el-button type="primary" @click="dialogVisible = false"
> </el-button
>
</span>
</el-dialog>
<el-dialog :visible.sync="dialogImageVisible">
<img width="100%" :src="dialogImageUrl" alt="" />
</el-dialog>
</div>
</template>
<script>
import Draggable from 'vuedraggable'
import { toolMixin } from '@/mixins/tool.js'
import ToolSingleImg from '@/views/theme/components/rootcompToolbar/toolModule/tool-single-img.vue'
import DraggableSlot from '@/views/theme/components/rootcompToolbar/pc/components/draggableSlot.vue'
export default {
name: 'EditorFooter',
mixins: [toolMixin],
components: {Draggable, ToolSingleImg, DraggableSlot},
data () {
return {
dialogVisible: false,
dialogImageVisible: false,
dialogImageUrl: null
}
},
methods: {
// 添加图文
addImgText () {
this.activeComponent.componentContent.publicList.push({
'title': '',
'des': '',
'linkTo': '',
'pic': ''
})
},
deleteItem (item, index) {
this.$confirm('确定删除此项?')
.then((_) => {
this.activeComponent.componentContent.publicList.splice(index, 1)
})
.catch((_) => {})
},
deleteIt (index) {
this.$message.error('该模块无法删除')
// this.activeComponent.componentContent.publicList.splice(index, 1)
}
}
}
</script>
<style lang="scss">
.editorFooter{
padding: 8px 12px;
.editorList{
.item {
border: 1px solid #e8eaec;
border-radius: 4px;
margin: 10px 0;
}
.addImgBtn {
border-radius: 4px;
background: $mainColor;
text-align: center;
height: 36px;
color: #ffffff;
font-size: 14px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
margin-bottom: 30px;
span {
font-size: 20px;
margin-right: 5px;
}
}
}
}
</style>
@@ -0,0 +1,130 @@
/**
个人中心编辑
*/
<template>
<div class="editorNavPersonal">
<!-- <h2>个人中心</h2>
<ul class="editorList">
<draggable v-model="activeComponent.componentContent.txtRoute">
<li
class="item"
v-for="(item, index) in activeComponent.componentContent
.txtRoute"
:key="index"
>
<DraggableSlot :obj="item" :index="index" @deleteIt="deleteIt">
<div class="addContent">
<div class="titleBox">{{ '测试' }}</div>
<el-input
placeholder="请输入新的内容"
resize="none"
/>
<div class="titleBox">{{ '测试' }}</div>
<el-input
placeholder="请输入新的内容"
resize="none"
/>
</div>
<div @click="deleteItem(item, index)" class="deleteItem">
<span class="iconfont">&#xe633;</span>删除内容
</div>
</DraggableSlot>
</li>
</draggable>
<div class="addImgBtn" @click="addImgText">
<span class="iconfont">&#xe64a;</span>添加图文
</div>
</ul>
<el-dialog
title="提示"
:visible.sync="dialogVisible"
width="30%"
:before-close="deleteItem"
>
<span>点击确定删除此项</span>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false">取 消</el-button>
<el-button type="primary" @click="dialogVisible = false"
>确 定</el-button
>
</span>
</el-dialog> -->
</div>
</template>
<script>
import DraggableSlot from '@/views/theme/components/rootcompToolbar/pc/components/draggableSlot.vue'
import Draggable from 'vuedraggable'
import { toolMixin } from '@/mixins/tool.js'
export default {
name: 'TopPersonalNav',
mixins: [toolMixin],
components: {Draggable, DraggableSlot},
data () {
return {
dialogVisible: false
}
},
methods: {
// 添加图文
addImgText () {
this.activeComponent.componentContent.txtRoute.push({
'title': '',
'type': '文本',
'des': '',
'linkTo': '',
'pic': '',
'notice': 0,
'editors': [
{
'editorTitle': '',
'editorType': '文本',
'editorDes': '' // 编辑内容
}
]
})
},
deleteItem (item, index) {
this.$confirm('确定删除此项?')
.then((_) => {
this.activeComponent.componentContent.txtRoute.splice(index, 1)
})
.catch((_) => {})
},
deleteIt (index) {
this.activeComponent.componentContent.txtRoute.splice(index, 1)
}
}
}
</script>
<style lang="scss">
.editorNavPersonal{
padding: 8px 12px;
.editorList{
.item {
border: 1px solid #e8eaec;
border-radius: 4px;
margin: 10px 0;
}
.addImgBtn {
border-radius: 4px;
background: $mainColor;
text-align: center;
height: 36px;
color: #ffffff;
font-size: 14px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
margin-bottom: 30px;
span {
font-size: 20px;
margin-right: 5px;
}
}
}
}
</style>
@@ -0,0 +1,122 @@
/**
编辑器_专区导航组件
*/
<template>
<div class="editorNavType">
<h2>专区导航</h2>
<ul class="editorList">
<draggable v-model="activeComponent.componentContent.typeRoute">
<li
class="item"
v-for="(item, index) in activeComponent.componentContent.typeRoute"
:key="index"
>
<DraggableSlot :obj="item" :index="index" @deleteIt="deleteIt">
<div class="addContent">
<!-- 文本编辑 -->
<div class="titleBox">{{ '模块' }}</div>
<el-input
placeholder="请输入新的内容"
resize="none"
v-model="item.des"
/>
<div class="titleBox">{{ '跳转地址' }}</div>
<el-input
placeholder="请输入新的内容"
resize="none"
v-model="item.linkTo"
/>
</div>
<div @click="deleteItem(item, index)" class="deleteItem">
<span class="iconfont">&#xe633;</span>删除内容
</div>
</DraggableSlot>
</li>
</draggable>
<div class="addImgBtn" @click="addImgText">
<span class="iconfont">&#xe64a;</span>添加图文
</div>
</ul>
<el-dialog
title="提示"
:visible.sync="dialogVisible"
width="30%"
:before-close="deleteItem"
>
<span>点击确定删除此项</span>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false"> </el-button>
<el-button type="primary" @click="dialogVisible = false"
> </el-button
>
</span>
</el-dialog>
</div>
</template>
<script>
import Draggable from 'vuedraggable'
import { toolMixin } from '@/mixins/tool.js'
import DraggableSlot from '@/views/theme/components/rootcompToolbar/pc/components/draggableSlot.vue'
export default {
name: 'TopTypeNav',
mixins: [toolMixin],
components: {Draggable, DraggableSlot},
data () {
return {
dialogVisible: false
}
},
methods: {
// 添加图文
addImgText () {
this.activeComponent.componentContent.typeRoute.push({
'title': '',
'des': '',
'linkTo': '',
'pic': ''
})
},
deleteItem (item, index) {
this.$confirm('确定删除此项?')
.then((_) => {
this.activeComponent.componentContent.typeRoute.splice(index, 1)
})
.catch((_) => {})
},
deleteIt (index) {
this.activeComponent.componentContent.typeRoute.splice(index, 1)
}
}
}
</script>
<style lang="scss">
.editorNavType{
padding: 8px 12px;
.editorList{
.item {
border: 1px solid #e8eaec;
border-radius: 4px;
margin: 10px 0;
}
.addImgBtn {
border-radius: 4px;
background: $mainColor;
text-align: center;
height: 36px;
color: #ffffff;
font-size: 14px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
margin-bottom: 30px;
span {
font-size: 20px;
margin-right: 5px;
}
}
}
}
</style>
@@ -0,0 +1,25 @@
/**
编辑器_砍价专区
*/
<template>
<div class="canvanProductDiscount">
</div>
</template>
<script>
export default {
data () {
return {
obj: {
'title': '砍价专区',
'bcText': 'BARGAINING ZONE',
'interface': ''
}
}
}
}
</script>
<style lang="scss" scoped>
</style>
@@ -0,0 +1,147 @@
/**
编辑器_拼团专区
*/
<template>
<div class="editorSeckillProduct">
<h2>拼团专区</h2>
<ul class="editorList">
<draggable v-model="activeComponent.componentContent.product">
<li
class="item"
v-for="(item, index) in activeComponent.componentContent.product"
:key="index"
>
<DraggableSlot :obj="item" :index="index" @deleteIt="deleteIt">
<div class="addContent">
<ToolSingleImg
v-if="item.pic !== undefined && item.pic !== null"
:imageUrl.sync="item.pic" />
<div class="titleBox">{{ item.title }}</div>
<el-input
placeholder="描述"
resize="none"
v-model="item.des"
/>
<div class="titleBox">{{ '商品id' }}</div>
<el-input
placeholder="请输入新的内容"
resize="none"
v-model="item.id"
/>
<div class="titleBox">{{ '商品名称' }}</div>
<el-input
placeholder="请输入新的内容"
resize="none"
v-model="item.storeName"
/>
<div class="titleBox">{{ '商品价格' }}</div>
<el-input
placeholder="请输入新的内容"
resize="none"
v-model="item.price"
/>
</div>
<div @click="deleteItem(item, index)" class="deleteItem">
<span class="iconfont">&#xe633;</span>删除内容
</div>
</DraggableSlot>
</li>
</draggable>
<div
class="addImgBtn"
@click="addImgText(activeComponent.componentContent.product.length)">
<span class="iconfont">&#xe64a;</span>添加图文
</div>
</ul>
<el-dialog
title="提示"
:visible.sync="dialogVisible"
width="30%"
:before-close="deleteItem"
>
<span>点击确定删除此项</span>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false"> </el-button>
<el-button type="primary" @click="dialogVisible = false"
> </el-button
>
</span>
</el-dialog>
<el-dialog :visible.sync="dialogImageVisible">
<img width="100%" :src="dialogImageUrl" alt="" />
</el-dialog>
</div>
</template>
<script>
import Draggable from 'vuedraggable'
import { toolMixin } from '@/mixins/tool.js'
import ToolSingleImg from '@/views/theme/components/rootcompToolbar/toolModule/tool-single-img.vue'
import DraggableSlot from '@/views/theme/components/rootcompToolbar/pc/components/draggableSlot.vue'
export default {
name: 'ProductComb',
mixins: [toolMixin],
components: {Draggable, ToolSingleImg, DraggableSlot},
data () {
return {
dialogVisible: false,
dialogImageVisible: false,
dialogImageUrl: null
}
},
methods: {
// 添加图文
addImgText (index) {
this.activeComponent.componentContent.product.push({
'title': `拼团商品${index + 1}`,
'type': 2,
'id': '',
'pic': '',
'storeName': '',
'price': ''
})
},
deleteItem (item, index) {
this.$confirm('确定删除此项?')
.then((_) => {
this.activeComponent.componentContent.product.splice(index, 1)
})
.catch((_) => {})
},
deleteIt (index) {
this.activeComponent.componentContent.product.splice(index, 1)
}
}
}
</script>
<style lang="scss" scoped>
.editorSeckillProduct{
padding: 8px 12px;
.editorList{
.item {
border: 1px solid #e8eaec;
border-radius: 4px;
margin: 10px 0;
}
.addImgBtn {
border-radius: 4px;
background: $mainColor;
text-align: center;
height: 36px;
color: #ffffff;
font-size: 14px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
margin-bottom: 30px;
span {
font-size: 20px;
margin-right: 5px;
}
}
}
}
</style>
@@ -0,0 +1,25 @@
/**
编辑器_折扣专区
*/
<template>
<div class="canvanProductDiscount">
</div>
</template>
<script>
export default {
data () {
return {
obj: {
'title': '折扣专区',
'bcText': 'DISCOUNT ZONE',
'interface': ''
}
}
}
}
</script>
<style lang="scss" scoped>
</style>
@@ -0,0 +1,146 @@
/**
编辑器_人气爆款模块
*/
<template>
<div class="editorNewProduct">
<h2>人气爆款</h2>
<ul class="editorList">
<draggable v-model="activeComponent.componentContent.product">
<li
class="item"
v-for="(item, index) in activeComponent.componentContent.product"
:key="index"
>
<DraggableSlot :obj="item" :index="index" @deleteIt="deleteIt">
<div class="addContent">
<ToolSingleImg
v-if="item.pic !== undefined && item.pic !== null"
:imageUrl.sync="item.pic" />
<div class="titleBox">{{ item.title }}</div>
<el-input
placeholder="描述"
resize="none"
v-model="item.des"
/>
<div class="titleBox">{{ '商品id' }}</div>
<el-input
placeholder="请输入新的内容"
resize="none"
v-model="item.id"
/>
<div class="titleBox">{{ '商品名称' }}</div>
<el-input
placeholder="请输入新的内容"
resize="none"
v-model="item.storeName"
/>
<div class="titleBox">{{ '商品价格' }}</div>
<el-input
placeholder="请输入新的内容"
resize="none"
v-model="item.price"
/>
</div>
<div @click="deleteItem(item, index)" class="deleteItem">
<span class="iconfont">&#xe633;</span>删除内容
</div>
</DraggableSlot>
</li>
</draggable>
<div
class="addImgBtn"
@click="addImgText(activeComponent.componentContent.product.length)">
<span class="iconfont">&#xe64a;</span>添加图文
</div>
</ul>
<el-dialog
title="提示"
:visible.sync="dialogVisible"
width="30%"
:before-close="deleteItem"
>
<span>点击确定删除此项</span>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false"> </el-button>
<el-button type="primary" @click="dialogVisible = false"
> </el-button
>
</span>
</el-dialog>
<el-dialog :visible.sync="dialogImageVisible">
<img width="100%" :src="dialogImageUrl" alt="" />
</el-dialog>
</div>
</template>
<script>
import Draggable from 'vuedraggable'
import { toolMixin } from '@/mixins/tool.js'
import ToolSingleImg from '@/views/theme/components/rootcompToolbar/toolModule/tool-single-img.vue'
import DraggableSlot from '@/views/theme/components/rootcompToolbar/pc/components/draggableSlot.vue'
export default {
name: 'ProductNew',
mixins: [toolMixin],
components: {Draggable, ToolSingleImg, DraggableSlot},
data () {
return {
dialogVisible: false,
dialogImageVisible: false,
dialogImageUrl: null
}
},
methods: {
// 添加图文
addImgText (index) {
this.activeComponent.componentContent.product.push({
'title': `爆款商品${index + 1}`,
'type': 0,
'id': '',
'pic': '',
'storeName': '',
'price': ''
})
},
deleteItem (item, index) {
this.$confirm('确定删除此项?')
.then((_) => {
this.activeComponent.componentContent.product.splice(index, 1)
})
.catch((_) => {})
},
deleteIt (index) {
this.activeComponent.componentContent.product.splice(index, 1)
}
}
}
</script>
<style lang="scss" scoped>
.editorNewProduct{
padding: 8px 12px;
.editorList{
.item {
border: 1px solid #e8eaec;
border-radius: 4px;
margin: 10px 0;
}
.addImgBtn {
border-radius: 4px;
background: $mainColor;
text-align: center;
height: 36px;
color: #ffffff;
font-size: 14px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
margin-bottom: 30px;
span {
font-size: 20px;
margin-right: 5px;
}
}
}
}
</style>
@@ -0,0 +1,147 @@
/**
编辑器_新品首发模块
*/
<template>
<div class="editorNewProduct">
<h2>新品首发</h2>
<ul class="editorList">
<draggable v-model="activeComponent.componentContent.product">
<li
class="item"
v-for="(item, index) in activeComponent.componentContent.product"
:key="index"
>
<DraggableSlot :obj="item" :index="index" @deleteIt="deleteIt">
<div class="addContent">
<ToolSingleImg
v-if="item.pic !== undefined && item.pic !== null"
:imageUrl.sync="item.pic" />
<div class="titleBox">{{ item.title }}</div>
<el-input
placeholder="描述"
resize="none"
v-model="item.des"
/>
<div class="titleBox">{{ '商品id' }}</div>
<el-input
placeholder="请输入新的内容"
resize="none"
v-model="item.id"
/>
<div class="titleBox">{{ '商品名称' }}</div>
<el-input
placeholder="请输入新的内容"
resize="none"
v-model="item.storeName"
/>
<div class="titleBox">{{ '商品价格' }}</div>
<el-input
placeholder="请输入新的内容"
resize="none"
v-model="item.price"
/>
</div>
<div @click="deleteItem(item, index)" class="deleteItem">
<span class="iconfont">&#xe633;</span>删除内容
</div>
</DraggableSlot>
</li>
</draggable>
<div
class="addImgBtn"
@click="addImgText(activeComponent.componentContent.product.length)">
<span class="iconfont">&#xe64a;</span>添加图文
</div>
</ul>
<el-dialog
title="提示"
:visible.sync="dialogVisible"
width="30%"
:before-close="deleteItem"
>
<span>点击确定删除此项</span>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false"> </el-button>
<el-button type="primary" @click="dialogVisible = false"
> </el-button
>
</span>
</el-dialog>
<el-dialog :visible.sync="dialogImageVisible">
<img width="100%" :src="dialogImageUrl" alt="" />
</el-dialog>
</div>
</template>
<script>
import Draggable from 'vuedraggable'
import { toolMixin } from '@/mixins/tool.js'
import ToolSingleImg from '@/views/theme/components/rootcompToolbar/toolModule/tool-single-img.vue'
import DraggableSlot from '@/views/theme/components/rootcompToolbar/pc/components/draggableSlot.vue'
export default {
name: 'ProductNew',
mixins: [toolMixin],
components: {Draggable, ToolSingleImg, DraggableSlot},
data () {
return {
dialogVisible: false,
dialogImageVisible: false,
dialogImageUrl: null
}
},
methods: {
// 添加图文
addImgText (index) {
console.log(index)
this.activeComponent.componentContent.product.push({
'title': `新款商品${index + 1}`,
'type': 0,
'id': '',
'pic': '',
'storeName': '',
'price': ''
})
},
deleteItem (item, index) {
this.$confirm('确定删除此项?')
.then((_) => {
this.activeComponent.componentContent.product.splice(index, 1)
})
.catch((_) => {})
},
deleteIt (index) {
this.activeComponent.componentContent.product.splice(index, 1)
}
}
}
</script>
<style lang="scss" scoped>
.editorNewProduct{
padding: 8px 12px;
.editorList{
.item {
border: 1px solid #e8eaec;
border-radius: 4px;
margin: 10px 0;
}
.addImgBtn {
border-radius: 4px;
background: $mainColor;
text-align: center;
height: 36px;
color: #ffffff;
font-size: 14px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
margin-bottom: 30px;
span {
font-size: 20px;
margin-right: 5px;
}
}
}
}
</style>
@@ -0,0 +1,147 @@
/**
编辑器_秒杀专区
*/
<template>
<div class="editorSeckillProduct">
<h2>秒杀专区</h2>
<ul class="editorList">
<draggable v-model="activeComponent.componentContent.product">
<li
class="item"
v-for="(item, index) in activeComponent.componentContent.product"
:key="index"
>
<DraggableSlot :obj="item" :index="index" @deleteIt="deleteIt">
<div class="addContent">
<ToolSingleImg
v-if="item.pic !== undefined && item.pic !== null"
:imageUrl.sync="item.pic" />
<div class="titleBox">{{ item.title }}</div>
<el-input
placeholder="描述"
resize="none"
v-model="item.des"
/>
<div class="titleBox">{{ '商品id' }}</div>
<el-input
placeholder="请输入新的内容"
resize="none"
v-model="item.id"
/>
<div class="titleBox">{{ '商品名称' }}</div>
<el-input
placeholder="请输入新的内容"
resize="none"
v-model="item.storeName"
/>
<div class="titleBox">{{ '商品价格' }}</div>
<el-input
placeholder="请输入新的内容"
resize="none"
v-model="item.price"
/>
</div>
<div @click="deleteItem(item, index)" class="deleteItem">
<span class="iconfont">&#xe633;</span>删除内容
</div>
</DraggableSlot>
</li>
</draggable>
<div
class="addImgBtn"
@click="addImgText(activeComponent.componentContent.product.length)">
<span class="iconfont">&#xe64a;</span>添加图文
</div>
</ul>
<el-dialog
title="提示"
:visible.sync="dialogVisible"
width="30%"
:before-close="deleteItem"
>
<span>点击确定删除此项</span>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false"> </el-button>
<el-button type="primary" @click="dialogVisible = false"
> </el-button
>
</span>
</el-dialog>
<el-dialog :visible.sync="dialogImageVisible">
<img width="100%" :src="dialogImageUrl" alt="" />
</el-dialog>
</div>
</template>
<script>
import Draggable from 'vuedraggable'
import { toolMixin } from '@/mixins/tool.js'
import ToolSingleImg from '@/views/theme/components/rootcompToolbar/toolModule/tool-single-img.vue'
import DraggableSlot from '@/views/theme/components/rootcompToolbar/pc/components/draggableSlot.vue'
export default {
name: 'ProductNew',
mixins: [toolMixin],
components: {Draggable, ToolSingleImg, DraggableSlot},
data () {
return {
dialogVisible: false,
dialogImageVisible: false,
dialogImageUrl: null
}
},
methods: {
// 添加图文
addImgText (index) {
console.log(index)
this.activeComponent.componentContent.product.push({
'title': `秒杀商品${index + 1}`,
'type': 1,
'id': '',
'pic': '',
'storeName': '',
'price': ''
})
},
deleteItem (item, index) {
this.$confirm('确定删除此项?')
.then((_) => {
this.activeComponent.componentContent.product.splice(index, 1)
})
.catch((_) => {})
},
deleteIt (index) {
this.activeComponent.componentContent.product.splice(index, 1)
}
}
}
</script>
<style lang="scss">
.editorSeckillProduct{
padding: 8px 12px;
.editorList{
.item {
border: 1px solid #e8eaec;
border-radius: 4px;
margin: 10px 0;
}
.addImgBtn {
border-radius: 4px;
background: $mainColor;
text-align: center;
height: 36px;
color: #ffffff;
font-size: 14px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
margin-bottom: 30px;
span {
font-size: 20px;
margin-right: 5px;
}
}
}
}
</style>
@@ -0,0 +1,65 @@
/**
右上角角标组件
*/
<template>
<div class="canvasBadge">
<sup class="badge red" :class="bgwidth" v-if="sum != 0">{{ sum }}</sup>
</div>
</template>
<script>
export default {
name: 'zxBadge',
props: {
num: Number,
size: String
},
computed: {
sum: function () {
if (this.num > 99) {
return '99+'
} else {
return this.num
}
},
bgwidth: function () {
if (!this.size) {
return 'small'
} else {
return this.size
}
}
}
}
</script>
<style lang="scss">
.canvasBadge{
text-align: center;
.badge{
border-radius: 48px;
padding: 0 3px;
}
.red{
color: #FFFFFF;
background-color: #FF0000;
}
.big{
width: 48px;
height: 48px;
line-height: 32px;
}
.regular{
font-size: 14px;
width: 32px;
height: 32px;
line-height: 32px;
}
.small{
font-size: 12px;
width: 18px;
height: 18px;
line-height: 18px;
}
}
</style>
@@ -0,0 +1,159 @@
/**
画布编辑器插槽
*/
<template>
<div class="draggableSlot">
<div class="draggableItem">
<div class="listItemBox">
<!-- 标题 -->
<div class="addImgTit" @click="openAddImg(obj, index)">
<div class="titLeft">
<span class="iconfont">&#xe703;</span>
<span class="iconfont">&#xe64a;</span>
<span>{{ obj.title }}</span>
</div>
<div class="titRight">
<span class="iconfont"
@click.stop="deleteItem(obj, index)"
>&#xe633;</span>
<span
v-html="imgCurrent === index ? '&#xe660;' : '&#xe695;'"
class="iconfont"
></span>
</div>
</div>
<!-- 编辑部分 -->
<div class="addBox" v-show="imgCurrent === index">
<slot></slot>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
props: {
obj: Object,
index: Number
},
data () {
return {
imgCurrent: null
}
},
methods: {
openAddImg (item, index) {
if (this.imgCurrent === index) {
this.imgCurrent = null
return false
}
this.imgCurrent = index
},
// 删除内容
deleteItem (item, index) {
this.$confirm('确定删除此项?')
.then((_) => {
this.$emit('deleteIt', index)
})
.catch((_) => {})
}
}
}
</script>
<style lang="scss">
.draggableSlot{
.listItemBox {
.addImgTit {
padding: 10px;
display: flex;
justify-content: space-between;
align-items: center;
background: #f6f7f9;
cursor: pointer;
.titLeft {
display: flex;
align-items: center;
span {
color: #7d7e80;
}
span:nth-child(1) {
font-size: 28px;
}
span:nth-child(2) {
font-size: 25px;
margin: 0 6px;
}
span:nth-child(3) {
font-size: 14px;
}
}
.titRight {
display: flex;
align-items: center;
span:nth-child(1) {
width: 40px;
text-align: center;
display: block;
height: 30px;
line-height: 30px;
}
}
}
.addContent {
margin-top: 10px;
padding: 5px 13px;
.imgIsShow {
display: flex;
justify-content: space-between;
margin: 18px 0 22px 0;
span {
font-size: 14px;
color: #666666;
}
}
.titleBox{
margin: 10px 0;
}
.deleteItem {
border-radius: 4px;
background: $mainColor;
text-align: center;
height: 36px;
color: #ffffff;
font-size: 14px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
margin-bottom: 10px;
span {
font-size: 18px;
color: #ffffff;
margin-right: 5px;
}
}
}
.deleteItem {
margin-top: 10px;
padding: 10px;
display: flex;
align-items: center;
justify-content: center;
background: #f6f7f9;
cursor: pointer;
color: $mainColor;
font-size: 14px;
span {
font-size: 16px;
margin-right: 5px;
}
&:hover{
color: #f6f7f9;
background: $mainColor;;
}
}
}
}
</style>
@@ -0,0 +1,32 @@
<template>
<el-cascader style="width: 100%"
ref="cascader"
:options="categoryList"
:props="{ checkStrictly: true,label: 'categoryName',value: 'id',children: 'childs' }"
clearable></el-cascader>
</template>
<script>
import { checkEmptyChild } from '@/mixins/tool.js'
import { getClassify } from '@/api/canvasApi.js'
export default {
name: 'category-select',
data() {
return {
categoryList: []
}
},
mounted() {
this.getCategory()
},
methods: {
// 获取类别
getCategory() {
getClassify().then(res => {
this.categoryList = res.data
checkEmptyChild(this.categoryList)
})
}
}
}
</script>
@@ -0,0 +1,121 @@
<template>
<div class="product-select">
<el-form :inline="true" :model="formData" class="demo-form-inline">
<el-form-item label="">
<el-input v-model="formData.keyword" placeholder="店铺名称/商品ID/商品分组"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onSubmit">查询</el-button>
</el-form-item>
</el-form>
<el-table
:data="tableData"
max-height="500"
border
style="width: 100%"
@selection-change="handleSelectionChange">
<el-table-column type="selection" width="55"></el-table-column>
<el-table-column prop="name" label="优惠券名称" width="180"></el-table-column>
<el-table-column prop="productId" label="适用商品"></el-table-column>
<el-table-column prop="price" label="优惠内容"></el-table-column>
<el-table-column prop="originalPrice" label="领取人限制" width="100"></el-table-column>
<el-table-column prop="stockNumber" label="限领次数"></el-table-column>
<el-table-column prop="number" label="剩余库存"></el-table-column>
<el-table-column prop="number" label="状态"></el-table-column>
</el-table>
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="currentPage"
:hide-on-single-page="true"
:page-sizes="[10, 20, 50, 100]"
:page-size="pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="total">
</el-pagination>
</div>
</template>
<script>
import { getProducts } from '@/api/canvasApi.js'
export default {
name: 'coupon-select',
data () {
return {
tableRadio: '',
formData: {
keyword: '',
status: '',
categoryId: ''
},
currentPage: 1,
total: 0,
pageSize: 10,
multipleSelection: [],
tableData: [{
id: 100,
name: '测试'
}]
}
},
mounted () {
// this.getTableData()
},
methods: {
// 获取产品信息
getTableData () {
let params = {
page: this.currentPage,
pageSize: this.pageSize
}
if (this.formData.keyword) {
params.search = this.formData.keyword
}
if (this.formData.status) {
params.shelveState = this.formData.status
}
let nodesObj = this.$refs['cascader'].getCheckedNodes()
if (nodesObj && nodesObj.length !== 0) {
params.classifyId = nodesObj[0].value
}
getProducts(params).then(res => {
this.tableData = res.data.list
this.total = res.data.total
})
},
// 搜索
onSubmit () {
this.getTableData()
},
// 每页条数改变
handleSizeChange (val) {
this.pageSize = val
this.getTableData()
},
// 当前页改变
handleCurrentChange (val) {
this.currentPage = val
this.getTableData()
},
// 多选改变
handleSelectionChange (val) {
this.multipleSelection = val
}
}
}
</script>
<style lang="scss" scoped>
.product-select{
.el-pagination{
padding: 0px;
margin-top: 30px;
}
.el-table{
.img{
width: 80px;
height: 80px;
}
}
}
</style>
@@ -0,0 +1,161 @@
<template>
<div class="product-select">
<el-form :inline="true" :model="formData" class="demo-form-inline">
<el-form-item label="">
<el-input v-model="formData.keyword" placeholder="店铺名称/商品ID/商品分组"></el-input>
</el-form-item>
<el-form-item label="上架状态">
<el-select v-model="formData.status" placeholder="请选择">
<el-option label="全部" value=""></el-option>
<el-option label="上架" value="1"></el-option>
<el-option label="下架" value="0"></el-option>
</el-select>
</el-form-item>
<el-form-item label="官方分类">
<el-cascader
ref="cascader"
v-model="formData.categoryId"
:options="categoryList"
:props="{ checkStrictly: true,label: 'categoryName',value: 'id',children: 'childs' }"
clearable></el-cascader>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onSubmit">查询</el-button>
</el-form-item>
</el-form>
<el-table
:data="tableData"
max-height="500"
border
style="width: 100%">
<el-table-column label="" width="35" align="center">
<template slot-scope="scope">
<el-radio v-model="tableRadio" :label="scope.row"><i></i></el-radio>
</template>
</el-table-column>
<el-table-column label="产品主图" width="180" align="center">
<template slot-scope="scope">
<el-image
style="width: 80px; height: 80px"
:src="scope.row.image"
fit="contain"></el-image>
</template>
</el-table-column>
<el-table-column
prop="productName"
label="产品名称"
width="180"></el-table-column>
<el-table-column
prop="productId"
label="产品ID"></el-table-column>
<el-table-column
prop="price"
label="售价"></el-table-column>
<el-table-column
prop="originalPrice"
label="原价"></el-table-column>
<el-table-column
prop="stockNumber"
label="库存"></el-table-column>
<el-table-column
prop="number"
label="销量"></el-table-column>
</el-table>
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="currentPage"
:hide-on-single-page="true"
:page-sizes="[10, 20, 50, 100]"
:page-size="pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="total">
</el-pagination>
</div>
</template>
<script>
import { checkEmptyChild } from '@/mixins/tool.js'
import { getClassify, getProducts } from '@/api/canvasApi.js'
export default {
name: 'product-select',
data () {
return {
tableRadio: '',
formData: {
keyword: '',
status: '',
categoryId: ''
},
currentPage: 1,
total: 0,
pageSize: 10,
categoryList: [],
tableData: []
}
},
mounted () {
this.getCategory()
this.getTableData()
},
methods: {
// 获取类别
getCategory() {
getClassify().then(res => {
this.categoryList = res.data
checkEmptyChild(this.categoryList)
})
},
// 获取产品信息
getTableData() {
let params = {
page: this.currentPage,
pageSize: this.pageSize
}
if (this.formData.keyword) {
params.search = this.formData.keyword
}
if (this.formData.status) {
params.shelveState = this.formData.status
}
let nodesObj = this.$refs['cascader'].getCheckedNodes()
if (nodesObj && nodesObj.length !== 0) {
params.classifyId = nodesObj[0].value
}
getProducts(params).then(res => {
this.tableData = res.data.list
this.total = res.data.total
})
},
// 搜索
onSubmit () {
this.getTableData()
},
// 每页条数改变
handleSizeChange (val) {
this.pageSize = val
this.getTableData()
},
// 当前页改变
handleCurrentChange (val) {
this.currentPage = val
this.getTableData()
}
}
}
</script>
<style lang="scss" scoped>
.product-select{
.el-pagination{
padding: 0px;
margin-top: 30px;
}
.el-table{
.img{
width: 80px;
height: 80px;
}
}
}
</style>
@@ -0,0 +1,124 @@
<template>
<div class="product-select">
<el-form :inline="true" :model="formData" class="demo-form-inline">
<el-form-item label="">
<el-input v-model="formData.keyword" placeholder="店铺名称"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onSubmit">查询</el-button>
</el-form-item>
</el-form>
<el-table
:data="tableData"
max-height="500"
border
style="width: 100%">
<el-table-column label="" width="35" align="center">
<template slot-scope="scope">
<el-radio v-model="tableRadio" :label="scope.row"><i></i></el-radio>
</template>
</el-table-column>
<el-table-column
prop="shopName"
label="店铺名称">
</el-table-column>
<el-table-column
prop="phone"
label="手机号">
</el-table-column>
</el-table>
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="currentPage"
:page-sizes="[10, 20, 50, 100]"
:page-size="pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="total">
</el-pagination>
</div>
</template>
<script>
import { getShops } from '@/api/canvasApi.js'
export default {
name: 'shop-select',
props: {
categoryList: {
type: Array,
default: () => [
{
value: '/index',
label: '首页'
},
{
value: '/category',
label: '分类页面'
},
{
value: '/shop',
label: '店辅主页'
},
{
value: '/detail',
label: '商品详情'
}
]
}
},
data () {
return {
tableRadio: '',
currentPage: 1,
total: 0,
pageSize: 10,
formData: {
keyword: ''
},
tableData: []
}
},
mounted () {
this.getTableData()
},
methods: {
// 获取店辅信息
getTableData () {
let params = {
page: this.currentPage,
pageSize: this.pageSize
}
if (this.formData.keyword) {
params.search = this.formData.keyword
}
getShops(params).then(res => {
this.tableData = res.data.list
this.total = res.data.total
})
},
// 搜索
onSubmit () {
this.getTableData()
},
// 每页条数改变
handleSizeChange (val) {
this.pageSize = val
this.getTableData()
},
// 当前页改变
handleCurrentChange (val) {
this.currentPage = val
this.getTableData()
}
}
}
</script>
<style lang="scss" scoped>
.product-select{
.el-pagination{
padding: 0px;
margin-top: 30px;
}
}
</style>
@@ -0,0 +1,110 @@
<template>
<div class="tool-coupon">
<div class="selectMode">
<div>添加优惠券</div>
<el-radio-group class="modeRight" v-model="modeValue" @change="modeChange">
<el-radio label="1">手动添加</el-radio>
<div class="mode2">
<el-radio label="2">自动获取</el-radio>
<el-tooltip class="item" effect="dark" content="系统自动获取仅设置为“公开领取”的店铺优惠券,新创建的券排在前面" placement="bottom">
<span class="iconfont">&#xe60a;</span>
</el-tooltip>
</div>
</el-radio-group>
</div>
<div class="addCouponBox" v-show="couponBtnVisible">
<div class="addCouponBtn" @click="addCoupon">
<i class="iconfont">&#xe685;</i><span>添加优惠券</span>
</div>
</div>
<el-dialog title="选择优惠券" :visible.sync="couponDialogVisible" width="1000">
<coupon-select ref="couponSelect"></coupon-select>
<span slot="footer" class="dialog-footer">
<el-button @click="couponDialogVisible = false"> </el-button>
<el-button type="primary" @click="couponChanged"> </el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import CouponSelect from '@/views/theme/components/rootcompToolbar/toolModule/coupon-select.vue'
export default {
name: 'tool-coupon',
components: { CouponSelect },
data () {
return {
modeValue: '1', // 添加优惠券方式
couponBtnVisible: true,
selectedCoupon: [],
couponDialogVisible: false
}
},
methods: {
// 添加优惠券
addCoupon () {
this.couponDialogVisible = true
this.$refs.couponSelect.multipleSelection = []
},
couponChanged () {
this.selectedCoupon = this.$refs.couponSelect.multipleSelection
this.couponDialogVisible = false
console.log(this.selectedCoupon)
},
modeChange (val) {
this.couponBtnVisible = val === '1'
}
}
}
</script>
<style lang="scss" scoped>
.tool-coupon{
padding-bottom: 20px;
}
.selectMode {
display: flex;
justify-content: space-between;
align-items: center;
.modeRight {
display: flex;
.iconfont{
cursor: pointer;
}
}
>>> .el-radio {
margin-right: 0;
}
>>> .el-radio__label {
padding-left: 5px;
}
.mode2 {
margin-left: 10px;
span {
font-size: 14px;
color: #999999;
}
}
}
.addCouponBox {
background: #F6F7F9;
padding: 10px 13px;
margin: 20px 0 0;
.addCouponBtn {
display: flex;
justify-content: center;
align-items: center;
height: 40px;
line-height: 40px;
background: #ffffff;
font-size: 14px;
color: $mainColor;
border: 1px solid $mainColor;
box-sizing: border-box;
cursor: pointer;
i {
margin-right: 10px;
}
}
}
</style>
@@ -0,0 +1,147 @@
<template>
<div class="module-box link-select">
<div class="module-box__title">
<label class="module-box__label">{{title}}</label>
</div>
<div class="link-select__confirm">
<div class="btn" v-if="selectedCategoryList && selectedCategoryList.length === 0" @click="openDialog">
<span class="iconfont">&#xe685;</span> 添加类别
</div>
<div class="info" v-else>
<div><span>{{selectedCategoryList[0].categoryName}}</span><span v-if="selectedCategoryList.length > 1">+{{selectedCategoryList.length-1}}</span></div>
<div class="operation">
<i class="iconfont" @click="openDialog">&#xe66c;</i>
<i class="iconfont" @click="deleteCategory">&#xe633;</i>
</div>
</div>
</div>
<el-dialog width="500" title="选择类别" :visible.sync="categoryVisible">
<el-select
v-model="categoryValue"
multiple
collapse-tags
placeholder="请选择">
<el-option
v-for="item in categoryList"
:key="item.id"
:label="item.categoryName"
:value="item.id">
</el-option>
</el-select>
<span slot="footer" class="dialog-footer">
<el-button @click="categoryVisible = false"> </el-button>
<el-button type="primary" @click="categoryChanged"> </el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import { getClassify } from '@/api/canvasApi.js'
export default {
name: 'tool-select-category',
data () {
return {
selectName: '',
categoryValue: [],
selectedCategoryList: [],
categoryList: [],
categoryVisible: false
}
},
props: {
title: {
type: String,
default: '链接'
},
category: {
type: Array,
default: () => []
}
},
mounted () {
this.getCategory()
this.selectedCategoryList = this.category
},
methods: {
// 获取类别
getCategory () {
getClassify().then(res => {
this.categoryList = res.data
})
},
// 打开添加弹窗
openDialog () {
this.categoryVisible = true
},
// 类别选择
categoryChanged () {
this.categoryVisible = false
this.selectedCategoryList = this.categoryList.filter((item) => {
for (let i = 0; i < this.categoryValue.length; i++) {
if (this.categoryValue[i] === item.id) {
return true
}
}
})
this.$emit('update:category', this.selectedCategoryList)
},
// 删除选择
deleteCategory () {
this.categoryValue = []
this.$emit('update:category', [])
}
}
}
</script>
<style lang="scss" scoped>
.link-select{
&__select{
width: 100%;
}
&__confirm{
margin-top: 10px;
.btn{
text-align: center;
background-color: $mainColor;
color: #fff;
height: 36px;
line-height: 36px;
border-radius: 4px;
cursor: pointer;
}
.info{
height: 36px;
line-height: 36px;
border-radius: 4px;
padding: 0 10px;
border:1px solid $mainColor;
display: flex;
justify-content: space-between;
span{
background-color: #f4f4f5;
border:1px solid #e9e9eb;
color: #909399;
height: 26px;
padding: 0 8px;
line-height: 24px;
border-radius: 4px;
margin: 5px 6px 5px 0px;
display: inline-block;
}
.operation{
float: right;
i{
width: 35px;
display: inline-block;
height: 35px;
line-height: 35px;
text-align: center;
cursor: pointer;
}
}
}
}
}
</style>
@@ -0,0 +1,261 @@
<template>
<div class="module-box link-select">
<div class="module-box__title">
<label class="module-box__label">{{title}}</label>
</div>
<el-select class="link-select__select" :popper-append-to-body="false" v-model="selsectValue" placeholder="请选择跳转到的页面" @change="selectChanged">
<el-option
v-for="item in options"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
<div class="link-select__confirm" v-show="confirmBtnVisible">
<div class="btn" v-if="!selectName" @click="openDialog">
<span class="iconfont">&#xe685;</span> 添加{{typeText}}
</div>
<div class="info" v-else>
<span class="text">{{typeText}}</span>
<span class="name">{{selectName}}</span>
<span class="iconfont" @click="openDialog">&#xe66c;</span>
<span class="iconfont" @click="delSelect">&#xe651;</span>
</div>
</div>
<el-dialog width="600px" title="选择类别" :visible.sync="categoryVisible">
<category-select ref="categorySelect"></category-select>
<span slot="footer" class="dialog-footer">
<el-button @click="categoryVisible = false"> </el-button>
<el-button type="primary" @click="categoryChanged"> </el-button>
</span>
</el-dialog>
<el-dialog title="选择商品" :visible.sync="productVisible">
<product-select ref="productSelect"></product-select>
<span slot="footer" class="dialog-footer">
<el-button @click="productVisible = false"> </el-button>
<el-button type="primary" @click="productChanged"> </el-button>
</span>
</el-dialog>
<el-dialog title="选择店辅" :visible.sync="shopVisible">
<shop-select ref="shopSelect"></shop-select>
<span slot="footer" class="dialog-footer">
<el-button @click="shopVisible = false"> </el-button>
<el-button type="primary" @click="shopChanged"> </el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import ProductSelect from './product-select'
import ShopSelect from './shop-select'
import CategorySelect from './category-select'
export default {
name: 'tool-select-link',
components: { CategorySelect, ShopSelect, ProductSelect },
data () {
return {
selsectValue: '',
confirmBtnVisible: false,
selectName: '',
typeText: '',
productVisible: false,
shopVisible: false,
categoryVisible: false
}
},
props: {
title: {
type: String,
default: '链接'
},
linkObj: {
type: Object,
default: () => ({
selsectValue: '',
selectName: '',
typeText: '',
url: ''
})
},
options: {
type: Array,
default: () => [
{
value: '/index',
label: '首页'
},
{
value: '/category',
label: '分类页面'
},
{
value: '/shop',
label: '店辅主页'
},
{
value: '/detail',
label: '商品详情'
}
]
}
},
mounted () {
this.selsectValue = this.linkObj.selsectValue
this.selectName = this.linkObj.selectName
this.typeText = this.linkObj.typeText
this.confirmBtnVisible = this.selsectValue !== '/index'
},
methods: {
// 链接选择
selectChanged (value) {
this.categoryVisible = false
this.shopVisible = false
this.productVisible = false
this.confirmBtnVisible = true
this.selectName = ''
this.typeText = ''
switch (value) {
case '/category':
this.typeText = '类别'
break
case '/shop':
this.typeText = '店辅'
break
case '/detail':
this.typeText = '商品'
break
default:
this.confirmBtnVisible = false
let linkObj = {
selsectValue: this.selsectValue,
selectName: '',
typeText: '',
url: '/'
}
this.$emit('update:linkObj', linkObj)
}
},
// 打开添加弹窗
openDialog () {
switch (this.typeText) {
case '类别':
this.categoryVisible = true
break
case '店辅':
this.shopVisible = true
break
case '商品':
this.productVisible = true
break
}
},
// 类别选择
categoryChanged () {
let nodesObj = this.$refs.categorySelect.$refs['cascader'].getCheckedNodes()
if (nodesObj) {
var data = nodesObj[0].data
this.selectName = nodesObj[0].label
this.categoryVisible = false
let linkObj = {
selsectValue: this.selsectValue,
selectName: this.selectName,
typeText: this.typeText,
data: data
}
this.$emit('update:linkObj', linkObj)
}
},
// 商品选择
productChanged () {
var data = this.$refs.productSelect.tableRadio
this.productVisible = false
this.selectName = this.$refs.productSelect.tableRadio.productName
let linkObj = {
selsectValue: this.selsectValue,
selectName: this.selectName,
typeText: this.typeText,
data: data
}
this.$emit('update:linkObj', linkObj)
},
// 店辅选择
shopChanged () {
var data = this.$refs.shopSelect.tableRadio
this.shopVisible = false
this.selectName = this.$refs.shopSelect.tableRadio.shopName
let linkObj = {
selsectValue: this.selsectValue,
selectName: this.selectName,
typeText: this.typeText,
data: data
}
this.$emit('update:linkObj', linkObj)
},
// 删除选择
delSelect () {
let linkObj = {
selsectValue: '',
selectName: '',
typeText: '',
data: {}
}
this.$emit('update:linkObj', linkObj)
}
},
watch: {
linkObj: {
handler (newVal, oldVal) {
this.selsectValue = newVal.selsectValue
this.selectName = newVal.selectName
this.typeText = newVal.typeText
this.confirmBtnVisible = this.selsectValue !== '/index'
},
deep: true
}
}
}
</script>
<style lang="scss" scoped>
.link-select{
&__select{
width: 100%;
}
&__confirm{
margin-top: 10px;
.btn{
text-align: center;
background-color: $mainColor;
color: #fff;
height: 36px;
line-height: 36px;
border-radius: 4px;
cursor: pointer;
}
.info{
height: 36px;
line-height: 36px;
border-radius: 4px;
padding: 0 10px;
border:1px solid $mainColor;
display: flex;
.text{
color: $mainColor;
}
.name{
flex: 1;
margin-left: 10px;
overflow: hidden;
text-overflow:ellipsis;
white-space: nowrap;
}
.iconfont{
margin-left: 10px;
cursor: pointer;
color: #666;
}
}
}
}
</style>
@@ -0,0 +1,56 @@
<template>
<div class="module-box link-select">
<div class="module-box__title">
<label class="module-box__label">{{title}}</label>
</div>
<el-select class="link-select__select" :popper-append-to-body="false" v-model="selsectValue" placeholder="请选择跳转到的页面" @change="selectChanged">
<el-option
v-for="item in options"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</div>
</template>
<script>
export default {
name: 'tool-select',
data () {
return {
selsectValue: ''
}
},
props: {
title: {
type: String,
default: '标题'
},
linkValue: {
type: String,
default: ''
},
options: {
type: Array,
default: () => []
}
},
mounted () {
this.selsectValue = this.linkValue // props 不能直接修改
},
methods: {
selectChanged (value) {
this.$emit('update:linkValue', value)
}
}
}
</script>
<style lang="scss" scoped>
.link-select{
&__select{
width: 100%;
}
}
</style>
@@ -0,0 +1,123 @@
<template>
<div class="module-box single-img">
<div class="single-img__box">
<el-upload
drag
:action="fileUploadURL"
:on-success="handleAvatarSuccess"
:before-upload="beforeAvatarUpload"
:show-file-list="false"
>
<img v-if="imageUrl" :src="imageUrl" class="single-img__img">
<i v-else class="el-icon-upload">
<div class="el-upload__text"><em>选择图片</em></div>
<div class="el-upload__tip" slot="tip">{{tip}}</div>
</i>
</el-upload>
<div class="overlay" v-if="imageUrl">
<!-- <i class="iconfont icon-chakan" @click="showImage"></i>
<i class="iconfont icon-shanchu1" @click="delImage"></i> -->
</div>
</div>
<el-dialog title="图片展示" :visible.sync="dialogVisible">
<img width="100%" :src="dialogImageUrl" alt="">
</el-dialog>
</div>
</template>
<script>
export default {
name: 'tool-single-img',
data () {
return {
dialogVisible: false,
dialogImageUrl: '',
fileUploadURL: ''
}
},
props: {
imageUrl: {
type: String,
default: ''
},
tip: {
type: String,
default: '建议尺寸: 1080*900px, 小于1MB'
}
},
mounted () {
this.fileUploadURL = process.env.VUE_APP_BASE_API +'/api/canvas/upload?name=demo&type=console'
},
methods: {
handleAvatarSuccess (res, file) {
this.$emit('update:imageUrl', res.link)
},
beforeAvatarUpload (file) {
const isLt1M = file.size / 1024 / 1024 < 1
if (!isLt1M) {
this.$message.error('上传图片大小不能超过 1MB!')
}
return isLt1M
},
showImage () {
this.dialogImageUrl = this.imageUrl
this.dialogVisible = true
},
delImage () {
this.$emit('update:imageUrl', '')
}
}
}
</script>
<style lang="scss" scoped>
.single-img{
&__box{
position: relative;
>>> .el-upload{
width: 100%;
}
>>> .el-upload-dragger{
width: 100%;
.el-upload__text{
line-height: 40px;
}
.el-upload__tip{
line-height: 1em;
}
}
.overlay{
display: none;
}
&:hover .overlay{
position: absolute;
top:0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0,0,0,0.3);
color: #fff;
display: flex;
justify-content: center;
align-items: center;
.iconfont{
padding: 5px;
margin: 0 5px;
font-size: 20px;
cursor: pointer;
}
}
}
&__img{
position: absolute;
max-width: 100%;
height: 100%;
max-height: 100%;
margin: auto;
top: 0;
right: 0;
bottom: 0;
left: 0;
}
}
</style>
@@ -0,0 +1,190 @@
<template>
<div class="toolWarp">
<!-------------------------Mobile---------------------------------->
<!-- 店铺头部-->
<div class="toolPanel" v-if="activeComponent.type == 'header'">
<shop-top></shop-top>
</div>
<!-- 轮播图 -->
<div class="toolPanel" v-if="activeComponent.type == 'banner'">
<banner></banner>
</div>
<!-- 菜单 -->
<div class="toolPanel" v-if="activeComponent.type == 'menu'">
<menus></menus>
</div>
<!-- 公告 -->
<div class="toolPanel" v-if="activeComponent.type == 'adv'">
<adv></adv>
</div>
<!-- 菜单 -->
<div class="toolPanel" v-if="activeComponent.type == 'noticeBar'">
<noticeBar></noticeBar>
</div>
<!-- 文本控件-->
<div class="toolPanel" v-if="activeComponent.type == 'text'">
<text-tool></text-tool>
</div>
<!-- 视频控件-->
<div class="toolPanel" v-if="activeComponent.type == 'videoBox'">
<video-tool></video-tool>
</div>
<!-- 图文控件-->
<div class="toolPanel" v-if="activeComponent.type == 'imageText'">
<image-text></image-text>
</div>
<!-- 自定义控件-->
<div class="toolPanel" v-if="activeComponent.type == 'custom'">
<custom-tool></custom-tool>
</div>
<!-- 品牌列表-->
<div class="toolPanel" v-if="activeComponent.type == 'brandList'">
<brand-list></brand-list>
</div>
<!-- 图文列表-->
<div class="toolPanel" v-if="activeComponent.type == 'imageTextList'">
<image-text-list></image-text-list>
</div>
<!-- 优惠券-->
<div class="toolPanel" v-if="activeComponent.type == 'coupon'">
<coupon-tool></coupon-tool>
</div>
<!-- 类别列表-->
<div class="toolPanel" v-if="activeComponent.type == 'categoryList'">
<category-list></category-list>
</div>
<!-- 商品列表-->
<div class="toolPanel" v-if="activeComponent.type == 'productList'">
<product-list></product-list>
</div>
<!-------------------------PC---------------------------------->
<!-- 个人中心导航 -->
<div class="toolPanel" v-if="activeComponent.type == 'NavPersonal'">
<!-- <NavPersonal /> -->
</div>
<!-- 分类导航 -->
<div class="toolPanel" v-if="activeComponent.type == 'NavType'">
<NavType />
</div>
<!-- 轮播图 -->
<div class="toolPanel" v-if="activeComponent.type == 'PcBanner'">
<PcBanner />
</div>
<!-- 底部版权相关 -->
<div class="toolPanel" v-if="activeComponent.type == 'Footer'">
<PcFooter />
</div>
<!-- 新品首发 -->
<div class="toolPanel" v-if="activeComponent.type == 'ProductNew'">
<!-- <ProductNew /> -->
</div>
<!-- 人气爆款 -->
<div class="toolPanel" v-if="activeComponent.type == 'ProductHot'">
<!-- <ProductHot /> -->
</div>
<!-- 秒杀专区 -->
<div class="toolPanel" v-if="activeComponent.type == 'ProductSeckill'">
<!-- <ProductSeckill /> -->
</div>
<!-- 拼团专区 -->
<div class="toolPanel" v-if="activeComponent.type == 'ProductComb'">
<!-- <ProductComb /> -->
</div>
<!-- 折扣专区 -->
<div class="toolPanel" v-if="activeComponent.type == 'ProductDiscount'">
<!-- <ProductDiscount /> -->
</div>
<!-- 砍价专区 -->
<div class="toolPanel" v-if="activeComponent.type == 'ProductBargin'">
<!-- <ProductBargin /> -->
</div>
</div>
</template>
<script>
// mobile
import shopTop from '@/views/theme/components/rootcompToolbar/mobile/shopTop.vue'
import banner from '@/views/theme/components/rootcompToolbar/mobile/banner.vue'
import menus from '@/views/theme/components/rootcompToolbar/mobile/menus.vue'
import adv from '@/views/theme/components/rootcompToolbar/mobile/adv.vue'
import noticeBar from '@/views/theme/components/rootcompToolbar/mobile/noticeBar.vue'
import textTool from '@/views/theme/components/rootcompToolbar/mobile/textTool.vue'
import videoTool from '@/views/theme/components/rootcompToolbar/mobile/videoTool.vue'
import imageText from '@/views/theme/components/rootcompToolbar/mobile/imageText.vue'
import customTool from '@/views/theme/components/rootcompToolbar/mobile/customTool.vue'
import brandList from '@/views/theme/components/rootcompToolbar/mobile/brandList.vue'
import imageTextList from '@/views/theme/components/rootcompToolbar/mobile/imageTextList.vue'
import couponTool from '@/views/theme/components/rootcompToolbar/mobile/couponTool.vue'
import categoryList from '@/views/theme/components/rootcompToolbar/mobile/categoryTool.vue'
import productList from '@/views/theme/components/rootcompToolbar/mobile/productList.vue'
// pc 21.4月单商户改版
import NavPersonal from '@/views/theme/components/rootcompToolbar/pc/NavPersonal'
import NavType from '@/views/theme/components/rootcompToolbar/pc/NavType'
import PcBanner from '@/views/theme/components/rootcompToolbar/pc/Banner'
import PcFooter from '@/views/theme/components/rootcompToolbar/pc/Footer'
import ProductNew from '@/views/theme/components/rootcompToolbar/pc/ProductNew'
import ProductHot from '@/views/theme/components/rootcompToolbar/pc/ProductHot'
import ProductSeckill from '@/views/theme/components/rootcompToolbar/pc/ProductSeckill'
import ProductComb from '@/views/theme/components/rootcompToolbar/pc/ProductComb'
import ProductDiscount from '@/views/theme/components/rootcompToolbar/pc/ProductDiscount'
import ProductBargin from '@/views/theme/components/rootcompToolbar/pc/ProductBargin'
import { mapGetters } from 'vuex'
export default {
components: {
shopTop,
banner,
menus,
adv,
noticeBar,
textTool,
videoTool,
imageText,
customTool,
brandList,
imageTextList,
couponTool,
categoryList,
productList,
NavPersonal,
NavType,
PcBanner,
PcFooter,
ProductNew,
ProductHot,
ProductSeckill,
ProductComb,
ProductDiscount,
ProductBargin
},
computed: {
...mapGetters(['activeComponent'])
}
}
</script>
<style lang="scss" scoped>
.toolWarp {
width: 320px;
}
.toolPanel {
width: 320px;
}
.toolPanel::-webkit-scrollbar {
width: 4px;
height: 1px;
}
.toolPanel::-webkit-scrollbar-thumb {
border-radius: 4px;
-webkit-box-shadow: inset 0 0 5px rgba(156, 148, 148, 0.2);
background: #cdcdcd;
}
.toolPanel::-webkit-scrollbar-track {
-webkit-box-shadow: inset 0 0 5px rgba(158, 150, 150, 0.2);
border-radius: 4px;
background: #ededed;
}
</style>
+226
View File
@@ -0,0 +1,226 @@
<template>
<div class="containerMall">
<div class="topBox">
<!-- <a class="btn-black">返回店铺</a> -->
<ul>
<li
v-for="(item, index) in deviceList"
:key="index"
@click="toggleDevice(item.id)"
:class="{ on: terminal == item.id }"
>
<!-- <i class="iconfont" :class="'icon-' + item.name"></i> -->
<i class="iconfont" :class="'icon-' + item.name"></i>
</li>
</ul>
<el-button class="btn-save"
type="primary" @click="canvasSave">保存画布</el-button>
</div>
<div class="bottomWarp">
<div class="leftBox">
<LeftBar />
</div>
<div class="mainContentWarp">
<div class="mainContent" :class="'view-' + terminal">
<CereshopLayout :terminal="terminal"></CereshopLayout>
</div>
</div>
<div class="RightBox">
<ToolPanel />
</div>
</div>
</div>
</template>
<script>
import { mapGetters, mapMutations } from 'vuex'
import LeftBar from '../components/leftBar/panel.vue'
import ToolPanel from '@/views/theme/components/rootcompToolbar/toolPanel.vue'
import CereshopLayout from '../components/canvasEditPage'
import {
getCanvasData,
getProducts,
saveCanvasData
} from '@/api/canvasApi.js'
export default {
components: {
CereshopLayout,
LeftBar,
ToolPanel
},
data() {
return {
deviceList: [
// {
// id: 1,
// name: "xiaochengxu",
// },
// {
// id: 2,
// name: "h5",
// },
{
id: 3,
name: 'phone'
},
{
id: 4,
name: 'pc'
}
// {
// id: 1,
// name: 'pc'
// }
],
canvasId: null
}
},
computed: {
...mapGetters(['terminal', 'componentsData'])
},
mounted () {
this.canvasGet()
},
methods: {
...mapMutations({
setTerminal: 'SET_TERMINAL',
setComponentsData: 'SET_COMPONENTSDATA'
}),
toggleDevice (id) {
this.setTerminal(id)
this.canvasGet()
},
// 保存画布
canvasSave () {
// 删除非必要的字符
let cloneComponentsData = JSON.parse(JSON.stringify(this.componentsData))
for (let i = 0; i < cloneComponentsData.length; i++) {
delete cloneComponentsData[i].icon
delete cloneComponentsData[i].iconH
if (cloneComponentsData[i].type === 'productList') {
cloneComponentsData[i].componentContent.imgTextData = []
}
}
saveCanvasData({
terminal: this.terminal,
json: JSON.stringify(cloneComponentsData),
name: '1',
canvasId: this.canvasId || ''
}).then(res => {
if (res) {
this.$message.success('保存成功!')
}
})
},
// 读取画布
async canvasGet () {
// var res = await getCanvasData({'terminal': 3})
var res = await getCanvasData({'terminal': this.terminal})
if (JSON.stringify(res) !== '{}') {
this.canvasId = res.canvasId
var componentsData = JSON.parse(res.json)
for (let i = 0; i < componentsData.length; i++) {
if (componentsData[i].type === 'productList') {
if (componentsData[i].componentContent.categoryId) {
getProducts({
'pageSize': 20,
'page': 1,
'classifyId': componentsData[i].componentContent.categoryId
}).then(res => {
componentsData[i].componentContent.imgTextData = res.list
})
}
}
}
this.setComponentsData(componentsData)
} else {
this.setComponentsData([])
}
}
}
}
</script>
<style lang="scss" scoped>
.containerMall {
position: relative;
display: flex;
flex-direction: column;
height:calc(100vh - 84px);
overflow: hidden;
.topBox {
height: 52px;
line-height: 52px;
border-bottom: 1px solid #f0f3f4;
position: relative;
display: flex;
align-items: center;
justify-content: center;
// .btn-black {
// position: absolute;
// left: 20px;
// top: 0;
// }
ul{
margin: 0;
padding: 0;
height: 52px;
display: flex;
align-items: center;
}
li {
width: 56px;
height: 52px;
cursor: pointer;
text-align: center;
display: inline-block;
vertical-align: text-top;
.iconfont {
font-size: 24px;
// line-height: 52px;
}
&:hover,
&.on {
background-color: $mainColor;
color: #fff;
}
}
.btn-save {
position: absolute;
right: 20px;
top: 5px;
font-weight: 500;
padding: 12px 20px;
font-size: 14px;
border-radius: 4px;
}
}
.bottomWarp {
flex: 1;
display: flex;
overflow:hidden
}
.leftBox {
height: 100%;
}
.mainContentWarp {
background-color: #f0f3f4;
overflow: auto;
height: 100%;
flex: 1;
.mainContent {
margin: 0 auto;
max-width: 100%;
width: 500px;
&.view-4 {
width: 1200px;
}
}
}
.RightBox {
height: 100%;
overflow: auto;
}
}
</style>