From c0962fec187e79a89c16b00b8e235ceda8c40a98 Mon Sep 17 00:00:00 2001 From: Netfan Date: Wed, 11 Jun 2025 12:20:52 +0800 Subject: [PATCH 01/22] fix: auto close popup on deactivated (#6368) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 修复挂载到内容区域的弹窗和抽屉被意外关闭的问题 --- .../ui-kit/popup-ui/src/drawer/drawer.vue | 20 +++++++++++++++++- .../ui-kit/popup-ui/src/drawer/use-drawer.ts | 8 ------- .../@core/ui-kit/popup-ui/src/modal/modal.vue | 21 ++++++++++++++++++- .../ui-kit/popup-ui/src/modal/use-modal.ts | 9 +------- 4 files changed, 40 insertions(+), 18 deletions(-) diff --git a/packages/@core/ui-kit/popup-ui/src/drawer/drawer.vue b/packages/@core/ui-kit/popup-ui/src/drawer/drawer.vue index ebd98fa2b..8a3c0c53f 100644 --- a/packages/@core/ui-kit/popup-ui/src/drawer/drawer.vue +++ b/packages/@core/ui-kit/popup-ui/src/drawer/drawer.vue @@ -1,7 +1,15 @@ - - diff --git a/apps/web-antd/src/components/cropper/cropper-modal.vue b/apps/web-antd/src/components/cropper/cropper-modal.vue index 04b1f3627..d2dedb6de 100644 --- a/apps/web-antd/src/components/cropper/cropper-modal.vue +++ b/apps/web-antd/src/components/cropper/cropper-modal.vue @@ -37,7 +37,6 @@ const cropper = ref(); let scaleX = 1; let scaleY = 1; -const prefixCls = 'cropper-am'; const [Modal, modalApi] = useVbenModal({ onConfirm: handleOk, onOpenChange(isOpen) { @@ -129,9 +128,13 @@ async function handleOk() { :title="$t('ui.cropper.modalTitle')" class="w-2/3" > -
-
-
+
+ +
+ +
-
+ +
-
-
+ + +
+ +
+ + - - diff --git a/apps/web-antd/src/components/cropper/cropper.vue b/apps/web-antd/src/components/cropper/cropper.vue index c2d62755e..cc8836c9f 100644 --- a/apps/web-antd/src/components/cropper/cropper.vue +++ b/apps/web-antd/src/components/cropper/cropper.vue @@ -33,7 +33,6 @@ const imgElRef = ref>(); const cropper = ref(); const isReady = ref(false); -const prefixCls = 'cropper-image'; const debounceRealTimeCropped = useDebounceFn(realTimeCropped, 80); const getImageStyle = computed((): CSSProperties => { @@ -46,10 +45,9 @@ const getImageStyle = computed((): CSSProperties => { const getClass = computed(() => { return [ - prefixCls, attrs.class, { - [`${prefixCls}--circled`]: props.circled, + 'cropper-image--circled': props.circled, }, ]; }); @@ -115,10 +113,9 @@ function cropped() { imgInfo, }); }; - // eslint-disable-next-line unicorn/prefer-add-event-listener - fileReader.onerror = () => { + fileReader.addEventListener('error', () => { emit('cropendError'); - }; + }); }, 'image/png'); } @@ -157,6 +154,7 @@ function getRoundedCanvas() { :crossorigin="crossorigin" :src="src" :style="getImageStyle" + class="h-auto max-w-full" />
-- Gitee From a4f0a48bfebbd0b81da28ee6f10d2d89ffeec628 Mon Sep 17 00:00:00 2001 From: xingyu4j Date: Thu, 19 Jun 2025 14:26:13 +0800 Subject: [PATCH 05/22] feat: mall coupon --- .../src/views/mall/promotion/coupon/data.ts | 129 +++++++++ .../views/mall/promotion/coupon/formatter.ts | 65 +++++ .../src/views/mall/promotion/coupon/index.vue | 148 ++++++++-- .../mall/promotion/coupon/template/data.ts | 252 ++++++++++++++++++ .../mall/promotion/coupon/template/index.vue | 208 +++++++++++++-- .../coupon/template/modules/form.vue | 89 +++++++ 6 files changed, 842 insertions(+), 49 deletions(-) create mode 100644 apps/web-antd/src/views/mall/promotion/coupon/data.ts create mode 100644 apps/web-antd/src/views/mall/promotion/coupon/formatter.ts create mode 100644 apps/web-antd/src/views/mall/promotion/coupon/template/data.ts create mode 100644 apps/web-antd/src/views/mall/promotion/coupon/template/modules/form.vue 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 @@ + + + -- Gitee From df396f3441ae520c84330d3c719d4818b291b1b9 Mon Sep 17 00:00:00 2001 From: xingyu4j Date: Thu, 19 Jun 2025 15:47:28 +0800 Subject: [PATCH 06/22] feat: mall seckill activity --- .../mall/promotion/seckill/activity/data.ts | 126 ++++++++++ .../promotion/seckill/activity/formatter.ts | 34 +++ .../mall/promotion/seckill/activity/index.vue | 216 ++++++++++++++++-- .../seckill/activity/modules/form.vue | 121 ++++++++++ 4 files changed, 472 insertions(+), 25 deletions(-) create mode 100644 apps/web-antd/src/views/mall/promotion/seckill/activity/data.ts create mode 100644 apps/web-antd/src/views/mall/promotion/seckill/activity/formatter.ts create mode 100644 apps/web-antd/src/views/mall/promotion/seckill/activity/modules/form.vue diff --git a/apps/web-antd/src/views/mall/promotion/seckill/activity/data.ts b/apps/web-antd/src/views/mall/promotion/seckill/activity/data.ts new file mode 100644 index 000000000..5b7e1c28c --- /dev/null +++ b/apps/web-antd/src/views/mall/promotion/seckill/activity/data.ts @@ -0,0 +1,126 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { DICT_TYPE, getDictOptions } from '#/utils'; + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'name', + label: '活动名称', + component: 'Input', + componentProps: { + placeholder: '请输入活动名称', + clearable: true, + }, + }, + { + fieldName: 'status', + label: '活动状态', + component: 'Select', + componentProps: { + placeholder: '请选择活动状态', + clearable: true, + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'id', + title: '活动编号', + minWidth: 80, + }, + { + field: 'name', + title: '活动名称', + minWidth: 140, + }, + { + field: 'configIds', + title: '秒杀时段', + width: 220, + slots: { default: 'configIds' }, + }, + { + field: 'startTime', + title: '活动时间', + minWidth: 210, + slots: { default: 'timeRange' }, + }, + { + field: 'picUrl', + title: '商品图片', + minWidth: 80, + cellRender: { + name: 'CellImage', + }, + }, + { + field: 'spuName', + title: '商品标题', + minWidth: 300, + }, + { + field: 'marketPrice', + title: '原价', + minWidth: 100, + formatter: ({ row }) => `¥${(row.marketPrice / 100).toFixed(2)}`, + }, + { + field: 'seckillPrice', + title: '秒杀价', + minWidth: 100, + formatter: ({ row }) => { + if (!(row.products || row.products.length === 0)) { + return '¥0.00'; + } + const seckillPrice = Math.min( + ...row.products.map((item: any) => item.seckillPrice), + ); + return `¥${(seckillPrice / 100).toFixed(2)}`; + }, + }, + { + field: 'status', + title: '活动状态', + align: 'center', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.COMMON_STATUS }, + }, + }, + { + field: 'stock', + title: '库存', + align: 'center', + minWidth: 80, + }, + { + field: 'totalStock', + title: '总库存', + align: 'center', + minWidth: 80, + }, + { + field: 'createTime', + title: '创建时间', + align: 'center', + width: 180, + formatter: 'formatDateTime', + }, + { + title: '操作', + align: 'center', + width: 150, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-antd/src/views/mall/promotion/seckill/activity/formatter.ts b/apps/web-antd/src/views/mall/promotion/seckill/activity/formatter.ts new file mode 100644 index 000000000..db1bce54d --- /dev/null +++ b/apps/web-antd/src/views/mall/promotion/seckill/activity/formatter.ts @@ -0,0 +1,34 @@ +import { formatDate } from '@vben/utils'; + +// 全局变量,用于存储配置列表 +let configList: any[] = []; + +/** 设置配置列表 */ +export function setConfigList(list: any[]) { + configList = list; +} + +/** 格式化配置名称 */ +export function formatConfigNames(configId: number): string { + const config = configList.find((item) => item.id === configId); + return config === null || config === undefined + ? '' + : `${config.name}[${config.startTime} ~ ${config.endTime}]`; +} + +/** 格式化秒杀价格 */ +export function formatSeckillPrice(products: any[]): string { + if (!products || products.length === 0) { + return '¥0.00'; + } + const seckillPrice = Math.min(...products.map((item) => item.seckillPrice)); + return `¥${(seckillPrice / 100).toFixed(2)}`; +} + +/** 格式化活动时间范围 */ +export function formatTimeRange( + startTime: Date | string, + endTime: Date | string, +): string { + return `${formatDate(startTime, 'YYYY-MM-DD')} ~ ${formatDate(endTime, 'YYYY-MM-DD')}`; +} diff --git a/apps/web-antd/src/views/mall/promotion/seckill/activity/index.vue b/apps/web-antd/src/views/mall/promotion/seckill/activity/index.vue index 7eb15646c..0d3a6cb08 100644 --- a/apps/web-antd/src/views/mall/promotion/seckill/activity/index.vue +++ b/apps/web-antd/src/views/mall/promotion/seckill/activity/index.vue @@ -1,32 +1,198 @@ diff --git a/apps/web-antd/src/views/mall/promotion/seckill/activity/modules/form.vue b/apps/web-antd/src/views/mall/promotion/seckill/activity/modules/form.vue new file mode 100644 index 000000000..99c2767db --- /dev/null +++ b/apps/web-antd/src/views/mall/promotion/seckill/activity/modules/form.vue @@ -0,0 +1,121 @@ + + + -- Gitee From 1518ec2f6700eae8fe062a939cf4e997646b8fe2 Mon Sep 17 00:00:00 2001 From: xingyu4j Date: Thu, 19 Jun 2025 15:51:11 +0800 Subject: [PATCH 07/22] feat: mall brokeage record --- .../views/mall/trade/brokerage/record/data.ts | 128 ++++++++++++++++++ .../mall/trade/brokerage/record/index.vue | 79 +++++++---- 2 files changed, 183 insertions(+), 24 deletions(-) create mode 100644 apps/web-antd/src/views/mall/trade/brokerage/record/data.ts diff --git a/apps/web-antd/src/views/mall/trade/brokerage/record/data.ts b/apps/web-antd/src/views/mall/trade/brokerage/record/data.ts new file mode 100644 index 000000000..086bd3f00 --- /dev/null +++ b/apps/web-antd/src/views/mall/trade/brokerage/record/data.ts @@ -0,0 +1,128 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { fenToYuan } from '@vben/utils'; + +import { DICT_TYPE, getDictOptions, getRangePickerDefaultProps } from '#/utils'; + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'userId', + label: '用户编号', + component: 'Input', + componentProps: { + placeholder: '请输入用户编号', + clearable: true, + }, + }, + { + fieldName: 'bizType', + label: '业务类型', + component: 'Select', + componentProps: { + placeholder: '请选择业务类型', + clearable: true, + options: getDictOptions(DICT_TYPE.BROKERAGE_RECORD_BIZ_TYPE, 'number'), + }, + }, + { + fieldName: 'status', + label: '状态', + component: 'Select', + componentProps: { + placeholder: '请选择状态', + clearable: true, + options: getDictOptions(DICT_TYPE.BROKERAGE_RECORD_STATUS, 'number'), + }, + }, + { + fieldName: 'createTime', + label: '创建时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + clearable: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'id', + title: '编号', + minWidth: 60, + }, + { + field: 'userId', + title: '用户编号', + minWidth: 80, + }, + { + field: 'userAvatar', + title: '头像', + width: 70, + slots: { default: 'userAvatar' }, + }, + { + field: 'userNickname', + title: '昵称', + minWidth: 80, + }, + { + field: 'bizType', + title: '业务类型', + minWidth: 85, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.BROKERAGE_RECORD_BIZ_TYPE }, + }, + }, + { + field: 'bizId', + title: '业务编号', + minWidth: 80, + }, + { + field: 'title', + title: '标题', + minWidth: 110, + }, + { + field: 'price', + title: '金额', + minWidth: 60, + formatter: ({ row }) => `¥${fenToYuan(row.price)}`, + }, + { + field: 'description', + title: '说明', + minWidth: 120, + }, + { + field: 'status', + title: '状态', + minWidth: 85, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.BROKERAGE_RECORD_STATUS }, + }, + }, + { + field: 'unfreezeTime', + title: '解冻时间', + width: 180, + formatter: 'formatDateTime', + }, + { + field: 'createTime', + title: '创建时间', + width: 180, + formatter: 'formatDateTime', + }, + ]; +} diff --git a/apps/web-antd/src/views/mall/trade/brokerage/record/index.vue b/apps/web-antd/src/views/mall/trade/brokerage/record/index.vue index 9eb31672a..80c064a7f 100644 --- a/apps/web-antd/src/views/mall/trade/brokerage/record/index.vue +++ b/apps/web-antd/src/views/mall/trade/brokerage/record/index.vue @@ -1,32 +1,63 @@ -- Gitee From 81bd36a1868e365aa55061e56cac451a65d51716 Mon Sep 17 00:00:00 2001 From: "frank.han" <1184394504@qq.com> Date: Thu, 19 Jun 2025 16:10:45 +0800 Subject: [PATCH 08/22] =?UTF-8?q?fix:=20=E9=83=A8=E9=97=A8=E5=88=97?= =?UTF-8?q?=E8=A1=A8=E4=B8=8D=E6=98=BE=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/web-antd/src/views/system/dept/index.vue | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apps/web-antd/src/views/system/dept/index.vue b/apps/web-antd/src/views/system/dept/index.vue index 638865004..5c1eebd1c 100644 --- a/apps/web-antd/src/views/system/dept/index.vue +++ b/apps/web-antd/src/views/system/dept/index.vue @@ -111,6 +111,9 @@ const [Grid, gridApi] = useVbenVxeGrid({ }, }, }, + pagerConfig: { + enabled: false, + }, rowConfig: { keyField: 'id', isHover: true, -- Gitee From f0d221ebf9b31fa8071bc0bfc774a7cb4fd923be Mon Sep 17 00:00:00 2001 From: xingyu4j Date: Thu, 19 Jun 2025 18:56:17 +0800 Subject: [PATCH 09/22] feat: mall brokerage user --- .../api/mall/trade/brokerage/user/index.ts | 10 +- .../views/mall/trade/brokerage/user/data.ts | 133 +++++++++ .../views/mall/trade/brokerage/user/index.vue | 252 ++++++++++++++++-- .../user/modules/order-list-modal.vue | 193 ++++++++++++++ .../user/modules/user-create-form.vue | 166 ++++++++++++ .../user/modules/user-list-modal.vue | 157 +++++++++++ .../user/modules/user-update-form.vue | 131 +++++++++ 7 files changed, 1013 insertions(+), 29 deletions(-) create mode 100644 apps/web-antd/src/views/mall/trade/brokerage/user/data.ts create mode 100644 apps/web-antd/src/views/mall/trade/brokerage/user/modules/order-list-modal.vue create mode 100644 apps/web-antd/src/views/mall/trade/brokerage/user/modules/user-create-form.vue create mode 100644 apps/web-antd/src/views/mall/trade/brokerage/user/modules/user-list-modal.vue create mode 100644 apps/web-antd/src/views/mall/trade/brokerage/user/modules/user-update-form.vue diff --git a/apps/web-antd/src/api/mall/trade/brokerage/user/index.ts b/apps/web-antd/src/api/mall/trade/brokerage/user/index.ts index d523f1d6e..51c24f25a 100644 --- a/apps/web-antd/src/api/mall/trade/brokerage/user/index.ts +++ b/apps/web-antd/src/api/mall/trade/brokerage/user/index.ts @@ -29,12 +29,14 @@ export namespace MallBrokerageUserApi { export interface CreateRequest { /** 用户编号 */ userId: number; + /** 推广员编号 */ + bindUserId: number; } /** 修改推广员请求 */ export interface UpdateBindUserRequest { /** 用户编号 */ - userId: number; + id: number; /** 推广员编号 */ bindUserId: number; } @@ -42,15 +44,15 @@ export namespace MallBrokerageUserApi { /** 清除推广员请求 */ export interface ClearBindUserRequest { /** 用户编号 */ - userId: number; + id: number; } /** 修改推广资格请求 */ export interface UpdateBrokerageEnabledRequest { /** 用户编号 */ - userId: number; + id: number; /** 是否启用分销 */ - brokerageEnabled: boolean; + enabled: boolean; } } diff --git a/apps/web-antd/src/views/mall/trade/brokerage/user/data.ts b/apps/web-antd/src/views/mall/trade/brokerage/user/data.ts new file mode 100644 index 000000000..e37e1ee1c --- /dev/null +++ b/apps/web-antd/src/views/mall/trade/brokerage/user/data.ts @@ -0,0 +1,133 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { fenToYuan } from '@vben/utils'; + +import { getRangePickerDefaultProps } from '#/utils'; + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'bindUserId', + label: '推广员编号', + component: 'Input', + componentProps: { + placeholder: '请输入推广员编号', + clearable: true, + }, + }, + { + fieldName: 'brokerageEnabled', + label: '推广资格', + component: 'Select', + componentProps: { + placeholder: '请选择推广资格', + clearable: true, + options: [ + { label: '有', value: true }, + { label: '无', value: false }, + ], + }, + }, + { + fieldName: 'createTime', + label: '创建时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + clearable: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'id', + title: '用户编号', + minWidth: 80, + }, + { + field: 'avatar', + title: '头像', + width: 70, + slots: { default: 'avatar' }, + }, + { + field: 'nickname', + title: '昵称', + minWidth: 80, + }, + { + field: 'brokerageUserCount', + title: '推广人数', + width: 80, + }, + { + field: 'brokerageOrderCount', + title: '推广订单数量', + minWidth: 110, + }, + { + field: 'brokerageOrderPrice', + title: '推广订单金额', + minWidth: 110, + formatter: ({ row }) => `¥${fenToYuan(row.brokerageOrderPrice)}`, + }, + { + field: 'withdrawPrice', + title: '已提现金额', + minWidth: 100, + formatter: ({ row }) => `¥${fenToYuan(row.withdrawPrice)}`, + }, + { + field: 'withdrawCount', + title: '已提现次数', + minWidth: 100, + }, + { + field: 'price', + title: '未提现金额', + minWidth: 100, + formatter: ({ row }) => `¥${fenToYuan(row.price)}`, + }, + { + field: 'frozenPrice', + title: '冻结中佣金', + minWidth: 100, + formatter: ({ row }) => `¥${fenToYuan(row.frozenPrice)}`, + }, + { + field: 'brokerageEnabled', + title: '推广资格', + minWidth: 80, + slots: { default: 'brokerageEnabled' }, + }, + { + field: 'brokerageTime', + title: '成为推广员时间', + width: 180, + formatter: 'formatDateTime', + }, + { + field: 'bindUserId', + title: '上级推广员编号', + width: 150, + }, + { + field: 'bindUserTime', + title: '推广员绑定时间', + width: 180, + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 150, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-antd/src/views/mall/trade/brokerage/user/index.vue b/apps/web-antd/src/views/mall/trade/brokerage/user/index.vue index 969426470..56c004ba3 100644 --- a/apps/web-antd/src/views/mall/trade/brokerage/user/index.vue +++ b/apps/web-antd/src/views/mall/trade/brokerage/user/index.vue @@ -1,32 +1,234 @@ diff --git a/apps/web-antd/src/views/mall/trade/brokerage/user/modules/order-list-modal.vue b/apps/web-antd/src/views/mall/trade/brokerage/user/modules/order-list-modal.vue new file mode 100644 index 000000000..e10839e5b --- /dev/null +++ b/apps/web-antd/src/views/mall/trade/brokerage/user/modules/order-list-modal.vue @@ -0,0 +1,193 @@ + + + diff --git a/apps/web-antd/src/views/mall/trade/brokerage/user/modules/user-create-form.vue b/apps/web-antd/src/views/mall/trade/brokerage/user/modules/user-create-form.vue new file mode 100644 index 000000000..4d49231c7 --- /dev/null +++ b/apps/web-antd/src/views/mall/trade/brokerage/user/modules/user-create-form.vue @@ -0,0 +1,166 @@ + + + diff --git a/apps/web-antd/src/views/mall/trade/brokerage/user/modules/user-list-modal.vue b/apps/web-antd/src/views/mall/trade/brokerage/user/modules/user-list-modal.vue new file mode 100644 index 000000000..18dcc46ee --- /dev/null +++ b/apps/web-antd/src/views/mall/trade/brokerage/user/modules/user-list-modal.vue @@ -0,0 +1,157 @@ + + + diff --git a/apps/web-antd/src/views/mall/trade/brokerage/user/modules/user-update-form.vue b/apps/web-antd/src/views/mall/trade/brokerage/user/modules/user-update-form.vue new file mode 100644 index 000000000..4f2fe59e8 --- /dev/null +++ b/apps/web-antd/src/views/mall/trade/brokerage/user/modules/user-update-form.vue @@ -0,0 +1,131 @@ + + + -- Gitee From bcabc4d6d013d4c154be990df92e8370c3c3cb33 Mon Sep 17 00:00:00 2001 From: xingyu4j Date: Thu, 19 Jun 2025 19:29:53 +0800 Subject: [PATCH 10/22] feat: mall brokerage withdraw --- .../views/mall/trade/brokerage/user/index.vue | 7 - .../mall/trade/brokerage/withdraw/data.ts | 145 ++++++++++++ .../mall/trade/brokerage/withdraw/index.vue | 213 ++++++++++++++++-- 3 files changed, 333 insertions(+), 32 deletions(-) create mode 100644 apps/web-antd/src/views/mall/trade/brokerage/withdraw/data.ts diff --git a/apps/web-antd/src/views/mall/trade/brokerage/user/index.vue b/apps/web-antd/src/views/mall/trade/brokerage/user/index.vue index 56c004ba3..b1e48ada3 100644 --- a/apps/web-antd/src/views/mall/trade/brokerage/user/index.vue +++ b/apps/web-antd/src/views/mall/trade/brokerage/user/index.vue @@ -2,8 +2,6 @@ import type { VxeTableGridOptions } from '#/adapter/vxe-table'; import type { MallBrokerageUserApi } from '#/api/mall/trade/brokerage/user'; -import { onMounted } from 'vue'; - import { useAccess } from '@vben/access'; import { DocAlert, Page, useVbenModal } from '@vben/common-ui'; import { $t } from '@vben/locales'; @@ -143,11 +141,6 @@ const [Grid, gridApi] = useVbenVxeGrid({ }, } as VxeTableGridOptions, }); - -/** 初始化 */ -onMounted(() => { - // 表格初始化时会自动查询,无需手动调用 -});