mirror of
https://gitee.com/beijing_hongye_huicheng/lilishop-ui.git
synced 2026-11-06 17:09:08 +08:00
feat(manager): 热区组件配置面板重做为内容/样式双 tab
- 新增 PanelFlexOne:内容 tab(选图+设置热区,复用 ossManage 与 hotzone 编辑器),样式 tab(背景颜色/上下左右边距/页面间距/背景圆角/内容圆角) - 注册进 panelMap 替换 flexOne 的通用老面板 - 画布预览 tpl_flex_one 应用相同样式字段,缺字段兜底保持原样
This commit is contained in:
@@ -0,0 +1,229 @@
|
||||
<template>
|
||||
<div class="panel-flex-one">
|
||||
<div class="panel-tabs">
|
||||
<div
|
||||
v-for="tab in tabs"
|
||||
:key="tab.key"
|
||||
class="panel-tab"
|
||||
:class="{ active: activeTab === tab.key }"
|
||||
@click="activeTab = tab.key"
|
||||
>
|
||||
{{ tab.title }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<template v-if="activeTab === 'content'">
|
||||
<div class="section-title">内容设置</div>
|
||||
<div class="section-tip">选定布局区域,在下方添加图片,建议添加比例一致的图片</div>
|
||||
<div class="img-preview" v-if="item.img">
|
||||
<img :src="item.img" alt="" />
|
||||
</div>
|
||||
<div class="img-placeholder" v-else>尺寸不限</div>
|
||||
<div class="btn-row">
|
||||
<el-button plain size="small" type="primary" @click="pickImage">选择照片</el-button>
|
||||
<el-button plain size="small" type="primary" @click="openHotzone">设置热区</el-button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template v-else>
|
||||
<div class="section-title">颜色设置</div>
|
||||
<color-field
|
||||
v-model="res.options.bgColor"
|
||||
label="背景颜色"
|
||||
:default-value="defaults.bgColor"
|
||||
/>
|
||||
<div class="section-title">边距设置</div>
|
||||
<slider-field
|
||||
v-model="res.options.paddingTop"
|
||||
label="上边距"
|
||||
:min="0"
|
||||
:max="100"
|
||||
/>
|
||||
<slider-field
|
||||
v-model="res.options.paddingBottom"
|
||||
label="下边距"
|
||||
:min="0"
|
||||
:max="100"
|
||||
/>
|
||||
<slider-field
|
||||
v-model="res.options.paddingX"
|
||||
label="左右边距"
|
||||
:min="0"
|
||||
:max="30"
|
||||
/>
|
||||
<slider-field
|
||||
v-model="res.options.pageGap"
|
||||
label="页面间距"
|
||||
:min="0"
|
||||
:max="100"
|
||||
/>
|
||||
<div class="section-title">圆角设置</div>
|
||||
<slider-field
|
||||
v-model="res.options.borderRadius"
|
||||
label="背景圆角"
|
||||
:min="0"
|
||||
:max="50"
|
||||
/>
|
||||
<slider-field
|
||||
v-model="res.options.imgRadius"
|
||||
label="内容圆角"
|
||||
:min="0"
|
||||
:max="50"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<hotzone ref="hotzone" @changeZone="changeZone"></hotzone>
|
||||
|
||||
<el-dialog v-model="picModelFlag" width="1200px" append-to-body destroy-on-close>
|
||||
<ossManage
|
||||
@callback="callbackSelected"
|
||||
:is-component="true"
|
||||
:initialize="picModelFlag"
|
||||
:max-select="1"
|
||||
ref="ossManage"
|
||||
/>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ColorField from "../controls/ColorField.vue";
|
||||
import SliderField from "../controls/SliderField.vue";
|
||||
import hotzone from "@/components/hotzone";
|
||||
import ossManage from "@/views/sys/oss-manage/ossManage";
|
||||
|
||||
const DEFAULTS = {
|
||||
bgColor: "#FFFFFF",
|
||||
paddingTop: 10,
|
||||
paddingBottom: 10,
|
||||
paddingX: 12,
|
||||
pageGap: 10,
|
||||
borderRadius: 0,
|
||||
imgRadius: 0,
|
||||
};
|
||||
|
||||
export default {
|
||||
name: "PanelFlexOne",
|
||||
components: { ColorField, SliderField, hotzone, ossManage },
|
||||
props: {
|
||||
res: { type: Object, required: true },
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
defaults: DEFAULTS,
|
||||
activeTab: "content",
|
||||
tabs: [
|
||||
{ key: "content", title: "内容" },
|
||||
{ key: "style", title: "样式" },
|
||||
],
|
||||
picModelFlag: false,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
item() {
|
||||
return this.res.options.list[0];
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.res.options = Object.assign({}, DEFAULTS, this.res.options);
|
||||
if (!Array.isArray(this.res.options.list) || !this.res.options.list.length) {
|
||||
this.res.options.list = [
|
||||
{ img: "", url: "", link: "", size: "750*280", model: "hotzone" },
|
||||
];
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
pickImage() {
|
||||
this.picModelFlag = true;
|
||||
this.$nextTick(() => {
|
||||
const oss = this.$refs.ossManage;
|
||||
if (!oss) return;
|
||||
oss.selectImage = true;
|
||||
oss.fileType = "pic";
|
||||
oss.changeFileType();
|
||||
});
|
||||
},
|
||||
callbackSelected(val) {
|
||||
this.picModelFlag = false;
|
||||
if (val && val.url) {
|
||||
this.item.img = val.url;
|
||||
}
|
||||
},
|
||||
openHotzone() {
|
||||
if (!this.item.img) {
|
||||
this.$Message.warning("请先选择照片");
|
||||
return;
|
||||
}
|
||||
this.$refs.hotzone.open(this.item);
|
||||
},
|
||||
changeZone(zoneInfo) {
|
||||
this.item.zoneInfo = zoneInfo;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.panel-tabs {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 8px;
|
||||
margin-bottom: 14px;
|
||||
.panel-tab {
|
||||
padding: 5px 18px;
|
||||
font-size: 13px;
|
||||
border-radius: 999px;
|
||||
cursor: pointer;
|
||||
color: #606266;
|
||||
background: #f4f4f5;
|
||||
&.active {
|
||||
background: #409eff;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
.section-title {
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
margin: 14px 0 10px;
|
||||
&:first-of-type {
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
.section-tip {
|
||||
font-size: 12px;
|
||||
color: #909399;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.img-preview {
|
||||
border: 1px dashed #dcdfe6;
|
||||
border-radius: 6px;
|
||||
padding: 6px;
|
||||
margin-bottom: 10px;
|
||||
img {
|
||||
width: 100%;
|
||||
display: block;
|
||||
border-radius: 4px;
|
||||
}
|
||||
}
|
||||
.img-placeholder {
|
||||
height: 120px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border: 1px dashed #dcdfe6;
|
||||
border-radius: 6px;
|
||||
color: #909399;
|
||||
font-size: 12px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.btn-row {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
.el-button {
|
||||
flex: 1;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -7,6 +7,7 @@ import PanelIntegral from "./PanelIntegral.vue";
|
||||
import PanelCoupon from "./PanelCoupon.vue";
|
||||
import PanelArticle from "./PanelArticle.vue";
|
||||
import PanelShop from "./PanelShop.vue";
|
||||
import PanelFlexOne from "./PanelFlexOne.vue";
|
||||
|
||||
export default {
|
||||
blank: PanelBlank,
|
||||
@@ -16,4 +17,5 @@ export default {
|
||||
coupon: PanelCoupon,
|
||||
article: PanelArticle,
|
||||
shop: PanelShop,
|
||||
flexOne: PanelFlexOne,
|
||||
};
|
||||
|
||||
@@ -1,6 +1,15 @@
|
||||
<template>
|
||||
<div class="layout">
|
||||
<div class="flex-one">
|
||||
<div
|
||||
class="layout"
|
||||
:style="{
|
||||
background: res.bgColor ?? 'transparent',
|
||||
padding: `${res.paddingTop ?? 0}px ${res.paddingX ?? 0}px ${res.paddingBottom ?? 0}px`,
|
||||
marginBottom: (res.pageGap ?? 0) + 'px',
|
||||
borderRadius: (res.borderRadius ?? 0) + 'px',
|
||||
overflow: (res.borderRadius ?? 0) > 0 ? 'hidden' : 'visible',
|
||||
}"
|
||||
>
|
||||
<div class="flex-one" :style="{ borderRadius: (res.imgRadius ?? 0) + 'px' }">
|
||||
<img :src="res.list[0].img" alt="">
|
||||
</div>
|
||||
</div>
|
||||
@@ -21,4 +30,4 @@ export default {
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user