管理端楼层装修增加热区功能

master
paulGao 2022-09-06 19:45:02 +08:00
parent 55aa57d812
commit f6ff0b8a12
11 changed files with 380 additions and 95 deletions

View File

@ -8,7 +8,7 @@
width: 100%; width: 100%;
max-width: 100%; max-width: 100%;
height: auto; height: auto;
max-height: 100%; /* max-height: 100%; */
user-select: none; user-select: none;
} }

View File

@ -1,17 +1,65 @@
<template> <template>
<div ref="content" class="hz-m-wrap"> <div class="hotzone-box">
<img class="hz-u-img" :src="image" /> <div class="hotzone-item">
<ul class="hz-m-area" v-add-item> <div ref="content" class="hz-m-wrap">
<zone <img class="hz-u-img" :src="image" />
class="hz-m-item" <ul class="hz-m-area" v-add-item>
v-for="(zone, index) in zones" <zone
:key="index" class="hz-m-item"
:index="index" v-for="(zone, index) in zones"
:setting="zone" :key="index"
@delItem="removeItem($event)" :index="index"
@changeInfo="changeInfo($event)" :setting="zone"
></zone> :ref="`zone${index}`"
</ul> @delItem="removeItem($event)"
@changeInfo="changeInfo($event)"
></zone>
</ul>
</div>
</div>
<div>
<div class="hotzone-add-box-body">
<div
v-for="(zone, index) in zones"
:key="index"
class="hotzone-box-item-main"
>
<div class="hotzone-box-item wes-2">
<div>{{ index + 1 }}</div>
<div @click="editZone(index)">
<div class="hotzone-box-item-text">
{{ showZoneText(zone) }}
</div>
</div>
<div class="flex">
<div class="hotzone-btn" @click="editZone(index)"></div>
&nbsp;&nbsp;&nbsp;&nbsp;
<div class="hotzone-btn" @click="delZone(index)"></div>
</div>
</div>
</div>
</div>
<div class="hotzone-add-box-footer" @click="addHotzone">
<svg
viewBox="64 64 896 896"
focusable="false"
class=""
data-icon="plus"
width="1em"
height="1em"
fill="currentColor"
aria-hidden="true"
>
<path
d="M482 152h60q8 0 8 8v704q0 8-8 8h-60q-8 0-8-8V160q0-8 8-8z"
></path>
<path
d="M176 474h672q8 0 8 8v60q0 8-8 8H176q-8 0-8-8v-60q0-8 8-8z"
></path>
</svg>
<div class="hotzone-add-box-text">添加热区</div>
</div>
</div>
</div> </div>
</template> </template>
@ -43,6 +91,43 @@ export default {
this.zones = this.zonesInit.concat(); this.zones = this.zonesInit.concat();
}, },
methods: { methods: {
addHotzone() {
let perInfo = {
topPer: 0.15,
leftPer: 0.4,
widthPer: 0.2,
heightPer: 0.05,
img: "",
link: "",
type: "",
title: "",
};
this.addItem(perInfo);
},
editZone(index) {
this.$refs[`zone${index}`][0].showModalFn(index);
},
delZone(index) {
this.$refs[`zone${index}`][0].delItem(index);
},
showZoneText(zone) {
switch(zone.type) {
case 'goods':
return `商品:${zone.goodsName}`;
case "category":
return `分类:${zone.name}`;
case "shops":
return `店铺:${zone.storeName}`;
case "pages":
return `文章:${zone.title}`;
case "marketing":
return `促销活动商品:${zone.goodsName}`;
case "other":
return `${zone.title}`;
default:
return '请选择跳转链接';
}
},
changeInfo(res) { changeInfo(res) {
let { info, index, zoneInfo } = res; let { info, index, zoneInfo } = res;
info = { ...zoneInfo, ...info }; info = { ...zoneInfo, ...info };
@ -96,6 +181,77 @@ export default {
}; };
</script> </script>
<style scoped> <style scoped lang="scss">
@import "../assets/styles/main.css"; @import "../assets/styles/main.css";
.hotzone-box {
display: flex;
justify-content: center;
align-items: center;
height: 468px;
> div {
margin: 6px;
padding: 12px;
border-radius: 10px;
height: 100%;
}
> div:nth-of-type(1) {
// display: flex;
width: 50%;
overflow: auto;
// justify-content: center;
background: #ededed;
}
> div:nth-of-type(2) {
width: 50%;
background: #f7f7f7;
}
}
.hotzone-add-box-body {
height: 90%;
overflow-y: auto;
}
.hotzone-box-item-main {
margin-top: 10px;
margin-bottom: 20px;
}
.hotzone-box-item {
align-items: center;
display: flex;
border-bottom: 1px solid #ededed;
font-size: 12px;
justify-content: space-between;
padding: 5px 10px 0;
width: 100%;
}
.hotzone-add-box-footer {
align-items: center;
background: #fff;
border: none;
border-radius: 5px;
color: #ff5c58;
display: flex;
height: 40px;
justify-content: center;
margin-top: 10px;
cursor: pointer;
}
.hotzone-btn {
cursor: pointer;
}
.hotzone-box-item-text {
width: 200px;
cursor: pointer;
}
.hotzone-add-box-text {
font-size: 12px;
line-height: 20px;
margin: 0 0 0 4px;
}
</style> </style>

View File

@ -50,6 +50,7 @@
<li class="hz-u-square hz-u-square-bc" data-pointer="dealBC"></li> <li class="hz-u-square hz-u-square-bc" data-pointer="dealBC"></li>
<li class="hz-u-square hz-u-square-br" data-pointer="dealBR"></li> <li class="hz-u-square hz-u-square-br" data-pointer="dealBR"></li>
</ul> </ul>
<Modal <Modal
v-model="showModal" v-model="showModal"
title="编辑热区" title="编辑热区"
@ -58,11 +59,7 @@
:mask="false" :mask="false"
ok-text="保存" ok-text="保存"
@on-ok="saveZone" @on-ok="saveZone"
@on-cancel=" @on-cancel="cancelZone"
() => {
showModal = false;
}
"
> >
<div> <div>
<div class="hz-edit-img"> <div class="hz-edit-img">
@ -70,14 +67,15 @@
</div> </div>
<Form :model="zoneForm" :label-width="80"> <Form :model="zoneForm" :label-width="80">
<FormItem label="图片链接:"> <!-- <FormItem label="图片链接:">
<Input v-model="zoneForm.img"></Input> <Input v-model="zoneForm.img"></Input>
<Button size="small" type="primary" @click="handleSelectImg" <Button size="small" type="primary" @click="handleSelectImg"
>选择图片</Button >选择图片</Button
> >
</FormItem> :v-model="zoneForm.type === 'goods' ? zoneForm.goodsName : zoneForm.link"
</FormItem> -->
<FormItem label="跳转链接:"> <FormItem label="跳转链接:">
<Input v-model="zoneForm.link"></Input> <Input type="textarea" v-if="zoneForm.type === 'other' && zoneForm.title === ''" v-model="zoneForm.link" ></Input>
<Button size="small" type="primary" @click="handleSelectLink" <Button size="small" type="primary" @click="handleSelectLink"
>选择链接</Button >选择链接</Button
> >
@ -108,6 +106,7 @@ export default {
components: { components: {
ossManage, ossManage,
}, },
data() { data() {
return { return {
zoneTop: "", zoneTop: "",
@ -119,6 +118,7 @@ export default {
showModal: false, showModal: false,
picModelFlag: false, picModelFlag: false,
currentIndex: 0, currentIndex: 0,
currentShowIndex: -1,
zoneForm: { zoneForm: {
img: "", img: "",
link: "", link: "",
@ -126,10 +126,8 @@ export default {
}, },
}; };
}, },
props: ["index", "setting"], props: ["index", "setting"],
mounted() { mounted() {
console.log(this.setting);
this.setZoneInfo(this.setting); this.setZoneInfo(this.setting);
}, },
methods: { methods: {
@ -139,9 +137,10 @@ export default {
this.zoneWidth = this.getZoneStyle(val.widthPer); this.zoneWidth = this.getZoneStyle(val.widthPer);
this.zoneHeight = this.getZoneStyle(val.heightPer); this.zoneHeight = this.getZoneStyle(val.heightPer);
this.tooSmall = val.widthPer < 0.01 && val.heightPer < 0.01; this.tooSmall = val.widthPer < 0.01 && val.heightPer < 0.01;
this.zoneForm.img = val.img; this.zoneForm = {
this.zoneForm.link = val.link; ...val,
this.zoneForm.type = val.type; ...this.zoneForm,
};
}, },
handlehideZone(isHide = true) { handlehideZone(isHide = true) {
if (this.hideZone === isHide) { if (this.hideZone === isHide) {
@ -162,6 +161,7 @@ export default {
showModalFn(index) { showModalFn(index) {
this.showModal = true; this.showModal = true;
this.currentIndex = index; this.currentIndex = index;
console.log(this.zoneForm);
}, },
// //
handleSelectImg() { handleSelectImg() {
@ -183,8 +183,40 @@ export default {
selectedLink(val) { selectedLink(val) {
this.zoneForm.link = this.$options.filters.formatLinkType(val); this.zoneForm.link = this.$options.filters.formatLinkType(val);
this.zoneForm.type = val.___type; this.zoneForm.type = val.___type;
this.zoneForm.title = val.title;
switch (val.___type) {
case "goods":
this.zoneForm.id = val.id;
this.zoneForm.goodsId = val.goodsId;
this.zoneForm.goodsName = val.goodsName;
break;
case "category":
this.zoneForm.id = val.allId;
this.zoneForm.name = val.name;
break;
case "shops":
this.zoneForm.id = val.id;
this.zoneForm.storeName = val.storeName;
break;
case "pages":
this.zoneForm.id = val.id;
this.zoneForm.___path = val.___path;
this.zoneForm.title = val.title;
break;
case "marketing":
this.zoneForm.id = val.id;
this.zoneForm.goodsId = val.goodsId;
this.zoneForm.goodsName = val.goodsName;
break;
default:
break;
}
this.changeInfo(this.zoneForm);
}, },
saveZone() {}, saveZone() {},
cancelZone() {
this.showModal = false;
},
delZone() { delZone() {
this.delItem(this.currentIndex); this.delItem(this.currentIndex);
}, },

View File

@ -4,10 +4,10 @@ export default {
bind: function (el, binding, vnode) { bind: function (el, binding, vnode) {
const MIN_LIMIT = _.MIN_LIMIT const MIN_LIMIT = _.MIN_LIMIT
el.addEventListener('mousedown', handleMouseDown,{ passive: false }) el.addEventListener('mousedown', handleMouseDown, { passive: false })
function handleMouseDown (e) { function handleMouseDown(e) {
console.log('additem', e) // console.log('additem', e)
e && e.preventDefault() e && e.preventDefault()
let itemInfo = { let itemInfo = {
@ -30,10 +30,10 @@ export default {
vnode.context.addItem(setting)// 这里去添加并发送了add通知不应该发送通知 vnode.context.addItem(setting)// 这里去添加并发送了add通知不应该发送通知
window.addEventListener('mousemove', handleChange,{ passive: false }) window.addEventListener('mousemove', handleChange, { passive: false })
window.addEventListener('mouseup', handleMouseUp,{ passive: false }) window.addEventListener('mouseup', handleMouseUp, { passive: false })
function handleChange (e) { function handleChange(e) {
e && e.preventDefault() e && e.preventDefault()
let moveX = _.getPageX(e) - preX let moveX = _.getPageX(e) - preX
@ -57,7 +57,7 @@ export default {
}) })
} }
function handleMouseUp () { function handleMouseUp() {
let perInfo = { let perInfo = {
topPer: _.decimalPoint(itemInfo.top / container.height), topPer: _.decimalPoint(itemInfo.top / container.height),
leftPer: _.decimalPoint(itemInfo.left / container.width), leftPer: _.decimalPoint(itemInfo.left / container.width),
@ -66,6 +66,7 @@ export default {
img: "", img: "",
link: "", link: "",
type: "", type: "",
title: ""
} }
if (vnode.context.isOverRange()) { if (vnode.context.isOverRange()) {

View File

@ -1,4 +1,4 @@
import hotzone from './components/Hotzone.vue' import hotzone from './index.vue'
hotzone.install = (Vue) => { hotzone.install = (Vue) => {
Vue.component(hotzone.name, hotzone) Vue.component(hotzone.name, hotzone)

View File

@ -0,0 +1,69 @@
<template>
<Modal
:styles="{ top: '120px' }"
width="800"
@on-cancel="clickClose"
@on-ok="clickOK"
v-model="flag"
:mask-closable="false"
title="绘制热区"
scrollable
>
<template v-if="flag">
<hotzone
ref="hotzone"
@change="changeHotzone"
:zonesInit="res.zoneInfo"
:image="res.img"
></hotzone>
</template>
</Modal>
</template>
<script>
import hotzone from "./components/Hotzone.vue";
export default {
components: {
hotzone,
},
data() {
return {
flag: false, // modal
};
},
props: ["res"],
mounted() {},
methods: {
changeHotzone(info) {
this.$emit("changeZone", info);
},
//
clickClose() {
this.$emit("closeFlag", false);
},
//
clickOK() {
this.clickClose();
},
//
open(type, mutiple) {
this.flag = true;
},
//
close() {
this.flag = false;
},
},
};
</script>
<style scoped lang="scss">
/deep/ .ivu-modal {
overflow: hidden;
height: 650px !important;
}
/deep/ .ivu-modal-body {
width: 100%;
height: 500px;
overflow: hidden;
}
</style>

View File

@ -380,7 +380,7 @@ export default {
getPromotion(res) { getPromotion(res) {
if (res.result) { if (res.result) {
this.promotionList = res.result; this.promotionList = res.result;
this.typeOption(Object.keys(res.result)[0]).methodsed(); Object.keys(res.result)[0] && this.typeOption(Object.keys(res.result)[0]).methodsed();
} }
// if (Object.keys(res.result).length) { // if (Object.keys(res.result).length) {

View File

@ -21,11 +21,31 @@ export let homeData = {};
* close:true 右侧关闭按钮 * close:true 右侧关闭按钮
*/ */
export const modelData = [ export const modelData = [
{
type: "flexOne",
name: "图片",
// drawer: true,
notAdd: true,
onlyImg: true,
img: "md-image",
options: {
list: [
{
img: "https://i.loli.net/2020/12/05/8wSNWbnqujDh6HL.png",
url: "",
link: "",
size: "750*280",
model: "link"
}
]
}
},
{ {
type: "carousel", type: "carousel",
name: "图片轮播", name: "轮播",
img: "md-image", img: "md-image",
onlyImg: true, // onlyImg: true,
notTitle: false, notTitle: false,
close: true, close: true,
options: { options: {
@ -59,7 +79,7 @@ export const modelData = [
name: "左一右二", name: "左一右二",
notAdd: true, notAdd: true,
drawer: true, drawer: true,
onlyImg: true, // onlyImg: true,
view: "tpl_ad_list", view: "tpl_ad_list",
img: "md-image", img: "md-image",
options: { options: {
@ -116,7 +136,7 @@ export const modelData = [
name: "左二右一", name: "左二右一",
notAdd: true, notAdd: true,
drawer: true, drawer: true,
onlyImg: true, // onlyImg: true,
img: "md-image", img: "md-image",
options: { options: {
list: [ list: [
@ -149,7 +169,7 @@ export const modelData = [
name: "三列单行", name: "三列单行",
drawer: true, drawer: true,
notAdd: true, notAdd: true,
onlyImg: true, // onlyImg: true,
img: "md-image", img: "md-image",
options: { options: {
list: [ list: [
@ -177,31 +197,12 @@ export const modelData = [
] ]
} }
}, },
{
type: "flexOne",
name: "一张大图",
drawer: true,
notAdd: true,
onlyImg: true,
img: "md-image",
options: {
list: [
{
img: "https://i.loli.net/2020/12/05/8wSNWbnqujDh6HL.png",
url: "",
link: "",
size: "750*280",
model: "link"
}
]
}
},
{ {
type: "flexTwo", type: "flexTwo",
name: "两张横图", name: "两张横图",
drawer: true, drawer: true,
notAdd: true, notAdd: true,
onlyImg: true, // onlyImg: true,
img: "md-image", img: "md-image",
options: { options: {
list: [ list: [
@ -227,7 +228,7 @@ export const modelData = [
name: "上一下二", name: "上一下二",
drawer: true, drawer: true,
notAdd: true, notAdd: true,
onlyImg: true, // onlyImg: true,
img: "md-image", img: "md-image",
options: { options: {
list: [ list: [
@ -260,7 +261,7 @@ export const modelData = [
name: "上二下一", name: "上二下一",
drawer: true, drawer: true,
notAdd: true, notAdd: true,
onlyImg: true, // onlyImg: true,
img: "md-image", img: "md-image",
options: { options: {
list: [ list: [
@ -293,7 +294,7 @@ export const modelData = [
name: "五列单行", name: "五列单行",
drawer: true, drawer: true,
notAdd: true, notAdd: true,
onlyImg: true, // onlyImg: true,
img: "md-image", img: "md-image",
options: { options: {
list: [ list: [
@ -340,7 +341,7 @@ export const modelData = [
name: "四列单行", name: "四列单行",
drawer: true, drawer: true,
notAdd: true, notAdd: true,
onlyImg: true, // onlyImg: true,
img: "md-image", img: "md-image",
options: { options: {
list: [ list: [

View File

@ -145,7 +145,7 @@
<div> <div>
<img class="show-image" :src="item.img" alt /> <img class="show-image" :src="item.img" alt />
<div class="tips"> <div class="tips" v-if="!res.onlyImg">
建议尺寸 建议尺寸
<span>{{ item.size }}</span> <span>{{ item.size }}</span>
</div> </div>
@ -302,8 +302,19 @@
<!-- 填写链接 --> <!-- 填写链接 -->
<div class="decorate-view" v-if="!res.notLink"> <div class="decorate-view" v-if="res.onlyImg">
<div class="decorate-view-title">选择模式</div> <div class="decorate-view-title">选择模式</div>
<div>
<RadioGroup v-model="item.model" type="button">
<Radio value="link" label="link">链接</Radio>
<Radio value="hotzone" label="hotzone">热区</Radio>
</RadioGroup>
</div>
</div>
<div class="decorate-view" v-if="!res.notLink">
<div class="decorate-view-title">选择链接</div>
<div <div
v-if="item.url && item.url.length != 0" v-if="item.url && item.url.length != 0"
class="decorate-view-link" class="decorate-view-link"
@ -349,34 +360,31 @@
> >
</span> </span>
</div> </div>
<div> <div>
<RadioGroup <Button
@on-change="clickLink(item, index, res)" ghost
v-model="item.model" size="small"
type="button" type="primary"
@click="clickLink(item, index, res)"
>
{{ item.model === "hotzone" ? "绘制热区" : "选择链接" }}</Button
> >
<Radio value="link" label="link">链接</Radio>
<Radio v-if="res.onlyImg" value="hotzone" label="hotzone"
>热区</Radio
>
</RadioGroup>
</div> </div>
</div> <!-- 链接地址-->
<!-- 链接地址--> <div
<div class="decorate-view"
class="decorate-view" v-if="item.url && item.url.url && item.url.___type == 'other'"
v-if="item.url && item.url.url && item.url.___type == 'other'" >
> <div class="decorate-view-title">外部链接</div>
<div class="decorate-view-title">外部链接</div> <div>
<div> <Input v-model="item.url.url" style="width: 200px" />
<Input v-model="item.url.url" style="width: 200px" /> </div>
</div> </div>
</div>
<p v-if="item.url && item.url.url && item.url.___type == 'other'"> <p v-if="item.url && item.url.url && item.url.___type == 'other'">
(如非同域名下则在小程序与公众号中无效) (如非同域名下则在小程序与公众号中无效)
</p> </p>
</div>
</div> </div>
</div> </div>
</div> </div>
@ -400,6 +408,8 @@
@selectedGoodsData="selectedGoodsData" @selectedGoodsData="selectedGoodsData"
></liliDialog> ></liliDialog>
<hotzone ref="hotzone" @changeZone="changeZone"></hotzone>
<Modal width="1200px" v-model="picModelFlag"> <Modal width="1200px" v-model="picModelFlag">
<ossManage @callback="callbackSelected" ref="ossManage" /> <ossManage @callback="callbackSelected" ref="ossManage" />
</Modal> </Modal>
@ -408,10 +418,12 @@
<script> <script>
import ossManage from "@/views/sys/oss-manage/ossManage"; import ossManage from "@/views/sys/oss-manage/ossManage";
import { modelData } from "./config"; import { modelData } from "./config";
import hotzone from "@/components/hotzone";
import ways from "@/components/lili-dialog/wap.js"; // import ways from "@/components/lili-dialog/wap.js"; //
export default { export default {
components: { components: {
ossManage, ossManage,
hotzone,
}, },
data() { data() {
return { return {
@ -455,6 +467,9 @@ export default {
}, },
// //
selectedLink(val) { selectedLink(val) {
delete val.selected;
delete val.intro;
delete val.mobileIntro;
this.selectedLinks.url = val; this.selectedLinks.url = val;
}, },
// //
@ -498,11 +513,23 @@ export default {
}, },
// //
clickLink(val, index, oval) { clickLink(val, index, oval) {
if (val.model === "link") { this.selectedLinks = val;
this.selectedLinks = val; if (val.model === "hotzone") {
if (!val.zoneInfo) {
val.zoneInfo = [];
}
this.$refs.hotzone.flag = true;
this.$refs.hotzone.res = val;
} else {
this.liliDialogFlag(false); this.liliDialogFlag(false);
} }
}, },
addZone(zoneInfo) {
this.selectedLinks.zoneInfo.push(zoneInfo);
},
changeZone(zoneInfo) {
this.selectedLinks.zoneInfo = zoneInfo;
},
//base64 //base64
changeFile(item, index) { changeFile(item, index) {
const file = document.getElementById("files" + index).files[0]; const file = document.getElementById("files" + index).files[0];

View File

@ -153,7 +153,7 @@ export default {
// //
goback() { goback() {
this.$router.push({ this.$router.push({
path: "/wapList", path: "/decoration/wap",
}); });
}, },

View File

@ -15,7 +15,6 @@ export default {
.flex-one{ .flex-one{
width: 100%; width: 100%;
display: block; display: block;
height: 110px;
overflow: hidden; overflow: hidden;
>img{ >img{
width: 100%; width: 100%;