feat:【antd】【mall】diy-editor 代码风格统一 & 逐个测试 30%
This commit is contained in:
@@ -133,6 +133,7 @@ function handleSliderChange(prop: string) {
|
||||
</TabPane>
|
||||
|
||||
<!-- 每个组件的通用内容 -->
|
||||
<!-- TODO @xingyu:这里的样式,貌似没 ele 版本的好看。 -->
|
||||
<TabPane tab="样式" key="style" force-render>
|
||||
<p class="text-lg font-bold">组件样式:</p>
|
||||
<div class="flex flex-col gap-2 rounded-md p-4 shadow-lg">
|
||||
@@ -159,6 +160,7 @@ function handleSliderChange(prop: string) {
|
||||
<template #tip>建议宽度 750px</template>
|
||||
</UploadImg>
|
||||
</FormItem>
|
||||
<!-- TODO @xingyu:没完全对齐 -->
|
||||
<Tree :tree-data="treeData" default-expand-all :block-node="true">
|
||||
<template #title="{ dataRef }">
|
||||
<FormItem
|
||||
|
||||
@@ -49,6 +49,7 @@ const emits = defineEmits<{
|
||||
type DiyComponentWithStyle = DiyComponent<any> & {
|
||||
property: { style?: ComponentStyle };
|
||||
};
|
||||
|
||||
/** 组件样式 */
|
||||
const style = computed(() => {
|
||||
const componentStyle = props.component.property.style;
|
||||
@@ -108,6 +109,7 @@ const handleDeleteComponent = () => {
|
||||
class="component-toolbar"
|
||||
v-if="showToolbar && component.name && active"
|
||||
>
|
||||
<!-- TODO @xingyu:按钮少的时候,会存在遮住的情况; -->
|
||||
<VerticalButtonGroup size="small">
|
||||
<Button
|
||||
:disabled="!canMoveUp"
|
||||
|
||||
@@ -19,6 +19,7 @@ const props = defineProps<{
|
||||
list: DiyComponentLibrary[];
|
||||
}>();
|
||||
|
||||
// TODO @xingyu:要不要换成 reactive,和 ele 一致
|
||||
const groups = ref<any[]>([]); // 组件分组
|
||||
const extendGroups = ref<string[]>([]); // 展开的折叠面板
|
||||
|
||||
@@ -99,4 +100,5 @@ function handleCloneComponent(component: DiyComponent<any>) {
|
||||
</Collapse.Panel>
|
||||
</Collapse>
|
||||
</div>
|
||||
<!-- TODO @xingyu:ele 里面有一些 style,看看是不是都迁移完了;特别是 drag-area 是全局样式; -->
|
||||
</template>
|
||||
|
||||
@@ -11,7 +11,6 @@ defineOptions({ name: 'ImageBar' });
|
||||
defineProps<{ property: ImageBarProperty }>();
|
||||
</script>
|
||||
<template>
|
||||
<!-- 无图片 -->
|
||||
<div
|
||||
class="bg-card flex h-12 items-center justify-center"
|
||||
v-if="!property.imgUrl"
|
||||
|
||||
@@ -9,11 +9,13 @@ import { AppLinkInput } from '#/views/mall/promotion/components';
|
||||
|
||||
import ComponentContainerProperty from '../../component-container-property.vue';
|
||||
|
||||
// 图片展示属性面板
|
||||
/** 图片展示属性面板 */
|
||||
defineOptions({ name: 'ImageBarProperty' });
|
||||
|
||||
const props = defineProps<{ modelValue: ImageBarProperty }>();
|
||||
|
||||
const emit = defineEmits(['update:modelValue']);
|
||||
|
||||
const formData = useVModel(props, 'modelValue', emit);
|
||||
</script>
|
||||
|
||||
|
||||
@@ -13,10 +13,11 @@ import { getSpuDetailList } from '#/api/mall/product/spu';
|
||||
|
||||
/** 商品卡片 */
|
||||
defineOptions({ name: 'ProductCard' });
|
||||
// 定义属性
|
||||
|
||||
const props = defineProps<{ property: ProductCardProperty }>();
|
||||
// 商品列表
|
||||
const spuList = ref<MallSpuApi.Spu[]>([]);
|
||||
|
||||
const spuList = ref<MallSpuApi.Spu[]>([]); // 商品列表
|
||||
|
||||
watch(
|
||||
() => props.property.spuIds,
|
||||
async () => {
|
||||
@@ -28,28 +29,21 @@ watch(
|
||||
},
|
||||
);
|
||||
|
||||
/**
|
||||
* 计算商品的间距
|
||||
* @param index 商品索引
|
||||
*/
|
||||
/** 计算商品的间距 */
|
||||
function calculateSpace(index: number) {
|
||||
// 商品的列数
|
||||
const columns = props.property.layoutType === 'twoCol' ? 2 : 1;
|
||||
// 第一列没有左边距
|
||||
const marginLeft = index % columns === 0 ? '0' : `${props.property.space}px`;
|
||||
// 第一行没有上边距
|
||||
const marginTop = index < columns ? '0' : `${props.property.space}px`;
|
||||
|
||||
const columns = props.property.layoutType === 'twoCol' ? 2 : 1; // 商品的列数
|
||||
const marginLeft = index % columns === 0 ? '0' : `${props.property.space}px`; // 第一列没有左边距
|
||||
const marginTop = index < columns ? '0' : `${props.property.space}px`; // 第一行没有上边距
|
||||
return { marginLeft, marginTop };
|
||||
}
|
||||
|
||||
// 容器
|
||||
const containerRef = ref();
|
||||
// 计算商品的宽度
|
||||
const containerRef = ref(); // 容器
|
||||
|
||||
/** 计算商品的宽度 */
|
||||
function calculateWidth() {
|
||||
let width = '100%';
|
||||
// 双列时每列的宽度为:(总宽度 - 间距)/ 2
|
||||
if (props.property.layoutType === 'twoCol') {
|
||||
// 双列时每列的宽度为:(总宽度 - 间距)/ 2
|
||||
width = `${(containerRef.value.offsetWidth - props.property.space) / 2}px`;
|
||||
}
|
||||
return { width };
|
||||
@@ -61,7 +55,7 @@ function calculateWidth() {
|
||||
ref="containerRef"
|
||||
>
|
||||
<div
|
||||
class="bg-card relative box-content flex flex-row flex-wrap overflow-hidden"
|
||||
class="relative box-content flex flex-row flex-wrap overflow-hidden"
|
||||
:style="{
|
||||
...calculateSpace(index),
|
||||
...calculateWidth(),
|
||||
|
||||
@@ -27,14 +27,11 @@ export interface DiyComponentLibrary {
|
||||
components: string[]; // 组件列表
|
||||
}
|
||||
|
||||
// 组件样式
|
||||
/** 组件样式 */
|
||||
export interface ComponentStyle {
|
||||
// 背景类型
|
||||
bgType: 'color' | 'img';
|
||||
// 背景颜色
|
||||
bgColor: string;
|
||||
// 背景图片
|
||||
bgImg: string;
|
||||
bgType: 'color' | 'img'; // 背景类型
|
||||
bgColor: string; // 背景颜色
|
||||
bgImg: string; // 背景图片
|
||||
// 外边距
|
||||
margin: number;
|
||||
marginTop: number;
|
||||
|
||||
@@ -27,7 +27,7 @@ const props = defineProps<{ modelValue: ComponentStyle }>();
|
||||
const emit = defineEmits(['update:modelValue']);
|
||||
const formData = useVModel(props, 'modelValue', emit);
|
||||
|
||||
const treeData = [
|
||||
const treeData: any[] = [
|
||||
{
|
||||
label: '外部边距',
|
||||
prop: 'margin',
|
||||
@@ -96,7 +96,7 @@ const treeData = [
|
||||
},
|
||||
];
|
||||
|
||||
const handleSliderChange = (prop: string) => {
|
||||
function handleSliderChange(prop: string) {
|
||||
switch (prop) {
|
||||
case 'borderRadius': {
|
||||
formData.value.borderTopLeftRadius = formData.value.borderRadius;
|
||||
@@ -120,7 +120,7 @@ const handleSliderChange = (prop: string) => {
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
@@ -53,11 +53,11 @@ watch(
|
||||
);
|
||||
|
||||
/** 克隆组件 */
|
||||
const handleCloneComponent = (component: DiyComponent<any>) => {
|
||||
function handleCloneComponent(component: DiyComponent<any>) {
|
||||
const instance = cloneDeep(component);
|
||||
instance.uid = Date.now();
|
||||
return instance;
|
||||
};
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
@@ -11,7 +11,7 @@ export interface ImageBarProperty {
|
||||
export const component = {
|
||||
id: 'ImageBar',
|
||||
name: '图片展示',
|
||||
icon: 'ep:picture',
|
||||
icon: 'lucide:image',
|
||||
property: {
|
||||
imgUrl: '',
|
||||
url: '',
|
||||
|
||||
@@ -13,7 +13,9 @@ import ComponentContainerProperty from '../../component-container-property.vue';
|
||||
defineOptions({ name: 'ImageBarProperty' });
|
||||
|
||||
const props = defineProps<{ modelValue: ImageBarProperty }>();
|
||||
|
||||
const emit = defineEmits(['update:modelValue']);
|
||||
|
||||
const formData = useVModel(props, 'modelValue', emit);
|
||||
</script>
|
||||
|
||||
|
||||
@@ -1,32 +1,25 @@
|
||||
import { defineAsyncComponent } from 'vue';
|
||||
|
||||
/*
|
||||
/**
|
||||
* 组件注册
|
||||
*
|
||||
* 组件规范:
|
||||
* 1. 每个子目录就是一个独立的组件,每个目录包括以下三个文件:
|
||||
* 2. config.ts:组件配置,必选,用于定义组件、组件默认的属性、定义属性的类型
|
||||
* 3. index.vue:组件展示,用于展示组件的渲染效果。可以不提供,如 Page(页面设置),只需要属性配置表单即可
|
||||
* 4. property.vue:组件属性表单,用于配置组件,必选,
|
||||
* 组件规范:每个子目录就是一个独立的组件,每个目录包括以下三个文件:
|
||||
* 1. config.ts:组件配置,必选,用于定义组件、组件默认的属性、定义属性的类型
|
||||
* 2. index.vue:组件展示,用于展示组件的渲染效果。可以不提供,如 Page(页面设置),只需要属性配置表单即可
|
||||
* 3. property.vue:组件属性表单,用于配置组件,必选,
|
||||
*
|
||||
* 注:
|
||||
* 组件ID以config.ts中配置的id为准,与组件目录的名称无关,但还是建议组件目录的名称与组件ID保持一致
|
||||
* 组件 ID 以 config.ts 中配置的 id 为准,与组件目录的名称无关,但还是建议组件目录的名称与组件 ID 保持一致
|
||||
*/
|
||||
import { defineAsyncComponent } from 'vue';
|
||||
|
||||
// 导入组件界面模块
|
||||
const viewModules: Record<string, any> = import.meta.glob('./*/*.vue');
|
||||
// 导入配置模块
|
||||
const viewModules: Record<string, any> = import.meta.glob('./*/*.vue'); // 导入组件界面模块
|
||||
const configModules: Record<string, any> = import.meta.glob('./*/config.ts', {
|
||||
eager: true,
|
||||
});
|
||||
}); // 导入配置模块
|
||||
|
||||
// 界面模块
|
||||
const components: Record<string, any> = {};
|
||||
// 组件配置模块
|
||||
const componentConfigs: Record<string, any> = {};
|
||||
const components: Record<string, any> = {}; // 界面模块
|
||||
const componentConfigs: Record<string, any> = {}; // 组件配置模块
|
||||
|
||||
// 组件界面的类型
|
||||
type ViewType = 'index' | 'property';
|
||||
type ViewType = 'index' | 'property'; // 组件界面的类型
|
||||
|
||||
/**
|
||||
* 注册组件的界面模块
|
||||
|
||||
@@ -9,19 +9,19 @@ import { fenToYuan } from '@vben/utils';
|
||||
|
||||
import { ElImage } from 'element-plus';
|
||||
|
||||
import * as ProductSpuApi from '#/api/mall/product/spu';
|
||||
import { getSpuDetailList } from '#/api/mall/product/spu';
|
||||
|
||||
/** 商品卡片 */
|
||||
defineOptions({ name: 'ProductCard' });
|
||||
|
||||
const props = defineProps<{ property: ProductCardProperty }>();
|
||||
|
||||
const spuList = ref<MallSpuApi.Spu[]>([]);
|
||||
const spuList = ref<MallSpuApi.Spu[]>([]); // 商品列表
|
||||
|
||||
watch(
|
||||
() => props.property.spuIds,
|
||||
async () => {
|
||||
spuList.value = await ProductSpuApi.getSpuDetailList(props.property.spuIds);
|
||||
spuList.value = await getSpuDetailList(props.property.spuIds);
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
@@ -37,17 +37,17 @@ function calculateSpace(index: number) {
|
||||
return { marginLeft, marginTop };
|
||||
}
|
||||
|
||||
const containerRef = ref();
|
||||
const containerRef = ref(); // 容器
|
||||
|
||||
/** 计算商品的宽度 */
|
||||
const calculateWidth = () => {
|
||||
function calculateWidth() {
|
||||
let width = '100%';
|
||||
if (props.property.layoutType === 'twoCol') {
|
||||
// 双列时每列的宽度为:(总宽度 - 间距)/ 2
|
||||
width = `${(containerRef.value.offsetWidth - props.property.space) / 2}px`;
|
||||
}
|
||||
return { width };
|
||||
};
|
||||
}
|
||||
</script>
|
||||
<template>
|
||||
<div
|
||||
|
||||
@@ -27,14 +27,11 @@ export interface DiyComponentLibrary {
|
||||
components: string[]; // 组件列表
|
||||
}
|
||||
|
||||
// 组件样式
|
||||
/** 组件样式 */
|
||||
export interface ComponentStyle {
|
||||
// 背景类型
|
||||
bgType: 'color' | 'img';
|
||||
// 背景颜色
|
||||
bgColor: string;
|
||||
// 背景图片
|
||||
bgImg: string;
|
||||
bgType: 'color' | 'img'; // 背景类型
|
||||
bgColor: string; // 背景颜色
|
||||
bgImg: string; // 背景图片
|
||||
// 外边距
|
||||
margin: number;
|
||||
marginTop: number;
|
||||
|
||||
Reference in New Issue
Block a user