diff --git a/apps/web-antd/src/views/mall/promotion/coupon/data.ts b/apps/web-antd/src/views/mall/promotion/coupon/data.ts new file mode 100644 index 000000000..a8efb9f5e --- /dev/null +++ b/apps/web-antd/src/views/mall/promotion/coupon/data.ts @@ -0,0 +1,129 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { DICT_TYPE, getDictOptions, getRangePickerDefaultProps } from '#/utils'; + +import { discountFormat } from './formatter'; + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'nickname', + label: '会员昵称', + component: 'Input', + componentProps: { + placeholder: '请输入会员昵称', + clearable: true, + }, + }, + { + fieldName: 'createTime', + label: '领取时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + clearable: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'nickname', + title: '会员昵称', + minWidth: 100, + }, + { + field: 'name', + title: '优惠券名称', + minWidth: 140, + }, + { + field: 'productScope', + title: '类型', + minWidth: 110, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.PROMOTION_PRODUCT_SCOPE }, + }, + }, + { + field: 'discountType', + title: '优惠', + minWidth: 110, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.PROMOTION_DISCOUNT_TYPE }, + }, + }, + { + field: 'discountPrice', + title: '优惠力度', + minWidth: 110, + formatter: ({ row }) => { + return discountFormat(row); + }, + }, + { + field: 'takeType', + title: '领取方式', + minWidth: 110, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.PROMOTION_COUPON_TAKE_TYPE }, + }, + }, + { + field: 'status', + title: '状态', + minWidth: 110, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.PROMOTION_COUPON_STATUS }, + }, + }, + { + field: 'createTime', + title: '领取时间', + width: 180, + formatter: 'formatDateTime', + }, + { + field: 'useTime', + title: '使用时间', + width: 180, + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 100, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} + +/** 获取状态选项卡配置 */ +export function getStatusTabs() { + const tabs = [ + { + label: '全部', + value: 'all', + }, + ]; + + // 添加字典状态选项 + const statusOptions = getDictOptions(DICT_TYPE.PROMOTION_COUPON_STATUS); + for (const option of statusOptions) { + tabs.push({ + label: option.label, + value: String(option.value), + }); + } + + return tabs; +} diff --git a/apps/web-antd/src/views/mall/promotion/coupon/formatter.ts b/apps/web-antd/src/views/mall/promotion/coupon/formatter.ts new file mode 100644 index 000000000..9dfbac415 --- /dev/null +++ b/apps/web-antd/src/views/mall/promotion/coupon/formatter.ts @@ -0,0 +1,65 @@ +import type { MallCouponTemplateApi } from '#/api/mall/promotion/coupon/couponTemplate'; + +import { floatToFixed2, formatDate } from '@vben/utils'; + +import { + CouponTemplateValidityTypeEnum, + PromotionDiscountTypeEnum, +} from '#/utils'; + +// 格式化【优惠金额/折扣】 +export function discountFormat(row: MallCouponTemplateApi.CouponTemplate) { + if (row.discountType === PromotionDiscountTypeEnum.PRICE.type) { + return `¥${floatToFixed2(row.discountPrice)}`; + } + if (row.discountType === PromotionDiscountTypeEnum.PERCENT.type) { + return `${row.discountPercent}%`; + } + return `未知【${row.discountType}】`; +} + +// 格式化【领取上限】 +export function takeLimitCountFormat( + row: MallCouponTemplateApi.CouponTemplate, +) { + if (row.takeLimitCount) { + if (row.takeLimitCount === -1) { + return '无领取限制'; + } + return `${row.takeLimitCount} 张/人`; + } else { + return ' '; + } +} + +// 格式化【有效期限】 +export function validityTypeFormat(row: MallCouponTemplateApi.CouponTemplate) { + if (row.validityType === CouponTemplateValidityTypeEnum.DATE.type) { + return `${formatDate(row.validStartTime)} 至 ${formatDate(row.validEndTime)}`; + } + if (row.validityType === CouponTemplateValidityTypeEnum.TERM.type) { + return `领取后第 ${row.fixedStartTerm} - ${row.fixedEndTerm} 天内可用`; + } + return `未知【${row.validityType}】`; +} + +// 格式化【totalCount】 +export function totalCountFormat(row: MallCouponTemplateApi.CouponTemplate) { + if (row.totalCount === -1) { + return '不限制'; + } + return row.totalCount; +} + +// 格式化【剩余数量】 +export function remainedCountFormat(row: MallCouponTemplateApi.CouponTemplate) { + if (row.totalCount === -1) { + return '不限制'; + } + return row.totalCount - row.takeCount; +} + +// 格式化【最低消费】 +export function usePriceFormat(row: MallCouponTemplateApi.CouponTemplate) { + return `¥${floatToFixed2(row.usePrice)}`; +} diff --git a/apps/web-antd/src/views/mall/promotion/coupon/index.vue b/apps/web-antd/src/views/mall/promotion/coupon/index.vue index 90f761d43..27fbb2e38 100644 --- a/apps/web-antd/src/views/mall/promotion/coupon/index.vue +++ b/apps/web-antd/src/views/mall/promotion/coupon/index.vue @@ -1,32 +1,132 @@ diff --git a/apps/web-antd/src/views/mall/promotion/coupon/template/data.ts b/apps/web-antd/src/views/mall/promotion/coupon/template/data.ts new file mode 100644 index 000000000..08ea5b772 --- /dev/null +++ b/apps/web-antd/src/views/mall/promotion/coupon/template/data.ts @@ -0,0 +1,252 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +// 格式化函数移到组件内部实现 +import { z } from '#/adapter/form'; +import { + CommonStatusEnum, + DICT_TYPE, + getDictOptions, + getRangePickerDefaultProps, +} from '#/utils'; + +import { + discountFormat, + remainedCountFormat, + takeLimitCountFormat, + totalCountFormat, + validityTypeFormat, +} from '../formatter'; + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'id', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'name', + label: '优惠券名称', + component: 'Input', + componentProps: { + placeholder: '请输入优惠券名称', + }, + rules: 'required', + }, + { + fieldName: 'description', + label: '优惠券描述', + component: 'Textarea', + }, + // TODO + { + fieldName: 'productScope', + label: '优惠类型', + component: 'RadioGroup', + componentProps: { + options: getDictOptions(DICT_TYPE.PROMOTION_PRODUCT_SCOPE, 'number'), + }, + rules: 'required', + }, + { + fieldName: 'takeType', + label: '领取方式', + component: 'Select', + componentProps: { + placeholder: '请选择领取方式', + options: getDictOptions(DICT_TYPE.PROMOTION_COUPON_TAKE_TYPE, 'number'), + }, + rules: 'required', + }, + { + fieldName: 'validityType', + label: '有效期类型', + component: 'Select', + componentProps: { + placeholder: '请选择有效期类型', + options: getDictOptions( + DICT_TYPE.PROMOTION_COUPON_TEMPLATE_VALIDITY_TYPE, + 'number', + ), + }, + rules: 'required', + }, + { + fieldName: 'totalCount', + label: '发放数量', + component: 'InputNumber', + componentProps: { + min: 0, + placeholder: '请输入发放数量', + }, + rules: 'required', + }, + { + fieldName: 'takeLimitCount', + label: '领取上限', + component: 'InputNumber', + componentProps: { + min: 0, + placeholder: '请输入领取上限', + }, + rules: 'required', + }, + { + fieldName: 'status', + label: '优惠券状态', + component: 'RadioGroup', + componentProps: { + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + buttonStyle: 'solid', + optionType: 'button', + }, + rules: z.number().default(CommonStatusEnum.ENABLE), + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'name', + label: '优惠券名称', + component: 'Input', + componentProps: { + placeholder: '请输入优惠券名称', + clearable: true, + }, + }, + { + fieldName: 'discountType', + label: '优惠类型', + component: 'Select', + componentProps: { + placeholder: '请选择优惠类型', + clearable: true, + options: getDictOptions(DICT_TYPE.PROMOTION_DISCOUNT_TYPE, 'number'), + }, + }, + { + fieldName: 'status', + label: '优惠券状态', + component: 'Select', + componentProps: { + placeholder: '请选择优惠券状态', + clearable: true, + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + }, + }, + { + fieldName: 'createTime', + label: '创建时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + clearable: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { type: 'checkbox', width: 40 }, + { + field: 'name', + title: '优惠券名称', + minWidth: 140, + }, + { + field: 'productScope', + title: '类型', + minWidth: 130, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.PROMOTION_PRODUCT_SCOPE }, + }, + }, + { + field: 'discountType', + title: '优惠', + minWidth: 110, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.PROMOTION_DISCOUNT_TYPE }, + }, + }, + { + field: 'discountPrice', + title: '优惠力度', + minWidth: 110, + formatter: ({ row }) => { + return discountFormat(row); + }, + }, + { + field: 'takeType', + title: '领取方式', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.PROMOTION_COUPON_TAKE_TYPE }, + }, + }, + { + field: 'validityType', + title: '使用时间', + minWidth: 180, + formatter: ({ row }) => { + return validityTypeFormat(row); + }, + }, + { + field: 'totalCount', + title: '发放数量', + minWidth: 100, + formatter: ({ row }) => { + return totalCountFormat(row); + }, + }, + { + field: 'remainedCount', + title: '剩余数量', + minWidth: 100, + formatter: ({ row }) => { + return remainedCountFormat(row); + }, + }, + { + field: 'takeLimitCount', + title: '领取上限', + minWidth: 100, + formatter: ({ row }) => { + return takeLimitCountFormat(row); + }, + }, + { + field: 'status', + title: '状态', + minWidth: 100, + slots: { default: 'status' }, + }, + { + field: 'createTime', + title: '创建时间', + width: 180, + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 120, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-antd/src/views/mall/promotion/coupon/template/index.vue b/apps/web-antd/src/views/mall/promotion/coupon/template/index.vue index d5e866f89..985295643 100644 --- a/apps/web-antd/src/views/mall/promotion/coupon/template/index.vue +++ b/apps/web-antd/src/views/mall/promotion/coupon/template/index.vue @@ -1,32 +1,190 @@ diff --git a/apps/web-antd/src/views/mall/promotion/coupon/template/modules/form.vue b/apps/web-antd/src/views/mall/promotion/coupon/template/modules/form.vue new file mode 100644 index 000000000..f64360980 --- /dev/null +++ b/apps/web-antd/src/views/mall/promotion/coupon/template/modules/form.vue @@ -0,0 +1,89 @@ + + +