feat:【mall】diy editor 的 coupon-card 部分代码的优化

This commit is contained in:
YunaiV
2025-10-28 17:07:08 +08:00
parent 0f3f220d4b
commit 958f64a9c8
7 changed files with 125 additions and 152 deletions

View File

@@ -1,4 +1,87 @@
// 导出所有优惠券相关组件
export { CouponDiscount } from './coupon-discount';
export { CouponDiscountDesc } from './coupon-discount-desc';
export { CouponValidTerm } from './coupon-validTerm';
import type { MallCouponTemplateApi } from '#/api/mall/promotion/coupon/couponTemplate';
import { defineComponent } from 'vue';
import {
CouponTemplateValidityTypeEnum,
PromotionDiscountTypeEnum,
} from '@vben/constants';
import { floatToFixed2, formatDate } from '@vben/utils';
/** 有效期 */
export const CouponValidTerm = defineComponent({
name: 'CouponValidTerm',
props: {
coupon: {
type: Object as () => MallCouponTemplateApi.CouponTemplate,
required: true,
},
},
setup(props) {
const coupon = props.coupon as MallCouponTemplateApi.CouponTemplate;
const text =
coupon.validityType === CouponTemplateValidityTypeEnum.DATE.type
? `有效期:${formatDate(coupon.validStartTime, 'YYYY-MM-DD')}${formatDate(
coupon.validEndTime,
'YYYY-MM-DD',
)}`
: `领取后第 ${coupon.fixedStartTerm} - ${coupon.fixedEndTerm} 天内可用`;
return () => <div>{text}</div>;
},
});
/** 优惠值 */
export const CouponDiscount = defineComponent({
name: 'CouponDiscount',
props: {
coupon: {
type: Object as () => MallCouponTemplateApi.CouponTemplate,
required: true,
},
},
setup(props) {
const coupon = props.coupon as MallCouponTemplateApi.CouponTemplate;
// 折扣
let value = `${(coupon.discountPercent ?? 0) / 10}`;
let suffix = ' 折';
// 满减
if (coupon.discountType === PromotionDiscountTypeEnum.PRICE.type) {
value = floatToFixed2(coupon.discountPrice);
suffix = ' 元';
}
return () => (
<div>
<span class={'text-20px font-bold'}>{value}</span>
<span>{suffix}</span>
</div>
);
},
});
/** 优惠描述 */
export const CouponDiscountDesc = defineComponent({
name: 'CouponDiscountDesc',
props: {
coupon: {
type: Object as () => MallCouponTemplateApi.CouponTemplate,
required: true,
},
},
setup(props) {
const coupon = props.coupon as MallCouponTemplateApi.CouponTemplate;
// 使用条件
const useCondition =
coupon.usePrice > 0 ? `${floatToFixed2(coupon.usePrice)}元,` : '';
// 优惠描述
const discountDesc =
coupon.discountType === PromotionDiscountTypeEnum.PRICE.type
? `${floatToFixed2(coupon.discountPrice)}`
: `${(coupon.discountPercent ?? 0) / 10}`;
return () => (
<div>
<span>{useCondition}</span>
<span>{discountDesc}</span>
</div>
);
},
});

View File

@@ -1,29 +1,20 @@
import type { ComponentStyle, DiyComponent } from '../../../util';
/** 商品卡片属性 */
/** 优惠劵卡片属性 */
export interface CouponCardProperty {
// 列数
columns: number;
// 背景图
bgImg: string;
// 文字颜色
textColor: string;
// 按钮样式
columns: number; // 列数
bgImg: string; // 背景图
textColor: string; // 文字颜色
button: {
// 背景颜色
bgColor: string;
// 颜色
color: string;
};
// 间距
space: number;
// 优惠券编号列表
couponIds: number[];
// 组件样式
style: ComponentStyle;
bgColor: string; // 背景颜色
color: string; // 文字颜色
}; // 按钮样式
space: number; // 间距
couponIds: number[]; // 优惠券编号列表
style: ComponentStyle; // 组件样式
}
// 定义组件
/** 定义组件 */
export const component = {
id: 'CouponCard',
name: '优惠券',

View File

@@ -1,34 +0,0 @@
import type { MallCouponTemplateApi } from '#/api/mall/promotion/coupon/couponTemplate';
import { defineComponent } from 'vue';
import { PromotionDiscountTypeEnum } from '@vben/constants';
import { floatToFixed2 } from '@vben/utils';
// 优惠描述
export const CouponDiscountDesc = defineComponent({
name: 'CouponDiscountDesc',
props: {
coupon: {
type: Object as () => MallCouponTemplateApi.CouponTemplate,
required: true,
},
},
setup(props) {
const coupon = props.coupon as MallCouponTemplateApi.CouponTemplate;
// 使用条件
const useCondition =
coupon.usePrice > 0 ? `${floatToFixed2(coupon.usePrice)}元,` : '';
// 优惠描述
const discountDesc =
coupon.discountType === PromotionDiscountTypeEnum.PRICE.type
? `${floatToFixed2(coupon.discountPrice)}`
: `${coupon.discountPercent / 10}`;
return () => (
<div>
<span>{useCondition}</span>
<span>{discountDesc}</span>
</div>
);
},
});

View File

@@ -1,34 +0,0 @@
import type { MallCouponTemplateApi } from '#/api/mall/promotion/coupon/couponTemplate';
import { defineComponent } from 'vue';
import { PromotionDiscountTypeEnum } from '@vben/constants';
import { floatToFixed2 } from '@vben/utils';
// 优惠值
export const CouponDiscount = defineComponent({
name: 'CouponDiscount',
props: {
coupon: {
type: Object as () => MallCouponTemplateApi.CouponTemplate,
required: true,
},
},
setup(props) {
const coupon = props.coupon as MallCouponTemplateApi.CouponTemplate;
// 折扣
let value = `${coupon.discountPercent / 10}`;
let suffix = ' 折';
// 满减
if (coupon.discountType === PromotionDiscountTypeEnum.PRICE.type) {
value = floatToFixed2(coupon.discountPrice);
suffix = ' 元';
}
return () => (
<div>
<span class={'text-20px font-bold'}>{value}</span>
<span>{suffix}</span>
</div>
);
},
});

View File

@@ -1,28 +0,0 @@
import type { MallCouponTemplateApi } from '#/api/mall/promotion/coupon/couponTemplate';
import { defineComponent } from 'vue';
import { CouponTemplateValidityTypeEnum } from '@vben/constants';
import { formatDate } from '@vben/utils';
// 有效期
export const CouponValidTerm = defineComponent({
name: 'CouponValidTerm',
props: {
coupon: {
type: Object as () => MallCouponTemplateApi.CouponTemplate,
required: true,
},
},
setup(props) {
const coupon = props.coupon as MallCouponTemplateApi.CouponTemplate;
const text =
coupon.validityType === CouponTemplateValidityTypeEnum.DATE.type
? `有效期:${formatDate(coupon.validStartTime, 'YYYY-MM-DD')}${formatDate(
coupon.validEndTime,
'YYYY-MM-DD',
)}`
: `领取后第 ${coupon.fixedStartTerm} - ${coupon.fixedEndTerm} 天内可用`;
return () => <div>{text}</div>;
},
});

View File

@@ -15,12 +15,19 @@ import {
CouponValidTerm,
} from './component';
/** 商品卡片 */
/** 优惠劵卡片 */
defineOptions({ name: 'CouponCard' });
// 定义属性
/** 定义属性 */
const props = defineProps<{ property: CouponCardProperty }>();
// 商品列表
const couponList = ref<MallCouponTemplateApi.CouponTemplate[]>([]);
const couponList = ref<MallCouponTemplateApi.CouponTemplate[]>([]); // 优惠劵列表
const phoneWidth = ref(375); // 手机宽度
const containerRef = ref(); // 容器引用
const scrollbarWidth = ref('100%'); // 滚动条宽度
const couponWidth = ref(375); // 优惠券宽度
/** 监听优惠券 ID 变化,加载优惠券列表 */
watch(
() => props.property.couponIds,
async () => {
@@ -36,15 +43,7 @@ watch(
},
);
// 手机宽度
const phoneWidth = ref(375);
// 容器
const containerRef = ref();
// 滚动条宽度
const scrollbarWidth = ref('100%');
// 优惠券的宽度
const couponWidth = ref(375);
// 计算布局参数
/** 计算布局参数 */
watch(
() => [props.property, phoneWidth, couponList.value.length],
() => {
@@ -60,8 +59,9 @@ watch(
},
{ immediate: true, deep: true },
);
/** 提取手机宽度 */
onMounted(() => {
// 提取手机宽度
phoneWidth.value = containerRef.value?.wrapRef?.offsetWidth || 375;
});
</script>
@@ -86,17 +86,14 @@ onMounted(() => {
v-for="(coupon, index) in couponList"
:key="index"
>
<!-- 布局11-->
<!-- 布局 11 -->
<div
v-if="property.columns === 1"
class="ml-4 flex flex-row justify-between p-2"
>
<div class="flex flex-col justify-evenly gap-1">
<!-- 优惠值 -->
<CouponDiscount :coupon="coupon" />
<!-- 优惠描述 -->
<CouponDiscountDesc :coupon="coupon" />
<!-- 有效期 -->
<CouponValidTerm :coupon="coupon" />
</div>
<div class="flex flex-col justify-evenly">
@@ -111,17 +108,14 @@ onMounted(() => {
</div>
</div>
</div>
<!-- 布局22-->
<!-- 布局 22 -->
<div
v-else-if="property.columns === 2"
class="ml-4 flex flex-row justify-between p-2"
>
<div class="flex flex-col justify-evenly gap-1">
<!-- 优惠值 -->
<CouponDiscount :coupon="coupon" />
<!-- 优惠描述 -->
<CouponDiscountDesc :coupon="coupon" />
<!-- 领取说明 -->
<div v-if="coupon.totalCount >= 0">
仅剩{{ coupon.totalCount - coupon.takeCount }}
</div>
@@ -139,11 +133,9 @@ onMounted(() => {
</div>
</div>
</div>
<!-- 布局33-->
<!-- 布局 33 -->
<div v-else class="flex flex-col items-center justify-around gap-1 p-1">
<!-- 优惠值 -->
<CouponDiscount :coupon="coupon" />
<!-- 优惠描述 -->
<CouponDiscountDesc :coupon="coupon" />
<div
class="rounded-full px-2 py-0.5"
@@ -159,4 +151,3 @@ onMounted(() => {
</div>
</ElScrollbar>
</template>
<style scoped lang="scss"></style>

View File

@@ -31,20 +31,24 @@ import ComponentContainerProperty from '../../component-container-property.vue';
// TODO: 添加组件
// import CouponSelect from '#/views/mall/promotion/coupon/components/coupon-select.vue';
// 优惠券卡片属性面板
/** 优惠券卡片属性面板 */
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 couponList = ref<MallCouponTemplateApi.CouponTemplate[]>([]); // 已选择的优惠券列表
const couponSelectDialog = ref();
// 添加优惠券
/** 添加优惠劵 */
const handleAddCoupon = () => {
couponSelectDialog.value.open();
};
/** 处理优惠劵选择 */
const handleCouponSelect = () => {
formData.value.couponIds = couponList.value.map((coupon) => coupon.id);
};
@@ -151,7 +155,9 @@ watch(
</ElCard>
</ElForm>
</ComponentContainerProperty>
<!-- 优惠券选择 -->
<!-- TODO @AI优惠劵的选择 -->
<CouponSelect
ref="couponSelectDialog"
v-model:multiple-selection="couponList"
@@ -159,5 +165,3 @@ watch(
@change="handleCouponSelect"
/>
</template>
<style scoped lang="scss"></style>