From 5e1c7bb54cb94b6252c46fee2fa7415a7e9d6f0c Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 1 Nov 2025 09:21:26 +0800 Subject: [PATCH] =?UTF-8?q?feat=EF=BC=9A=E3=80=90mall=E3=80=91diy=20editor?= =?UTF-8?q?=20=E7=9A=84=20navigation-bar=20=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/cell-property.vue | 25 +++-- .../mobile/navigation-bar/config.ts | 65 ++++-------- .../mobile/navigation-bar/index.vue | 18 ++-- .../mobile/navigation-bar/property.vue | 100 ++++++++++-------- 4 files changed, 103 insertions(+), 105 deletions(-) diff --git a/apps/web-ele/src/views/mall/promotion/components/diy-editor/components/mobile/navigation-bar/components/cell-property.vue b/apps/web-ele/src/views/mall/promotion/components/diy-editor/components/mobile/navigation-bar/components/cell-property.vue index 585a0f0a7..366723d88 100644 --- a/apps/web-ele/src/views/mall/promotion/components/diy-editor/components/mobile/navigation-bar/components/cell-property.vue +++ b/apps/web-ele/src/views/mall/promotion/components/diy-editor/components/mobile/navigation-bar/components/cell-property.vue @@ -22,7 +22,7 @@ import { MagicCubeEditor, } from '#/views/mall/promotion/components'; -// 导航栏属性面板 +/** 导航栏单元格属性面板 */ defineOptions({ name: 'NavigationBarCellProperty' }); const props = defineProps({ @@ -35,13 +35,19 @@ const props = defineProps({ default: () => [], }, }); + const emit = defineEmits(['update:modelValue']); + const cellList = useVModel(props, 'modelValue', emit); -// 单元格数量:小程序6个(右侧胶囊按钮占了2个),其它平台8个 +/** + * 计算单元格数量 + * 1. 小程序:6 个(因为右侧有胶囊按钮占据 2 个格子的空间) + * 2. 其它平台:8 个(全部空间可用) + */ const cellCount = computed(() => (props.isMp ? 6 : 8)); -// 转换为Rect格式的数据 +/** 转换为 Rect 格式的数据:MagicCubeEditor 组件需要 Rect 格式的数据来渲染热区 */ const rectList = computed(() => { return cellList.value.map((cell) => ({ left: cell.left, @@ -53,18 +59,19 @@ const rectList = computed(() => { })); }); -// 选中的热区 -const selectedHotAreaIndex = ref(0); -const handleHotAreaSelected = ( +const selectedHotAreaIndex = ref(0); // 选中的热区 + +/** 处理热区被选中事件 */ +function handleHotAreaSelected( cellValue: NavigationBarCellProperty, index: number, -) => { +) { selectedHotAreaIndex.value = index; if (!cellValue.type) { cellValue.type = 'text'; cellValue.textColor = '#111111'; } -}; +} - - diff --git a/apps/web-ele/src/views/mall/promotion/components/diy-editor/components/mobile/navigation-bar/config.ts b/apps/web-ele/src/views/mall/promotion/components/diy-editor/components/mobile/navigation-bar/config.ts index fd675b16e..f898ce9e8 100644 --- a/apps/web-ele/src/views/mall/promotion/components/diy-editor/components/mobile/navigation-bar/config.ts +++ b/apps/web-ele/src/views/mall/promotion/components/diy-editor/components/mobile/navigation-bar/config.ts @@ -2,56 +2,35 @@ import type { DiyComponent } from '../../../util'; /** 顶部导航栏属性 */ export interface NavigationBarProperty { - // 背景类型 - bgType: 'color' | 'img'; - // 背景颜色 - bgColor: string; - // 图片链接 - bgImg: string; - // 样式类型:默认 | 沉浸式 - styleType: 'inner' | 'normal'; - // 常驻显示 - alwaysShow: boolean; - // 小程序单元格列表 - mpCells: NavigationBarCellProperty[]; - // 其它平台单元格列表 - otherCells: NavigationBarCellProperty[]; - // 本地变量 + bgType: 'color' | 'img'; // 背景类型 + bgColor: string; // 背景颜色 + bgImg: string; // 图片链接 + styleType: 'inner' | 'normal'; // 样式类型:默认 | 沉浸式 + alwaysShow: boolean; // 常驻显示 + mpCells: NavigationBarCellProperty[]; // 小程序单元格列表 + otherCells: NavigationBarCellProperty[]; // 其它平台单元格列表 _local: { - // 预览顶部导航(小程序) - previewMp: boolean; - // 预览顶部导航(非小程序) - previewOther: boolean; - }; + previewMp: boolean; // 预览顶部导航(小程序) + previewOther: boolean; // 预览顶部导航(非小程序) + }; // 本地变量 } /** 顶部导航栏 - 单元格 属性 */ export interface NavigationBarCellProperty { - // 类型:文字 | 图片 | 搜索框 - type: 'image' | 'search' | 'text'; - // 宽度 - width: number; - // 高度 - height: number; - // 顶部位置 - top: number; - // 左侧位置 - left: number; - // 文字内容 - text: string; - // 文字颜色 - textColor: string; - // 图片地址 - imgUrl: string; - // 图片链接 - url: string; - // 搜索框:提示文字 - placeholder: string; - // 搜索框:边框圆角半径 - borderRadius: number; + type: 'image' | 'search' | 'text'; // 类型:文字 | 图片 | 搜索框 + width: number; // 宽度 + height: number; // 高度 + top: number; // 顶部位置 + left: number; // 左侧位置 + text: string; // 文字内容 + textColor: string; // 文字颜色 + imgUrl: string; // 图片地址 + url: string; // 图片链接 + placeholder: string; // 搜索框:提示文字 + borderRadius: number; // 搜索框:边框圆角半径 } -// 定义组件 +/** 定义组件 */ export const component = { id: 'NavigationBar', name: '顶部导航栏', diff --git a/apps/web-ele/src/views/mall/promotion/components/diy-editor/components/mobile/navigation-bar/index.vue b/apps/web-ele/src/views/mall/promotion/components/diy-editor/components/mobile/navigation-bar/index.vue index 9e3b17a07..3460ee53e 100644 --- a/apps/web-ele/src/views/mall/promotion/components/diy-editor/components/mobile/navigation-bar/index.vue +++ b/apps/web-ele/src/views/mall/promotion/components/diy-editor/components/mobile/navigation-bar/index.vue @@ -18,7 +18,7 @@ defineOptions({ name: 'NavigationBar' }); const props = defineProps<{ property: NavigationBarProperty }>(); -// 背景 +/** 计算背景样式 */ const bgStyle = computed(() => { const background = props.property.bgType === 'img' && props.property.bgImg @@ -26,27 +26,31 @@ const bgStyle = computed(() => { : props.property.bgColor; return { background }; }); -// 单元格列表 + +/** 获取当前预览的单元格列表 */ const cellList = computed(() => props.property._local?.previewMp ? props.property.mpCells : props.property.otherCells, ); -// 单元格宽度 + +/** 计算单元格宽度 */ const cellWidth = computed(() => { return props.property._local?.previewMp ? (375 - 80 - 86) / 6 : (375 - 90) / 8; }); -// 获得单元格样式 -const getCellStyle = (cell: NavigationBarCellProperty) => { + +/** 获取单元格样式 */ +function getCellStyle(cell: NavigationBarCellProperty) { return { width: `${cell.width * cellWidth.value + (cell.width - 1) * 10}px`, left: `${cell.left * cellWidth.value + (cell.left + 1) * 10}px`, position: 'absolute', } as StyleValue; -}; -// 获得搜索框属性 +} + +/** 获取搜索框属性配置 */ const getSearchProp = computed(() => (cell: NavigationBarCellProperty) => { return { height: 30, diff --git a/apps/web-ele/src/views/mall/promotion/components/diy-editor/components/mobile/navigation-bar/property.vue b/apps/web-ele/src/views/mall/promotion/components/diy-editor/components/mobile/navigation-bar/property.vue index ce3e3f698..9703be641 100644 --- a/apps/web-ele/src/views/mall/promotion/components/diy-editor/components/mobile/navigation-bar/property.vue +++ b/apps/web-ele/src/views/mall/promotion/components/diy-editor/components/mobile/navigation-bar/property.vue @@ -2,19 +2,31 @@ import type { NavigationBarProperty } from './config'; import { useVModel } from '@vueuse/core'; +import { + ElCard, + ElCheckbox, + ElForm, + ElFormItem, + ElRadio, + ElRadioGroup, + ElTooltip, +} from 'element-plus'; + +import UploadImg from '#/components/upload/image-upload.vue'; +import { ColorInput } from '#/views/mall/promotion/components'; import NavigationBarCellProperty from './components/cell-property.vue'; -// 导航栏属性面板 +/** 导航栏属性面板 */ defineOptions({ name: 'NavigationBarProperty' }); + const props = defineProps<{ modelValue: NavigationBarProperty }>(); const emit = defineEmits(['update:modelValue']); -// 表单校验 const rules = { name: [{ required: true, message: '请输入页面名称', trigger: 'blur' }], -}; +}; // 表单校验 const formData = useVModel(props, 'modelValue', emit); if (!formData.value._local) { @@ -23,47 +35,47 @@ if (!formData.value._local) { - -