feat:【mall】diy editor 的 hot-zone 代码优化(50%)

pull/251/head
YunaiV 2025-10-28 19:22:27 +08:00
parent a4f7a51ba0
commit 4de0050610
6 changed files with 77 additions and 69 deletions

View File

@ -2,10 +2,9 @@ import type { StyleValue } from 'vue';
import type { HotZoneItemProperty } from '../../config';
// 热区的最小宽高
export const HOT_ZONE_MIN_SIZE = 100;
export const HOT_ZONE_MIN_SIZE = 100; // 热区的最小宽高
// 控制的类型
/** 控制的类型 */
export enum CONTROL_TYPE_ENUM {
LEFT,
TOP,
@ -13,14 +12,14 @@ export enum CONTROL_TYPE_ENUM {
HEIGHT,
}
// 定义热区的控制点
/** 定义热区的控制点 */
export interface ControlDot {
position: string;
types: CONTROL_TYPE_ENUM[];
style: StyleValue;
}
// 热区的8个控制点
/** 热区的 8 个控制点 */
export const CONTROL_DOT_LIST = [
{
position: '左上角',
@ -98,10 +97,10 @@ export const CONTROL_DOT_LIST = [
] as ControlDot[];
// region 热区的缩放
// 热区的缩放比例
export const HOT_ZONE_SCALE_RATE = 2;
// 缩小:缩回适合手机屏幕的大小
export const zoomOut = (list?: HotZoneItemProperty[]) => {
export const HOT_ZONE_SCALE_RATE = 2; // 热区的缩放比例
/** 缩小:缩回适合手机屏幕的大小 */
export function zoomOut(list?: HotZoneItemProperty[]) {
return (
list?.map((hotZone) => ({
...hotZone,
@ -111,9 +110,10 @@ export const zoomOut = (list?: HotZoneItemProperty[]) => {
height: (hotZone.height /= HOT_ZONE_SCALE_RATE),
})) || []
);
};
// 放大:作用是为了方便在电脑屏幕上编辑
export const zoomIn = (list?: HotZoneItemProperty[]) => {
}
/** 放大:作用是为了方便在电脑屏幕上编辑 */
export function zoomIn(list?: HotZoneItemProperty[]) {
return (
list?.map((hotZone) => ({
...hotZone,
@ -123,7 +123,8 @@ export const zoomIn = (list?: HotZoneItemProperty[]) => {
height: (hotZone.height *= HOT_ZONE_SCALE_RATE),
})) || []
);
};
}
// endregion
/**

View File

@ -10,6 +10,8 @@ import { IconifyIcon } from '@vben/icons';
import { ElButton, ElDialog, ElImage } from 'element-plus';
import { AppLinkSelectDialog } from '#/views/mall/promotion/components';
import {
CONTROL_DOT_LIST,
CONTROL_TYPE_ENUM,
@ -22,7 +24,7 @@ import {
/** 热区编辑对话框 */
defineOptions({ name: 'HotZoneEditDialog' });
//
/** 定义属性 */
const props = defineProps({
modelValue: {
type: Array<HotZoneItemProperty>,
@ -33,51 +35,53 @@ const props = defineProps({
default: '',
},
});
const emit = defineEmits(['update:modelValue']);
const formData = ref<HotZoneItemProperty[]>([]);
//
const dialogVisible = ref(false);
//
const dialogVisible = ref(false); //
/** 打开弹窗 */
const open = () => {
//
formData.value = zoomIn(props.modelValue);
dialogVisible.value = true;
};
// open
defineExpose({ open });
//
const container = ref<HTMLDivElement>();
defineExpose({ open }); // open
//
const handleAdd = () => {
const container = ref<HTMLDivElement>(); //
/** 增加热区 */
function handleAdd() {
formData.value.push({
width: HOT_ZONE_MIN_SIZE,
height: HOT_ZONE_MIN_SIZE,
top: 0,
left: 0,
} 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) => {
setLeft(item, left + moveWidth);
setTop(item, top + moveHeight);
});
};
}
//
const handleResize = (
/** 调整热区大小、位置 */
function handleResize(
item: HotZoneItemProperty,
ctrlDot: ControlDot,
e: MouseEvent,
) => {
) {
useDraggable(item, e, (left, top, width, height, moveWidth, moveHeight) => {
ctrlDot.types.forEach((type) => {
switch (type) {
@ -112,23 +116,25 @@ const handleResize = (
}
});
});
};
}
// X
const setLeft = (item: HotZoneItemProperty, left: number) => {
/** 设置 X 轴坐标 */
function setLeft(item: HotZoneItemProperty, left: number) {
//
if (left >= 0 && left <= container.value!.offsetWidth - item.width) {
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) {
item.top = top;
}
};
//
}
/** 设置宽度 */
const setWidth = (item: HotZoneItemProperty, width: number) => {
// &&
if (
@ -138,7 +144,8 @@ const setWidth = (item: HotZoneItemProperty, width: number) => {
item.width = width;
}
};
//
/** 设置高度 */
const setHeight = (item: HotZoneItemProperty, height: number) => {
// &&
if (
@ -149,13 +156,12 @@ const setHeight = (item: HotZoneItemProperty, height: number) => {
}
};
//
/** 处理对话框关闭 */
const handleSubmit = () => {
// handleClose
dialogVisible.value = false;
};
//
/** 处理对话框关闭 */
const handleClose = () => {
//
const list = zoomOut(formData.value);
@ -164,12 +170,16 @@ const handleClose = () => {
const activeHotZone = ref<HotZoneItemProperty>();
const appLinkDialogRef = ref();
const handleShowAppLinkDialog = (hotZone: HotZoneItemProperty) => {
activeHotZone.value = hotZone;
appLinkDialogRef.value.open(hotZone.url);
};
const handleAppLinkChange = (appLink: AppLink) => {
if (!appLink || !activeHotZone.value) return;
if (!appLink || !activeHotZone.value) {
return;
}
activeHotZone.value.name = appLink.name;
activeHotZone.value.url = appLink.path;
};
@ -231,6 +241,7 @@ const handleAppLinkChange = (appLink: AppLink) => {
</ElButton>
</template>
</ElDialog>
<AppLinkSelectDialog
ref="appLinkDialogRef"
@app-link-change="handleAppLinkChange"

View File

@ -2,31 +2,22 @@ import type { ComponentStyle, DiyComponent } from '../../../util';
/** 热区属性 */
export interface HotZoneProperty {
// 图片地址
imgUrl: string;
// 导航菜单列表
list: HotZoneItemProperty[];
// 组件样式
style: ComponentStyle;
imgUrl: string; // 图片地址
list: HotZoneItemProperty[]; // 导航菜单列表
style: ComponentStyle; // 组件样式
}
/** 热区项目属性 */
export interface HotZoneItemProperty {
// 链接的名称
name: string;
// 链接
url: string;
// 宽
width: number;
// 高
height: number;
// 上
top: number;
// 左
left: number;
name: string; // 链接的名称
url: string; // 链接
width: number; // 宽
height: number; // 高
top: number; // 上
left: number; // 左
}
// 定义组件
/** 定义组件 */
export const component = {
id: 'HotZone',
name: '热区',

View File

@ -5,6 +5,7 @@ import { ElImage } from 'element-plus';
/** 热区 */
defineOptions({ name: 'HotZone' });
const props = defineProps<{ property: HotZoneProperty }>();
</script>

View File

@ -15,12 +15,14 @@ import HotZoneEditDialog from './components/hot-zone-edit-dialog/index.vue';
defineOptions({ name: 'HotZoneProperty' });
const props = defineProps<{ modelValue: HotZoneProperty }>();
const emit = defineEmits(['update:modelValue']);
const formData = useVModel(props, 'modelValue', emit);
//
const editDialogRef = ref();
//
const editDialogRef = ref(); //
/** 打开热区编辑对话框 */
const handleOpenEditDialog = () => {
editDialogRef.value.open();
};
@ -49,6 +51,7 @@ const handleOpenEditDialog = () => {
设置热区
</ElButton>
</ComponentContainerProperty>
<!-- 热区编辑对话框 -->
<HotZoneEditDialog
ref="editDialogRef"

View File

@ -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 ColorInput } from './color-input/index.vue';
export { default as DiyEditor } from './diy-editor/index.vue';