feat:【antd】【mall】diy-editor 的整体继续迁移
This commit is contained in:
@@ -1,4 +1,100 @@
|
||||
<script setup lang="ts">
|
||||
import { Page } from '@vben/common-ui';
|
||||
import type { DividerProperty } from './config';
|
||||
|
||||
import { IconifyIcon } from '@vben/icons';
|
||||
|
||||
import { useVModel } from '@vueuse/core';
|
||||
import {
|
||||
Form,
|
||||
FormItem,
|
||||
RadioButton,
|
||||
RadioGroup,
|
||||
Slider,
|
||||
Tooltip,
|
||||
} from 'ant-design-vue';
|
||||
|
||||
import { ColorInput } from '#/views/mall/promotion/components';
|
||||
|
||||
/** 导航栏属性面板 */
|
||||
defineOptions({ name: 'DividerProperty' });
|
||||
|
||||
const props = defineProps<{ modelValue: DividerProperty }>();
|
||||
|
||||
const emit = defineEmits(['update:modelValue']);
|
||||
|
||||
const BORDER_TYPES = [
|
||||
{
|
||||
icon: 'vaadin:line-h',
|
||||
text: '实线',
|
||||
type: 'solid',
|
||||
},
|
||||
{
|
||||
icon: 'tabler:line-dashed',
|
||||
text: '虚线',
|
||||
type: 'dashed',
|
||||
},
|
||||
{
|
||||
icon: 'tabler:line-dotted',
|
||||
text: '点线',
|
||||
type: 'dotted',
|
||||
},
|
||||
{
|
||||
icon: 'entypo:progress-empty',
|
||||
text: '无',
|
||||
type: 'none',
|
||||
},
|
||||
]; // 线类型
|
||||
const formData = useVModel(props, 'modelValue', emit);
|
||||
</script>
|
||||
<template><Page>待完成</Page></template>
|
||||
|
||||
<template>
|
||||
<Form :model="formData">
|
||||
<FormItem label="高度" name="height">
|
||||
<Slider
|
||||
v-model:value="formData.height"
|
||||
:min="1"
|
||||
:max="100"
|
||||
/>
|
||||
</FormItem>
|
||||
<FormItem label="选择样式" name="borderType">
|
||||
<RadioGroup v-model:value="formData!.borderType">
|
||||
<Tooltip
|
||||
placement="top"
|
||||
v-for="(item, index) in BORDER_TYPES"
|
||||
:key="index"
|
||||
:title="item.text"
|
||||
>
|
||||
<RadioButton :value="item.type">
|
||||
<IconifyIcon :icon="item.icon" />
|
||||
</RadioButton>
|
||||
</Tooltip>
|
||||
</RadioGroup>
|
||||
</FormItem>
|
||||
<template v-if="formData.borderType !== 'none'">
|
||||
<FormItem label="线宽" name="lineWidth">
|
||||
<Slider
|
||||
v-model:value="formData.lineWidth"
|
||||
:min="1"
|
||||
:max="30"
|
||||
/>
|
||||
</FormItem>
|
||||
<FormItem label="左右边距" name="paddingType">
|
||||
<RadioGroup v-model:value="formData!.paddingType">
|
||||
<Tooltip title="无边距" placement="top">
|
||||
<RadioButton value="none">
|
||||
<IconifyIcon icon="tabler:box-padding" />
|
||||
</RadioButton>
|
||||
</Tooltip>
|
||||
<Tooltip title="左右留边" placement="top">
|
||||
<RadioButton value="horizontal">
|
||||
<IconifyIcon icon="vaadin:padding" />
|
||||
</RadioButton>
|
||||
</Tooltip>
|
||||
</RadioGroup>
|
||||
</FormItem>
|
||||
<FormItem label="颜色">
|
||||
<ColorInput v-model="formData.lineColor" />
|
||||
</FormItem>
|
||||
</template>
|
||||
</Form>
|
||||
</template>
|
||||
|
||||
@@ -1,4 +1,57 @@
|
||||
<script setup lang="ts">
|
||||
import { Page } from '@vben/common-ui';
|
||||
import type { PopoverProperty } from './config';
|
||||
|
||||
import { useVModel } from '@vueuse/core';
|
||||
import {
|
||||
Form,
|
||||
FormItem,
|
||||
Radio,
|
||||
RadioGroup,
|
||||
Tooltip,
|
||||
} from 'ant-design-vue';
|
||||
|
||||
import UploadImg from '#/components/upload/image-upload.vue';
|
||||
import { AppLinkInput, Draggable } from '#/views/mall/promotion/components';
|
||||
|
||||
/** 弹窗广告属性面板 */
|
||||
defineOptions({ name: 'PopoverProperty' });
|
||||
|
||||
const props = defineProps<{ modelValue: PopoverProperty }>();
|
||||
|
||||
const emit = defineEmits(['update:modelValue']);
|
||||
|
||||
const formData = useVModel(props, 'modelValue', emit);
|
||||
</script>
|
||||
<template><Page>待完成</Page></template>
|
||||
|
||||
<template>
|
||||
<Form :model="formData">
|
||||
<Draggable v-model="formData.list" :empty-item="{ showType: 'once' }">
|
||||
<template #default="{ element, index }">
|
||||
<FormItem label="图片" :name="`list[${index}].imgUrl`">
|
||||
<UploadImg
|
||||
v-model="element.imgUrl"
|
||||
height="56px"
|
||||
width="56px"
|
||||
:show-description="false"
|
||||
/>
|
||||
</FormItem>
|
||||
<FormItem label="跳转链接" :name="`list[${index}].url`">
|
||||
<AppLinkInput v-model="element.url" />
|
||||
</FormItem>
|
||||
<FormItem label="显示次数" :name="`list[${index}].showType`">
|
||||
<RadioGroup v-model:value="element.showType">
|
||||
<Tooltip
|
||||
title="只显示一次,下次打开时不显示"
|
||||
placement="bottom"
|
||||
>
|
||||
<Radio value="once">一次</Radio>
|
||||
</Tooltip>
|
||||
<Tooltip title="每次打开时都会显示" placement="bottom">
|
||||
<Radio value="always">不限</Radio>
|
||||
</Tooltip>
|
||||
</RadioGroup>
|
||||
</FormItem>
|
||||
</template>
|
||||
</Draggable>
|
||||
</Form>
|
||||
</template>
|
||||
|
||||
@@ -1,4 +1,176 @@
|
||||
<script setup lang="ts">
|
||||
import { Page } from '@vben/common-ui';
|
||||
import type { CouponCardProperty } from './config';
|
||||
|
||||
import type { MallCouponTemplateApi } from '#/api/mall/promotion/coupon/couponTemplate';
|
||||
|
||||
import { ref, watch } from 'vue';
|
||||
|
||||
import { useVbenModal } from '@vben/common-ui';
|
||||
import {
|
||||
CouponTemplateTakeTypeEnum,
|
||||
PromotionDiscountTypeEnum,
|
||||
} from '@vben/constants';
|
||||
import { IconifyIcon } from '@vben/icons';
|
||||
import { floatToFixed2 } from '@vben/utils';
|
||||
|
||||
import { useVModel } from '@vueuse/core';
|
||||
import {
|
||||
Button,
|
||||
Card,
|
||||
Form,
|
||||
FormItem,
|
||||
RadioButton,
|
||||
RadioGroup,
|
||||
Slider,
|
||||
Tooltip,
|
||||
Typography,
|
||||
} from 'ant-design-vue';
|
||||
|
||||
import * as CouponTemplateApi from '#/api/mall/promotion/coupon/couponTemplate';
|
||||
import UploadImg from '#/components/upload/image-upload.vue';
|
||||
import { ColorInput } from '#/views/mall/promotion/components';
|
||||
import CouponSelect from '#/views/mall/promotion/coupon/components/select.vue';
|
||||
|
||||
import ComponentContainerProperty from '../../component-container-property.vue';
|
||||
|
||||
const { Text: ATypographyText } = Typography;
|
||||
|
||||
/** 优惠券卡片属性面板 */
|
||||
defineOptions({ name: 'CouponCardProperty' });
|
||||
|
||||
const props = defineProps<{ modelValue: CouponCardProperty }>();
|
||||
|
||||
const emit = defineEmits(['update:modelValue']);
|
||||
|
||||
const formData = useVModel(props, 'modelValue', emit);
|
||||
|
||||
const couponList = ref<MallCouponTemplateApi.CouponTemplate[]>([]); // 已选择的优惠券列表
|
||||
|
||||
const [CouponSelectModal, couponSelectModalApi] = useVbenModal({
|
||||
connectedComponent: CouponSelect,
|
||||
destroyOnClose: true,
|
||||
});
|
||||
|
||||
/** 添加优惠劵 */
|
||||
const handleAddCoupon = () => {
|
||||
couponSelectModalApi.open();
|
||||
};
|
||||
|
||||
/** 处理优惠劵选择 */
|
||||
const handleCouponSelect = (
|
||||
selectedCoupons: MallCouponTemplateApi.CouponTemplate[],
|
||||
) => {
|
||||
couponList.value = selectedCoupons;
|
||||
formData.value.couponIds = selectedCoupons.map((coupon) => coupon.id);
|
||||
};
|
||||
|
||||
/** 监听优惠券 ID 变化,加载优惠券列表 */
|
||||
watch(
|
||||
() => formData.value.couponIds,
|
||||
async () => {
|
||||
if (formData.value.couponIds?.length > 0) {
|
||||
couponList.value = await CouponTemplateApi.getCouponTemplateList(
|
||||
formData.value.couponIds,
|
||||
);
|
||||
}
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
deep: true,
|
||||
},
|
||||
);
|
||||
</script>
|
||||
<template><Page>待完成</Page></template>
|
||||
|
||||
<template>
|
||||
<ComponentContainerProperty v-model="formData.style">
|
||||
<Form :model="formData">
|
||||
<Card title="优惠券列表" class="property-group">
|
||||
<div
|
||||
v-for="(coupon, index) in couponList"
|
||||
:key="index"
|
||||
class="flex items-center justify-between"
|
||||
>
|
||||
<ATypographyText ellipsis class="text-base">{{ coupon.name }}</ATypographyText>
|
||||
<ATypographyText type="secondary" ellipsis>
|
||||
<span v-if="coupon.usePrice > 0">
|
||||
满{{ floatToFixed2(coupon.usePrice) }}元,
|
||||
</span>
|
||||
<span
|
||||
v-if="
|
||||
coupon.discountType === PromotionDiscountTypeEnum.PRICE.type
|
||||
"
|
||||
>
|
||||
减{{ floatToFixed2(coupon.discountPrice) }}元
|
||||
</span>
|
||||
<span v-else> 打{{ coupon.discountPercent }}折 </span>
|
||||
</ATypographyText>
|
||||
</div>
|
||||
<FormItem>
|
||||
<Button
|
||||
@click="handleAddCoupon"
|
||||
type="primary"
|
||||
ghost
|
||||
class="mt-2 w-full"
|
||||
>
|
||||
<template #icon>
|
||||
<IconifyIcon icon="ep:plus" />
|
||||
</template>
|
||||
添加
|
||||
</Button>
|
||||
</FormItem>
|
||||
</Card>
|
||||
<Card title="优惠券样式" class="property-group">
|
||||
<FormItem label="列数" name="type">
|
||||
<RadioGroup v-model:value="formData.columns">
|
||||
<Tooltip title="一列" placement="bottom">
|
||||
<RadioButton :value="1">
|
||||
<IconifyIcon icon="fluent:text-column-one-24-filled" />
|
||||
</RadioButton>
|
||||
</Tooltip>
|
||||
<Tooltip title="二列" placement="bottom">
|
||||
<RadioButton :value="2">
|
||||
<IconifyIcon icon="fluent:text-column-two-24-filled" />
|
||||
</RadioButton>
|
||||
</Tooltip>
|
||||
<Tooltip title="三列" placement="bottom">
|
||||
<RadioButton :value="3">
|
||||
<IconifyIcon icon="fluent:text-column-three-24-filled" />
|
||||
</RadioButton>
|
||||
</Tooltip>
|
||||
</RadioGroup>
|
||||
</FormItem>
|
||||
<FormItem label="背景图片" name="bgImg">
|
||||
<UploadImg
|
||||
v-model="formData.bgImg"
|
||||
height="80px"
|
||||
width="100%"
|
||||
class="min-w-[160px]"
|
||||
:show-description="false"
|
||||
/>
|
||||
</FormItem>
|
||||
<FormItem label="文字颜色" name="textColor">
|
||||
<ColorInput v-model="formData.textColor" />
|
||||
</FormItem>
|
||||
<FormItem label="按钮背景" name="button.bgColor">
|
||||
<ColorInput v-model="formData.button.bgColor" />
|
||||
</FormItem>
|
||||
<FormItem label="按钮文字" name="button.color">
|
||||
<ColorInput v-model="formData.button.color" />
|
||||
</FormItem>
|
||||
<FormItem label="间隔" name="space">
|
||||
<Slider
|
||||
v-model:value="formData.space"
|
||||
:max="100"
|
||||
:min="0"
|
||||
/>
|
||||
</FormItem>
|
||||
</Card>
|
||||
</Form>
|
||||
</ComponentContainerProperty>
|
||||
|
||||
<!-- 优惠券选择 -->
|
||||
<CouponSelectModal
|
||||
:take-type="CouponTemplateTakeTypeEnum.USER.type"
|
||||
@success="handleCouponSelect"
|
||||
/>
|
||||
</template>
|
||||
|
||||
@@ -1,4 +1,68 @@
|
||||
<script setup lang="ts">
|
||||
import { Page } from '@vben/common-ui';
|
||||
import type { FloatingActionButtonProperty } from './config';
|
||||
|
||||
import { useVModel } from '@vueuse/core';
|
||||
import {
|
||||
Card,
|
||||
Form,
|
||||
FormItem,
|
||||
Radio,
|
||||
RadioGroup,
|
||||
Switch,
|
||||
} from 'ant-design-vue';
|
||||
|
||||
import UploadImg from '#/components/upload/image-upload.vue';
|
||||
import {
|
||||
AppLinkInput,
|
||||
Draggable,
|
||||
InputWithColor,
|
||||
} from '#/views/mall/promotion/components';
|
||||
|
||||
/** 悬浮按钮属性面板 */
|
||||
defineOptions({ name: 'FloatingActionButtonProperty' });
|
||||
|
||||
const props = defineProps<{ modelValue: FloatingActionButtonProperty }>();
|
||||
|
||||
const emit = defineEmits(['update:modelValue']);
|
||||
|
||||
const formData = useVModel(props, 'modelValue', emit);
|
||||
</script>
|
||||
<template><Page>待完成</Page></template>
|
||||
|
||||
<template>
|
||||
<Form :model="formData">
|
||||
<Card title="按钮配置" class="property-group">
|
||||
<FormItem label="展开方向" name="direction">
|
||||
<RadioGroup v-model:value="formData.direction">
|
||||
<Radio value="vertical">垂直</Radio>
|
||||
<Radio value="horizontal">水平</Radio>
|
||||
</RadioGroup>
|
||||
</FormItem>
|
||||
<FormItem label="显示文字" name="showText">
|
||||
<Switch v-model:checked="formData.showText" />
|
||||
</FormItem>
|
||||
</Card>
|
||||
<Card title="按钮列表" class="property-group">
|
||||
<Draggable v-model="formData.list" :empty-item="{ textColor: '#fff' }">
|
||||
<template #default="{ element, index }">
|
||||
<FormItem label="图标" :name="`list[${index}].imgUrl`">
|
||||
<UploadImg
|
||||
v-model="element.imgUrl"
|
||||
height="56px"
|
||||
width="56px"
|
||||
:show-description="false"
|
||||
/>
|
||||
</FormItem>
|
||||
<FormItem label="文字" :name="`list[${index}].text`">
|
||||
<InputWithColor
|
||||
v-model="element.text"
|
||||
v-model:color="element.textColor"
|
||||
/>
|
||||
</FormItem>
|
||||
<FormItem label="跳转链接" :name="`list[${index}].url`">
|
||||
<AppLinkInput v-model="element.url" />
|
||||
</FormItem>
|
||||
</template>
|
||||
</Draggable>
|
||||
</Card>
|
||||
</Form>
|
||||
</template>
|
||||
|
||||
@@ -1,4 +1,245 @@
|
||||
<script setup lang="ts">
|
||||
import { Page } from '@vben/common-ui';
|
||||
import type { HotZoneItemProperty } from '../../config';
|
||||
import type { ControlDot } from './controller';
|
||||
|
||||
import type { AppLink } from '#/views/mall/promotion/components/app-link-input/data';
|
||||
|
||||
import { ref } from 'vue';
|
||||
|
||||
import { useVbenModal } from '@vben/common-ui';
|
||||
import { IconifyIcon } from '@vben/icons';
|
||||
|
||||
import { Button, Image } from 'ant-design-vue';
|
||||
|
||||
import { AppLinkSelectDialog } from '#/views/mall/promotion/components';
|
||||
|
||||
import {
|
||||
CONTROL_DOT_LIST,
|
||||
CONTROL_TYPE_ENUM,
|
||||
HOT_ZONE_MIN_SIZE,
|
||||
useDraggable,
|
||||
zoomIn,
|
||||
zoomOut,
|
||||
} from './controller';
|
||||
|
||||
/** 热区编辑对话框 */
|
||||
defineOptions({ name: 'HotZoneEditDialog' });
|
||||
|
||||
/** 定义属性 */
|
||||
const props = defineProps({
|
||||
modelValue: {
|
||||
type: Array<HotZoneItemProperty>,
|
||||
default: () => [],
|
||||
},
|
||||
imgUrl: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits(['update:modelValue']);
|
||||
|
||||
const formData = ref<HotZoneItemProperty[]>([]);
|
||||
|
||||
const [Modal, modalApi] = useVbenModal({
|
||||
showCancelButton: false,
|
||||
onConfirm() {
|
||||
const list = zoomOut(formData.value);
|
||||
emit('update:modelValue', list);
|
||||
modalApi.close();
|
||||
},
|
||||
});
|
||||
|
||||
/** 打开弹窗 */
|
||||
function open() {
|
||||
// 放大
|
||||
formData.value = zoomIn(props.modelValue);
|
||||
modalApi.open();
|
||||
}
|
||||
|
||||
defineExpose({ open }); // 提供 open 方法,用于打开弹窗
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/** 删除热区 */
|
||||
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);
|
||||
});
|
||||
}
|
||||
|
||||
/** 调整热区大小、位置 */
|
||||
function handleResize(
|
||||
item: HotZoneItemProperty,
|
||||
ctrlDot: ControlDot,
|
||||
e: MouseEvent,
|
||||
) {
|
||||
useDraggable(item, e, (left, top, width, height, moveWidth, moveHeight) => {
|
||||
ctrlDot.types.forEach((type) => {
|
||||
switch (type) {
|
||||
case CONTROL_TYPE_ENUM.HEIGHT: {
|
||||
{
|
||||
// 左移时,宽度为减少
|
||||
const direction = ctrlDot.types.includes(CONTROL_TYPE_ENUM.TOP)
|
||||
? -1
|
||||
: 1;
|
||||
setHeight(item, height + moveHeight * direction);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CONTROL_TYPE_ENUM.LEFT: {
|
||||
setLeft(item, left + moveWidth);
|
||||
break;
|
||||
}
|
||||
case CONTROL_TYPE_ENUM.TOP: {
|
||||
setTop(item, top + moveHeight);
|
||||
break;
|
||||
}
|
||||
case CONTROL_TYPE_ENUM.WIDTH: {
|
||||
{
|
||||
// 上移时,高度为减少
|
||||
const direction = ctrlDot.types.includes(CONTROL_TYPE_ENUM.LEFT)
|
||||
? -1
|
||||
: 1;
|
||||
setWidth(item, width + moveWidth * direction);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/** 设置 X 轴坐标 */
|
||||
function setLeft(item: HotZoneItemProperty, left: number) {
|
||||
// 不能超出容器
|
||||
if (left >= 0 && left <= container.value!.offsetWidth - item.width) {
|
||||
item.left = left;
|
||||
}
|
||||
}
|
||||
|
||||
/** 设置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 (
|
||||
width >= HOT_ZONE_MIN_SIZE &&
|
||||
item.left + width <= container.value!.offsetWidth
|
||||
) {
|
||||
item.width = width;
|
||||
}
|
||||
};
|
||||
|
||||
/** 设置高度 */
|
||||
const setHeight = (item: HotZoneItemProperty, height: number) => {
|
||||
// 不能小于最小高度 && 不能超出容器底部
|
||||
if (
|
||||
height >= HOT_ZONE_MIN_SIZE &&
|
||||
item.top + height <= container.value!.offsetHeight
|
||||
) {
|
||||
item.height = height;
|
||||
}
|
||||
};
|
||||
|
||||
const activeHotZone = ref<HotZoneItemProperty>();
|
||||
const appLinkDialogRef = ref();
|
||||
|
||||
/** 显示 App 链接选择对话框 */
|
||||
const handleShowAppLinkDialog = (hotZone: HotZoneItemProperty) => {
|
||||
activeHotZone.value = hotZone;
|
||||
appLinkDialogRef.value.open(hotZone.url);
|
||||
};
|
||||
|
||||
/** 处理 App 链接选择变更 */
|
||||
const handleAppLinkChange = (appLink: AppLink) => {
|
||||
if (!appLink || !activeHotZone.value) {
|
||||
return;
|
||||
}
|
||||
activeHotZone.value.name = appLink.name;
|
||||
activeHotZone.value.url = appLink.path;
|
||||
};
|
||||
</script>
|
||||
<template><Page>待完成</Page></template>
|
||||
|
||||
<template>
|
||||
<Modal title="设置热区" class="w-[780px]">
|
||||
<div ref="container" class="w-750px relative h-full">
|
||||
<Image
|
||||
:src="imgUrl"
|
||||
:preview="false"
|
||||
class="w-750px pointer-events-none h-full select-none"
|
||||
/>
|
||||
<div
|
||||
v-for="(item, hotZoneIndex) in formData"
|
||||
:key="hotZoneIndex"
|
||||
class="group absolute z-10 flex cursor-move items-center justify-center border text-base opacity-80"
|
||||
:style="{
|
||||
width: `${item.width}px`,
|
||||
height: `${item.height}px`,
|
||||
top: `${item.top}px`,
|
||||
left: `${item.left}px`,
|
||||
color: 'var(--ant-color-primary)',
|
||||
background: 'color-mix(in srgb, var(--ant-color-primary) 30%, transparent)',
|
||||
borderColor: 'var(--ant-color-primary)',
|
||||
}"
|
||||
@mousedown="handleMove(item, $event)"
|
||||
@dblclick="handleShowAppLinkDialog(item)"
|
||||
>
|
||||
<span class="pointer-events-none select-none">
|
||||
{{ item.name || '双击选择链接' }}
|
||||
</span>
|
||||
<IconifyIcon
|
||||
icon="ep:close"
|
||||
class="absolute right-0 top-0 hidden cursor-pointer rounded-bl-[80%] p-[2px_2px_6px_6px] text-right text-white group-hover:block"
|
||||
:style="{ backgroundColor: 'var(--ant-color-primary)' }"
|
||||
:size="14"
|
||||
@click="handleRemove(item)"
|
||||
/>
|
||||
|
||||
<!-- 8 个控制点 -->
|
||||
<span
|
||||
class="ctrl-dot absolute z-[11] h-2 w-2 rounded-full bg-white"
|
||||
v-for="(dot, dotIndex) in CONTROL_DOT_LIST"
|
||||
:key="dotIndex"
|
||||
:style="{ ...dot.style, border: 'inherit' }"
|
||||
@mousedown="handleResize(item, dot, $event)"
|
||||
></span>
|
||||
</div>
|
||||
</div>
|
||||
<template #prepend-footer>
|
||||
<Button @click="handleAdd" type="primary" ghost>
|
||||
<template #icon>
|
||||
<IconifyIcon icon="ep:plus" />
|
||||
</template>
|
||||
添加热区
|
||||
</Button>
|
||||
</template>
|
||||
</Modal>
|
||||
|
||||
<AppLinkSelectDialog
|
||||
ref="appLinkDialogRef"
|
||||
@app-link-change="handleAppLinkChange"
|
||||
/>
|
||||
</template>
|
||||
|
||||
@@ -1,4 +1,86 @@
|
||||
<script setup lang="ts">
|
||||
import { Page } from '@vben/common-ui';
|
||||
import type { MagicCubeProperty } from './config';
|
||||
|
||||
import { ref } from 'vue';
|
||||
|
||||
import { useVModel } from '@vueuse/core';
|
||||
import { Form, FormItem, Slider, Typography } from 'ant-design-vue';
|
||||
|
||||
import UploadImg from '#/components/upload/image-upload.vue';
|
||||
import {
|
||||
AppLinkInput,
|
||||
MagicCubeEditor,
|
||||
} from '#/views/mall/promotion/components';
|
||||
|
||||
import ComponentContainerProperty from '../../component-container-property.vue';
|
||||
|
||||
const { Text: ATypographyText } = Typography;
|
||||
|
||||
/** 广告魔方属性面板 */
|
||||
defineOptions({ name: 'MagicCubeProperty' });
|
||||
|
||||
const props = defineProps<{ modelValue: MagicCubeProperty }>();
|
||||
|
||||
const emit = defineEmits(['update:modelValue']);
|
||||
|
||||
const formData = useVModel(props, 'modelValue', emit);
|
||||
|
||||
const selectedHotAreaIndex = ref(-1); // 选中的热区
|
||||
|
||||
/** 处理热区被选中事件 */
|
||||
const handleHotAreaSelected = (_: any, index: number) => {
|
||||
selectedHotAreaIndex.value = index;
|
||||
};
|
||||
</script>
|
||||
<template><Page>待完成</Page></template>
|
||||
|
||||
<template>
|
||||
<ComponentContainerProperty v-model="formData.style">
|
||||
<Form :model="formData" class="mt-2">
|
||||
<ATypographyText tag="p"> 魔方设置 </ATypographyText>
|
||||
<ATypographyText type="secondary" class="text-sm"> 每格尺寸187 * 187 </ATypographyText>
|
||||
<MagicCubeEditor
|
||||
class="my-4"
|
||||
v-model="formData.list"
|
||||
:rows="4"
|
||||
:cols="4"
|
||||
@hot-area-selected="handleHotAreaSelected"
|
||||
/>
|
||||
<template v-for="(hotArea, index) in formData.list" :key="index">
|
||||
<template v-if="selectedHotAreaIndex === index">
|
||||
<FormItem label="上传图片" :name="`list[${index}].imgUrl`">
|
||||
<UploadImg
|
||||
v-model="hotArea.imgUrl"
|
||||
height="80px"
|
||||
width="80px"
|
||||
:show-description="false"
|
||||
/>
|
||||
</FormItem>
|
||||
<FormItem label="链接" :name="`list[${index}].url`">
|
||||
<AppLinkInput v-model="hotArea.url" />
|
||||
</FormItem>
|
||||
</template>
|
||||
</template>
|
||||
<FormItem label="上圆角" name="borderRadiusTop">
|
||||
<Slider
|
||||
v-model:value="formData.borderRadiusTop"
|
||||
:max="100"
|
||||
:min="0"
|
||||
/>
|
||||
</FormItem>
|
||||
<FormItem label="下圆角" name="borderRadiusBottom">
|
||||
<Slider
|
||||
v-model:value="formData.borderRadiusBottom"
|
||||
:max="100"
|
||||
:min="0"
|
||||
/>
|
||||
</FormItem>
|
||||
<FormItem label="间隔" name="space">
|
||||
<Slider
|
||||
v-model:value="formData.space"
|
||||
:max="100"
|
||||
:min="0"
|
||||
/>
|
||||
</FormItem>
|
||||
</Form>
|
||||
</ComponentContainerProperty>
|
||||
</template>
|
||||
|
||||
@@ -1,4 +1,68 @@
|
||||
<script setup lang="ts">
|
||||
import { Page } from '@vben/common-ui';
|
||||
import type { MenuListProperty } from './config';
|
||||
|
||||
import { useVModel } from '@vueuse/core';
|
||||
import { Form, Typography } from 'ant-design-vue';
|
||||
|
||||
import UploadImg from '#/components/upload/image-upload.vue';
|
||||
import {
|
||||
AppLinkInput,
|
||||
Draggable,
|
||||
InputWithColor,
|
||||
} from '#/views/mall/promotion/components';
|
||||
|
||||
import ComponentContainerProperty from '../../component-container-property.vue';
|
||||
import { EMPTY_MENU_LIST_ITEM_PROPERTY } from './config';
|
||||
|
||||
const { Text: ATypographyText } = Typography;
|
||||
|
||||
/** 列表导航属性面板 */
|
||||
defineOptions({ name: 'MenuListProperty' });
|
||||
|
||||
const props = defineProps<{ modelValue: MenuListProperty }>();
|
||||
|
||||
const emit = defineEmits(['update:modelValue']);
|
||||
|
||||
const formData = useVModel(props, 'modelValue', emit);
|
||||
</script>
|
||||
<template><Page>待完成</Page></template>
|
||||
|
||||
<template>
|
||||
<ComponentContainerProperty v-model="formData.style">
|
||||
<ATypographyText tag="p"> 菜单设置 </ATypographyText>
|
||||
<ATypographyText type="secondary" class="text-sm"> 拖动左侧的小圆点可以调整顺序 </ATypographyText>
|
||||
<Form :model="formData" class="mt-2">
|
||||
<Draggable
|
||||
v-model="formData.list"
|
||||
:empty-item="EMPTY_MENU_LIST_ITEM_PROPERTY"
|
||||
>
|
||||
<template #default="{ element }">
|
||||
<FormItem label="图标" name="iconUrl">
|
||||
<UploadImg
|
||||
v-model="element.iconUrl"
|
||||
height="80px"
|
||||
width="80px"
|
||||
:show-description="false"
|
||||
>
|
||||
<template #tip> 建议尺寸:44 * 44 </template>
|
||||
</UploadImg>
|
||||
</FormItem>
|
||||
<FormItem label="标题" name="title">
|
||||
<InputWithColor
|
||||
v-model="element.title"
|
||||
v-model:color="element.titleColor"
|
||||
/>
|
||||
</FormItem>
|
||||
<FormItem label="副标题" name="subtitle">
|
||||
<InputWithColor
|
||||
v-model="element.subtitle"
|
||||
v-model:color="element.subtitleColor"
|
||||
/>
|
||||
</FormItem>
|
||||
<FormItem label="链接" name="url">
|
||||
<AppLinkInput v-model="element.url" />
|
||||
</FormItem>
|
||||
</template>
|
||||
</Draggable>
|
||||
</Form>
|
||||
</ComponentContainerProperty>
|
||||
</template>
|
||||
|
||||
@@ -1,4 +1,103 @@
|
||||
<script setup lang="ts">
|
||||
import { Page } from '@vben/common-ui';
|
||||
import type { MenuSwiperProperty } from './config';
|
||||
|
||||
import { cloneDeep } from '@vben/utils';
|
||||
|
||||
import { useVModel } from '@vueuse/core';
|
||||
import {
|
||||
Card,
|
||||
Form,
|
||||
FormItem,
|
||||
Radio,
|
||||
RadioGroup,
|
||||
Switch,
|
||||
} from 'ant-design-vue';
|
||||
|
||||
import UploadImg from '#/components/upload/image-upload.vue';
|
||||
import {
|
||||
AppLinkInput,
|
||||
ColorInput,
|
||||
Draggable,
|
||||
InputWithColor,
|
||||
} from '#/views/mall/promotion/components';
|
||||
|
||||
import ComponentContainerProperty from '../../component-container-property.vue';
|
||||
import { EMPTY_MENU_SWIPER_ITEM_PROPERTY } from './config';
|
||||
|
||||
/** 菜单导航属性面板 */
|
||||
defineOptions({ name: 'MenuSwiperProperty' });
|
||||
|
||||
const props = defineProps<{ modelValue: MenuSwiperProperty }>();
|
||||
|
||||
const emit = defineEmits(['update:modelValue']);
|
||||
|
||||
const formData = useVModel(props, 'modelValue', emit);
|
||||
</script>
|
||||
<template><Page>待完成</Page></template>
|
||||
|
||||
<template>
|
||||
<ComponentContainerProperty v-model="formData.style">
|
||||
<Form :model="formData" class="mt-2">
|
||||
<FormItem label="布局" name="layout">
|
||||
<RadioGroup v-model:value="formData.layout">
|
||||
<Radio value="iconText">图标+文字</Radio>
|
||||
<Radio value="icon">仅图标</Radio>
|
||||
</RadioGroup>
|
||||
</FormItem>
|
||||
<FormItem label="行数" name="row">
|
||||
<RadioGroup v-model:value="formData.row">
|
||||
<Radio :value="1">1行</Radio>
|
||||
<Radio :value="2">2行</Radio>
|
||||
</RadioGroup>
|
||||
</FormItem>
|
||||
<FormItem label="列数" name="column">
|
||||
<RadioGroup v-model:value="formData.column">
|
||||
<Radio :value="3">3列</Radio>
|
||||
<Radio :value="4">4列</Radio>
|
||||
<Radio :value="5">5列</Radio>
|
||||
</RadioGroup>
|
||||
</FormItem>
|
||||
<Card title="菜单设置" class="property-group">
|
||||
<Draggable
|
||||
v-model="formData.list"
|
||||
:empty-item="cloneDeep(EMPTY_MENU_SWIPER_ITEM_PROPERTY)"
|
||||
>
|
||||
<template #default="{ element }">
|
||||
<FormItem label="图标" name="iconUrl">
|
||||
<UploadImg
|
||||
v-model="element.iconUrl"
|
||||
height="80px"
|
||||
width="80px"
|
||||
:show-description="false"
|
||||
>
|
||||
<template #tip> 建议尺寸:98 * 98 </template>
|
||||
</UploadImg>
|
||||
</FormItem>
|
||||
<FormItem label="标题" name="title">
|
||||
<InputWithColor
|
||||
v-model="element.title"
|
||||
v-model:color="element.titleColor"
|
||||
/>
|
||||
</FormItem>
|
||||
<FormItem label="链接" name="url">
|
||||
<AppLinkInput v-model="element.url" />
|
||||
</FormItem>
|
||||
<FormItem label="显示角标" name="badge.show">
|
||||
<Switch v-model:checked="element.badge.show" />
|
||||
</FormItem>
|
||||
<template v-if="element.badge.show">
|
||||
<FormItem label="角标内容" name="badge.text">
|
||||
<InputWithColor
|
||||
v-model="element.badge.text"
|
||||
v-model:color="element.badge.textColor"
|
||||
/>
|
||||
</FormItem>
|
||||
<FormItem label="背景颜色" name="badge.bgColor">
|
||||
<ColorInput v-model="element.badge.bgColor" />
|
||||
</FormItem>
|
||||
</template>
|
||||
</template>
|
||||
</Draggable>
|
||||
</Card>
|
||||
</Form>
|
||||
</ComponentContainerProperty>
|
||||
</template>
|
||||
|
||||
@@ -1,4 +1,61 @@
|
||||
<script setup lang="ts">
|
||||
import { Page } from '@vben/common-ui';
|
||||
import type { NoticeBarProperty } from './config';
|
||||
|
||||
import { useVModel } from '@vueuse/core';
|
||||
import { Card, Form, FormItem, Input } from 'ant-design-vue';
|
||||
|
||||
import UploadImg from '#/components/upload/image-upload.vue';
|
||||
import {
|
||||
AppLinkInput,
|
||||
ColorInput,
|
||||
Draggable,
|
||||
} from '#/views/mall/promotion/components';
|
||||
|
||||
import ComponentContainerProperty from '../../component-container-property.vue';
|
||||
|
||||
/** 公告栏属性面板 */
|
||||
defineOptions({ name: 'NoticeBarProperty' });
|
||||
|
||||
const props = defineProps<{ modelValue: NoticeBarProperty }>();
|
||||
|
||||
const emit = defineEmits(['update:modelValue']);
|
||||
|
||||
const formData = useVModel(props, 'modelValue', emit);
|
||||
const rules = {
|
||||
content: [{ required: true, message: '请输入公告', trigger: 'blur' }],
|
||||
}; // 表单校验
|
||||
</script>
|
||||
<template><Page>待完成</Page></template>
|
||||
|
||||
<template>
|
||||
<ComponentContainerProperty v-model="formData.style">
|
||||
<Form :model="formData" :rules="rules">
|
||||
<FormItem label="公告图标" name="iconUrl">
|
||||
<UploadImg
|
||||
v-model="formData.iconUrl"
|
||||
height="48px"
|
||||
:show-description="false"
|
||||
>
|
||||
<template #tip>建议尺寸:24 * 24</template>
|
||||
</UploadImg>
|
||||
</FormItem>
|
||||
<FormItem label="背景颜色" name="backgroundColor">
|
||||
<ColorInput v-model="formData.backgroundColor" />
|
||||
</FormItem>
|
||||
<FormItem label="文字颜色" name="textColor">
|
||||
<ColorInput v-model="formData.textColor" />
|
||||
</FormItem>
|
||||
<Card title="公告内容" class="property-group">
|
||||
<Draggable v-model="formData.contents">
|
||||
<template #default="{ element }">
|
||||
<FormItem label="公告" name="text">
|
||||
<Input v-model:value="element.text" placeholder="请输入公告" />
|
||||
</FormItem>
|
||||
<FormItem label="链接" name="url">
|
||||
<AppLinkInput v-model="element.url" />
|
||||
</FormItem>
|
||||
</template>
|
||||
</Draggable>
|
||||
</Card>
|
||||
</Form>
|
||||
</ComponentContainerProperty>
|
||||
</template>
|
||||
|
||||
@@ -1,4 +1,170 @@
|
||||
<script setup lang="ts">
|
||||
import { Page } from '@vben/common-ui';
|
||||
import type { ProductCardProperty } from './config';
|
||||
|
||||
import { IconifyIcon } from '@vben/icons';
|
||||
|
||||
import { useVModel } from '@vueuse/core';
|
||||
import {
|
||||
Card,
|
||||
Checkbox,
|
||||
Form,
|
||||
FormItem,
|
||||
Input,
|
||||
RadioButton,
|
||||
RadioGroup,
|
||||
Slider,
|
||||
Switch,
|
||||
Tooltip,
|
||||
} from 'ant-design-vue';
|
||||
|
||||
import UploadImg from '#/components/upload/image-upload.vue';
|
||||
import { SpuShowcase } from '#/views/mall/product/spu/components';
|
||||
import { ColorInput } from '#/views/mall/promotion/components';
|
||||
|
||||
import ComponentContainerProperty from '../../component-container-property.vue';
|
||||
|
||||
/** 商品卡片属性面板 */
|
||||
defineOptions({ name: 'ProductCardProperty' });
|
||||
|
||||
const props = defineProps<{ modelValue: ProductCardProperty }>();
|
||||
|
||||
const emit = defineEmits(['update:modelValue']);
|
||||
|
||||
const formData = useVModel(props, 'modelValue', emit);
|
||||
</script>
|
||||
<template><Page>待完成</Page></template>
|
||||
|
||||
<template>
|
||||
<ComponentContainerProperty v-model="formData.style">
|
||||
<Form :model="formData">
|
||||
<Card title="商品列表" class="property-group">
|
||||
<SpuShowcase v-model="formData.spuIds" />
|
||||
</Card>
|
||||
<Card title="商品样式" class="property-group">
|
||||
<FormItem label="布局" name="type">
|
||||
<RadioGroup v-model:value="formData.layoutType">
|
||||
<Tooltip title="单列大图" placement="bottom">
|
||||
<RadioButton value="oneColBigImg">
|
||||
<IconifyIcon icon="fluent:text-column-one-24-filled" />
|
||||
</RadioButton>
|
||||
</Tooltip>
|
||||
<Tooltip title="单列小图" placement="bottom">
|
||||
<RadioButton value="oneColSmallImg">
|
||||
<IconifyIcon icon="fluent:text-column-two-left-24-filled" />
|
||||
</RadioButton>
|
||||
</Tooltip>
|
||||
<Tooltip title="双列" placement="bottom">
|
||||
<RadioButton value="twoCol">
|
||||
<IconifyIcon icon="fluent:text-column-two-24-filled" />
|
||||
</RadioButton>
|
||||
</Tooltip>
|
||||
</RadioGroup>
|
||||
</FormItem>
|
||||
<FormItem label="商品名称" name="fields.name.show">
|
||||
<div class="flex gap-2">
|
||||
<ColorInput v-model="formData.fields.name.color" />
|
||||
<Checkbox v-model:checked="formData.fields.name.show" />
|
||||
</div>
|
||||
</FormItem>
|
||||
<FormItem label="商品简介" name="fields.introduction.show">
|
||||
<div class="flex gap-2">
|
||||
<ColorInput v-model="formData.fields.introduction.color" />
|
||||
<Checkbox v-model:checked="formData.fields.introduction.show" />
|
||||
</div>
|
||||
</FormItem>
|
||||
<FormItem label="商品价格" name="fields.price.show">
|
||||
<div class="flex gap-2">
|
||||
<ColorInput v-model="formData.fields.price.color" />
|
||||
<Checkbox v-model:checked="formData.fields.price.show" />
|
||||
</div>
|
||||
</FormItem>
|
||||
<FormItem label="市场价" name="fields.marketPrice.show">
|
||||
<div class="flex gap-2">
|
||||
<ColorInput v-model="formData.fields.marketPrice.color" />
|
||||
<Checkbox v-model:checked="formData.fields.marketPrice.show" />
|
||||
</div>
|
||||
</FormItem>
|
||||
<FormItem label="商品销量" name="fields.salesCount.show">
|
||||
<div class="flex gap-2">
|
||||
<ColorInput v-model="formData.fields.salesCount.color" />
|
||||
<Checkbox v-model:checked="formData.fields.salesCount.show" />
|
||||
</div>
|
||||
</FormItem>
|
||||
<FormItem label="商品库存" name="fields.stock.show">
|
||||
<div class="flex gap-2">
|
||||
<ColorInput v-model="formData.fields.stock.color" />
|
||||
<Checkbox v-model:checked="formData.fields.stock.show" />
|
||||
</div>
|
||||
</FormItem>
|
||||
</Card>
|
||||
<Card title="角标" class="property-group">
|
||||
<FormItem label="角标" name="badge.show">
|
||||
<Switch v-model:checked="formData.badge.show" />
|
||||
</FormItem>
|
||||
<FormItem label="角标" name="badge.imgUrl" v-if="formData.badge.show">
|
||||
<UploadImg
|
||||
v-model="formData.badge.imgUrl"
|
||||
height="44px"
|
||||
width="72px"
|
||||
:show-description="false"
|
||||
>
|
||||
<template #tip> 建议尺寸:36 * 22 </template>
|
||||
</UploadImg>
|
||||
</FormItem>
|
||||
</Card>
|
||||
<Card title="按钮" class="property-group">
|
||||
<FormItem label="按钮类型" name="btnBuy.type">
|
||||
<RadioGroup v-model:value="formData.btnBuy.type">
|
||||
<RadioButton value="text">文字</RadioButton>
|
||||
<RadioButton value="img">图片</RadioButton>
|
||||
</RadioGroup>
|
||||
</FormItem>
|
||||
<template v-if="formData.btnBuy.type === 'text'">
|
||||
<FormItem label="按钮文字" name="btnBuy.text">
|
||||
<Input v-model:value="formData.btnBuy.text" />
|
||||
</FormItem>
|
||||
<FormItem label="左侧背景" name="btnBuy.bgBeginColor">
|
||||
<ColorInput v-model="formData.btnBuy.bgBeginColor" />
|
||||
</FormItem>
|
||||
<FormItem label="右侧背景" name="btnBuy.bgEndColor">
|
||||
<ColorInput v-model="formData.btnBuy.bgEndColor" />
|
||||
</FormItem>
|
||||
</template>
|
||||
<template v-else>
|
||||
<FormItem label="图片" name="btnBuy.imgUrl">
|
||||
<UploadImg
|
||||
v-model="formData.btnBuy.imgUrl"
|
||||
height="56px"
|
||||
width="56px"
|
||||
:show-description="false"
|
||||
>
|
||||
<template #tip> 建议尺寸:56 * 56 </template>
|
||||
</UploadImg>
|
||||
</FormItem>
|
||||
</template>
|
||||
</Card>
|
||||
<Card title="商品样式" class="property-group">
|
||||
<FormItem label="上圆角" name="borderRadiusTop">
|
||||
<Slider
|
||||
v-model:value="formData.borderRadiusTop"
|
||||
:max="100"
|
||||
:min="0"
|
||||
/>
|
||||
</FormItem>
|
||||
<FormItem label="下圆角" name="borderRadiusBottom">
|
||||
<Slider
|
||||
v-model:value="formData.borderRadiusBottom"
|
||||
:max="100"
|
||||
:min="0"
|
||||
/>
|
||||
</FormItem>
|
||||
<FormItem label="间隔" name="space">
|
||||
<Slider
|
||||
v-model:value="formData.space"
|
||||
:max="100"
|
||||
:min="0"
|
||||
/>
|
||||
</FormItem>
|
||||
</Card>
|
||||
</Form>
|
||||
</ComponentContainerProperty>
|
||||
</template>
|
||||
|
||||
@@ -1,4 +1,168 @@
|
||||
<script setup lang="ts">
|
||||
import { Page } from '@vben/common-ui';
|
||||
<script lang="ts" setup>
|
||||
import type { PromotionPointProperty } from './config';
|
||||
|
||||
import { IconifyIcon } from '@vben/icons';
|
||||
|
||||
import { useVModel } from '@vueuse/core';
|
||||
import {
|
||||
Card,
|
||||
Checkbox,
|
||||
Form,
|
||||
FormItem,
|
||||
Input,
|
||||
RadioButton,
|
||||
RadioGroup,
|
||||
Slider,
|
||||
Switch,
|
||||
Tooltip,
|
||||
} from 'ant-design-vue';
|
||||
|
||||
import UploadImg from '#/components/upload/image-upload.vue';
|
||||
import { ColorInput } from '#/views/mall/promotion/components';
|
||||
import { PointShowcase } from '#/views/mall/promotion/point/components';
|
||||
|
||||
import ComponentContainerProperty from '../../component-container-property.vue';
|
||||
|
||||
/** 积分属性面板 */
|
||||
defineOptions({ name: 'PromotionPointProperty' });
|
||||
|
||||
const props = defineProps<{ modelValue: PromotionPointProperty }>();
|
||||
const emit = defineEmits(['update:modelValue']);
|
||||
const formData = useVModel(props, 'modelValue', emit);
|
||||
</script>
|
||||
<template><Page>待完成</Page></template>
|
||||
|
||||
<template>
|
||||
<ComponentContainerProperty v-model="formData.style">
|
||||
<Form :model="formData">
|
||||
<Card title="积分商城活动" class="property-group">
|
||||
<PointShowcase v-model="formData.activityIds" />
|
||||
</Card>
|
||||
<Card title="商品样式" class="property-group">
|
||||
<FormItem label="布局" name="type">
|
||||
<RadioGroup v-model:value="formData.layoutType">
|
||||
<Tooltip title="单列大图" placement="bottom">
|
||||
<RadioButton value="oneColBigImg">
|
||||
<IconifyIcon icon="fluent:text-column-one-24-filled" />
|
||||
</RadioButton>
|
||||
</Tooltip>
|
||||
<Tooltip title="单列小图" placement="bottom">
|
||||
<RadioButton value="oneColSmallImg">
|
||||
<IconifyIcon icon="fluent:text-column-two-left-24-filled" />
|
||||
</RadioButton>
|
||||
</Tooltip>
|
||||
<Tooltip title="双列" placement="bottom">
|
||||
<RadioButton value="twoCol">
|
||||
<IconifyIcon icon="fluent:text-column-two-24-filled" />
|
||||
</RadioButton>
|
||||
</Tooltip>
|
||||
</RadioGroup>
|
||||
</FormItem>
|
||||
<FormItem label="商品名称" name="fields.name.show">
|
||||
<div class="flex gap-2">
|
||||
<ColorInput v-model="formData.fields.name.color" />
|
||||
<Checkbox v-model:checked="formData.fields.name.show" />
|
||||
</div>
|
||||
</FormItem>
|
||||
<FormItem label="商品简介" name="fields.introduction.show">
|
||||
<div class="flex gap-2">
|
||||
<ColorInput v-model="formData.fields.introduction.color" />
|
||||
<Checkbox v-model:checked="formData.fields.introduction.show" />
|
||||
</div>
|
||||
</FormItem>
|
||||
<FormItem label="商品价格" name="fields.price.show">
|
||||
<div class="flex gap-2">
|
||||
<ColorInput v-model="formData.fields.price.color" />
|
||||
<Checkbox v-model:checked="formData.fields.price.show" />
|
||||
</div>
|
||||
</FormItem>
|
||||
<FormItem label="市场价" name="fields.marketPrice.show">
|
||||
<div class="flex gap-2">
|
||||
<ColorInput v-model="formData.fields.marketPrice.color" />
|
||||
<Checkbox v-model:checked="formData.fields.marketPrice.show" />
|
||||
</div>
|
||||
</FormItem>
|
||||
<FormItem label="商品销量" name="fields.salesCount.show">
|
||||
<div class="flex gap-2">
|
||||
<ColorInput v-model="formData.fields.salesCount.color" />
|
||||
<Checkbox v-model:checked="formData.fields.salesCount.show" />
|
||||
</div>
|
||||
</FormItem>
|
||||
<FormItem label="商品库存" name="fields.stock.show">
|
||||
<div class="flex gap-2">
|
||||
<ColorInput v-model="formData.fields.stock.color" />
|
||||
<Checkbox v-model:checked="formData.fields.stock.show" />
|
||||
</div>
|
||||
</FormItem>
|
||||
</Card>
|
||||
<Card title="角标" class="property-group">
|
||||
<FormItem label="角标" name="badge.show">
|
||||
<Switch v-model:checked="formData.badge.show" />
|
||||
</FormItem>
|
||||
<FormItem label="角标" name="badge.imgUrl" v-if="formData.badge.show">
|
||||
<UploadImg
|
||||
v-model="formData.badge.imgUrl"
|
||||
height="44px"
|
||||
width="72px"
|
||||
:show-description="false"
|
||||
>
|
||||
<template #tip> 建议尺寸:36 * 22 </template>
|
||||
</UploadImg>
|
||||
</FormItem>
|
||||
</Card>
|
||||
<Card title="按钮" class="property-group">
|
||||
<FormItem label="按钮类型" name="btnBuy.type">
|
||||
<RadioGroup v-model:value="formData.btnBuy.type">
|
||||
<RadioButton value="text">文字</RadioButton>
|
||||
<RadioButton value="img">图片</RadioButton>
|
||||
</RadioGroup>
|
||||
</FormItem>
|
||||
<template v-if="formData.btnBuy.type === 'text'">
|
||||
<FormItem label="按钮文字" name="btnBuy.text">
|
||||
<Input v-model:value="formData.btnBuy.text" />
|
||||
</FormItem>
|
||||
<FormItem label="左侧背景" name="btnBuy.bgBeginColor">
|
||||
<ColorInput v-model="formData.btnBuy.bgBeginColor" />
|
||||
</FormItem>
|
||||
<FormItem label="右侧背景" name="btnBuy.bgEndColor">
|
||||
<ColorInput v-model="formData.btnBuy.bgEndColor" />
|
||||
</FormItem>
|
||||
</template>
|
||||
<template v-else>
|
||||
<FormItem label="图片" name="btnBuy.imgUrl">
|
||||
<UploadImg
|
||||
v-model="formData.btnBuy.imgUrl"
|
||||
height="56px"
|
||||
width="56px"
|
||||
:show-description="false"
|
||||
>
|
||||
<template #tip> 建议尺寸:56 * 56 </template>
|
||||
</UploadImg>
|
||||
</FormItem>
|
||||
</template>
|
||||
</Card>
|
||||
<Card title="商品样式" class="property-group">
|
||||
<FormItem label="上圆角" name="borderRadiusTop">
|
||||
<Slider
|
||||
v-model:value="formData.borderRadiusTop"
|
||||
:max="100"
|
||||
:min="0"
|
||||
/>
|
||||
</FormItem>
|
||||
<FormItem label="下圆角" name="borderRadiusBottom">
|
||||
<Slider
|
||||
v-model:value="formData.borderRadiusBottom"
|
||||
:max="100"
|
||||
:min="0"
|
||||
/>
|
||||
</FormItem>
|
||||
<FormItem label="间隔" name="space">
|
||||
<Slider
|
||||
v-model:value="formData.space"
|
||||
:max="100"
|
||||
:min="0"
|
||||
/>
|
||||
</FormItem>
|
||||
</Card>
|
||||
</Form>
|
||||
</ComponentContainerProperty>
|
||||
</template>
|
||||
|
||||
@@ -1,4 +1,170 @@
|
||||
<script setup lang="ts">
|
||||
import { Page } from '@vben/common-ui';
|
||||
import type { PromotionSeckillProperty } from './config';
|
||||
|
||||
import { IconifyIcon } from '@vben/icons';
|
||||
|
||||
import { useVModel } from '@vueuse/core';
|
||||
import {
|
||||
Card,
|
||||
Checkbox,
|
||||
Form,
|
||||
FormItem,
|
||||
Input,
|
||||
RadioButton,
|
||||
RadioGroup,
|
||||
Slider,
|
||||
Switch,
|
||||
Tooltip,
|
||||
} from 'ant-design-vue';
|
||||
|
||||
import UploadImg from '#/components/upload/image-upload.vue';
|
||||
import { ColorInput } from '#/views/mall/promotion/components';
|
||||
import { SeckillShowcase } from '#/views/mall/promotion/seckill/components';
|
||||
|
||||
import ComponentContainerProperty from '../../component-container-property.vue';
|
||||
|
||||
/** 秒杀属性面板 */
|
||||
defineOptions({ name: 'PromotionSeckillProperty' });
|
||||
|
||||
const props = defineProps<{ modelValue: PromotionSeckillProperty }>();
|
||||
|
||||
const emit = defineEmits(['update:modelValue']);
|
||||
|
||||
const formData = useVModel(props, 'modelValue', emit);
|
||||
</script>
|
||||
<template><Page>待完成</Page></template>
|
||||
|
||||
<template>
|
||||
<ComponentContainerProperty v-model="formData.style">
|
||||
<Form :model="formData">
|
||||
<Card title="秒杀活动" class="property-group">
|
||||
<SeckillShowcase v-model="formData.activityIds" />
|
||||
</Card>
|
||||
<Card title="商品样式" class="property-group">
|
||||
<FormItem label="布局" name="type">
|
||||
<RadioGroup v-model:value="formData.layoutType">
|
||||
<Tooltip title="单列大图" placement="bottom">
|
||||
<RadioButton value="oneColBigImg">
|
||||
<IconifyIcon icon="fluent:text-column-one-24-filled" />
|
||||
</RadioButton>
|
||||
</Tooltip>
|
||||
<Tooltip title="单列小图" placement="bottom">
|
||||
<RadioButton value="oneColSmallImg">
|
||||
<IconifyIcon icon="fluent:text-column-two-left-24-filled" />
|
||||
</RadioButton>
|
||||
</Tooltip>
|
||||
<Tooltip title="双列" placement="bottom">
|
||||
<RadioButton value="twoCol">
|
||||
<IconifyIcon icon="fluent:text-column-two-24-filled" />
|
||||
</RadioButton>
|
||||
</Tooltip>
|
||||
</RadioGroup>
|
||||
</FormItem>
|
||||
<FormItem label="商品名称" name="fields.name.show">
|
||||
<div class="flex gap-2">
|
||||
<ColorInput v-model="formData.fields.name.color" />
|
||||
<Checkbox v-model:checked="formData.fields.name.show" />
|
||||
</div>
|
||||
</FormItem>
|
||||
<FormItem label="商品简介" name="fields.introduction.show">
|
||||
<div class="flex gap-2">
|
||||
<ColorInput v-model="formData.fields.introduction.color" />
|
||||
<Checkbox v-model:checked="formData.fields.introduction.show" />
|
||||
</div>
|
||||
</FormItem>
|
||||
<FormItem label="商品价格" name="fields.price.show">
|
||||
<div class="flex gap-2">
|
||||
<ColorInput v-model="formData.fields.price.color" />
|
||||
<Checkbox v-model:checked="formData.fields.price.show" />
|
||||
</div>
|
||||
</FormItem>
|
||||
<FormItem label="市场价" name="fields.marketPrice.show">
|
||||
<div class="flex gap-2">
|
||||
<ColorInput v-model="formData.fields.marketPrice.color" />
|
||||
<Checkbox v-model:checked="formData.fields.marketPrice.show" />
|
||||
</div>
|
||||
</FormItem>
|
||||
<FormItem label="商品销量" name="fields.salesCount.show">
|
||||
<div class="flex gap-2">
|
||||
<ColorInput v-model="formData.fields.salesCount.color" />
|
||||
<Checkbox v-model:checked="formData.fields.salesCount.show" />
|
||||
</div>
|
||||
</FormItem>
|
||||
<FormItem label="商品库存" name="fields.stock.show">
|
||||
<div class="flex gap-2">
|
||||
<ColorInput v-model="formData.fields.stock.color" />
|
||||
<Checkbox v-model:checked="formData.fields.stock.show" />
|
||||
</div>
|
||||
</FormItem>
|
||||
</Card>
|
||||
<Card title="角标" class="property-group">
|
||||
<FormItem label="角标" name="badge.show">
|
||||
<Switch v-model:checked="formData.badge.show" />
|
||||
</FormItem>
|
||||
<FormItem label="角标" name="badge.imgUrl" v-if="formData.badge.show">
|
||||
<UploadImg
|
||||
v-model="formData.badge.imgUrl"
|
||||
height="44px"
|
||||
width="72px"
|
||||
:show-description="false"
|
||||
>
|
||||
<template #tip> 建议尺寸:36 * 22 </template>
|
||||
</UploadImg>
|
||||
</FormItem>
|
||||
</Card>
|
||||
<Card title="按钮" class="property-group">
|
||||
<FormItem label="按钮类型" name="btnBuy.type">
|
||||
<RadioGroup v-model:value="formData.btnBuy.type">
|
||||
<RadioButton value="text">文字</RadioButton>
|
||||
<RadioButton value="img">图片</RadioButton>
|
||||
</RadioGroup>
|
||||
</FormItem>
|
||||
<template v-if="formData.btnBuy.type === 'text'">
|
||||
<FormItem label="按钮文字" name="btnBuy.text">
|
||||
<Input v-model:value="formData.btnBuy.text" />
|
||||
</FormItem>
|
||||
<FormItem label="左侧背景" name="btnBuy.bgBeginColor">
|
||||
<ColorInput v-model="formData.btnBuy.bgBeginColor" />
|
||||
</FormItem>
|
||||
<FormItem label="右侧背景" name="btnBuy.bgEndColor">
|
||||
<ColorInput v-model="formData.btnBuy.bgEndColor" />
|
||||
</FormItem>
|
||||
</template>
|
||||
<template v-else>
|
||||
<FormItem label="图片" name="btnBuy.imgUrl">
|
||||
<UploadImg
|
||||
v-model="formData.btnBuy.imgUrl"
|
||||
height="56px"
|
||||
width="56px"
|
||||
:show-description="false"
|
||||
>
|
||||
<template #tip> 建议尺寸:56 * 56</template>
|
||||
</UploadImg>
|
||||
</FormItem>
|
||||
</template>
|
||||
</Card>
|
||||
<Card title="商品样式" class="property-group">
|
||||
<FormItem label="上圆角" name="borderRadiusTop">
|
||||
<Slider
|
||||
v-model:value="formData.borderRadiusTop"
|
||||
:max="100"
|
||||
:min="0"
|
||||
/>
|
||||
</FormItem>
|
||||
<FormItem label="下圆角" name="borderRadiusBottom">
|
||||
<Slider
|
||||
v-model:value="formData.borderRadiusBottom"
|
||||
:max="100"
|
||||
:min="0"
|
||||
/>
|
||||
</FormItem>
|
||||
<FormItem label="间隔" name="space">
|
||||
<Slider
|
||||
v-model:value="formData.space"
|
||||
:max="100"
|
||||
:min="0"
|
||||
/>
|
||||
</FormItem>
|
||||
</Card>
|
||||
</Form>
|
||||
</ComponentContainerProperty>
|
||||
</template>
|
||||
|
||||
@@ -1,4 +1,159 @@
|
||||
<script setup lang="ts">
|
||||
import { Page } from '@vben/common-ui';
|
||||
import type { TitleBarProperty } from './config';
|
||||
|
||||
import { IconifyIcon } from '@vben/icons';
|
||||
|
||||
import { useVModel } from '@vueuse/core';
|
||||
import {
|
||||
Card,
|
||||
Checkbox,
|
||||
Form,
|
||||
FormItem,
|
||||
Input,
|
||||
Radio,
|
||||
RadioButton,
|
||||
RadioGroup,
|
||||
Slider,
|
||||
Tooltip,
|
||||
} from 'ant-design-vue';
|
||||
|
||||
import UploadImg from '#/components/upload/image-upload.vue';
|
||||
import {
|
||||
AppLinkInput,
|
||||
InputWithColor,
|
||||
} from '#/views/mall/promotion/components';
|
||||
|
||||
import ComponentContainerProperty from '../../component-container-property.vue';
|
||||
|
||||
/** 导航栏属性面板 */
|
||||
defineOptions({ name: 'TitleBarProperty' });
|
||||
|
||||
const props = defineProps<{ modelValue: TitleBarProperty }>();
|
||||
|
||||
const emit = defineEmits(['update:modelValue']);
|
||||
|
||||
const formData = useVModel(props, 'modelValue', emit);
|
||||
|
||||
const rules = {}; // 表单校验
|
||||
</script>
|
||||
<template><Page>待完成</Page></template>
|
||||
<template>
|
||||
<ComponentContainerProperty v-model="formData.style">
|
||||
<Form :model="formData" :rules="rules">
|
||||
<Card title="风格" class="property-group">
|
||||
<FormItem label="背景图片" name="bgImgUrl">
|
||||
<UploadImg
|
||||
v-model="formData.bgImgUrl"
|
||||
width="100%"
|
||||
height="40px"
|
||||
:show-description="false"
|
||||
>
|
||||
<template #tip>建议尺寸 750*80</template>
|
||||
</UploadImg>
|
||||
</FormItem>
|
||||
<FormItem label="标题位置" name="textAlign">
|
||||
<RadioGroup v-model:value="formData!.textAlign">
|
||||
<Tooltip title="居左" placement="top">
|
||||
<RadioButton value="left">
|
||||
<IconifyIcon icon="ant-design:align-left-outlined" />
|
||||
</RadioButton>
|
||||
</Tooltip>
|
||||
<Tooltip title="居中" placement="top">
|
||||
<RadioButton value="center">
|
||||
<IconifyIcon icon="ant-design:align-center-outlined" />
|
||||
</RadioButton>
|
||||
</Tooltip>
|
||||
</RadioGroup>
|
||||
</FormItem>
|
||||
<FormItem label="偏移量" name="marginLeft">
|
||||
<Slider
|
||||
v-model:value="formData.marginLeft"
|
||||
:max="100"
|
||||
:min="0"
|
||||
/>
|
||||
</FormItem>
|
||||
<FormItem label="高度" name="height">
|
||||
<Slider
|
||||
v-model:value="formData.height"
|
||||
:max="200"
|
||||
:min="20"
|
||||
/>
|
||||
</FormItem>
|
||||
</Card>
|
||||
<Card title="主标题" class="property-group">
|
||||
<FormItem label="文字" name="title">
|
||||
<InputWithColor
|
||||
v-model="formData.title"
|
||||
v-model:color="formData.titleColor"
|
||||
show-count
|
||||
:maxlength="20"
|
||||
/>
|
||||
</FormItem>
|
||||
<FormItem label="大小" name="titleSize">
|
||||
<Slider
|
||||
v-model:value="formData.titleSize"
|
||||
:max="60"
|
||||
:min="10"
|
||||
/>
|
||||
</FormItem>
|
||||
<FormItem label="粗细" name="titleWeight">
|
||||
<Slider
|
||||
v-model:value="formData.titleWeight"
|
||||
:min="100"
|
||||
:max="900"
|
||||
:step="100"
|
||||
/>
|
||||
</FormItem>
|
||||
</Card>
|
||||
<Card title="副标题" class="property-group">
|
||||
<FormItem label="文字" name="description">
|
||||
<InputWithColor
|
||||
v-model="formData.description"
|
||||
v-model:color="formData.descriptionColor"
|
||||
show-count
|
||||
:maxlength="50"
|
||||
/>
|
||||
</FormItem>
|
||||
<FormItem label="大小" name="descriptionSize">
|
||||
<Slider
|
||||
v-model:value="formData.descriptionSize"
|
||||
:max="60"
|
||||
:min="10"
|
||||
/>
|
||||
</FormItem>
|
||||
<FormItem label="粗细" name="descriptionWeight">
|
||||
<Slider
|
||||
v-model:value="formData.descriptionWeight"
|
||||
:min="100"
|
||||
:max="900"
|
||||
:step="100"
|
||||
/>
|
||||
</FormItem>
|
||||
</Card>
|
||||
<Card title="查看更多" class="property-group">
|
||||
<FormItem label="是否显示" name="more.show">
|
||||
<Checkbox v-model:checked="formData.more.show" />
|
||||
</FormItem>
|
||||
<!-- 更多按钮的 样式选择 -->
|
||||
<template v-if="formData.more.show">
|
||||
<FormItem label="样式" name="more.type">
|
||||
<RadioGroup v-model:value="formData.more.type">
|
||||
<Radio value="text">文字</Radio>
|
||||
<Radio value="icon">图标</Radio>
|
||||
<Radio value="all">文字+图标</Radio>
|
||||
</RadioGroup>
|
||||
</FormItem>
|
||||
<FormItem
|
||||
label="更多文字"
|
||||
name="more.text"
|
||||
v-show="formData.more.type !== 'icon'"
|
||||
>
|
||||
<Input v-model:value="formData.more.text" />
|
||||
</FormItem>
|
||||
<FormItem label="跳转链接" name="more.url">
|
||||
<AppLinkInput v-model="formData.more.url" />
|
||||
</FormItem>
|
||||
</template>
|
||||
</Card>
|
||||
</Form>
|
||||
</ComponentContainerProperty>
|
||||
</template>
|
||||
|
||||
Reference in New Issue
Block a user