From beef6a0a9478dd43c2c91d537097c169e3c156c7 Mon Sep 17 00:00:00 2001 From: owen Date: Sat, 26 Aug 2023 22:29:55 +0800 Subject: [PATCH 01/15] =?UTF-8?q?mall:=20=E5=AE=8C=E5=96=84=E5=90=8E?= =?UTF-8?q?=E5=8F=B0=E5=8F=91=E9=80=81=E4=BC=98=E6=83=A0=E5=88=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/mall/promotion/coupon/coupon.ts | 8 + .../mall/promotion/coupon/couponTemplate.ts | 8 + .../coupon/components/CouponSend.vue | 162 ++++++++++++++++++ src/views/mall/promotion/coupon/formatter.ts | 44 +++++ .../mall/promotion/coupon/template/index.vue | 47 ++--- src/views/member/user/index.vue | 32 +++- 6 files changed, 263 insertions(+), 38 deletions(-) create mode 100644 src/views/mall/promotion/coupon/components/CouponSend.vue create mode 100644 src/views/mall/promotion/coupon/formatter.ts diff --git a/src/api/mall/promotion/coupon/coupon.ts b/src/api/mall/promotion/coupon/coupon.ts index 565b86f7f..2ebff5dad 100755 --- a/src/api/mall/promotion/coupon/coupon.ts +++ b/src/api/mall/promotion/coupon/coupon.ts @@ -16,3 +16,11 @@ export const getCouponPage = async (params: PageParam) => { params: params }) } + +// 发送优惠券 +export const sendCoupon = async (data: any) => { + return request.post({ + url: '/promotion/coupon/send', + data: data + }) +} diff --git a/src/api/mall/promotion/coupon/couponTemplate.ts b/src/api/mall/promotion/coupon/couponTemplate.ts index 6a58876e9..daac1334f 100755 --- a/src/api/mall/promotion/coupon/couponTemplate.ts +++ b/src/api/mall/promotion/coupon/couponTemplate.ts @@ -73,6 +73,14 @@ export function getCouponTemplatePage(params: PageParam) { }) } +// 获得可用于领取的优惠劵模板分页 +export function getCanTakeCouponTemplatePage(params: PageParam) { + return request.get({ + url: '/promotion/coupon-template/can-take-page', + params: params + }) +} + // 导出优惠劵模板 Excel export function exportCouponTemplateExcel(params: PageParam) { return request.get({ diff --git a/src/views/mall/promotion/coupon/components/CouponSend.vue b/src/views/mall/promotion/coupon/components/CouponSend.vue new file mode 100644 index 000000000..7686539b0 --- /dev/null +++ b/src/views/mall/promotion/coupon/components/CouponSend.vue @@ -0,0 +1,162 @@ + + + diff --git a/src/views/mall/promotion/coupon/formatter.ts b/src/views/mall/promotion/coupon/formatter.ts new file mode 100644 index 000000000..60eebb5d3 --- /dev/null +++ b/src/views/mall/promotion/coupon/formatter.ts @@ -0,0 +1,44 @@ +import { CouponTemplateValidityTypeEnum, PromotionDiscountTypeEnum } from '@/utils/constants' +import { formatDate } from '@/utils/formatTime' +import { CouponTemplateVO } from '@/api/mall/promotion/coupon/couponTemplate' +import { floatToFixed2 } from '@/utils' + +// 格式化【优惠金额/折扣】 +export const discountFormat = (row: CouponTemplateVO) => { + if (row.discountType === PromotionDiscountTypeEnum.PRICE.type) { + return `¥${floatToFixed2(row.discountPrice)}` + } + if (row.discountType === PromotionDiscountTypeEnum.PERCENT.type) { + return `${row.discountPrice}%` + } + return '未知【' + row.discountType + '】' +} + +// 格式化【领取上限】 +export const takeLimitCountFormat = (row: CouponTemplateVO) => { + if (row.takeLimitCount === -1) { + return '无领取限制' + } + return `${row.takeLimitCount} 张/人` +} + +// 格式化【有效期限】 +export const validityTypeFormat = (row: CouponTemplateVO) => { + 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 + '】' +} + +// 格式化【剩余数量】 +export const remainedCountFormat = (row: CouponTemplateVO) => { + return row.totalCount - row.takeCount +} + +// 格式化【最低消费】 +export const userPriceFormat = (row: CouponTemplateVO) => { + return `¥${floatToFixed2(row.usePrice)}` +} diff --git a/src/views/mall/promotion/coupon/template/index.vue b/src/views/mall/promotion/coupon/template/index.vue index ee8dad46f..ad0077cec 100755 --- a/src/views/mall/promotion/coupon/template/index.vue +++ b/src/views/mall/promotion/coupon/template/index.vue @@ -103,7 +103,7 @@ label="剩余数量" align="center" prop="totalCount" - :formatter="(row) => row.totalCount - row.takeCount" + :formatter="remainedCountFormat" /> import * as CouponTemplateApi from '@/api/mall/promotion/coupon/couponTemplate' -import { - CommonStatusEnum, - CouponTemplateValidityTypeEnum, - PromotionDiscountTypeEnum -} from '@/utils/constants' +import { CommonStatusEnum } from '@/utils/constants' import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' -import { dateFormatter, formatDate } from '@/utils/formatTime' +import { dateFormatter } from '@/utils/formatTime' import CouponTemplateForm from './CouponTemplateForm.vue' +import { + discountFormat, + remainedCountFormat, + takeLimitCountFormat, + validityTypeFormat +} from '@/views/mall/promotion/coupon/formatter' defineOptions({ name: 'PromotionCouponTemplate' }) @@ -193,6 +195,7 @@ const queryParams = reactive({ pageSize: 10, name: null, status: null, + discountType: null, type: null, createTime: [] }) @@ -258,36 +261,6 @@ const handleDelete = async (id: number) => { } catch {} } -// 格式化【优惠金额/折扣】 -const discountFormat = (row: any) => { - if (row.discountType === PromotionDiscountTypeEnum.PRICE.type) { - return `¥${(row.discountPrice / 100.0).toFixed(2)}` - } - if (row.discountType === PromotionDiscountTypeEnum.PERCENT.type) { - return `¥${(row.discountPrice / 100.0).toFixed(2)}` - } - return '未知【' + row.discountType + '】' -} - -// 格式化【领取上限】 -const takeLimitCountFormat = (row: any) => { - if (row.takeLimitCount === -1) { - return '无领取限制' - } - return `${row.takeLimitCount} 张/人` -} - -// 格式化【有效期限】 -const validityTypeFormat = (row: any) => { - 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 + '】' -} - /** 初始化 **/ onMounted(() => { getList() diff --git a/src/views/member/user/index.vue b/src/views/member/user/index.vue index bae5c0485..672e9bfc2 100644 --- a/src/views/member/user/index.vue +++ b/src/views/member/user/index.vue @@ -60,13 +60,21 @@ 搜索 重置 + 发送优惠券 - + + + + From 27219e1833f49fa60acc2d7809f2f7497230a2e4 Mon Sep 17 00:00:00 2001 From: owen Date: Wed, 30 Aug 2023 20:54:20 +0800 Subject: [PATCH 03/15] =?UTF-8?q?mall=EF=BC=9A=E4=BC=98=E6=83=A0=E5=88=B8?= =?UTF-8?q?=20=E5=95=86=E5=93=81=E9=80=82=E7=94=A8=E8=8C=83=E5=9B=B4?= =?UTF-8?q?=EF=BC=8C=E5=A2=9E=E5=8A=A0=E5=95=86=E5=93=81=E5=88=86=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mall/promotion/coupon/couponTemplate.ts | 2 +- src/utils/constants.ts | 4 ++ .../components/ProductCategorySelect.vue | 47 +++++++++++++++++++ .../coupon/template/CouponTemplateForm.vue | 26 ++++++++-- 4 files changed, 75 insertions(+), 4 deletions(-) create mode 100644 src/views/mall/product/category/components/ProductCategorySelect.vue diff --git a/src/api/mall/promotion/coupon/couponTemplate.ts b/src/api/mall/promotion/coupon/couponTemplate.ts index daac1334f..bf294441e 100755 --- a/src/api/mall/promotion/coupon/couponTemplate.ts +++ b/src/api/mall/promotion/coupon/couponTemplate.ts @@ -9,7 +9,7 @@ export interface CouponTemplateVO { takeType: number usePrice: number productScope: number - productSpuIds: string + productSpuIds: number[] validityType: number validStartTime: Date validEndTime: Date diff --git a/src/utils/constants.ts b/src/utils/constants.ts index cd346a5cc..03c1f999d 100644 --- a/src/utils/constants.ts +++ b/src/utils/constants.ts @@ -220,6 +220,10 @@ export const PromotionProductScopeEnum = { SPU: { scope: 2, name: '指定商品参与' + }, + CATEGORY: { + scope: 3, + name: '指定品类参与' } } diff --git a/src/views/mall/product/category/components/ProductCategorySelect.vue b/src/views/mall/product/category/components/ProductCategorySelect.vue new file mode 100644 index 000000000..b8011290f --- /dev/null +++ b/src/views/mall/product/category/components/ProductCategorySelect.vue @@ -0,0 +1,47 @@ + + diff --git a/src/views/mall/promotion/coupon/template/CouponTemplateForm.vue b/src/views/mall/promotion/coupon/template/CouponTemplateForm.vue index 69132fbb3..e511dd0ca 100644 --- a/src/views/mall/promotion/coupon/template/CouponTemplateForm.vue +++ b/src/views/mall/promotion/coupon/template/CouponTemplateForm.vue @@ -172,6 +172,12 @@ + + + @@ -175,7 +185,11 @@ import { propTypes } from '@/utils/propTypes' import { checkSelectedNode, defaultProps, handleTree, treeToString } from '@/utils/tree' import { createImageViewer } from '@/components/ImageViewer' import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' -import { PropertyAndValues, SkuList } from '@/views/mall/product/spu/components/index.ts' +import { + PropertyAndValues, + RuleConfig, + SkuList +} from '@/views/mall/product/spu/components/index.ts' import ProductAttributes from './ProductAttributes.vue' import ProductPropertyAddForm from './ProductPropertyAddForm.vue' import { basicInfoSchema } from './spu.data' @@ -186,6 +200,30 @@ import * as ExpressTemplateApi from '@/api/mall/trade/delivery/expressTemplate' defineOptions({ name: 'ProductSpuBasicInfoForm' }) +// sku 相关属性校验规则 +const ruleConfig: RuleConfig[] = [ + { + name: 'stock', + rule: (arg) => arg >= 1, + message: '商品库存必须大于等于 1 !!!' + }, + { + name: 'price', + rule: (arg) => arg >= 0.01, + message: '商品销售价格必须大于等于 0.01 !!!' + }, + { + name: 'marketPrice', + rule: (arg) => arg >= 0.01, + message: '商品市场价格必须大于等于 0.01 !!!' + }, + { + name: 'costPrice', + rule: (arg) => arg >= 0.01, + message: '商品成本价格必须大于等于 0.01 !!!' + } +] + // ====== 商品详情相关操作 ====== const { allSchemas } = useCrudSchemas(basicInfoSchema) /** 商品图预览 */ diff --git a/src/views/mall/product/spu/form/index.vue b/src/views/mall/product/spu/form/index.vue index db5b04452..526bb338f 100644 --- a/src/views/mall/product/spu/form/index.vue +++ b/src/views/mall/product/spu/form/index.vue @@ -142,17 +142,17 @@ const submitForm = async () => { await unref(otherSettingsRef)?.validate() // 深拷贝一份, 这样最终 server 端不满足,不需要恢复, const deepCopyFormData = cloneDeep(unref(formData.value)) as ProductSpuApi.Spu - // 兜底处理 sku 空数据 - formData.value.skus!.forEach((sku) => { - // 因为是空数据这里判断一下商品条码是否为空就行 - if (sku.barCode === '') { - const index = deepCopyFormData.skus!.findIndex( - (item) => JSON.stringify(item.properties) === JSON.stringify(sku.properties) - ) - // 删除这条 sku - deepCopyFormData.skus!.splice(index, 1) - } - }) + // 兜底处理 sku 空数据 TODO 后续没得问题就移除 + // formData.value.skus!.forEach((sku) => { + // // 因为是空数据这里判断一下商品条码是否为空就行 + // if (sku.barCode === '') { + // const index = deepCopyFormData.skus!.findIndex( + // (item) => JSON.stringify(item.properties) === JSON.stringify(sku.properties) + // ) + // // 删除这条 sku + // deepCopyFormData.skus!.splice(index, 1) + // } + // }) deepCopyFormData.skus!.forEach((item) => { // 给sku name赋值 item.name = deepCopyFormData.name From 3918fab1ec69793f7e3a6e1b3cc86fa5f30d987e Mon Sep 17 00:00:00 2001 From: YunaiV Date: Fri, 1 Sep 2023 00:49:42 +0800 Subject: [PATCH 05/15] code review --- src/views/mall/product/brand/index.vue | 2 +- src/views/mall/product/category/index.vue | 2 +- src/views/mall/product/comment/index.vue | 2 +- .../mall/product/property/value/index.vue | 2 +- .../mall/product/spu/components/index.ts | 31 ++++++++++++++++++- .../mall/product/spu/form/BasicInfoForm.vue | 30 +----------------- src/views/mall/product/spu/form/index.vue | 2 +- src/views/mall/product/spu/index.vue | 18 +++++------ .../mall/trade/afterSale/detail/index.vue | 28 ++++++++--------- 9 files changed, 57 insertions(+), 60 deletions(-) diff --git a/src/views/mall/product/brand/index.vue b/src/views/mall/product/brand/index.vue index 9250befd3..c89fe5200 100644 --- a/src/views/mall/product/brand/index.vue +++ b/src/views/mall/product/brand/index.vue @@ -59,7 +59,7 @@ diff --git a/src/views/mall/product/category/index.vue b/src/views/mall/product/category/index.vue index a2adfe7ff..27ea53689 100644 --- a/src/views/mall/product/category/index.vue +++ b/src/views/mall/product/category/index.vue @@ -38,7 +38,7 @@ diff --git a/src/views/mall/product/comment/index.vue b/src/views/mall/product/comment/index.vue index 1b0745ba5..7c0737f57 100644 --- a/src/views/mall/product/comment/index.vue +++ b/src/views/mall/product/comment/index.vue @@ -115,7 +115,7 @@ :formatter="dateFormatter" width="170" /> - +