feat:【mall】diy editor 的 hot-zone 代码优化(50%)
This commit is contained in:
@@ -2,10 +2,9 @@ import type { StyleValue } from 'vue';
|
|||||||
|
|
||||||
import type { HotZoneItemProperty } from '../../config';
|
import type { HotZoneItemProperty } from '../../config';
|
||||||
|
|
||||||
// 热区的最小宽高
|
export const HOT_ZONE_MIN_SIZE = 100; // 热区的最小宽高
|
||||||
export const HOT_ZONE_MIN_SIZE = 100;
|
|
||||||
|
|
||||||
// 控制的类型
|
/** 控制的类型 */
|
||||||
export enum CONTROL_TYPE_ENUM {
|
export enum CONTROL_TYPE_ENUM {
|
||||||
LEFT,
|
LEFT,
|
||||||
TOP,
|
TOP,
|
||||||
@@ -13,14 +12,14 @@ export enum CONTROL_TYPE_ENUM {
|
|||||||
HEIGHT,
|
HEIGHT,
|
||||||
}
|
}
|
||||||
|
|
||||||
// 定义热区的控制点
|
/** 定义热区的控制点 */
|
||||||
export interface ControlDot {
|
export interface ControlDot {
|
||||||
position: string;
|
position: string;
|
||||||
types: CONTROL_TYPE_ENUM[];
|
types: CONTROL_TYPE_ENUM[];
|
||||||
style: StyleValue;
|
style: StyleValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 热区的8个控制点
|
/** 热区的 8 个控制点 */
|
||||||
export const CONTROL_DOT_LIST = [
|
export const CONTROL_DOT_LIST = [
|
||||||
{
|
{
|
||||||
position: '左上角',
|
position: '左上角',
|
||||||
@@ -98,10 +97,10 @@ export const CONTROL_DOT_LIST = [
|
|||||||
] as ControlDot[];
|
] as ControlDot[];
|
||||||
|
|
||||||
// region 热区的缩放
|
// region 热区的缩放
|
||||||
// 热区的缩放比例
|
export const HOT_ZONE_SCALE_RATE = 2; // 热区的缩放比例
|
||||||
export const HOT_ZONE_SCALE_RATE = 2;
|
|
||||||
// 缩小:缩回适合手机屏幕的大小
|
/** 缩小:缩回适合手机屏幕的大小 */
|
||||||
export const zoomOut = (list?: HotZoneItemProperty[]) => {
|
export function zoomOut(list?: HotZoneItemProperty[]) {
|
||||||
return (
|
return (
|
||||||
list?.map((hotZone) => ({
|
list?.map((hotZone) => ({
|
||||||
...hotZone,
|
...hotZone,
|
||||||
@@ -111,9 +110,10 @@ export const zoomOut = (list?: HotZoneItemProperty[]) => {
|
|||||||
height: (hotZone.height /= HOT_ZONE_SCALE_RATE),
|
height: (hotZone.height /= HOT_ZONE_SCALE_RATE),
|
||||||
})) || []
|
})) || []
|
||||||
);
|
);
|
||||||
};
|
}
|
||||||
// 放大:作用是为了方便在电脑屏幕上编辑
|
|
||||||
export const zoomIn = (list?: HotZoneItemProperty[]) => {
|
/** 放大:作用是为了方便在电脑屏幕上编辑 */
|
||||||
|
export function zoomIn(list?: HotZoneItemProperty[]) {
|
||||||
return (
|
return (
|
||||||
list?.map((hotZone) => ({
|
list?.map((hotZone) => ({
|
||||||
...hotZone,
|
...hotZone,
|
||||||
@@ -123,7 +123,8 @@ export const zoomIn = (list?: HotZoneItemProperty[]) => {
|
|||||||
height: (hotZone.height *= HOT_ZONE_SCALE_RATE),
|
height: (hotZone.height *= HOT_ZONE_SCALE_RATE),
|
||||||
})) || []
|
})) || []
|
||||||
);
|
);
|
||||||
};
|
}
|
||||||
|
|
||||||
// endregion
|
// endregion
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ import { IconifyIcon } from '@vben/icons';
|
|||||||
|
|
||||||
import { ElButton, ElDialog, ElImage } from 'element-plus';
|
import { ElButton, ElDialog, ElImage } from 'element-plus';
|
||||||
|
|
||||||
|
import { AppLinkSelectDialog } from '#/views/mall/promotion/components';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
CONTROL_DOT_LIST,
|
CONTROL_DOT_LIST,
|
||||||
CONTROL_TYPE_ENUM,
|
CONTROL_TYPE_ENUM,
|
||||||
@@ -22,7 +24,7 @@ import {
|
|||||||
/** 热区编辑对话框 */
|
/** 热区编辑对话框 */
|
||||||
defineOptions({ name: 'HotZoneEditDialog' });
|
defineOptions({ name: 'HotZoneEditDialog' });
|
||||||
|
|
||||||
// 定义属性
|
/** 定义属性 */
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
modelValue: {
|
modelValue: {
|
||||||
type: Array<HotZoneItemProperty>,
|
type: Array<HotZoneItemProperty>,
|
||||||
@@ -33,51 +35,53 @@ const props = defineProps({
|
|||||||
default: '',
|
default: '',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const emit = defineEmits(['update:modelValue']);
|
const emit = defineEmits(['update:modelValue']);
|
||||||
|
|
||||||
const formData = ref<HotZoneItemProperty[]>([]);
|
const formData = ref<HotZoneItemProperty[]>([]);
|
||||||
|
|
||||||
// 弹窗的是否显示
|
const dialogVisible = ref(false); // 弹窗的是否显示
|
||||||
const dialogVisible = ref(false);
|
|
||||||
// 打开弹窗
|
/** 打开弹窗 */
|
||||||
const open = () => {
|
const open = () => {
|
||||||
// 放大
|
// 放大
|
||||||
formData.value = zoomIn(props.modelValue);
|
formData.value = zoomIn(props.modelValue);
|
||||||
dialogVisible.value = true;
|
dialogVisible.value = true;
|
||||||
};
|
};
|
||||||
// 提供 open 方法,用于打开弹窗
|
|
||||||
defineExpose({ open });
|
|
||||||
|
|
||||||
// 热区容器
|
defineExpose({ open }); // 提供 open 方法,用于打开弹窗
|
||||||
const container = ref<HTMLDivElement>();
|
|
||||||
|
|
||||||
// 增加热区
|
const container = ref<HTMLDivElement>(); // 热区容器
|
||||||
const handleAdd = () => {
|
|
||||||
|
/** 增加热区 */
|
||||||
|
function handleAdd() {
|
||||||
formData.value.push({
|
formData.value.push({
|
||||||
width: HOT_ZONE_MIN_SIZE,
|
width: HOT_ZONE_MIN_SIZE,
|
||||||
height: HOT_ZONE_MIN_SIZE,
|
height: HOT_ZONE_MIN_SIZE,
|
||||||
top: 0,
|
top: 0,
|
||||||
left: 0,
|
left: 0,
|
||||||
} as HotZoneItemProperty);
|
} as HotZoneItemProperty);
|
||||||
};
|
}
|
||||||
// 删除热区
|
|
||||||
const handleRemove = (hotZone: HotZoneItemProperty) => {
|
|
||||||
formData.value = formData.value.filter((item) => item !== hotZone);
|
|
||||||
};
|
|
||||||
|
|
||||||
// 移动热区
|
/** 删除热区 */
|
||||||
const handleMove = (item: HotZoneItemProperty, e: MouseEvent) => {
|
function handleRemove(hotZone: HotZoneItemProperty) {
|
||||||
|
formData.value = formData.value.filter((item) => item !== hotZone);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 移动热区 */
|
||||||
|
function handleMove(item: HotZoneItemProperty, e: MouseEvent) {
|
||||||
useDraggable(item, e, (left, top, _, __, moveWidth, moveHeight) => {
|
useDraggable(item, e, (left, top, _, __, moveWidth, moveHeight) => {
|
||||||
setLeft(item, left + moveWidth);
|
setLeft(item, left + moveWidth);
|
||||||
setTop(item, top + moveHeight);
|
setTop(item, top + moveHeight);
|
||||||
});
|
});
|
||||||
};
|
}
|
||||||
|
|
||||||
// 调整热区大小、位置
|
/** 调整热区大小、位置 */
|
||||||
const handleResize = (
|
function handleResize(
|
||||||
item: HotZoneItemProperty,
|
item: HotZoneItemProperty,
|
||||||
ctrlDot: ControlDot,
|
ctrlDot: ControlDot,
|
||||||
e: MouseEvent,
|
e: MouseEvent,
|
||||||
) => {
|
) {
|
||||||
useDraggable(item, e, (left, top, width, height, moveWidth, moveHeight) => {
|
useDraggable(item, e, (left, top, width, height, moveWidth, moveHeight) => {
|
||||||
ctrlDot.types.forEach((type) => {
|
ctrlDot.types.forEach((type) => {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
@@ -112,23 +116,25 @@ const handleResize = (
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
}
|
||||||
|
|
||||||
// 设置X轴坐标
|
/** 设置 X 轴坐标 */
|
||||||
const setLeft = (item: HotZoneItemProperty, left: number) => {
|
function setLeft(item: HotZoneItemProperty, left: number) {
|
||||||
// 不能超出容器
|
// 不能超出容器
|
||||||
if (left >= 0 && left <= container.value!.offsetWidth - item.width) {
|
if (left >= 0 && left <= container.value!.offsetWidth - item.width) {
|
||||||
item.left = left;
|
item.left = left;
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
// 设置Y轴坐标
|
|
||||||
const setTop = (item: HotZoneItemProperty, top: number) => {
|
/** 设置Y轴坐标 */
|
||||||
|
function setTop(item: HotZoneItemProperty, top: number) {
|
||||||
// 不能超出容器
|
// 不能超出容器
|
||||||
if (top >= 0 && top <= container.value!.offsetHeight - item.height) {
|
if (top >= 0 && top <= container.value!.offsetHeight - item.height) {
|
||||||
item.top = top;
|
item.top = top;
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
// 设置宽度
|
|
||||||
|
/** 设置宽度 */
|
||||||
const setWidth = (item: HotZoneItemProperty, width: number) => {
|
const setWidth = (item: HotZoneItemProperty, width: number) => {
|
||||||
// 不能小于最小宽度 && 不能超出容器右边
|
// 不能小于最小宽度 && 不能超出容器右边
|
||||||
if (
|
if (
|
||||||
@@ -138,7 +144,8 @@ const setWidth = (item: HotZoneItemProperty, width: number) => {
|
|||||||
item.width = width;
|
item.width = width;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
// 设置高度
|
|
||||||
|
/** 设置高度 */
|
||||||
const setHeight = (item: HotZoneItemProperty, height: number) => {
|
const setHeight = (item: HotZoneItemProperty, height: number) => {
|
||||||
// 不能小于最小高度 && 不能超出容器底部
|
// 不能小于最小高度 && 不能超出容器底部
|
||||||
if (
|
if (
|
||||||
@@ -149,13 +156,12 @@ const setHeight = (item: HotZoneItemProperty, height: number) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 处理对话框关闭
|
/** 处理对话框关闭 */
|
||||||
const handleSubmit = () => {
|
const handleSubmit = () => {
|
||||||
// 会自动触发handleClose
|
|
||||||
dialogVisible.value = false;
|
dialogVisible.value = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
// 处理对话框关闭
|
/** 处理对话框关闭 */
|
||||||
const handleClose = () => {
|
const handleClose = () => {
|
||||||
// 缩小
|
// 缩小
|
||||||
const list = zoomOut(formData.value);
|
const list = zoomOut(formData.value);
|
||||||
@@ -164,12 +170,16 @@ const handleClose = () => {
|
|||||||
|
|
||||||
const activeHotZone = ref<HotZoneItemProperty>();
|
const activeHotZone = ref<HotZoneItemProperty>();
|
||||||
const appLinkDialogRef = ref();
|
const appLinkDialogRef = ref();
|
||||||
|
|
||||||
const handleShowAppLinkDialog = (hotZone: HotZoneItemProperty) => {
|
const handleShowAppLinkDialog = (hotZone: HotZoneItemProperty) => {
|
||||||
activeHotZone.value = hotZone;
|
activeHotZone.value = hotZone;
|
||||||
appLinkDialogRef.value.open(hotZone.url);
|
appLinkDialogRef.value.open(hotZone.url);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleAppLinkChange = (appLink: AppLink) => {
|
const handleAppLinkChange = (appLink: AppLink) => {
|
||||||
if (!appLink || !activeHotZone.value) return;
|
if (!appLink || !activeHotZone.value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
activeHotZone.value.name = appLink.name;
|
activeHotZone.value.name = appLink.name;
|
||||||
activeHotZone.value.url = appLink.path;
|
activeHotZone.value.url = appLink.path;
|
||||||
};
|
};
|
||||||
@@ -231,6 +241,7 @@ const handleAppLinkChange = (appLink: AppLink) => {
|
|||||||
</ElButton>
|
</ElButton>
|
||||||
</template>
|
</template>
|
||||||
</ElDialog>
|
</ElDialog>
|
||||||
|
|
||||||
<AppLinkSelectDialog
|
<AppLinkSelectDialog
|
||||||
ref="appLinkDialogRef"
|
ref="appLinkDialogRef"
|
||||||
@app-link-change="handleAppLinkChange"
|
@app-link-change="handleAppLinkChange"
|
||||||
|
|||||||
@@ -2,31 +2,22 @@ import type { ComponentStyle, DiyComponent } from '../../../util';
|
|||||||
|
|
||||||
/** 热区属性 */
|
/** 热区属性 */
|
||||||
export interface HotZoneProperty {
|
export interface HotZoneProperty {
|
||||||
// 图片地址
|
imgUrl: string; // 图片地址
|
||||||
imgUrl: string;
|
list: HotZoneItemProperty[]; // 导航菜单列表
|
||||||
// 导航菜单列表
|
style: ComponentStyle; // 组件样式
|
||||||
list: HotZoneItemProperty[];
|
|
||||||
// 组件样式
|
|
||||||
style: ComponentStyle;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 热区项目属性 */
|
/** 热区项目属性 */
|
||||||
export interface HotZoneItemProperty {
|
export interface HotZoneItemProperty {
|
||||||
// 链接的名称
|
name: string; // 链接的名称
|
||||||
name: string;
|
url: string; // 链接
|
||||||
// 链接
|
width: number; // 宽
|
||||||
url: string;
|
height: number; // 高
|
||||||
// 宽
|
top: number; // 上
|
||||||
width: number;
|
left: number; // 左
|
||||||
// 高
|
|
||||||
height: number;
|
|
||||||
// 上
|
|
||||||
top: number;
|
|
||||||
// 左
|
|
||||||
left: number;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 定义组件
|
/** 定义组件 */
|
||||||
export const component = {
|
export const component = {
|
||||||
id: 'HotZone',
|
id: 'HotZone',
|
||||||
name: '热区',
|
name: '热区',
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { ElImage } from 'element-plus';
|
|||||||
|
|
||||||
/** 热区 */
|
/** 热区 */
|
||||||
defineOptions({ name: 'HotZone' });
|
defineOptions({ name: 'HotZone' });
|
||||||
|
|
||||||
const props = defineProps<{ property: HotZoneProperty }>();
|
const props = defineProps<{ property: HotZoneProperty }>();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -15,12 +15,14 @@ import HotZoneEditDialog from './components/hot-zone-edit-dialog/index.vue';
|
|||||||
defineOptions({ name: 'HotZoneProperty' });
|
defineOptions({ name: 'HotZoneProperty' });
|
||||||
|
|
||||||
const props = defineProps<{ modelValue: HotZoneProperty }>();
|
const props = defineProps<{ modelValue: HotZoneProperty }>();
|
||||||
|
|
||||||
const emit = defineEmits(['update:modelValue']);
|
const emit = defineEmits(['update:modelValue']);
|
||||||
|
|
||||||
const formData = useVModel(props, 'modelValue', emit);
|
const formData = useVModel(props, 'modelValue', emit);
|
||||||
|
|
||||||
// 热区编辑对话框
|
const editDialogRef = ref(); // 热区编辑对话框
|
||||||
const editDialogRef = ref();
|
|
||||||
// 打开热区编辑对话框
|
/** 打开热区编辑对话框 */
|
||||||
const handleOpenEditDialog = () => {
|
const handleOpenEditDialog = () => {
|
||||||
editDialogRef.value.open();
|
editDialogRef.value.open();
|
||||||
};
|
};
|
||||||
@@ -49,6 +51,7 @@ const handleOpenEditDialog = () => {
|
|||||||
设置热区
|
设置热区
|
||||||
</ElButton>
|
</ElButton>
|
||||||
</ComponentContainerProperty>
|
</ComponentContainerProperty>
|
||||||
|
|
||||||
<!-- 热区编辑对话框 -->
|
<!-- 热区编辑对话框 -->
|
||||||
<HotZoneEditDialog
|
<HotZoneEditDialog
|
||||||
ref="editDialogRef"
|
ref="editDialogRef"
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
export { default as AppLinkSelectDialog } from './app-link-input/app-link-select-dialog.vue';
|
||||||
export { default as AppLinkInput } from './app-link-input/index.vue';
|
export { default as AppLinkInput } from './app-link-input/index.vue';
|
||||||
export { default as ColorInput } from './color-input/index.vue';
|
export { default as ColorInput } from './color-input/index.vue';
|
||||||
export { default as DiyEditor } from './diy-editor/index.vue';
|
export { default as DiyEditor } from './diy-editor/index.vue';
|
||||||
|
|||||||
Reference in New Issue
Block a user