feat:【mall】diy editor 的 navigation-bar 优化
This commit is contained in:
@@ -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<Rect[]>(() => {
|
||||
return cellList.value.map((cell) => ({
|
||||
left: cell.left,
|
||||
@@ -53,18 +59,19 @@ const rectList = computed<Rect[]>(() => {
|
||||
}));
|
||||
});
|
||||
|
||||
// 选中的热区
|
||||
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';
|
||||
}
|
||||
};
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -141,5 +148,3 @@ const handleHotAreaSelected = (
|
||||
</template>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
|
||||
@@ -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: '顶部导航栏',
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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) {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<el-form label-width="80px" :model="formData" :rules="rules">
|
||||
<el-form-item label="样式" prop="styleType">
|
||||
<el-radio-group v-model="formData!.styleType">
|
||||
<el-radio value="normal">标准</el-radio>
|
||||
<el-tooltip
|
||||
<ElForm label-width="80px" :model="formData" :rules="rules">
|
||||
<ElFormItem label="样式" prop="styleType">
|
||||
<ElRadioGroup v-model="formData!.styleType">
|
||||
<ElRadio value="normal">标准</ElRadio>
|
||||
<ElTooltip
|
||||
content="沉侵式头部仅支持微信小程序、APP,建议页面第一个组件为图片展示类组件"
|
||||
placement="top"
|
||||
>
|
||||
<el-radio value="inner">沉浸式</el-radio>
|
||||
</el-tooltip>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
<ElRadio value="inner">沉浸式</ElRadio>
|
||||
</ElTooltip>
|
||||
</ElRadioGroup>
|
||||
</ElFormItem>
|
||||
<ElFormItem
|
||||
label="常驻显示"
|
||||
prop="alwaysShow"
|
||||
v-if="formData.styleType === 'inner'"
|
||||
>
|
||||
<el-radio-group v-model="formData!.alwaysShow">
|
||||
<el-radio :value="false">关闭</el-radio>
|
||||
<el-tooltip
|
||||
<ElRadioGroup v-model="formData!.alwaysShow">
|
||||
<ElRadio :value="false">关闭</ElRadio>
|
||||
<ElTooltip
|
||||
content="常驻显示关闭后,头部小组件将在页面滑动时淡入"
|
||||
placement="top"
|
||||
>
|
||||
<el-radio :value="true">开启</el-radio>
|
||||
</el-tooltip>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="背景类型" prop="bgType">
|
||||
<el-radio-group v-model="formData.bgType">
|
||||
<el-radio value="color">纯色</el-radio>
|
||||
<el-radio value="img">图片</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
<ElRadio :value="true">开启</ElRadio>
|
||||
</ElTooltip>
|
||||
</ElRadioGroup>
|
||||
</ElFormItem>
|
||||
<ElFormItem label="背景类型" prop="bgType">
|
||||
<ElRadioGroup v-model="formData.bgType">
|
||||
<ElRadio value="color">纯色</ElRadio>
|
||||
<ElRadio value="img">图片</ElRadio>
|
||||
</ElRadioGroup>
|
||||
</ElFormItem>
|
||||
<ElFormItem
|
||||
label="背景颜色"
|
||||
prop="bgColor"
|
||||
v-if="formData.bgType === 'color'"
|
||||
>
|
||||
<ColorInput v-model="formData.bgColor" />
|
||||
</el-form-item>
|
||||
<el-form-item label="背景图片" prop="bgImg" v-else>
|
||||
</ElFormItem>
|
||||
<ElFormItem label="背景图片" prop="bgImg" v-else>
|
||||
<div class="flex items-center">
|
||||
<UploadImg
|
||||
v-model="formData.bgImg"
|
||||
@@ -74,44 +86,42 @@ if (!formData.value._local) {
|
||||
/>
|
||||
<span class="mb-2 ml-2 text-xs text-gray-400">建议宽度:750</span>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-card class="property-group" shadow="never">
|
||||
</ElFormItem>
|
||||
<ElCard class="property-group" shadow="never">
|
||||
<template #header>
|
||||
<div class="flex items-center justify-between">
|
||||
<span>内容(小程序)</span>
|
||||
<el-form-item prop="_local.previewMp" class="mb-0">
|
||||
<el-checkbox
|
||||
<ElFormItem prop="_local.previewMp" class="mb-0">
|
||||
<ElCheckbox
|
||||
v-model="formData._local.previewMp"
|
||||
@change="
|
||||
formData._local.previewOther = !formData._local.previewMp
|
||||
"
|
||||
>
|
||||
预览
|
||||
</el-checkbox>
|
||||
</el-form-item>
|
||||
</ElCheckbox>
|
||||
</ElFormItem>
|
||||
</div>
|
||||
</template>
|
||||
<NavigationBarCellProperty v-model="formData.mpCells" is-mp />
|
||||
</el-card>
|
||||
<el-card class="property-group" shadow="never">
|
||||
</ElCard>
|
||||
<ElCard class="property-group" shadow="never">
|
||||
<template #header>
|
||||
<div class="flex items-center justify-between">
|
||||
<span>内容(非小程序)</span>
|
||||
<el-form-item prop="_local.previewOther" class="mb-0">
|
||||
<el-checkbox
|
||||
<ElFormItem prop="_local.previewOther" class="mb-0">
|
||||
<ElCheckbox
|
||||
v-model="formData._local.previewOther"
|
||||
@change="
|
||||
formData._local.previewMp = !formData._local.previewOther
|
||||
"
|
||||
>
|
||||
预览
|
||||
</el-checkbox>
|
||||
</el-form-item>
|
||||
</ElCheckbox>
|
||||
</ElFormItem>
|
||||
</div>
|
||||
</template>
|
||||
<NavigationBarCellProperty v-model="formData.otherCells" :is-mp="false" />
|
||||
</el-card>
|
||||
</el-form>
|
||||
</ElCard>
|
||||
</ElForm>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
|
||||
Reference in New Issue
Block a user