mirror of
https://gitee.com/beijing_hongye_huicheng/lilishop-ui.git
synced 2026-11-06 17:09:08 +08:00
feat(pc-decorate): 优化PC楼层装修组件自适应高度、支持可视化热区图绘制及编辑器交互修复
- fix(editor): 修复点击返回页面列表 autoSaveTimer is not defined 运行时错误,优化回退逻辑 - feat(hotzone): PC 端热区图接入可视化组件,支持拖拽画框、拉伸缩放与百分比自适应 - fix(floor-height): 商品宫格、宫格楼层、横幅楼层、商品条等默认行高改为自适应撑开,防止商品溢出截断 - fix(video): 修正视频组件默认行高与播放器高度对齐为 450px,避免底部遮挡 - fix(freelayout): 统一自由排版默认高度与后台画布高度为 450px,消除底部空白 - feat(adaptive): 频道宫格、品牌墙、优惠券等集合类组件支持动态行高与 autoCompTypes 弹性包裹 - refactor(preset): 优化双端 double11Preset 预设模板,清理遗留固定行高
This commit is contained in:
@@ -12,7 +12,7 @@
|
||||
|
||||
class="component-cell"
|
||||
|
||||
:style="getComponentCellStyle(comp.componentStyle, row.rowStyle, row.components ? row.components.length : 1)"
|
||||
:style="getComponentCellStyle(comp.componentStyle, row.rowStyle, row.components ? row.components.length : 1, comp.type)"
|
||||
|
||||
>
|
||||
|
||||
@@ -69,6 +69,10 @@ const props = defineProps({
|
||||
|
||||
|
||||
|
||||
const hasAutoComp = computed(() => {
|
||||
return Array.isArray(props.row.components) && props.row.components.some(c => ['goodsGrid', 'gridFloor', 'bannerFloor', 'goodsBar', 'channelFloor', 'goodsList', 'recommendFeed', 'articleContent', 'brandWall', 'channelGrid', 'couponList'].includes(c?.type));
|
||||
});
|
||||
|
||||
const rowWrapperStyle = computed(() => {
|
||||
const s = props.row.rowStyle || {};
|
||||
const style = {};
|
||||
@@ -96,8 +100,12 @@ const rowWrapperStyle = computed(() => {
|
||||
const h = String(s.height).trim();
|
||||
if (h && Number(h) > 0) {
|
||||
const hVal = /^\d+$/.test(h) ? `${h}px` : h;
|
||||
style.height = hVal;
|
||||
style.minHeight = hVal;
|
||||
if (hasAutoComp.value) {
|
||||
style.minHeight = hVal;
|
||||
} else {
|
||||
style.height = hVal;
|
||||
style.minHeight = hVal;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -164,8 +172,12 @@ const rowInnerFlexStyle = computed(() => {
|
||||
const h = String(s.height).trim();
|
||||
if (h && Number(h) > 0) {
|
||||
const hVal = /^\d+$/.test(h) ? `${h}px` : h;
|
||||
styleObj.height = hVal;
|
||||
styleObj.minHeight = hVal;
|
||||
if (hasAutoComp.value) {
|
||||
styleObj.minHeight = hVal;
|
||||
} else {
|
||||
styleObj.height = hVal;
|
||||
styleObj.minHeight = hVal;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -175,7 +187,8 @@ const rowInnerFlexStyle = computed(() => {
|
||||
|
||||
|
||||
|
||||
function getComponentCellStyle(style, rowStyle = {}, totalComps = 1) {
|
||||
function getComponentCellStyle(style, rowStyle = {}, totalComps = 1, compType = '') {
|
||||
const isAutoHeightComp = compType && ['goodsGrid', 'gridFloor', 'bannerFloor', 'goodsBar', 'channelFloor', 'goodsList', 'recommendFeed', 'articleContent', 'brandWall', 'channelGrid', 'couponList'].includes(compType);
|
||||
|
||||
if (!style) return { flex: '1 1 0%' };
|
||||
|
||||
@@ -185,8 +198,12 @@ function getComponentCellStyle(style, rowStyle = {}, totalComps = 1) {
|
||||
const rh = String(rowStyle.height).trim();
|
||||
if (rh && Number(rh) > 0) {
|
||||
const rhVal = /^\d+$/.test(rh) ? `${rh}px` : rh;
|
||||
s.height = rhVal;
|
||||
s.minHeight = rhVal;
|
||||
if (isAutoHeightComp) {
|
||||
s.minHeight = rhVal;
|
||||
} else {
|
||||
s.height = rhVal;
|
||||
s.minHeight = rhVal;
|
||||
}
|
||||
}
|
||||
}
|
||||
const gap = Number(rowStyle?.gap) || 0;
|
||||
|
||||
@@ -7,10 +7,10 @@
|
||||
:key="idx"
|
||||
class="zone-link"
|
||||
:style="{
|
||||
top: `${zone.top || 0}%`,
|
||||
left: `${zone.left || 0}%`,
|
||||
width: `${zone.width || 10}%`,
|
||||
height: `${zone.height || 10}%`
|
||||
top: `${zone.top !== undefined ? zone.top : ((zone.topPer || 0) * 100)}%`,
|
||||
left: `${zone.left !== undefined ? zone.left : ((zone.leftPer || 0) * 100)}%`,
|
||||
width: `${zone.width !== undefined ? zone.width : ((zone.widthPer || 0.1) * 100)}%`,
|
||||
height: `${zone.height !== undefined ? zone.height : ((zone.heightPer || 0.1) * 100)}%`
|
||||
}"
|
||||
:title="zone.title"
|
||||
@click="handleClickZone(zone)"
|
||||
@@ -68,7 +68,7 @@ const customStyle = computed(() => {
|
||||
});
|
||||
|
||||
function handleClickZone(zone) {
|
||||
const url = zone?.url ? String(zone.url).trim() : '';
|
||||
const url = (zone?.url || zone?.link) ? String(zone.url || zone.link).trim() : '';
|
||||
if (!url) return;
|
||||
if (/^https?:\/\//i.test(url)) {
|
||||
window.open(url, '_blank');
|
||||
|
||||
@@ -724,7 +724,7 @@ export const DOUBLE11_PAGE_DOCUMENT = {
|
||||
0,
|
||||
0
|
||||
],
|
||||
"height": 180
|
||||
"height": 220
|
||||
},
|
||||
"components": [
|
||||
{
|
||||
@@ -901,6 +901,7 @@ export const DOUBLE11_PAGE_DOCUMENT = {
|
||||
"backgroundColor": "transparent"
|
||||
},
|
||||
"options": {
|
||||
"height": 450,
|
||||
"elements": [
|
||||
{
|
||||
"type": "badge",
|
||||
@@ -979,7 +980,7 @@ export const DOUBLE11_PAGE_DOCUMENT = {
|
||||
16
|
||||
],
|
||||
"borderRadius": "8px",
|
||||
"height": 560
|
||||
"height": ""
|
||||
},
|
||||
"components": [
|
||||
{
|
||||
@@ -1061,7 +1062,7 @@ export const DOUBLE11_PAGE_DOCUMENT = {
|
||||
16
|
||||
],
|
||||
"borderRadius": "8px",
|
||||
"height": 560
|
||||
"height": ""
|
||||
},
|
||||
"components": [
|
||||
{
|
||||
@@ -1140,7 +1141,7 @@ export const DOUBLE11_PAGE_DOCUMENT = {
|
||||
16
|
||||
],
|
||||
"borderRadius": "8px",
|
||||
"height": 620
|
||||
"height": ""
|
||||
},
|
||||
"components": [
|
||||
{
|
||||
@@ -1249,7 +1250,7 @@ export const DOUBLE11_PAGE_DOCUMENT = {
|
||||
16
|
||||
],
|
||||
"borderRadius": "8px",
|
||||
"height": 420
|
||||
"height": ""
|
||||
},
|
||||
"components": [
|
||||
{
|
||||
@@ -1404,7 +1405,7 @@ export const DOUBLE11_PAGE_DOCUMENT = {
|
||||
16
|
||||
],
|
||||
"borderRadius": "8px",
|
||||
"height": 360
|
||||
"height": 450
|
||||
},
|
||||
"components": [
|
||||
{
|
||||
@@ -1417,6 +1418,7 @@ export const DOUBLE11_PAGE_DOCUMENT = {
|
||||
},
|
||||
"options": {
|
||||
"videoUrl": "https://vjs.zencdn.net/v/oceans.mp4",
|
||||
"height": 450,
|
||||
"coverUrl": "https://lilishop-pc.oss-cn-beijing.aliyuncs.com/static/video/video_cover.png",
|
||||
"url": "/goodsList?brand=1",
|
||||
"title": "双11全球狂欢发布盛典 · 年度旗舰好物真实开箱测评",
|
||||
@@ -1481,7 +1483,7 @@ export const DOUBLE11_PAGE_DOCUMENT = {
|
||||
16
|
||||
],
|
||||
"borderRadius": "8px",
|
||||
"height": 220
|
||||
"height": ""
|
||||
},
|
||||
"components": [
|
||||
{
|
||||
@@ -1656,7 +1658,7 @@ export const DOUBLE11_PAGE_DOCUMENT = {
|
||||
16
|
||||
],
|
||||
"borderRadius": "8px",
|
||||
"height": 980
|
||||
"height": ""
|
||||
},
|
||||
"components": [
|
||||
{
|
||||
@@ -1810,7 +1812,7 @@ export const DOUBLE11_PAGE_DOCUMENT = {
|
||||
16
|
||||
],
|
||||
"borderRadius": "8px",
|
||||
"height": 1270
|
||||
"height": ""
|
||||
},
|
||||
"components": [
|
||||
{
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
v-model="flag"
|
||||
width="800px"
|
||||
:width="width"
|
||||
:close-on-click-modal="false"
|
||||
title="绘制热区"
|
||||
top="120px"
|
||||
@@ -26,6 +26,13 @@
|
||||
import { ref } from "vue";
|
||||
import hotzone from "./components/Hotzone.vue";
|
||||
|
||||
const props = defineProps({
|
||||
width: {
|
||||
type: String,
|
||||
default: "800px",
|
||||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits(["changeZone", "closeFlag"]);
|
||||
|
||||
const flag = ref(false);
|
||||
|
||||
@@ -29,6 +29,10 @@
|
||||
<div class="hotzone-preview-box" v-if="options.imageUrl">
|
||||
<img :src="options.imageUrl" alt="hotzone" class="img-preview" />
|
||||
<div class="preview-actions-bar">
|
||||
<el-button size="small" type="primary" @click="handleOpenHotzone">
|
||||
<el-icon class="mr-4"><Aim /></el-icon>
|
||||
绘制热区
|
||||
</el-button>
|
||||
<el-button size="small" type="primary" plain @click="handleSelectImage">
|
||||
<el-icon class="mr-4"><Picture /></el-icon>
|
||||
更换底图
|
||||
@@ -46,6 +50,9 @@
|
||||
<div class="section-title flex-between">
|
||||
<span>热区列表 ({{ options.zones?.length || 0 }})</span>
|
||||
<div class="header-action-group">
|
||||
<el-button type="primary" plain size="small" @click="handleOpenHotzone">
|
||||
<el-icon class="mr-4"><Aim /></el-icon> 绘制热区
|
||||
</el-button>
|
||||
<el-button link type="primary" size="small" @click="handleAddZone">
|
||||
<el-icon><Plus /></el-icon> 添加热区
|
||||
</el-button>
|
||||
@@ -204,16 +211,25 @@
|
||||
</div>
|
||||
|
||||
<div class="empty-zones-box" v-else>
|
||||
<span>暂无热区,请点击右上角“添加热区”</span>
|
||||
<span>暂无热区,可点击“绘制热区”在底图上拖拽画热区</span>
|
||||
<div class="mt-8">
|
||||
<el-button type="primary" size="small" @click="handleOpenHotzone">
|
||||
<el-icon class="mr-4"><Aim /></el-icon> 立即绘制热区
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 绘制热区弹窗(复用移动端热区绘制器) -->
|
||||
<hotzone ref="hotzoneDialogRef" width="960px" @changeZone="handleChangeZone" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { inject } from 'vue';
|
||||
import { Plus, Delete, Link, Picture, Close, Top, Bottom } from '@element-plus/icons-vue';
|
||||
import { ElMessageBox } from 'element-plus';
|
||||
import { ref, inject } from 'vue';
|
||||
import { Plus, Delete, Link, Picture, Close, Top, Bottom, Aim } from '@element-plus/icons-vue';
|
||||
import { ElMessageBox, ElMessage } from 'element-plus';
|
||||
import hotzone from '@/components/hotzone';
|
||||
|
||||
const props = defineProps({
|
||||
component: {
|
||||
@@ -298,6 +314,68 @@ function handleAddZone() {
|
||||
height: 35
|
||||
});
|
||||
}
|
||||
|
||||
const hotzoneDialogRef = ref(null);
|
||||
|
||||
// 绘制热区弹窗打开
|
||||
function handleOpenHotzone() {
|
||||
const imgUrl = props.options.imageUrl || '';
|
||||
if (!imgUrl) {
|
||||
ElMessage.warning('请先输入或选择热区底图');
|
||||
return;
|
||||
}
|
||||
const zoneInfo = (props.options.zones || []).map((z, idx) => {
|
||||
const leftPer = z.leftPer !== undefined ? z.leftPer : (Number(z.left) || 0) / 100;
|
||||
const topPer = z.topPer !== undefined ? z.topPer : (Number(z.top) || 0) / 100;
|
||||
const widthPer = z.widthPer !== undefined ? z.widthPer : (Number(z.width) || 20) / 100;
|
||||
const heightPer = z.heightPer !== undefined ? z.heightPer : (Number(z.height) || 20) / 100;
|
||||
const link = z.url || z.link || '';
|
||||
|
||||
return {
|
||||
...z,
|
||||
leftPer,
|
||||
topPer,
|
||||
widthPer,
|
||||
heightPer,
|
||||
link,
|
||||
title: z.title || `热区 ${idx + 1}`,
|
||||
type: z.type || 'other'
|
||||
};
|
||||
});
|
||||
|
||||
if (hotzoneDialogRef.value) {
|
||||
hotzoneDialogRef.value.open({
|
||||
img: imgUrl,
|
||||
zoneInfo
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 热区绘制器变更回调
|
||||
function handleChangeZone(zoneList) {
|
||||
if (!Array.isArray(zoneList)) return;
|
||||
props.options.zones = zoneList.map((z, idx) => {
|
||||
const leftVal = z.leftPer !== undefined ? z.leftPer * 100 : (z.left !== undefined ? z.left : 0);
|
||||
const topVal = z.topPer !== undefined ? z.topPer * 100 : (z.top !== undefined ? z.top : 0);
|
||||
const widthVal = z.widthPer !== undefined ? z.widthPer * 100 : (z.width !== undefined ? z.width : 20);
|
||||
const heightVal = z.heightPer !== undefined ? z.heightPer * 100 : (z.height !== undefined ? z.height : 20);
|
||||
const linkVal = z.link || z.url || '';
|
||||
const titleVal = z.title || `热区 ${idx + 1}`;
|
||||
|
||||
return {
|
||||
...z,
|
||||
title: titleVal,
|
||||
url: linkVal,
|
||||
link: linkVal,
|
||||
left: Math.round(leftVal * 10) / 10,
|
||||
top: Math.round(topVal * 10) / 10,
|
||||
width: Math.round(widthVal * 10) / 10,
|
||||
height: Math.round(heightVal * 10) / 10,
|
||||
type: z.type || 'other'
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@@ -299,7 +299,7 @@ export const COMPONENT_DEFINITIONS = [
|
||||
{
|
||||
|
||||
type: 'channelGrid',
|
||||
defaultRowHeight: 120,
|
||||
defaultRowHeight: '',
|
||||
name: '频道宫格',
|
||||
group: 'navigation',
|
||||
icon: 'Grid',
|
||||
@@ -431,7 +431,7 @@ export const COMPONENT_DEFINITIONS = [
|
||||
{
|
||||
|
||||
type: 'brandWall',
|
||||
defaultRowHeight: 220,
|
||||
defaultRowHeight: '',
|
||||
name: '品牌图',
|
||||
group: 'media',
|
||||
icon: 'Medal',
|
||||
@@ -513,7 +513,7 @@ export const COMPONENT_DEFINITIONS = [
|
||||
|
||||
defaultOptions: {
|
||||
|
||||
height: 320,
|
||||
height: 450,
|
||||
|
||||
elements: []
|
||||
|
||||
@@ -532,7 +532,7 @@ export const COMPONENT_DEFINITIONS = [
|
||||
{
|
||||
|
||||
type: 'promoGroup',
|
||||
defaultRowHeight: 180,
|
||||
defaultRowHeight: 220,
|
||||
|
||||
name: '活动卡组',
|
||||
|
||||
@@ -567,13 +567,14 @@ export const COMPONENT_DEFINITIONS = [
|
||||
{
|
||||
|
||||
type: 'video',
|
||||
defaultRowHeight: 360,
|
||||
defaultRowHeight: 450,
|
||||
name: '视频',
|
||||
group: 'media',
|
||||
icon: 'VideoCamera',
|
||||
description: '品牌宣传与商品视频播放',
|
||||
defaultOptions: {
|
||||
videoUrl: '',
|
||||
height: 450,
|
||||
coverUrl: 'https://lilishop-pc.oss-cn-beijing.aliyuncs.com/static/video/video_cover.png',
|
||||
url: '',
|
||||
autoPlay: false,
|
||||
@@ -597,7 +598,7 @@ export const COMPONENT_DEFINITIONS = [
|
||||
{
|
||||
|
||||
type: 'goodsList',
|
||||
defaultRowHeight: 980,
|
||||
defaultRowHeight: '',
|
||||
|
||||
name: '商品列表',
|
||||
|
||||
@@ -727,7 +728,7 @@ export const COMPONENT_DEFINITIONS = [
|
||||
{
|
||||
|
||||
type: 'gridFloor',
|
||||
defaultRowHeight: 560,
|
||||
defaultRowHeight: '',
|
||||
|
||||
name: '宫格楼层',
|
||||
|
||||
@@ -843,7 +844,7 @@ export const COMPONENT_DEFINITIONS = [
|
||||
{
|
||||
|
||||
type: 'goodsGrid',
|
||||
defaultRowHeight: 420,
|
||||
defaultRowHeight: '',
|
||||
name: '商品宫格',
|
||||
group: 'commerce',
|
||||
icon: 'Menu',
|
||||
@@ -922,7 +923,7 @@ export const COMPONENT_DEFINITIONS = [
|
||||
{
|
||||
|
||||
type: 'bannerFloor',
|
||||
defaultRowHeight: 560,
|
||||
defaultRowHeight: '',
|
||||
|
||||
name: '横幅楼层',
|
||||
|
||||
@@ -964,7 +965,7 @@ export const COMPONENT_DEFINITIONS = [
|
||||
{
|
||||
|
||||
type: 'goodsBar',
|
||||
defaultRowHeight: 280,
|
||||
defaultRowHeight: '',
|
||||
|
||||
name: '商品条',
|
||||
|
||||
@@ -1001,7 +1002,7 @@ export const COMPONENT_DEFINITIONS = [
|
||||
},
|
||||
|
||||
{type: 'channelFloor',
|
||||
defaultRowHeight: 620,
|
||||
defaultRowHeight: '',
|
||||
|
||||
name: '频道楼层',
|
||||
|
||||
@@ -1045,7 +1046,7 @@ export const COMPONENT_DEFINITIONS = [
|
||||
|
||||
{
|
||||
type: 'recommendFeed',
|
||||
defaultRowHeight: 1270,
|
||||
defaultRowHeight: '',
|
||||
|
||||
name: '推荐商品',
|
||||
|
||||
@@ -1120,7 +1121,7 @@ export const COMPONENT_DEFINITIONS = [
|
||||
},
|
||||
{
|
||||
type: 'couponList',
|
||||
defaultRowHeight: 160,
|
||||
defaultRowHeight: '',
|
||||
|
||||
name: '优惠券',
|
||||
|
||||
|
||||
@@ -225,7 +225,7 @@
|
||||
|
||||
:class="{ 'is-row-selected': isCurrentRowSelected(row.id) }"
|
||||
|
||||
:style="getRowWrapperStyle(row.rowStyle)"
|
||||
:style="getRowWrapperStyle(row.rowStyle, row.components)"
|
||||
|
||||
@click.stop="handleSelectRow(row, rIndex)"
|
||||
|
||||
@@ -289,14 +289,14 @@
|
||||
group="pc-row-components"
|
||||
item-key="id"
|
||||
class="row-components-flex"
|
||||
:style="getRowFlexStyle(row.rowStyle)"
|
||||
:style="getRowFlexStyle(row.rowStyle, row.components)"
|
||||
@change="markDirty"
|
||||
>
|
||||
<template #item="{ element: comp, index: cIndex }">
|
||||
<div
|
||||
class="canvas-comp-wrap"
|
||||
:class="{ 'is-selected': selectedCompId === comp.id }"
|
||||
:style="getCompWrapperStyle(comp.componentStyle, row.rowStyle, row.components ? row.components.length : 1)"
|
||||
:style="getCompWrapperStyle(comp.componentStyle, row.rowStyle, row.components ? row.components.length : 1, comp.type)"
|
||||
@click.stop="handleSelectComp(row, rIndex, comp)"
|
||||
>
|
||||
<!-- 选中的组件左上角名称标识徽标(万米魔方设计) -->
|
||||
@@ -800,11 +800,19 @@ function clearSelection() {
|
||||
|
||||
function normalizeRows(list) {
|
||||
if (!Array.isArray(list)) return [];
|
||||
const autoCompTypes = ['goodsGrid', 'gridFloor', 'bannerFloor', 'goodsBar', 'channelFloor', 'goodsList', 'recommendFeed', 'articleContent', 'brandWall', 'channelGrid', 'couponList'];
|
||||
const legacyHeights = [40, '40', 280, '280', 420, '420', 560, '560', 620, '620', 980, '980', 1270, '1270'];
|
||||
const normalized = [];
|
||||
list.forEach(r => {
|
||||
if (!r) return;
|
||||
if (r.rowStyle && (r.rowStyle.height === 40 || r.rowStyle.height === "40")) {
|
||||
r.rowStyle.height = "";
|
||||
if (r.rowStyle) {
|
||||
if (r.rowStyle.height === 40 || r.rowStyle.height === "40") {
|
||||
r.rowStyle.height = "";
|
||||
}
|
||||
const hasAutoComp = Array.isArray(r.components) && r.components.some(c => autoCompTypes.includes(c?.type));
|
||||
if (hasAutoComp && legacyHeights.includes(r.rowStyle.height)) {
|
||||
r.rowStyle.height = "";
|
||||
}
|
||||
}
|
||||
normalized.push(r);
|
||||
});
|
||||
@@ -1252,7 +1260,8 @@ function getCompIcon(type) {
|
||||
|
||||
// 计算行样式
|
||||
|
||||
function getRowWrapperStyle(style) {
|
||||
function getRowWrapperStyle(style, components = []) {
|
||||
const hasAutoComp = Array.isArray(components) && components.some(c => ['goodsGrid', 'gridFloor', 'bannerFloor', 'goodsBar', 'channelFloor', 'goodsList', 'recommendFeed', 'articleContent', 'brandWall', 'channelGrid', 'couponList'].includes(c?.type));
|
||||
if (!style) return { width: '100%' };
|
||||
|
||||
const s = {};
|
||||
@@ -1280,8 +1289,12 @@ function getRowWrapperStyle(style) {
|
||||
const h = String(style.height).trim();
|
||||
if (h && Number(h) > 0) {
|
||||
const hVal = /^\d+$/.test(h) ? `${h}px` : h;
|
||||
s.height = hVal;
|
||||
s.minHeight = hVal;
|
||||
if (hasAutoComp) {
|
||||
s.minHeight = hVal;
|
||||
} else {
|
||||
s.height = hVal;
|
||||
s.minHeight = hVal;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1318,7 +1331,8 @@ function getRowWrapperStyle(style) {
|
||||
return s;
|
||||
}
|
||||
|
||||
function getRowFlexStyle(style) {
|
||||
function getRowFlexStyle(style, components = []) {
|
||||
const hasAutoComp = Array.isArray(components) && components.some(c => ['goodsGrid', 'gridFloor', 'bannerFloor', 'goodsBar', 'channelFloor', 'goodsList', 'recommendFeed', 'articleContent', 'brandWall', 'channelGrid', 'couponList'].includes(c?.type));
|
||||
if (!style) return { display: 'flex', flexDirection: 'row', flexWrap: 'nowrap', width: '100%', height: '100%' };
|
||||
const s = {
|
||||
display: 'flex',
|
||||
@@ -1333,8 +1347,12 @@ function getRowFlexStyle(style) {
|
||||
const h = String(style.height).trim();
|
||||
if (h && Number(h) > 0) {
|
||||
const hVal = /^\d+$/.test(h) ? `${h}px` : h;
|
||||
s.height = hVal;
|
||||
s.minHeight = hVal;
|
||||
if (hasAutoComp) {
|
||||
s.minHeight = hVal;
|
||||
} else {
|
||||
s.height = hVal;
|
||||
s.minHeight = hVal;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (style.gap !== undefined && style.gap !== '') {
|
||||
@@ -1348,7 +1366,8 @@ function getRowFlexStyle(style) {
|
||||
|
||||
// 计算组件外层样式
|
||||
|
||||
function getCompWrapperStyle(style, rowStyle = {}, totalComps = 1) {
|
||||
function getCompWrapperStyle(style, rowStyle = {}, totalComps = 1, compType = '') {
|
||||
const isAutoHeightComp = compType && ['goodsGrid', 'gridFloor', 'bannerFloor', 'goodsBar', 'channelFloor', 'goodsList', 'recommendFeed', 'articleContent', 'brandWall', 'channelGrid', 'couponList'].includes(compType);
|
||||
|
||||
if (!style) return {};
|
||||
|
||||
@@ -1358,8 +1377,12 @@ function getCompWrapperStyle(style, rowStyle = {}, totalComps = 1) {
|
||||
const rh = String(rowStyle.height).trim();
|
||||
if (rh && Number(rh) > 0) {
|
||||
const rhVal = /^\d+$/.test(rh) ? `${rh}px` : rh;
|
||||
s.height = rhVal;
|
||||
s.minHeight = rhVal;
|
||||
if (isAutoHeightComp) {
|
||||
s.minHeight = rhVal;
|
||||
} else {
|
||||
s.height = rhVal;
|
||||
s.minHeight = rhVal;
|
||||
}
|
||||
}
|
||||
}
|
||||
const gap = Number(rowStyle?.gap) || 0;
|
||||
@@ -1612,7 +1635,11 @@ function goBack() {
|
||||
|
||||
} else {
|
||||
|
||||
router.push('/pcFloor');
|
||||
if (window.history.state?.back) {
|
||||
router.go(-1);
|
||||
} else {
|
||||
window.close();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1643,6 +1670,8 @@ function goBack() {
|
||||
}
|
||||
|
||||
|
||||
let autoSaveTimer = null;
|
||||
|
||||
onMounted(() => {
|
||||
|
||||
const id = route.query.id;
|
||||
@@ -1671,7 +1700,10 @@ onMounted(() => {
|
||||
|
||||
onUnmounted(() => {
|
||||
|
||||
if (autoSaveTimer) clearInterval(autoSaveTimer);
|
||||
if (autoSaveTimer) {
|
||||
clearInterval(autoSaveTimer);
|
||||
autoSaveTimer = null;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
@@ -724,7 +724,7 @@ export const DOUBLE11_PAGE_DOCUMENT = {
|
||||
0,
|
||||
0
|
||||
],
|
||||
"height": 180
|
||||
"height": 220
|
||||
},
|
||||
"components": [
|
||||
{
|
||||
@@ -901,6 +901,7 @@ export const DOUBLE11_PAGE_DOCUMENT = {
|
||||
"backgroundColor": "transparent"
|
||||
},
|
||||
"options": {
|
||||
"height": 450,
|
||||
"elements": [
|
||||
{
|
||||
"type": "badge",
|
||||
@@ -979,7 +980,7 @@ export const DOUBLE11_PAGE_DOCUMENT = {
|
||||
16
|
||||
],
|
||||
"borderRadius": "8px",
|
||||
"height": 560
|
||||
"height": ""
|
||||
},
|
||||
"components": [
|
||||
{
|
||||
@@ -1061,7 +1062,7 @@ export const DOUBLE11_PAGE_DOCUMENT = {
|
||||
16
|
||||
],
|
||||
"borderRadius": "8px",
|
||||
"height": 560
|
||||
"height": ""
|
||||
},
|
||||
"components": [
|
||||
{
|
||||
@@ -1140,7 +1141,7 @@ export const DOUBLE11_PAGE_DOCUMENT = {
|
||||
16
|
||||
],
|
||||
"borderRadius": "8px",
|
||||
"height": 620
|
||||
"height": ""
|
||||
},
|
||||
"components": [
|
||||
{
|
||||
@@ -1249,7 +1250,7 @@ export const DOUBLE11_PAGE_DOCUMENT = {
|
||||
16
|
||||
],
|
||||
"borderRadius": "8px",
|
||||
"height": 420
|
||||
"height": ""
|
||||
},
|
||||
"components": [
|
||||
{
|
||||
@@ -1404,7 +1405,7 @@ export const DOUBLE11_PAGE_DOCUMENT = {
|
||||
16
|
||||
],
|
||||
"borderRadius": "8px",
|
||||
"height": 360
|
||||
"height": 450
|
||||
},
|
||||
"components": [
|
||||
{
|
||||
@@ -1417,6 +1418,7 @@ export const DOUBLE11_PAGE_DOCUMENT = {
|
||||
},
|
||||
"options": {
|
||||
"videoUrl": "https://vjs.zencdn.net/v/oceans.mp4",
|
||||
"height": 450,
|
||||
"coverUrl": "https://lilishop-pc.oss-cn-beijing.aliyuncs.com/static/video/video_cover.png",
|
||||
"url": "/goodsList?brand=1",
|
||||
"title": "双11全球狂欢发布盛典 · 年度旗舰好物真实开箱测评",
|
||||
@@ -1481,7 +1483,7 @@ export const DOUBLE11_PAGE_DOCUMENT = {
|
||||
16
|
||||
],
|
||||
"borderRadius": "8px",
|
||||
"height": 220
|
||||
"height": ""
|
||||
},
|
||||
"components": [
|
||||
{
|
||||
@@ -1656,7 +1658,7 @@ export const DOUBLE11_PAGE_DOCUMENT = {
|
||||
16
|
||||
],
|
||||
"borderRadius": "8px",
|
||||
"height": 980
|
||||
"height": ""
|
||||
},
|
||||
"components": [
|
||||
{
|
||||
@@ -1810,7 +1812,7 @@ export const DOUBLE11_PAGE_DOCUMENT = {
|
||||
16
|
||||
],
|
||||
"borderRadius": "8px",
|
||||
"height": 1270
|
||||
"height": ""
|
||||
},
|
||||
"components": [
|
||||
{
|
||||
|
||||
@@ -23,7 +23,7 @@ const props = defineProps({
|
||||
const customStyle = computed(() => {
|
||||
const s = props.componentStyle || {};
|
||||
return {
|
||||
height: `${props.options?.height || 260}px`,
|
||||
height: `${props.options?.height || 450}px`,
|
||||
backgroundColor: s.backgroundColor || '#f8fafc',
|
||||
borderRadius: Array.isArray(s.radius)
|
||||
? `${s.radius[0]}px ${s.radius[1]}px ${s.radius[2]}px ${s.radius[3]}px`
|
||||
|
||||
@@ -7,10 +7,10 @@
|
||||
:key="idx"
|
||||
class="zone-mask"
|
||||
:style="{
|
||||
top: `${zone.top || 0}%`,
|
||||
left: `${zone.left || 0}%`,
|
||||
width: `${zone.width || 10}%`,
|
||||
height: `${zone.height || 10}%`
|
||||
top: `${zone.top !== undefined ? zone.top : ((zone.topPer || 0) * 100)}%`,
|
||||
left: `${zone.left !== undefined ? zone.left : ((zone.leftPer || 0) * 100)}%`,
|
||||
width: `${zone.width !== undefined ? zone.width : ((zone.widthPer || 0.1) * 100)}%`,
|
||||
height: `${zone.height !== undefined ? zone.height : ((zone.heightPer || 0.1) * 100)}%`
|
||||
}"
|
||||
>
|
||||
<span class="zone-label">{{ zone.title || `热区 ${idx + 1}` }}</span>
|
||||
|
||||
Reference in New Issue
Block a user