feat:【mall 商城】优惠劵-模版(100% ele)
This commit is contained in:
@@ -243,7 +243,6 @@ export function useFormSchema(): VbenFormSchema[] {
|
|||||||
defaultValue: CouponTemplateValidityTypeEnum.DATE.type,
|
defaultValue: CouponTemplateValidityTypeEnum.DATE.type,
|
||||||
rules: 'required',
|
rules: 'required',
|
||||||
},
|
},
|
||||||
// TODO @AI:不太对;
|
|
||||||
{
|
{
|
||||||
fieldName: 'validTimes',
|
fieldName: 'validTimes',
|
||||||
label: '固定日期',
|
label: '固定日期',
|
||||||
|
|||||||
@@ -5,46 +5,28 @@ import { requestClient } from '#/api/request';
|
|||||||
export namespace MallCouponApi {
|
export namespace MallCouponApi {
|
||||||
/** 优惠券 */
|
/** 优惠券 */
|
||||||
export interface Coupon {
|
export interface Coupon {
|
||||||
/** 优惠券编号 */
|
id: number; // 优惠券编号
|
||||||
id: number;
|
name: string; // 优惠券名称
|
||||||
/** 优惠券名称 */
|
status: number; // 优惠券状态
|
||||||
name: string;
|
type: number; // 优惠券类型
|
||||||
/** 优惠券状态 */
|
price: number; // 优惠券金额
|
||||||
status: number;
|
usePrice: number; // 使用门槛
|
||||||
/** 优惠券类型 */
|
productScope: number; // 商品范围
|
||||||
type: number;
|
productSpuIds: number[]; // 商品编号数组
|
||||||
/** 优惠券金额 */
|
validityType: number; // 有效期类型
|
||||||
price: number;
|
validStartTime: Date; // 固定日期-生效开始时间
|
||||||
/** 使用门槛 */
|
validEndTime: Date; // 固定日期-生效结束时间
|
||||||
usePrice: number;
|
fixedStartTerm: number; // 领取日期-开始天数
|
||||||
/** 商品范围 */
|
fixedEndTerm: number; // 领取日期-结束天数
|
||||||
productScope: number;
|
takeLimitCount: number; // 每人限领个数
|
||||||
/** 商品编号数组 */
|
usePriceEnabled: boolean; // 是否设置满多少金额可用
|
||||||
productSpuIds: number[];
|
productCategoryIds: number[]; // 商品分类编号数组
|
||||||
/** 有效期类型 */
|
|
||||||
validityType: number;
|
|
||||||
/** 固定日期-生效开始时间 */
|
|
||||||
validStartTime: Date;
|
|
||||||
/** 固定日期-生效结束时间 */
|
|
||||||
validEndTime: Date;
|
|
||||||
/** 领取日期-开始天数 */
|
|
||||||
fixedStartTerm: number;
|
|
||||||
/** 领取日期-结束天数 */
|
|
||||||
fixedEndTerm: number;
|
|
||||||
/** 每人限领个数 */
|
|
||||||
takeLimitCount: number;
|
|
||||||
/** 是否设置满多少金额可用 */
|
|
||||||
usePriceEnabled: boolean;
|
|
||||||
/** 商品分类编号数组 */
|
|
||||||
productCategoryIds: number[];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 发送优惠券 */
|
/** 发送优惠券 */
|
||||||
export interface CouponSendReqVO {
|
export interface CouponSendReqVO {
|
||||||
/** 优惠券编号 */
|
templateId: number; // 优惠券编号
|
||||||
templateId: number;
|
userIds: number[]; // 用户编号数组
|
||||||
/** 用户编号数组 */
|
|
||||||
userIds: number[];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,54 +5,26 @@ import { requestClient } from '#/api/request';
|
|||||||
export namespace MallCouponTemplateApi {
|
export namespace MallCouponTemplateApi {
|
||||||
/** 优惠券模板 */
|
/** 优惠券模板 */
|
||||||
export interface CouponTemplate {
|
export interface CouponTemplate {
|
||||||
/** 模板编号 */
|
id: number; // 模板编号
|
||||||
id: number;
|
name: string; // 模板名称
|
||||||
/** 模板名称 */
|
status: number; // 状态
|
||||||
name: string;
|
totalCount: number; // 发放数量
|
||||||
/** 状态 */
|
takeLimitCount: number; // 每人限领个数
|
||||||
status: number;
|
takeType: number; // 领取方式
|
||||||
/** 发放数量 */
|
usePrice: number; // 使用门槛
|
||||||
totalCount: number;
|
productScope: number; // 商品范围
|
||||||
/** 每人限领个数 */
|
productScopeValues: number[]; // 商品范围值
|
||||||
takeLimitCount: number;
|
validityType: number; // 有效期类型
|
||||||
/** 领取方式 */
|
validStartTime: Date; // 固定日期-生效开始时间
|
||||||
takeType: number;
|
validEndTime: Date; // 固定日期-生效结束时间
|
||||||
/** 使用门槛 */
|
fixedStartTerm: number; // 领取日期-开始天数
|
||||||
usePrice: number;
|
fixedEndTerm: number; // 领取日期-结束天数
|
||||||
/** 商品范围 */
|
discountType: number; // 优惠类型
|
||||||
productScope: number;
|
discountPercent?: number; // 折扣百分比
|
||||||
/** 商品范围值 */
|
discountPrice: number; // 优惠金额
|
||||||
productScopeValues: number[];
|
discountLimitPrice?: number; // 折扣上限
|
||||||
/** 有效期类型 */
|
takeCount: number; // 已领取数量
|
||||||
validityType: number;
|
useCount: number; // 已使用数量
|
||||||
/** 固定日期-生效开始时间 */
|
|
||||||
validStartTime: Date;
|
|
||||||
/** 固定日期-生效结束时间 */
|
|
||||||
validEndTime: Date;
|
|
||||||
/** 领取日期-开始天数 */
|
|
||||||
fixedStartTerm: number;
|
|
||||||
/** 领取日期-结束天数 */
|
|
||||||
fixedEndTerm: number;
|
|
||||||
/** 优惠类型 */
|
|
||||||
discountType: number;
|
|
||||||
/** 折扣百分比 */
|
|
||||||
discountPercent: number;
|
|
||||||
/** 优惠金额 */
|
|
||||||
discountPrice: number;
|
|
||||||
/** 折扣上限 */
|
|
||||||
discountLimitPrice: number;
|
|
||||||
/** 已领取数量 */
|
|
||||||
takeCount: number;
|
|
||||||
/** 已使用数量 */
|
|
||||||
useCount: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 优惠券模板状态更新 */
|
|
||||||
export interface StatusUpdate {
|
|
||||||
/** 模板编号 */
|
|
||||||
id: number;
|
|
||||||
/** 状态 */
|
|
||||||
status: 0 | 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,9 +43,11 @@ export function updateCouponTemplate(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** 更新优惠劵模板的状态 */
|
/** 更新优惠劵模板的状态 */
|
||||||
export function updateCouponTemplateStatus(id: number, status: 0 | 1) {
|
export function updateCouponTemplateStatus(id: number, status: number) {
|
||||||
const data: MallCouponTemplateApi.StatusUpdate = { id, status };
|
return requestClient.put('/promotion/coupon-template/update-status', {
|
||||||
return requestClient.put('/promotion/coupon-template/update-status', data);
|
id,
|
||||||
|
status,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 删除优惠劵模板 */
|
/** 删除优惠劵模板 */
|
||||||
@@ -102,11 +76,3 @@ export function getCouponTemplateList(ids: number[]) {
|
|||||||
`/promotion/coupon-template/list?ids=${ids}`,
|
`/promotion/coupon-template/list?ids=${ids}`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 导出优惠劵模板 Excel */
|
|
||||||
export function exportCouponTemplateExcel(params: PageParam) {
|
|
||||||
return requestClient.get('/promotion/coupon-template/export-excel', {
|
|
||||||
params,
|
|
||||||
responseType: 'blob',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -6,11 +6,11 @@ export namespace MallOrderApi {
|
|||||||
/** 商品属性 */
|
/** 商品属性 */
|
||||||
export interface ProductProperty {
|
export interface ProductProperty {
|
||||||
/** 属性的编号 */
|
/** 属性的编号 */
|
||||||
propertyId?: null | number;
|
propertyId?: number;
|
||||||
/** 属性的名称 */
|
/** 属性的名称 */
|
||||||
propertyName?: string;
|
propertyName?: string;
|
||||||
/** 属性值的编号 */
|
/** 属性值的编号 */
|
||||||
valueId?: null | number;
|
valueId?: number;
|
||||||
/** 属性值的名称 */
|
/** 属性值的名称 */
|
||||||
valueName?: string;
|
valueName?: string;
|
||||||
}
|
}
|
||||||
@@ -18,35 +18,35 @@ export namespace MallOrderApi {
|
|||||||
/** 订单项 */
|
/** 订单项 */
|
||||||
export interface OrderItem {
|
export interface OrderItem {
|
||||||
/** 编号 */
|
/** 编号 */
|
||||||
id?: null | number;
|
id?: number;
|
||||||
/** 用户编号 */
|
/** 用户编号 */
|
||||||
userId?: null | number;
|
userId?: number;
|
||||||
/** 订单编号 */
|
/** 订单编号 */
|
||||||
orderId?: null | number;
|
orderId?: number;
|
||||||
/** 商品 SPU 编号 */
|
/** 商品 SPU 编号 */
|
||||||
spuId?: null | number;
|
spuId?: number;
|
||||||
/** 商品 SPU 名称 */
|
/** 商品 SPU 名称 */
|
||||||
spuName?: string;
|
spuName?: string;
|
||||||
/** 商品 SKU 编号 */
|
/** 商品 SKU 编号 */
|
||||||
skuId?: null | number;
|
skuId?: number;
|
||||||
/** 商品图片 */
|
/** 商品图片 */
|
||||||
picUrl?: string;
|
picUrl?: string;
|
||||||
/** 购买数量 */
|
/** 购买数量 */
|
||||||
count?: null | number;
|
count?: number;
|
||||||
/** 商品原价(总) */
|
/** 商品原价(总) */
|
||||||
originalPrice?: null | number;
|
originalPrice?: number;
|
||||||
/** 商品原价(单) */
|
/** 商品原价(单) */
|
||||||
originalUnitPrice?: null | number;
|
originalUnitPrice?: number;
|
||||||
/** 商品优惠(总) */
|
/** 商品优惠(总) */
|
||||||
discountPrice?: null | number;
|
discountPrice?: number;
|
||||||
/** 商品实付金额(总) */
|
/** 商品实付金额(总) */
|
||||||
payPrice?: null | number;
|
payPrice?: number;
|
||||||
/** 子订单分摊金额(总) */
|
/** 子订单分摊金额(总) */
|
||||||
orderPartPrice?: null | number;
|
orderPartPrice?: number;
|
||||||
/** 分摊后子订单实付金额(总) */
|
/** 分摊后子订单实付金额(总) */
|
||||||
orderDividePrice?: null | number;
|
orderDividePrice?: number;
|
||||||
/** 售后状态 */
|
/** 售后状态 */
|
||||||
afterSaleStatus?: null | number;
|
afterSaleStatus?: number;
|
||||||
/** 属性数组 */
|
/** 属性数组 */
|
||||||
properties?: ProductProperty[];
|
properties?: ProductProperty[];
|
||||||
price?: number;
|
price?: number;
|
||||||
@@ -54,104 +54,104 @@ export namespace MallOrderApi {
|
|||||||
|
|
||||||
/** 订单日志 */
|
/** 订单日志 */
|
||||||
export interface OrderLog {
|
export interface OrderLog {
|
||||||
/** 日志编号 */
|
|
||||||
id: number;
|
|
||||||
/** 日志内容 */
|
/** 日志内容 */
|
||||||
content?: string;
|
content?: string;
|
||||||
/** 创建时间 */
|
/** 创建时间 */
|
||||||
createTime?: Date;
|
createTime?: Date;
|
||||||
/** 用户类型 */
|
/** 用户类型 */
|
||||||
userType?: number;
|
userType?: number;
|
||||||
|
/** 用户编号 */
|
||||||
|
userId?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 订单 */
|
/** 订单 */
|
||||||
export interface Order {
|
export interface Order {
|
||||||
/** 订单编号 */
|
/** 订单编号 */
|
||||||
id?: null | number;
|
id?: number;
|
||||||
/** 订单流水号 */
|
/** 订单流水号 */
|
||||||
no?: string;
|
no?: string;
|
||||||
/** 下单时间 */
|
/** 下单时间 */
|
||||||
createTime?: Date | null;
|
createTime?: Date;
|
||||||
/** 订单类型 */
|
/** 订单类型 */
|
||||||
type?: null | number;
|
type?: number;
|
||||||
/** 订单来源 */
|
/** 订单来源 */
|
||||||
terminal?: null | number;
|
terminal?: number;
|
||||||
/** 用户编号 */
|
/** 用户编号 */
|
||||||
userId?: null | number;
|
userId?: number;
|
||||||
/** 用户 IP */
|
/** 用户 IP */
|
||||||
userIp?: string;
|
userIp?: string;
|
||||||
/** 用户备注 */
|
/** 用户备注 */
|
||||||
userRemark?: string;
|
userRemark?: string;
|
||||||
/** 订单状态 */
|
/** 订单状态 */
|
||||||
status?: null | number;
|
status?: number;
|
||||||
/** 购买的商品数量 */
|
/** 购买的商品数量 */
|
||||||
productCount?: null | number;
|
productCount?: number;
|
||||||
/** 订单完成时间 */
|
/** 订单完成时间 */
|
||||||
finishTime?: Date | null;
|
finishTime?: Date;
|
||||||
/** 订单取消时间 */
|
/** 订单取消时间 */
|
||||||
cancelTime?: Date | null;
|
cancelTime?: Date;
|
||||||
/** 取消类型 */
|
/** 取消类型 */
|
||||||
cancelType?: null | number;
|
cancelType?: number;
|
||||||
/** 商家备注 */
|
/** 商家备注 */
|
||||||
remark?: string;
|
remark?: string;
|
||||||
/** 支付订单编号 */
|
/** 支付订单编号 */
|
||||||
payOrderId?: null | number;
|
payOrderId?: number;
|
||||||
/** 是否已支付 */
|
/** 是否已支付 */
|
||||||
payStatus?: boolean;
|
payStatus?: boolean;
|
||||||
/** 付款时间 */
|
/** 付款时间 */
|
||||||
payTime?: Date | null;
|
payTime?: Date;
|
||||||
/** 支付渠道 */
|
/** 支付渠道 */
|
||||||
payChannelCode?: string;
|
payChannelCode?: string;
|
||||||
/** 商品原价(总) */
|
/** 商品原价(总) */
|
||||||
totalPrice?: null | number;
|
totalPrice?: number;
|
||||||
/** 订单优惠(总) */
|
/** 订单优惠(总) */
|
||||||
discountPrice?: null | number;
|
discountPrice?: number;
|
||||||
/** 运费金额 */
|
/** 运费金额 */
|
||||||
deliveryPrice?: null | number;
|
deliveryPrice?: number;
|
||||||
/** 订单调价(总) */
|
/** 订单调价(总) */
|
||||||
adjustPrice?: null | number;
|
adjustPrice?: number;
|
||||||
/** 应付金额(总) */
|
/** 应付金额(总) */
|
||||||
payPrice?: null | number | string;
|
payPrice?: number;
|
||||||
/** 发货方式 */
|
/** 发货方式 */
|
||||||
deliveryType?: null | number;
|
deliveryType?: number;
|
||||||
/** 自提门店编号 */
|
/** 自提门店编号 */
|
||||||
pickUpStoreId?: number;
|
pickUpStoreId?: number;
|
||||||
/** 自提核销码 */
|
/** 自提核销码 */
|
||||||
pickUpVerifyCode?: string;
|
pickUpVerifyCode?: string;
|
||||||
/** 配送模板编号 */
|
/** 配送模板编号 */
|
||||||
deliveryTemplateId?: null | number;
|
deliveryTemplateId?: number;
|
||||||
/** 发货物流公司编号 */
|
/** 发货物流公司编号 */
|
||||||
logisticsId?: number;
|
logisticsId?: number;
|
||||||
/** 发货物流单号 */
|
/** 发货物流单号 */
|
||||||
logisticsNo?: string;
|
logisticsNo?: string;
|
||||||
/** 发货时间 */
|
/** 发货时间 */
|
||||||
deliveryTime?: Date | null;
|
deliveryTime?: Date;
|
||||||
/** 收货时间 */
|
/** 收货时间 */
|
||||||
receiveTime?: Date | null;
|
receiveTime?: Date;
|
||||||
/** 收件人名称 */
|
/** 收件人名称 */
|
||||||
receiverName?: string;
|
receiverName?: string;
|
||||||
/** 收件人手机 */
|
/** 收件人手机 */
|
||||||
receiverMobile?: string;
|
receiverMobile?: string;
|
||||||
/** 收件人邮编 */
|
/** 收件人邮编 */
|
||||||
receiverPostCode?: null | number;
|
receiverPostCode?: number;
|
||||||
/** 收件人地区编号 */
|
/** 收件人地区编号 */
|
||||||
receiverAreaId?: null | number;
|
receiverAreaId?: number;
|
||||||
/** 收件人地区名字 */
|
/** 收件人地区名字 */
|
||||||
receiverAreaName?: string;
|
receiverAreaName?: string;
|
||||||
/** 收件人详细地址 */
|
/** 收件人详细地址 */
|
||||||
receiverDetailAddress?: string;
|
receiverDetailAddress?: string;
|
||||||
/** 售后状态 */
|
/** 售后状态 */
|
||||||
afterSaleStatus?: null | number;
|
afterSaleStatus?: number;
|
||||||
/** 退款金额 */
|
/** 退款金额 */
|
||||||
refundPrice?: null | number;
|
refundPrice?: number;
|
||||||
/** 优惠劵编号 */
|
/** 优惠劵编号 */
|
||||||
couponId?: null | number;
|
couponId?: number;
|
||||||
/** 优惠劵减免金额 */
|
/** 优惠劵减免金额 */
|
||||||
couponPrice?: null | number;
|
couponPrice?: number;
|
||||||
/** 积分抵扣的金额 */
|
/** 积分抵扣的金额 */
|
||||||
pointPrice?: null | number;
|
pointPrice?: number;
|
||||||
/** VIP 减免金额 */
|
/** VIP 减免金额 */
|
||||||
vipPrice?: null | number;
|
vipPrice?: number;
|
||||||
/** 订单项列表 */
|
/** 订单项列表 */
|
||||||
items?: OrderItem[];
|
items?: OrderItem[];
|
||||||
/** 下单用户信息 */
|
/** 下单用户信息 */
|
||||||
@@ -159,7 +159,7 @@ export namespace MallOrderApi {
|
|||||||
/** 用户头像 */
|
/** 用户头像 */
|
||||||
avatar?: string;
|
avatar?: string;
|
||||||
/** 用户编号 */
|
/** 用户编号 */
|
||||||
id?: null | number;
|
id?: number;
|
||||||
/** 用户昵称 */
|
/** 用户昵称 */
|
||||||
nickname?: string;
|
nickname?: string;
|
||||||
};
|
};
|
||||||
@@ -168,7 +168,7 @@ export namespace MallOrderApi {
|
|||||||
/** 用户头像 */
|
/** 用户头像 */
|
||||||
avatar?: string;
|
avatar?: string;
|
||||||
/** 用户编号 */
|
/** 用户编号 */
|
||||||
id?: null | number;
|
id?: number;
|
||||||
/** 用户昵称 */
|
/** 用户昵称 */
|
||||||
nickname?: string;
|
nickname?: string;
|
||||||
};
|
};
|
||||||
@@ -195,7 +195,7 @@ export namespace MallOrderApi {
|
|||||||
/** 发货方式 */
|
/** 发货方式 */
|
||||||
expressType: string;
|
expressType: string;
|
||||||
/** 物流公司编号 */
|
/** 物流公司编号 */
|
||||||
logisticsId: null | number;
|
logisticsId: number;
|
||||||
/** 物流编号 */
|
/** 物流编号 */
|
||||||
logisticsNo: string;
|
logisticsNo: string;
|
||||||
}
|
}
|
||||||
@@ -229,13 +229,6 @@ export namespace MallOrderApi {
|
|||||||
/** 收件人详细地址 */
|
/** 收件人详细地址 */
|
||||||
receiverDetailAddress: string;
|
receiverDetailAddress: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface OrderExpressTrackRespDTO {
|
|
||||||
/** 发生时间 */
|
|
||||||
time: Date;
|
|
||||||
/** 快递状态 */
|
|
||||||
content: string;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 查询交易订单列表 */
|
/** 查询交易订单列表 */
|
||||||
@@ -264,9 +257,7 @@ export function getOrder(id: number) {
|
|||||||
|
|
||||||
/** 查询交易订单物流详情 */
|
/** 查询交易订单物流详情 */
|
||||||
export function getExpressTrackList(id: number) {
|
export function getExpressTrackList(id: number) {
|
||||||
return requestClient.get<MallOrderApi.OrderExpressTrackRespDTO[]>(
|
return requestClient.get(`/trade/order/get-express-track-list?id=${id}`);
|
||||||
`/trade/order/get-express-track-list?id=${id}`,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 订单发货 */
|
/** 订单发货 */
|
||||||
@@ -296,7 +287,7 @@ export function pickUpOrder(id: number) {
|
|||||||
|
|
||||||
/** 订单核销 */
|
/** 订单核销 */
|
||||||
export function pickUpOrderByVerifyCode(pickUpVerifyCode: string) {
|
export function pickUpOrderByVerifyCode(pickUpVerifyCode: string) {
|
||||||
return requestClient.put('/trade/order/pick-up-by-verify-code', {
|
return requestClient.put('/trade/order/pick-up-by-verify-code', undefined, {
|
||||||
params: { pickUpVerifyCode },
|
params: { pickUpVerifyCode },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,223 +0,0 @@
|
|||||||
<script lang="ts" setup>
|
|
||||||
import type { MallCouponTemplateApi } from '#/api/mall/promotion/coupon/couponTemplate';
|
|
||||||
|
|
||||||
import { reactive, ref } from 'vue';
|
|
||||||
|
|
||||||
import { ContentWrap } from '@vben/common-ui';
|
|
||||||
import { CouponTemplateTakeTypeEnum, DICT_TYPE } from '@vben/constants';
|
|
||||||
import { getDictOptions } from '@vben/hooks';
|
|
||||||
import { IconifyIcon } from '@vben/icons';
|
|
||||||
|
|
||||||
import * as CouponTemplateApi from '#/api/mall/promotion/coupon/couponTemplate';
|
|
||||||
import {
|
|
||||||
discountFormat,
|
|
||||||
remainedCountFormat,
|
|
||||||
takeLimitCountFormat,
|
|
||||||
validityTypeFormat,
|
|
||||||
} from '#/views/mall/promotion/coupon/formatter';
|
|
||||||
|
|
||||||
defineOptions({ name: 'CouponSelect' });
|
|
||||||
|
|
||||||
const props = defineProps<{
|
|
||||||
multipleSelection?: MallCouponTemplateApi.CouponTemplate[];
|
|
||||||
takeType: number; // 领取方式
|
|
||||||
}>();
|
|
||||||
const emit = defineEmits<{
|
|
||||||
(
|
|
||||||
e: 'update:multipleSelection',
|
|
||||||
v: MallCouponTemplateApi.CouponTemplate[],
|
|
||||||
): void;
|
|
||||||
(e: 'change', v: MallCouponTemplateApi.CouponTemplate[]): void;
|
|
||||||
}>();
|
|
||||||
const dialogVisible = ref(false); // 弹窗的是否展示
|
|
||||||
const dialogTitle = ref('选择优惠劵'); // 弹窗的标题
|
|
||||||
const formLoading = ref(false); // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
|
|
||||||
const loading = ref(true); // 列表的加载中
|
|
||||||
const total = ref(0); // 列表的总页数
|
|
||||||
const list = ref<MallCouponTemplateApi.CouponTemplate[]>([]); // 字典表格数据
|
|
||||||
const queryParams = reactive({
|
|
||||||
pageNo: 1,
|
|
||||||
pageSize: 10,
|
|
||||||
name: null,
|
|
||||||
discountType: null,
|
|
||||||
canTakeTypes: [CouponTemplateTakeTypeEnum.USER.type], // 只获得直接领取的券
|
|
||||||
});
|
|
||||||
const queryFormRef = ref(); // 搜索的表单
|
|
||||||
const selectedCouponList = ref<MallCouponTemplateApi.CouponTemplate[]>([]); // 选择的数据
|
|
||||||
|
|
||||||
/** 查询列表 */
|
|
||||||
const getList = async () => {
|
|
||||||
loading.value = true;
|
|
||||||
try {
|
|
||||||
// 执行查询
|
|
||||||
queryParams.canTakeTypes = [props.takeType] as any;
|
|
||||||
const data = await CouponTemplateApi.getCouponTemplatePage(queryParams);
|
|
||||||
list.value = data.list;
|
|
||||||
total.value = data.total;
|
|
||||||
} finally {
|
|
||||||
loading.value = false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/** 搜索按钮操作 */
|
|
||||||
const handleQuery = () => {
|
|
||||||
queryParams.pageNo = 1;
|
|
||||||
getList();
|
|
||||||
};
|
|
||||||
|
|
||||||
/** 重置按钮操作 */
|
|
||||||
const resetQuery = () => {
|
|
||||||
queryFormRef?.value?.resetFields();
|
|
||||||
handleQuery();
|
|
||||||
};
|
|
||||||
|
|
||||||
/** 打开弹窗 */
|
|
||||||
const open = async () => {
|
|
||||||
dialogVisible.value = true;
|
|
||||||
resetQuery();
|
|
||||||
};
|
|
||||||
defineExpose({ open }); // 提供 open 方法,用于打开弹窗
|
|
||||||
|
|
||||||
const handleSelectionChange = (val: MallCouponTemplateApi.CouponTemplate[]) => {
|
|
||||||
if (props.multipleSelection) {
|
|
||||||
emit('update:multipleSelection', val);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
selectedCouponList.value = val;
|
|
||||||
};
|
|
||||||
|
|
||||||
const submitForm = () => {
|
|
||||||
dialogVisible.value = false;
|
|
||||||
emit('change', selectedCouponList.value);
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
<template>
|
|
||||||
<Dialog v-model="dialogVisible" :title="dialogTitle" width="65%">
|
|
||||||
<!-- 搜索工作栏 -->
|
|
||||||
<ContentWrap>
|
|
||||||
<el-form
|
|
||||||
ref="queryFormRef"
|
|
||||||
:inline="true"
|
|
||||||
:model="queryParams"
|
|
||||||
class="-mb-15px"
|
|
||||||
label-width="82px"
|
|
||||||
>
|
|
||||||
<el-form-item label="优惠券名称" prop="name">
|
|
||||||
<el-input
|
|
||||||
v-model="queryParams.name"
|
|
||||||
class="!w-240px"
|
|
||||||
clearable
|
|
||||||
placeholder="请输入优惠劵名"
|
|
||||||
@keyup="handleQuery"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="优惠类型" prop="discountType">
|
|
||||||
<el-select
|
|
||||||
v-model="queryParams.discountType"
|
|
||||||
class="!w-240px"
|
|
||||||
clearable
|
|
||||||
placeholder="请选择优惠券类型"
|
|
||||||
>
|
|
||||||
<el-option
|
|
||||||
v-for="dict in getDictOptions(
|
|
||||||
DICT_TYPE.PROMOTION_DISCOUNT_TYPE,
|
|
||||||
'number',
|
|
||||||
)"
|
|
||||||
:key="dict.value"
|
|
||||||
:label="dict.label"
|
|
||||||
:value="dict.value"
|
|
||||||
/>
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item>
|
|
||||||
<el-button @click="handleQuery">
|
|
||||||
<IconifyIcon class="mr-5px" icon="ep:search" />
|
|
||||||
搜索
|
|
||||||
</el-button>
|
|
||||||
<el-button @click="resetQuery">
|
|
||||||
<IconifyIcon class="mr-5px" icon="ep:refresh" />
|
|
||||||
重置
|
|
||||||
</el-button>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
</ContentWrap>
|
|
||||||
|
|
||||||
<!-- 列表 -->
|
|
||||||
<ContentWrap>
|
|
||||||
<el-table
|
|
||||||
v-loading="loading"
|
|
||||||
:data="list"
|
|
||||||
@selection-change="handleSelectionChange"
|
|
||||||
>
|
|
||||||
<el-table-column type="selection" width="55" />
|
|
||||||
<el-table-column label="优惠券名称" min-width="140" prop="name" />
|
|
||||||
<el-table-column label="类型" min-width="80" prop="productScope">
|
|
||||||
<template #default="scope">
|
|
||||||
<dict-tag
|
|
||||||
:type="DICT_TYPE.PROMOTION_PRODUCT_SCOPE"
|
|
||||||
:value="scope.row.productScope"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="优惠" min-width="100" prop="discount">
|
|
||||||
<template #default="scope">
|
|
||||||
<dict-tag
|
|
||||||
:type="DICT_TYPE.PROMOTION_DISCOUNT_TYPE"
|
|
||||||
:value="scope.row.discountType"
|
|
||||||
/>
|
|
||||||
{{ discountFormat(scope.row) }}
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="领取方式" min-width="100" prop="takeType">
|
|
||||||
<template #default="scope">
|
|
||||||
<dict-tag
|
|
||||||
:type="DICT_TYPE.PROMOTION_COUPON_TAKE_TYPE"
|
|
||||||
:value="scope.row.takeType"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column
|
|
||||||
:formatter="validityTypeFormat"
|
|
||||||
align="center"
|
|
||||||
label="使用时间"
|
|
||||||
prop="validityType"
|
|
||||||
width="185"
|
|
||||||
/>
|
|
||||||
<el-table-column align="center" label="发放数量" prop="totalCount" />
|
|
||||||
<el-table-column
|
|
||||||
:formatter="remainedCountFormat"
|
|
||||||
align="center"
|
|
||||||
label="剩余数量"
|
|
||||||
prop="totalCount"
|
|
||||||
/>
|
|
||||||
<el-table-column
|
|
||||||
:formatter="takeLimitCountFormat"
|
|
||||||
align="center"
|
|
||||||
label="领取上限"
|
|
||||||
prop="takeLimitCount"
|
|
||||||
/>
|
|
||||||
<el-table-column align="center" label="状态" prop="status">
|
|
||||||
<template #default="scope">
|
|
||||||
<dict-tag
|
|
||||||
:type="DICT_TYPE.COMMON_STATUS"
|
|
||||||
:value="scope.row.status"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
</el-table>
|
|
||||||
<!-- 分页 -->
|
|
||||||
<Pagination
|
|
||||||
v-model:limit="queryParams.pageSize"
|
|
||||||
v-model:page="queryParams.pageNo"
|
|
||||||
:total="total"
|
|
||||||
@pagination="getList"
|
|
||||||
/>
|
|
||||||
</ContentWrap>
|
|
||||||
<template #footer>
|
|
||||||
<el-button :disabled="formLoading" type="primary" @click="submitForm">
|
|
||||||
确 定
|
|
||||||
</el-button>
|
|
||||||
<el-button @click="dialogVisible = false">取 消</el-button>
|
|
||||||
</template>
|
|
||||||
</Dialog>
|
|
||||||
</template>
|
|
||||||
@@ -1,11 +1,17 @@
|
|||||||
import type { VbenFormSchema } from '#/adapter/form';
|
import type { VbenFormSchema } from '#/adapter/form';
|
||||||
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
|
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
|
||||||
|
import type { MallCouponTemplateApi } from '#/api/mall/promotion/coupon/couponTemplate';
|
||||||
|
|
||||||
import { CommonStatusEnum, DICT_TYPE } from '@vben/constants';
|
import {
|
||||||
|
CommonStatusEnum,
|
||||||
|
CouponTemplateTakeTypeEnum,
|
||||||
|
CouponTemplateValidityTypeEnum,
|
||||||
|
DICT_TYPE,
|
||||||
|
PromotionDiscountTypeEnum,
|
||||||
|
PromotionProductScopeEnum,
|
||||||
|
} from '@vben/constants';
|
||||||
import { getDictOptions } from '@vben/hooks';
|
import { getDictOptions } from '@vben/hooks';
|
||||||
|
|
||||||
// 格式化函数移到组件内部实现
|
|
||||||
import { z } from '#/adapter/form';
|
|
||||||
import { getRangePickerDefaultProps } from '#/utils';
|
import { getRangePickerDefaultProps } from '#/utils';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@@ -40,69 +46,289 @@ export function useFormSchema(): VbenFormSchema[] {
|
|||||||
fieldName: 'description',
|
fieldName: 'description',
|
||||||
label: '优惠券描述',
|
label: '优惠券描述',
|
||||||
component: 'Textarea',
|
component: 'Textarea',
|
||||||
|
componentProps: {
|
||||||
|
placeholder: '请输入优惠券描述',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
// TODO @霖:不同的优惠,不同的选择
|
|
||||||
{
|
{
|
||||||
fieldName: 'productScope',
|
fieldName: 'productScope',
|
||||||
label: '优惠类型',
|
label: '优惠劵类型',
|
||||||
component: 'RadioGroup',
|
component: 'RadioGroup',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
options: getDictOptions(DICT_TYPE.PROMOTION_PRODUCT_SCOPE, 'number'),
|
options: getDictOptions(DICT_TYPE.PROMOTION_PRODUCT_SCOPE, 'number'),
|
||||||
},
|
},
|
||||||
rules: 'required',
|
rules: 'required',
|
||||||
|
defaultValue: PromotionProductScopeEnum.ALL.scope,
|
||||||
|
},
|
||||||
|
// TODO @puhui999: 商品选择器优化
|
||||||
|
{
|
||||||
|
fieldName: 'productSpuIds',
|
||||||
|
label: '商品',
|
||||||
|
component: 'Input',
|
||||||
|
componentProps: {
|
||||||
|
placeholder: '请选择商品',
|
||||||
|
},
|
||||||
|
dependencies: {
|
||||||
|
triggerFields: ['productScope', 'productScopeValues'],
|
||||||
|
show: (model) =>
|
||||||
|
model.productScope === PromotionProductScopeEnum.SPU.scope,
|
||||||
|
trigger(values, form) {
|
||||||
|
// 当加载已有数据时,根据 productScopeValues 设置 productSpuIds
|
||||||
|
if (
|
||||||
|
values.productScope === PromotionProductScopeEnum.SPU.scope &&
|
||||||
|
values.productScopeValues
|
||||||
|
) {
|
||||||
|
form.setFieldValue('productSpuIds', values.productScopeValues);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
rules: 'required',
|
||||||
|
},
|
||||||
|
// TODO @puhui999: 商品分类选择器优化
|
||||||
|
{
|
||||||
|
fieldName: 'productCategoryIds',
|
||||||
|
label: '商品分类',
|
||||||
|
component: 'Input',
|
||||||
|
componentProps: {
|
||||||
|
placeholder: '请选择商品分类',
|
||||||
|
},
|
||||||
|
dependencies: {
|
||||||
|
triggerFields: ['productScope', 'productScopeValues'],
|
||||||
|
show: (model) =>
|
||||||
|
model.productScope === PromotionProductScopeEnum.CATEGORY.scope,
|
||||||
|
trigger(values, form) {
|
||||||
|
// 当加载已有数据时,根据 productScopeValues 设置 productCategoryIds
|
||||||
|
if (
|
||||||
|
values.productScope === PromotionProductScopeEnum.CATEGORY.scope &&
|
||||||
|
values.productScopeValues
|
||||||
|
) {
|
||||||
|
const categoryIds = values.productScopeValues;
|
||||||
|
// 单选时使用数组不能反显,取第一个元素
|
||||||
|
form.setFieldValue(
|
||||||
|
'productCategoryIds',
|
||||||
|
Array.isArray(categoryIds) && categoryIds.length > 0
|
||||||
|
? categoryIds[0]
|
||||||
|
: categoryIds,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
rules: 'required',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'discountType',
|
||||||
|
label: '优惠类型',
|
||||||
|
component: 'RadioGroup',
|
||||||
|
componentProps: {
|
||||||
|
options: getDictOptions(DICT_TYPE.PROMOTION_DISCOUNT_TYPE, 'number'),
|
||||||
|
},
|
||||||
|
rules: 'required',
|
||||||
|
defaultValue: PromotionDiscountTypeEnum.PRICE.type,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'discountPrice',
|
||||||
|
label: '优惠券面额',
|
||||||
|
component: 'InputNumber',
|
||||||
|
componentProps: {
|
||||||
|
min: 0,
|
||||||
|
precision: 2,
|
||||||
|
placeholder: '请输入优惠金额,单位:元',
|
||||||
|
addonAfter: '元',
|
||||||
|
controlsPosition: 'right',
|
||||||
|
class: '!w-full',
|
||||||
|
},
|
||||||
|
dependencies: {
|
||||||
|
triggerFields: ['discountType'],
|
||||||
|
show: (model) =>
|
||||||
|
model.discountType === PromotionDiscountTypeEnum.PRICE.type,
|
||||||
|
},
|
||||||
|
rules: 'required',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'discountPercent',
|
||||||
|
label: '优惠券折扣',
|
||||||
|
component: 'InputNumber',
|
||||||
|
componentProps: {
|
||||||
|
min: 1,
|
||||||
|
max: 9.9,
|
||||||
|
precision: 1,
|
||||||
|
placeholder: '优惠券折扣不能小于 1 折,且不可大于 9.9 折',
|
||||||
|
addonAfter: '折',
|
||||||
|
controlsPosition: 'right',
|
||||||
|
class: '!w-full',
|
||||||
|
},
|
||||||
|
dependencies: {
|
||||||
|
triggerFields: ['discountType'],
|
||||||
|
show: (model) =>
|
||||||
|
model.discountType === PromotionDiscountTypeEnum.PERCENT.type,
|
||||||
|
},
|
||||||
|
rules: 'required',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'discountLimitPrice',
|
||||||
|
label: '最多优惠',
|
||||||
|
component: 'InputNumber',
|
||||||
|
componentProps: {
|
||||||
|
min: 0,
|
||||||
|
precision: 2,
|
||||||
|
placeholder: '请输入最多优惠',
|
||||||
|
addonAfter: '元',
|
||||||
|
controlsPosition: 'right',
|
||||||
|
class: '!w-full',
|
||||||
|
},
|
||||||
|
dependencies: {
|
||||||
|
triggerFields: ['discountType'],
|
||||||
|
show: (model) =>
|
||||||
|
model.discountType === PromotionDiscountTypeEnum.PERCENT.type,
|
||||||
|
},
|
||||||
|
rules: 'required',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'usePrice',
|
||||||
|
label: '满多少元可以使用',
|
||||||
|
component: 'InputNumber',
|
||||||
|
componentProps: {
|
||||||
|
min: 0,
|
||||||
|
precision: 2,
|
||||||
|
placeholder: '无门槛请设为 0',
|
||||||
|
addonAfter: '元',
|
||||||
|
controlsPosition: 'right',
|
||||||
|
class: '!w-full',
|
||||||
|
},
|
||||||
|
rules: 'required',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
fieldName: 'takeType',
|
fieldName: 'takeType',
|
||||||
label: '领取方式',
|
label: '领取方式',
|
||||||
component: 'Select',
|
component: 'RadioGroup',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
placeholder: '请选择领取方式',
|
|
||||||
options: getDictOptions(DICT_TYPE.PROMOTION_COUPON_TAKE_TYPE, 'number'),
|
options: getDictOptions(DICT_TYPE.PROMOTION_COUPON_TAKE_TYPE, 'number'),
|
||||||
},
|
},
|
||||||
rules: 'required',
|
rules: 'required',
|
||||||
},
|
defaultValue: CouponTemplateTakeTypeEnum.USER.type,
|
||||||
// TODO @xingu:不同的有效期,不同的类型
|
|
||||||
{
|
|
||||||
fieldName: 'validityType',
|
|
||||||
label: '有效期类型',
|
|
||||||
component: 'Select',
|
|
||||||
componentProps: {
|
|
||||||
placeholder: '请选择有效期类型',
|
|
||||||
options: getDictOptions(
|
|
||||||
DICT_TYPE.PROMOTION_COUPON_TEMPLATE_VALIDITY_TYPE,
|
|
||||||
'number',
|
|
||||||
),
|
|
||||||
},
|
|
||||||
rules: 'required',
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
fieldName: 'totalCount',
|
fieldName: 'totalCount',
|
||||||
label: '发放数量',
|
label: '发放数量',
|
||||||
component: 'InputNumber',
|
component: 'InputNumber',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
min: 0,
|
min: -1,
|
||||||
placeholder: '请输入发放数量',
|
placeholder: '发放数量,没有之后不能领取或发放,-1 为不限制',
|
||||||
|
addonAfter: '张',
|
||||||
|
controlsPosition: 'right',
|
||||||
|
class: '!w-full',
|
||||||
|
},
|
||||||
|
dependencies: {
|
||||||
|
triggerFields: ['takeType'],
|
||||||
|
show: (model) =>
|
||||||
|
model.takeType === CouponTemplateTakeTypeEnum.USER.type,
|
||||||
},
|
},
|
||||||
rules: 'required',
|
rules: 'required',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
fieldName: 'takeLimitCount',
|
fieldName: 'takeLimitCount',
|
||||||
label: '领取上限',
|
label: '每人限领个数',
|
||||||
component: 'InputNumber',
|
component: 'InputNumber',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
min: 0,
|
min: -1,
|
||||||
placeholder: '请输入领取上限',
|
placeholder: '设置为 -1 时,可无限领取',
|
||||||
|
addonAfter: '张',
|
||||||
|
controlsPosition: 'right',
|
||||||
|
class: '!w-full',
|
||||||
|
},
|
||||||
|
dependencies: {
|
||||||
|
triggerFields: ['takeType'],
|
||||||
|
show: (model) => model.takeType === 1,
|
||||||
},
|
},
|
||||||
rules: 'required',
|
rules: 'required',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
fieldName: 'status',
|
fieldName: 'validityType',
|
||||||
label: '优惠券状态',
|
label: '有效期类型',
|
||||||
component: 'RadioGroup',
|
component: 'RadioGroup',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'),
|
options: getDictOptions(
|
||||||
|
DICT_TYPE.PROMOTION_COUPON_TEMPLATE_VALIDITY_TYPE,
|
||||||
|
'number',
|
||||||
|
),
|
||||||
|
},
|
||||||
|
defaultValue: CouponTemplateValidityTypeEnum.DATE.type,
|
||||||
|
rules: 'required',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'validTimes',
|
||||||
|
label: '固定日期',
|
||||||
|
component: 'RangePicker',
|
||||||
|
componentProps: {
|
||||||
|
...getRangePickerDefaultProps(),
|
||||||
|
valueFormat: 'x',
|
||||||
|
},
|
||||||
|
dependencies: {
|
||||||
|
triggerFields: ['validityType'],
|
||||||
|
show: (model) =>
|
||||||
|
model.validityType === CouponTemplateValidityTypeEnum.DATE.type,
|
||||||
|
},
|
||||||
|
rules: 'required',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'fixedStartTerm',
|
||||||
|
label: '领取日期',
|
||||||
|
component: 'InputNumber',
|
||||||
|
componentProps: {
|
||||||
|
min: 0,
|
||||||
|
placeholder: '第 0 为今天生效',
|
||||||
|
addonBefore: '第',
|
||||||
|
addonAfter: '天',
|
||||||
|
controlsPosition: 'right',
|
||||||
|
class: '!w-full',
|
||||||
|
},
|
||||||
|
dependencies: {
|
||||||
|
triggerFields: ['validityType'],
|
||||||
|
show: (model) =>
|
||||||
|
model.validityType === CouponTemplateValidityTypeEnum.TERM.type,
|
||||||
|
},
|
||||||
|
rules: 'required',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'fixedEndTerm',
|
||||||
|
component: 'InputNumber',
|
||||||
|
componentProps: {
|
||||||
|
min: 0,
|
||||||
|
placeholder: '请输入结束天数',
|
||||||
|
addonBefore: '至',
|
||||||
|
addonAfter: '天有效',
|
||||||
|
controlsPosition: 'right',
|
||||||
|
class: '!w-full',
|
||||||
|
},
|
||||||
|
dependencies: {
|
||||||
|
triggerFields: ['validityType'],
|
||||||
|
show: (model) =>
|
||||||
|
model.validityType === CouponTemplateValidityTypeEnum.TERM.type,
|
||||||
|
},
|
||||||
|
rules: 'required',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'productScopeValues',
|
||||||
|
component: 'Input',
|
||||||
|
dependencies: {
|
||||||
|
triggerFields: ['productScope', 'productSpuIds', 'productCategoryIds'],
|
||||||
|
show: () => false,
|
||||||
|
trigger(values, form) {
|
||||||
|
switch (values.productScope) {
|
||||||
|
case PromotionProductScopeEnum.CATEGORY.scope: {
|
||||||
|
const categoryIds = Array.isArray(values.productCategoryIds)
|
||||||
|
? values.productCategoryIds
|
||||||
|
: [values.productCategoryIds];
|
||||||
|
form.setFieldValue('productScopeValues', categoryIds);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case PromotionProductScopeEnum.SPU.scope: {
|
||||||
|
form.setFieldValue('productScopeValues', values.productSpuIds);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
},
|
},
|
||||||
rules: z.number().default(CommonStatusEnum.ENABLE),
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@@ -115,7 +341,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
|
|||||||
label: '优惠券名称',
|
label: '优惠券名称',
|
||||||
component: 'Input',
|
component: 'Input',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
placeholder: '请输入优惠券名称',
|
placeholder: '请输入优惠劵名',
|
||||||
clearable: true,
|
clearable: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -152,9 +378,13 @@ export function useGridFormSchema(): VbenFormSchema[] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** 列表的字段 */
|
/** 列表的字段 */
|
||||||
export function useGridColumns(): VxeTableGridOptions['columns'] {
|
export function useGridColumns(
|
||||||
|
onStatusChange?: (
|
||||||
|
newStatus: number,
|
||||||
|
row: MallCouponTemplateApi.CouponTemplate,
|
||||||
|
) => PromiseLike<boolean | undefined>,
|
||||||
|
): VxeTableGridOptions['columns'] {
|
||||||
return [
|
return [
|
||||||
{ type: 'checkbox', width: 40 },
|
|
||||||
{
|
{
|
||||||
field: 'name',
|
field: 'name',
|
||||||
title: '优惠券名称',
|
title: '优惠券名称',
|
||||||
@@ -231,7 +461,15 @@ export function useGridColumns(): VxeTableGridOptions['columns'] {
|
|||||||
field: 'status',
|
field: 'status',
|
||||||
title: '状态',
|
title: '状态',
|
||||||
minWidth: 100,
|
minWidth: 100,
|
||||||
slots: { default: 'status' },
|
align: 'center',
|
||||||
|
cellRender: {
|
||||||
|
attrs: { beforeChange: onStatusChange },
|
||||||
|
name: 'CellSwitch',
|
||||||
|
props: {
|
||||||
|
activeValue: CommonStatusEnum.ENABLE,
|
||||||
|
inactiveValue: CommonStatusEnum.DISABLE,
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'createTime',
|
field: 'createTime',
|
||||||
|
|||||||
@@ -2,13 +2,11 @@
|
|||||||
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
|
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
|
||||||
import type { MallCouponTemplateApi } from '#/api/mall/promotion/coupon/couponTemplate';
|
import type { MallCouponTemplateApi } from '#/api/mall/promotion/coupon/couponTemplate';
|
||||||
|
|
||||||
import { ref } from 'vue';
|
import { confirm, DocAlert, Page, useVbenModal } from '@vben/common-ui';
|
||||||
|
|
||||||
import { DocAlert, Page, useVbenModal } from '@vben/common-ui';
|
|
||||||
import { CommonStatusEnum } from '@vben/constants';
|
import { CommonStatusEnum } from '@vben/constants';
|
||||||
import { $t } from '@vben/locales';
|
import { $t } from '@vben/locales';
|
||||||
|
|
||||||
import { ElLoading, ElMessage, ElSwitch } from 'element-plus';
|
import { ElLoading, ElMessage } from 'element-plus';
|
||||||
|
|
||||||
import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
|
import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||||
import {
|
import {
|
||||||
@@ -48,7 +46,7 @@ async function handleDelete(row: MallCouponTemplateApi.CouponTemplate) {
|
|||||||
text: $t('ui.actionMessage.deleting', [row.name]),
|
text: $t('ui.actionMessage.deleting', [row.name]),
|
||||||
});
|
});
|
||||||
try {
|
try {
|
||||||
await deleteCouponTemplate(row.id as number);
|
await deleteCouponTemplate(row.id!);
|
||||||
ElMessage.success($t('ui.actionMessage.deleteSuccess', [row.name]));
|
ElMessage.success($t('ui.actionMessage.deleteSuccess', [row.name]));
|
||||||
handleRefresh();
|
handleRefresh();
|
||||||
} finally {
|
} finally {
|
||||||
@@ -56,33 +54,30 @@ async function handleDelete(row: MallCouponTemplateApi.CouponTemplate) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const checkedIds = ref<number[]>([]);
|
|
||||||
function handleRowCheckboxChange({
|
|
||||||
records,
|
|
||||||
}: {
|
|
||||||
records: MallCouponTemplateApi.CouponTemplate[];
|
|
||||||
}) {
|
|
||||||
checkedIds.value = records.map((item) => item.id!);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 优惠券模板状态修改 */
|
/** 优惠券模板状态修改 */
|
||||||
async function handleStatusChange(row: MallCouponTemplateApi.CouponTemplate) {
|
async function handleStatusChange(
|
||||||
const text = row.status === CommonStatusEnum.ENABLE ? '启用' : '停用';
|
newStatus: number,
|
||||||
const loadingInstance = ElLoading.service({
|
row: MallCouponTemplateApi.CouponTemplate,
|
||||||
text: `正在${text}优惠券模板...`,
|
): Promise<boolean | undefined> {
|
||||||
});
|
return new Promise((resolve, reject) => {
|
||||||
try {
|
confirm({
|
||||||
await updateCouponTemplateStatus(row.id as number, row.status as 0 | 1);
|
content: `你要将${row.name}的状态切换为【${newStatus === CommonStatusEnum.ENABLE ? '启用' : '停用'}】吗?`,
|
||||||
ElMessage.success(`${text}成功`);
|
})
|
||||||
} catch {
|
.then(async () => {
|
||||||
// 异常时,需要将 row.status 状态重置回之前的
|
// 更新优惠券模板状态
|
||||||
row.status =
|
const res = await updateCouponTemplateStatus(row.id!, newStatus);
|
||||||
row.status === CommonStatusEnum.ENABLE
|
if (res) {
|
||||||
? CommonStatusEnum.DISABLE
|
// 提示并返回成功
|
||||||
: CommonStatusEnum.ENABLE;
|
ElMessage.success($t('ui.actionMessage.operationSuccess'));
|
||||||
} finally {
|
resolve(true);
|
||||||
loadingInstance.close();
|
} else {
|
||||||
|
reject(new Error('更新失败'));
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
reject(new Error('取消操作'));
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const [Grid, gridApi] = useVbenVxeGrid({
|
const [Grid, gridApi] = useVbenVxeGrid({
|
||||||
@@ -90,7 +85,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
|
|||||||
schema: useGridFormSchema(),
|
schema: useGridFormSchema(),
|
||||||
},
|
},
|
||||||
gridOptions: {
|
gridOptions: {
|
||||||
columns: useGridColumns(),
|
columns: useGridColumns(handleStatusChange),
|
||||||
height: 'auto',
|
height: 'auto',
|
||||||
keepSource: true,
|
keepSource: true,
|
||||||
proxyConfig: {
|
proxyConfig: {
|
||||||
@@ -113,10 +108,6 @@ const [Grid, gridApi] = useVbenVxeGrid({
|
|||||||
search: true,
|
search: true,
|
||||||
},
|
},
|
||||||
} as VxeTableGridOptions<MallCouponTemplateApi.CouponTemplate>,
|
} as VxeTableGridOptions<MallCouponTemplateApi.CouponTemplate>,
|
||||||
gridEvents: {
|
|
||||||
checkboxAll: handleRowCheckboxChange,
|
|
||||||
checkboxChange: handleRowCheckboxChange,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -144,15 +135,6 @@ const [Grid, gridApi] = useVbenVxeGrid({
|
|||||||
]"
|
]"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template #status="{ row }">
|
|
||||||
<ElSwitch
|
|
||||||
v-model:checked="row.status"
|
|
||||||
:checked-value="CommonStatusEnum.ENABLE"
|
|
||||||
:un-checked-value="CommonStatusEnum.DISABLE"
|
|
||||||
@change="handleStatusChange(row)"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<template #actions="{ row }">
|
<template #actions="{ row }">
|
||||||
<TableAction
|
<TableAction
|
||||||
:actions="[
|
:actions="[
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ import type { MallCouponTemplateApi } from '#/api/mall/promotion/coupon/couponTe
|
|||||||
import { computed, ref } from 'vue';
|
import { computed, ref } from 'vue';
|
||||||
|
|
||||||
import { useVbenModal } from '@vben/common-ui';
|
import { useVbenModal } from '@vben/common-ui';
|
||||||
|
import { CouponTemplateTakeTypeEnum } from '@vben/constants';
|
||||||
|
import { convertToInteger, formatToFraction } from '@vben/utils';
|
||||||
|
|
||||||
import { ElMessage } from 'element-plus';
|
import { ElMessage } from 'element-plus';
|
||||||
|
|
||||||
@@ -31,7 +33,7 @@ const [Form, formApi] = useVbenForm({
|
|||||||
class: 'w-full',
|
class: 'w-full',
|
||||||
},
|
},
|
||||||
formItemClass: 'col-span-2',
|
formItemClass: 'col-span-2',
|
||||||
labelWidth: 80,
|
labelWidth: 120,
|
||||||
},
|
},
|
||||||
layout: 'horizontal',
|
layout: 'horizontal',
|
||||||
schema: useFormSchema(),
|
schema: useFormSchema(),
|
||||||
@@ -46,8 +48,8 @@ const [Modal, modalApi] = useVbenModal({
|
|||||||
}
|
}
|
||||||
modalApi.lock();
|
modalApi.lock();
|
||||||
// 提交表单
|
// 提交表单
|
||||||
const data =
|
const formValues = (await formApi.getValues()) as any;
|
||||||
(await formApi.getValues()) as MallCouponTemplateApi.CouponTemplate;
|
const data = await processSubmitData(formValues);
|
||||||
try {
|
try {
|
||||||
await (formData.value?.id
|
await (formData.value?.id
|
||||||
? updateCouponTemplate(data)
|
? updateCouponTemplate(data)
|
||||||
@@ -73,17 +75,75 @@ const [Modal, modalApi] = useVbenModal({
|
|||||||
modalApi.lock();
|
modalApi.lock();
|
||||||
try {
|
try {
|
||||||
formData.value = await getCouponTemplate(data.id);
|
formData.value = await getCouponTemplate(data.id);
|
||||||
// 设置到 values
|
const processedData = await processLoadData(formData.value);
|
||||||
await formApi.setValues(formData.value);
|
// 设置到表单
|
||||||
|
await formApi.setValues(processedData);
|
||||||
} finally {
|
} finally {
|
||||||
modalApi.unlock();
|
modalApi.unlock();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/** 处理提交数据 */
|
||||||
|
async function processSubmitData(
|
||||||
|
formValues: any,
|
||||||
|
): Promise<MallCouponTemplateApi.CouponTemplate> {
|
||||||
|
return {
|
||||||
|
...formValues,
|
||||||
|
// 金额转换:元转分
|
||||||
|
discountPrice: convertToInteger(formValues.discountPrice),
|
||||||
|
discountPercent:
|
||||||
|
formValues.discountPercent === undefined
|
||||||
|
? undefined
|
||||||
|
: formValues.discountPercent * 10,
|
||||||
|
discountLimitPrice: convertToInteger(formValues.discountLimitPrice),
|
||||||
|
usePrice: convertToInteger(formValues.usePrice),
|
||||||
|
// 处理有效期时间
|
||||||
|
validStartTime:
|
||||||
|
formValues.validTimes && formValues.validTimes.length === 2
|
||||||
|
? formValues.validTimes[0]
|
||||||
|
: undefined,
|
||||||
|
validEndTime:
|
||||||
|
formValues.validTimes && formValues.validTimes.length === 2
|
||||||
|
? formValues.validTimes[1]
|
||||||
|
: undefined,
|
||||||
|
// 处理发放数量和限领数量
|
||||||
|
totalCount:
|
||||||
|
formValues.takeType === CouponTemplateTakeTypeEnum.USER.type
|
||||||
|
? formValues.totalCount
|
||||||
|
: -1,
|
||||||
|
takeLimitCount:
|
||||||
|
formValues.takeType === CouponTemplateTakeTypeEnum.USER.type
|
||||||
|
? formValues.takeLimitCount
|
||||||
|
: -1,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 处理加载的数据 */
|
||||||
|
async function processLoadData(
|
||||||
|
data: MallCouponTemplateApi.CouponTemplate,
|
||||||
|
): Promise<any> {
|
||||||
|
return {
|
||||||
|
...data,
|
||||||
|
// 金额转换:分转元
|
||||||
|
discountPrice: formatToFraction(data.discountPrice),
|
||||||
|
discountPercent:
|
||||||
|
data.discountPercent === undefined
|
||||||
|
? undefined
|
||||||
|
: data.discountPercent / 10,
|
||||||
|
discountLimitPrice: formatToFraction(data.discountLimitPrice),
|
||||||
|
usePrice: formatToFraction(data.usePrice),
|
||||||
|
// 处理有效期时间
|
||||||
|
validTimes:
|
||||||
|
data.validStartTime && data.validEndTime
|
||||||
|
? [data.validStartTime, data.validEndTime]
|
||||||
|
: [],
|
||||||
|
};
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Modal class="w-2/5" :title="getTitle">
|
<Modal :title="getTitle" class="w-2/5">
|
||||||
<Form class="mx-4" />
|
<Form class="mx-4" />
|
||||||
</Modal>
|
</Modal>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
Reference in New Issue
Block a user