feat:【antd】【mall】diy-editor 修复 element-plus 组件之路:部分解决 21%

This commit is contained in:
YunaiV
2025-10-26 10:21:38 +08:00
parent 21d03d8bac
commit e218be3fdf
14 changed files with 191 additions and 28 deletions

View File

@@ -5,6 +5,8 @@ import { ref } from 'vue';
import { IconifyIcon } from '@vben/icons';
import { Image } from 'ant-design-vue';
/** 弹窗广告 */
defineOptions({ name: 'Popover' });
// 定义属性

View File

@@ -5,7 +5,7 @@ import { ref } from 'vue';
import { IconifyIcon } from '@vben/icons';
import { message } from 'ant-design-vue';
import { Image, message } from 'ant-design-vue';
/** 悬浮按钮 */
defineOptions({ name: 'FloatingActionButton' });

View File

@@ -3,6 +3,8 @@ import type { MenuListProperty } from './config';
import { IconifyIcon } from '@vben/icons';
import { Image } from 'ant-design-vue';
/** 列表导航 */
defineOptions({ name: 'MenuList' });
defineProps<{ property: MenuListProperty }>();

View File

@@ -1,4 +1,145 @@
<script lang="ts" setup>
import type { NavigationBarCellProperty } from '../config';
import type { Rect } from '#/views/mall/promotion/components/magic-cube-editor/util';
import { computed, ref } from 'vue';
import { useVModel } from '@vueuse/core';
import {
FormItem,
Input,
Radio,
RadioGroup,
Slider,
} from 'ant-design-vue';
import appNavBarMp from '#/assets/imgs/diy/app-nav-bar-mp.png';
import UploadImg from '#/components/upload/image-upload.vue';
import {
AppLinkInput,
ColorInput,
MagicCubeEditor,
} from '#/views/mall/promotion/components';
// 导航栏属性面板
defineOptions({ name: 'NavigationBarCellProperty' });
const props = defineProps({
isMp: {
type: Boolean,
default: true,
},
modelValue: {
type: Array as () => NavigationBarCellProperty[],
default: () => [],
},
});
const emit = defineEmits(['update:modelValue']);
const cellList = useVModel(props, 'modelValue', emit);
// 单元格数量小程序6个右侧胶囊按钮占了2个其它平台8个
const cellCount = computed(() => (props.isMp ? 6 : 8));
// 转换为Rect格式的数据
const rectList = computed<Rect[]>(() => {
return cellList.value.map((cell) => ({
left: cell.left,
top: cell.top,
width: cell.width,
height: cell.height,
right: cell.left + cell.width,
bottom: cell.top + cell.height,
}));
});
// 选中的热区
const selectedHotAreaIndex = ref(0);
const handleHotAreaSelected = (
cellValue: NavigationBarCellProperty,
index: number,
) => {
selectedHotAreaIndex.value = index;
if (!cellValue.type) {
cellValue.type = 'text';
cellValue.textColor = '#111111';
}
};
</script>
<template>
<div class="h-40px flex items-center justify-center">
<MagicCubeEditor
v-model="rectList"
:cols="cellCount"
:cube-size="38"
:rows="1"
class="m-b-16px"
@hot-area-selected="handleHotAreaSelected"
/>
<img
v-if="isMp"
alt=""
style="width: 76px; height: 30px"
:src="appNavBarMp"
/>
</div>
<template v-for="(cell, cellIndex) in cellList" :key="cellIndex">
<template v-if="selectedHotAreaIndex === Number(cellIndex)">
<FormItem :label="`类型`">
<RadioGroup v-model:value="cell.type">
<Radio value="text">文字</Radio>
<Radio value="image">图片</Radio>
<Radio value="search">搜索框</Radio>
</RadioGroup>
</FormItem>
<!-- 1. 文字 -->
<template v-if="cell.type === 'text'">
<FormItem :label="`内容`">
<Input v-model:value="cell!.text" :maxlength="10" show-count />
</FormItem>
<FormItem :label="`颜色`">
<ColorInput v-model="cell!.textColor" />
</FormItem>
<FormItem :label="`链接`">
<AppLinkInput v-model="cell.url" />
</FormItem>
</template>
<!-- 2. 图片 -->
<template v-else-if="cell.type === 'image'">
<FormItem :label="`图片`">
<UploadImg
v-model="cell.imgUrl"
:limit="1"
height="56px"
width="56px"
:show-description="false"
>
<template #tip>建议尺寸 56*56</template>
</UploadImg>
</FormItem>
<FormItem :label="`链接`">
<AppLinkInput v-model="cell.url" />
</FormItem>
</template>
<!-- 3. 搜索框 -->
<template v-else>
<FormItem :label="`提示文字`">
<Input v-model:value="cell.placeholder" :maxlength="10" show-count />
</FormItem>
<FormItem :label="`圆角`">
<Slider
v-model:value="cell.borderRadius"
:max="100"
:min="0"
/>
</FormItem>
</template>
</template>
</template>
</template>
<style lang="scss" scoped></style>

View File

@@ -1,12 +1,23 @@
<script setup lang="ts">
import type { NoticeBarProperty } from './config';
import { ref } from 'vue';
import { IconifyIcon } from '@vben/icons';
import { Divider, Image } from 'ant-design-vue';
/** 公告栏 */
defineOptions({ name: 'NoticeBar' });
defineProps<{ property: NoticeBarProperty }>();
const props = defineProps<{ property: NoticeBarProperty }>();
// 自动轮播
const activeIndex = ref(0);
setInterval(() => {
const contents = props.property.contents || [];
activeIndex.value = (activeIndex.value + 1) % (contents.length || 1);
}, 3000);
</script>
<template>
@@ -17,18 +28,11 @@ defineProps<{ property: NoticeBarProperty }>();
color: property.textColor,
}"
>
<ElImage :src="property.iconUrl" class="h-[18px]" />
<ElDivider direction="vertical" />
<ElCarousel
height="24px"
direction="vertical"
:autoplay="true"
class="flex-1 pr-2"
>
<ElCarouselItem v-for="(item, index) in property.contents" :key="index">
<div class="h-6 truncate leading-6">{{ item.text }}</div>
</ElCarouselItem>
</ElCarousel>
<Image :src="property.iconUrl" class="h-[18px]" :preview="false" />
<Divider type="vertical" />
<div class="flex-1 pr-2 h-6 truncate leading-6">
{{ property.contents?.[activeIndex]?.text }}
</div>
<IconifyIcon icon="ep:arrow-right" />
</div>
</template>

View File

@@ -7,6 +7,8 @@ import { ref, watch } from 'vue';
import { fenToYuan } from '@vben/utils';
import { Image } from 'ant-design-vue';
import * as ProductSpuApi from '#/api/mall/product/spu';
/** 商品卡片 */

View File

@@ -8,6 +8,8 @@ import { ref, watch } from 'vue';
import { fenToYuan } from '@vben/utils';
import { Image } from 'ant-design-vue';
import * as ProductSpuApi from '#/api/mall/product/spu';
import * as CombinationActivityApi from '#/api/mall/promotion/combination/combinationActivity';

View File

@@ -7,6 +7,8 @@ import { ref, watch } from 'vue';
import { fenToYuan } from '@vben/utils';
import { Image } from 'ant-design-vue';
import * as ProductSpuApi from '#/api/mall/product/spu';
import * as PointActivityApi from '#/api/mall/promotion/point';

View File

@@ -8,6 +8,8 @@ import { ref, watch } from 'vue';
import { fenToYuan } from '@vben/utils';
import { Image } from 'ant-design-vue';
import * as ProductSpuApi from '#/api/mall/product/spu';
import * as SeckillActivityApi from '#/api/mall/promotion/seckill/seckillActivity';

View File

@@ -3,6 +3,8 @@ import type { TabBarProperty } from './config';
import { IconifyIcon } from '@vben/icons';
import { Image } from 'ant-design-vue';
/** 页面底部导航栏 */
defineOptions({ name: 'TabBar' });

View File

@@ -3,6 +3,8 @@ import type { TitleBarProperty } from './config';
import { IconifyIcon } from '@vben/icons';
import { Image } from 'ant-design-vue';
/** 标题栏 */
defineOptions({ name: 'TitleBar' });

View File

@@ -1,6 +1,8 @@
<script setup lang="ts">
import type { VideoPlayerProperty } from './config';
import { Image } from 'ant-design-vue';
/** 视频播放 */
defineOptions({ name: 'VideoPlayer' });

View File

@@ -252,13 +252,13 @@ const handleDeleteComponent = (index: number) => {
}
};
// 注入无感刷新页面函数
const reload = inject<() => void>('reload'); // TODO @芋艿:是 vue3 + element-plus 独有的,可以清理掉。
// 重置
const handleReset = () => {
if (reload) reload();
emits('reset');
};
// // 注入无感刷新页面函数
// const reload = inject<() => void>('reload'); // TODO @芋艿:是 vue3 + element-plus 独有的,可以清理掉。
// // 重置
// const handleReset = () => {
// if (reload) reload();
// emits('reset');
// };
// 预览
const previewDialogVisible = ref(false);

View File

@@ -261,13 +261,13 @@ const handleDeleteComponent = (index: number) => {
}
};
// 注入无感刷新页面函数
const reload = inject<() => void>('reload'); // TODO @芋艿:是 vue3 + element-plus 独有的,可以清理掉。
// 重置
const handleReset = () => {
if (reload) reload();
emits('reset');
};
// // 注入无感刷新页面函数
// const reload = inject<() => void>('reload'); // TODO @芋艿:是 vue3 + element-plus 独有的,可以清理掉。
// // 重置
// const handleReset = () => {
// if (reload) reload();
// emits('reset');
// };
// 预览
const previewDialogVisible = ref(false);